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 {
1970 nClipTab = 0;
1971 for (SCTAB i = pCBFCP->nTabStart; i <= nTabEnd; i++)
1972 {
1973 if (pTab[i] && rMark.GetTableSelect(i) )
1974 {
1975 while (!ppClipTab[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1);
1976 SCsTAB nDz = ((SCsTAB)i) - nClipTab;
1977
1978 // #89081# ranges of consecutive selected tables (in clipboard and dest. doc)
1979 // must be handled in one UpdateReference call
1980 SCTAB nFollow = 0;
1981 while ( i + nFollow < nTabEnd
1982 && rMark.GetTableSelect( i + nFollow + 1 )
1983 && nClipTab + nFollow < MAXTAB
1984 && ppClipTab[nClipTab + nFollow + 1] )
1985 ++nFollow;
1986
1987 if ( pCBFCP->pClipDoc->GetClipParam().mbCutMode )
1988 {
1989 sal_Bool bOldInserting = IsInsertingFromOtherDoc();
1990 SetInsertingFromOtherDoc( sal_True);
1991 UpdateReference( URM_MOVE,
1992 nCol1, nRow1, i, nCol2, nRow2, i+nFollow,
1993 nDx, nDy, nDz, pCBFCP->pRefUndoDoc, sal_False );
1994 SetInsertingFromOtherDoc( bOldInserting);
1995 }
1996 else
1997 UpdateReference( URM_COPY,
1998 nCol1, nRow1, i, nCol2, nRow2, i+nFollow,
1999 nDx, nDy, nDz, pCBFCP->pRefUndoDoc, sal_False );
2000
2001 nClipTab = (nClipTab+nFollow+1) % (MAXTAB+1);
2002 i = sal::static_int_cast<SCTAB>( i + nFollow );
2003 }
2004 }
2005 }
2006 }
2007
2008
CopyNonFilteredFromClip(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,const ScMarkData & rMark,SCsCOL nDx,SCsROW,const ScCopyBlockFromClipParams * pCBFCP,SCROW & rClipStartRow)2009 void ScDocument::CopyNonFilteredFromClip( SCCOL nCol1, SCROW nRow1,
2010 SCCOL nCol2, SCROW nRow2,
2011 const ScMarkData& rMark,
2012 SCsCOL nDx, SCsROW /* nDy */,
2013 const ScCopyBlockFromClipParams* pCBFCP,
2014 SCROW & rClipStartRow )
2015 {
2016 // call CopyBlockFromClip for ranges of consecutive non-filtered rows
2017 // nCol1/nRow1 etc. is in target doc
2018
2019 // filtered state is taken from first used table in clipboard (as in GetClipArea)
2020 SCTAB nFlagTab = 0;
2021 ScTable** ppClipTab = pCBFCP->pClipDoc->pTab;
2022 while ( nFlagTab < MAXTAB && !ppClipTab[nFlagTab] )
2023 ++nFlagTab;
2024
2025 SCROW nSourceRow = rClipStartRow;
2026 SCROW nSourceEnd = 0;
2027 if (pCBFCP->pClipDoc->GetClipParam().maRanges.Count())
2028 nSourceEnd = pCBFCP->pClipDoc->GetClipParam().maRanges.First()->aEnd.Row();
2029 SCROW nDestRow = nRow1;
2030
2031 while ( nSourceRow <= nSourceEnd && nDestRow <= nRow2 )
2032 {
2033 // skip filtered rows
2034 nSourceRow = pCBFCP->pClipDoc->FirstNonFilteredRow(nSourceRow, nSourceEnd, nFlagTab);
2035
2036 if ( nSourceRow <= nSourceEnd )
2037 {
2038 // look for more non-filtered rows following
2039 SCROW nLastRow = nSourceRow;
2040 pCBFCP->pClipDoc->RowFiltered(nSourceRow, nFlagTab, NULL, &nLastRow);
2041 SCROW nFollow = nLastRow - nSourceRow;
2042
2043 if (nFollow > nSourceEnd - nSourceRow)
2044 nFollow = nSourceEnd - nSourceRow;
2045 if (nFollow > nRow2 - nDestRow)
2046 nFollow = nRow2 - nDestRow;
2047
2048 SCsROW nNewDy = ((SCsROW)nDestRow) - nSourceRow;
2049 CopyBlockFromClip( nCol1, nDestRow, nCol2, nDestRow + nFollow, rMark, nDx, nNewDy, pCBFCP );
2050
2051 nSourceRow += nFollow + 1;
2052 nDestRow += nFollow + 1;
2053 }
2054 }
2055 rClipStartRow = nSourceRow;
2056 }
2057
2058
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)2059 void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMark,
2060 sal_uInt16 nInsFlag,
2061 ScDocument* pRefUndoDoc, ScDocument* pClipDoc, sal_Bool bResetCut,
2062 sal_Bool bAsLink, sal_Bool bIncludeFiltered, sal_Bool bSkipAttrForEmpty,
2063 const ScRangeList * pDestRanges )
2064 {
2065 if (!bIsClip)
2066 {
2067 if (!pClipDoc)
2068 {
2069 DBG_ERROR("CopyFromClip: no ClipDoc");
2070 pClipDoc = SC_MOD()->GetClipDoc();
2071 }
2072 if (pClipDoc->bIsClip && pClipDoc->GetTableCount())
2073 {
2074 sal_Bool bOldAutoCalc = GetAutoCalc();
2075 SetAutoCalc( sal_False ); // avoid multiple recalculations
2076
2077 NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
2078
2079 ScClipRangeNameData aClipRangeNames;
2080 CopyRangeNamesFromClip(pClipDoc, aClipRangeNames);
2081
2082 SCCOL nAllCol1 = rDestRange.aStart.Col();
2083 SCROW nAllRow1 = rDestRange.aStart.Row();
2084 SCCOL nAllCol2 = rDestRange.aEnd.Col();
2085 SCROW nAllRow2 = rDestRange.aEnd.Row();
2086
2087 SCCOL nXw = 0;
2088 SCROW nYw = 0;
2089 ScRange aClipRange = pClipDoc->GetClipParam().getWholeRange();
2090 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) // find largest merge overlap
2091 if (pClipDoc->pTab[nTab]) // all sheets of the clipboard content
2092 {
2093 SCCOL nThisEndX = aClipRange.aEnd.Col();
2094 SCROW nThisEndY = aClipRange.aEnd.Row();
2095 pClipDoc->ExtendMerge( aClipRange.aStart.Col(),
2096 aClipRange.aStart.Row(),
2097 nThisEndX, nThisEndY, nTab );
2098 // only extra value from ExtendMerge
2099 nThisEndX = sal::static_int_cast<SCCOL>( nThisEndX - aClipRange.aEnd.Col() );
2100 nThisEndY = sal::static_int_cast<SCROW>( nThisEndY - aClipRange.aEnd.Row() );
2101 if ( nThisEndX > nXw )
2102 nXw = nThisEndX;
2103 if ( nThisEndY > nYw )
2104 nYw = nThisEndY;
2105 }
2106
2107 SCCOL nDestAddX;
2108 SCROW nDestAddY;
2109 pClipDoc->GetClipArea( nDestAddX, nDestAddY, bIncludeFiltered );
2110 nXw = sal::static_int_cast<SCCOL>( nXw + nDestAddX );
2111 nYw = sal::static_int_cast<SCROW>( nYw + nDestAddY ); // ClipArea, plus ExtendMerge value
2112
2113 /* Decide which contents to delete before copying. Delete all
2114 contents if nInsFlag contains any real content flag.
2115 #i102056# Notes are pasted from clipboard in a second pass,
2116 together with the special flag IDF_ADDNOTES that states to not
2117 overwrite/delete existing cells but to insert the notes into
2118 these cells. In this case, just delete old notes from the
2119 destination area. */
2120 sal_uInt16 nDelFlag = IDF_NONE;
2121 if ( (nInsFlag & (IDF_CONTENTS | IDF_ADDNOTES)) == (IDF_NOTE | IDF_ADDNOTES) )
2122 nDelFlag |= IDF_NOTE;
2123 else if ( nInsFlag & IDF_CONTENTS )
2124 nDelFlag |= IDF_CONTENTS;
2125 // With bSkipAttrForEmpty, don't remove attributes, copy
2126 // on top of existing attributes instead.
2127 if ( ( nInsFlag & IDF_ATTRIB ) && !bSkipAttrForEmpty )
2128 nDelFlag |= IDF_ATTRIB;
2129
2130 ScCopyBlockFromClipParams aCBFCP;
2131 aCBFCP.pRefUndoDoc = pRefUndoDoc;
2132 aCBFCP.pClipDoc = pClipDoc;
2133 aCBFCP.nInsFlag = nInsFlag;
2134 aCBFCP.bAsLink = bAsLink;
2135 aCBFCP.bSkipAttrForEmpty = bSkipAttrForEmpty;
2136 aCBFCP.nTabStart = MAXTAB; // wird in der Schleife angepasst
2137 aCBFCP.nTabEnd = 0; // wird in der Schleife angepasst
2138
2139 // Inc/DecRecalcLevel einmal aussen, damit nicht fuer jeden Block
2140 // die Draw-Seitengroesse neu berechnet werden muss
2141 //! nur wenn ganze Zeilen/Spalten kopiert werden?
2142
2143 for (SCTAB j = 0; j <= MAXTAB; j++)
2144 if (pTab[j] && rMark.GetTableSelect(j))
2145 {
2146 if ( j < aCBFCP.nTabStart )
2147 aCBFCP.nTabStart = j;
2148 aCBFCP.nTabEnd = j;
2149 pTab[j]->IncRecalcLevel();
2150 }
2151
2152 ScRangeList aLocalRangeList;
2153 if (!pDestRanges)
2154 {
2155 aLocalRangeList.Append( rDestRange);
2156 pDestRanges = &aLocalRangeList;
2157 }
2158
2159 bInsertingFromOtherDoc = sal_True; // kein Broadcast/Listener aufbauen bei Insert
2160
2161 // bei mindestens 64 Zeilen wird in ScColumn::CopyFromClip voralloziert
2162 sal_Bool bDoDouble = ( nYw < 64 && nAllRow2 - nAllRow1 > 64);
2163 sal_Bool bOldDouble = ScColumn::bDoubleAlloc;
2164 if (bDoDouble)
2165 ScColumn::bDoubleAlloc = sal_True;
2166
2167 SCCOL nClipStartCol = aClipRange.aStart.Col();
2168 SCROW nClipStartRow = aClipRange.aStart.Row();
2169 // WaE: commented because unused: SCCOL nClipEndCol = pClipDoc->aClipRange.aEnd.Col();
2170 SCROW nClipEndRow = aClipRange.aEnd.Row();
2171 for (sal_uLong nRange = 0; nRange < pDestRanges->Count(); ++nRange)
2172 {
2173 const ScRange* pRange = pDestRanges->GetObject( nRange);
2174 SCCOL nCol1 = pRange->aStart.Col();
2175 SCROW nRow1 = pRange->aStart.Row();
2176 SCCOL nCol2 = pRange->aEnd.Col();
2177 SCROW nRow2 = pRange->aEnd.Row();
2178
2179 DeleteArea(nCol1, nRow1, nCol2, nRow2, rMark, nDelFlag);
2180
2181 SCCOL nC1 = nCol1;
2182 SCROW nR1 = nRow1;
2183 SCCOL nC2 = nC1 + nXw;
2184 if (nC2 > nCol2)
2185 nC2 = nCol2;
2186 SCROW nR2 = nR1 + nYw;
2187 if (nR2 > nRow2)
2188 nR2 = nRow2;
2189
2190 const unsigned PERFORMANCEOPTIMIZATION4PATTERNTHRESHOLD = 8192;
2191 bool bNeedPerformanceOptimization4Pattern = nRow2 - nRow1 > PERFORMANCEOPTIMIZATION4PATTERNTHRESHOLD;
2192 std::vector< std::vector< SCSIZE > > vvPatternCount( bNeedPerformanceOptimization4Pattern ? nCol2 - nCol1 + 1 : 0 );
2193 std::vector< SCTAB > vTables;
2194
2195 if( bNeedPerformanceOptimization4Pattern )
2196 {
2197 for (SCTAB i = aCBFCP.nTabStart; i <= aCBFCP.nTabEnd; i++)
2198 if (pTab[i] && rMark.GetTableSelect( i ) )
2199 vTables.push_back( i );
2200
2201 for( SCSIZE i = 0; i < vvPatternCount.size(); i++ )
2202 {
2203 vvPatternCount[i].resize( vTables.size() );
2204
2205 for( std::vector< SCTAB >::size_type j = 0; j<vTables.size(); j++ )
2206 vvPatternCount[i][j] = this->GetPatternCount( vTables[j], nCol1+i );
2207 }
2208 }
2209
2210 do
2211 {
2212 // Pasting is done column-wise, when pasting to a filtered
2213 // area this results in partitioning and we have to
2214 // remember and reset the start row for each column until
2215 // it can be advanced for the next chunk of unfiltered
2216 // rows.
2217 SCROW nSaveClipStartRow = nClipStartRow;
2218 do
2219 {
2220 nClipStartRow = nSaveClipStartRow;
2221 SCsCOL nDx = ((SCsCOL)nC1) - nClipStartCol;
2222 SCsROW nDy = ((SCsROW)nR1) - nClipStartRow;
2223 if ( bIncludeFiltered )
2224 {
2225 CopyBlockFromClip( nC1, nR1, nC2, nR2, rMark, nDx,
2226 nDy, &aCBFCP );
2227 nClipStartRow += nR2 - nR1 + 1;
2228 }
2229 else
2230 {
2231 CopyNonFilteredFromClip( nC1, nR1, nC2, nR2, rMark,
2232 nDx, nDy, &aCBFCP, nClipStartRow );
2233 }
2234 // Not needed for columns, but if it was this would be how to.
2235 //if (nClipStartCol > nClipEndCol)
2236 // nClipStartCol = pClipDoc->aClipRange.aStart.Col();
2237 nC1 = nC2 + 1;
2238 nC2 = Min((SCCOL)(nC1 + nXw), nCol2);
2239 } while (nC1 <= nCol2);
2240 if (nClipStartRow > nClipEndRow)
2241 nClipStartRow = aClipRange.aStart.Row();
2242 nC1 = nCol1;
2243 nC2 = nC1 + nXw;
2244 if (nC2 > nCol2)
2245 nC2 = nCol2;
2246
2247 if( bNeedPerformanceOptimization4Pattern && vvPatternCount.size() )
2248 {
2249 for( SCSIZE i = 0; i < vvPatternCount.size(); i++ )
2250 {
2251 vvPatternCount[i].resize( vTables.size() );
2252
2253 for( std::vector< SCTAB >::size_type j = 0; j<vTables.size(); j++ )
2254 this->ReservedPatternCount( vTables[j], nCol1+i, vvPatternCount[i][j] + ( this->GetPatternCount( vTables[j], nCol1+i, nR1, nR2 ) ) * ( ( nRow2 - nRow1 + 1 ) / ( nYw + 1 ) ) );
2255 }
2256
2257 bNeedPerformanceOptimization4Pattern = false;
2258 vvPatternCount.clear();
2259 }
2260
2261 nR1 = nR2 + 1;
2262 nR2 = Min((SCROW)(nR1 + nYw), nRow2);
2263 } while (nR1 <= nRow2);
2264 }
2265
2266 ScColumn::bDoubleAlloc = bOldDouble;
2267
2268 for (SCTAB k = 0; k <= MAXTAB; k++)
2269 if (pTab[k] && rMark.GetTableSelect(k))
2270 pTab[k]->DecRecalcLevel();
2271
2272 bInsertingFromOtherDoc = sal_False;
2273
2274 UpdateRangeNamesInFormulas(aClipRangeNames, *pDestRanges, rMark, nXw, nYw);
2275
2276 // Listener aufbauen nachdem alles inserted wurde
2277 StartListeningFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
2278 // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
2279 BroadcastFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
2280 if (bResetCut)
2281 pClipDoc->GetClipParam().mbCutMode = false;
2282 SetAutoCalc( bOldAutoCalc );
2283 }
2284 }
2285 }
2286
lcl_getLastNonFilteredRow(const ScBitMaskCompressedArray<SCROW,sal_uInt8> & rFlags,SCROW nBegRow,SCROW nEndRow,SCROW nRowCount)2287 static SCROW lcl_getLastNonFilteredRow(
2288 const ScBitMaskCompressedArray<SCROW, sal_uInt8>& rFlags, SCROW nBegRow, SCROW nEndRow,
2289 SCROW nRowCount)
2290 {
2291 SCROW nFilteredRow = rFlags.GetFirstForCondition(
2292 nBegRow, nEndRow, CR_FILTERED, CR_FILTERED);
2293
2294 SCROW nRow = nFilteredRow - 1;
2295 if (nRow - nBegRow + 1 > nRowCount)
2296 // make sure the row range stays within the data size.
2297 nRow = nBegRow + nRowCount - 1;
2298
2299 return nRow;
2300 }
2301
CopyMultiRangeFromClip(const ScAddress & rDestPos,const ScMarkData & rMark,sal_uInt16 nInsFlag,ScDocument * pClipDoc,bool bResetCut,bool bAsLink,bool,bool bSkipAttrForEmpty)2302 void ScDocument::CopyMultiRangeFromClip(
2303 const ScAddress& rDestPos, const ScMarkData& rMark, sal_uInt16 nInsFlag, ScDocument* pClipDoc,
2304 bool bResetCut, bool bAsLink, bool /*bIncludeFiltered*/, bool bSkipAttrForEmpty)
2305 {
2306 if (bIsClip)
2307 return;
2308
2309 if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount())
2310 // There is nothing in the clip doc to copy.
2311 return;
2312
2313 sal_Bool bOldAutoCalc = GetAutoCalc();
2314 SetAutoCalc( sal_False ); // avoid multiple recalculations
2315
2316 NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
2317
2318 ScClipRangeNameData aClipRangeNames;
2319 CopyRangeNamesFromClip(pClipDoc, aClipRangeNames);
2320
2321 SCCOL nCol1 = rDestPos.Col();
2322 SCROW nRow1 = rDestPos.Row();
2323 ScClipParam& rClipParam = pClipDoc->GetClipParam();
2324
2325 ScCopyBlockFromClipParams aCBFCP;
2326 aCBFCP.pRefUndoDoc = NULL;
2327 aCBFCP.pClipDoc = pClipDoc;
2328 aCBFCP.nInsFlag = nInsFlag;
2329 aCBFCP.bAsLink = bAsLink;
2330 aCBFCP.bSkipAttrForEmpty = bSkipAttrForEmpty;
2331 aCBFCP.nTabStart = MAXTAB;
2332 aCBFCP.nTabEnd = 0;
2333
2334 for (SCTAB j = 0; j <= MAXTAB; ++j)
2335 {
2336 if (pTab[j] && rMark.GetTableSelect(j))
2337 {
2338 if ( j < aCBFCP.nTabStart )
2339 aCBFCP.nTabStart = j;
2340 aCBFCP.nTabEnd = j;
2341 pTab[j]->IncRecalcLevel();
2342 }
2343 }
2344
2345 ScRange aDestRange;
2346 rMark.GetMarkArea(aDestRange);
2347 SCROW nLastMarkedRow = aDestRange.aEnd.Row();
2348
2349 bInsertingFromOtherDoc = sal_True; // kein Broadcast/Listener aufbauen bei Insert
2350
2351 SCROW nBegRow = nRow1;
2352 sal_uInt16 nDelFlag = IDF_CONTENTS;
2353 const ScBitMaskCompressedArray<SCROW, sal_uInt8>& rFlags = GetRowFlagsArray(aCBFCP.nTabStart);
2354
2355 for (ScRange* p = rClipParam.maRanges.First(); p; p = rClipParam.maRanges.Next())
2356 {
2357 // The begin row must not be filtered.
2358
2359 SCROW nRowCount = p->aEnd.Row() - p->aStart.Row() + 1;
2360
2361 SCsCOL nDx = static_cast<SCsCOL>(nCol1 - p->aStart.Col());
2362 SCsROW nDy = static_cast<SCsROW>(nBegRow - p->aStart.Row());
2363 SCCOL nCol2 = nCol1 + p->aEnd.Col() - p->aStart.Col();
2364
2365 SCROW nEndRow = lcl_getLastNonFilteredRow(rFlags, nBegRow, nLastMarkedRow, nRowCount);
2366
2367 if (!bSkipAttrForEmpty)
2368 DeleteArea(nCol1, nBegRow, nCol2, nEndRow, rMark, nDelFlag);
2369
2370 CopyBlockFromClip(nCol1, nBegRow, nCol2, nEndRow, rMark, nDx, nDy, &aCBFCP);
2371 nRowCount -= nEndRow - nBegRow + 1;
2372
2373 while (nRowCount > 0)
2374 {
2375 // Get the first non-filtered row.
2376 SCROW nNonFilteredRow = rFlags.GetFirstForCondition(nEndRow+1, nLastMarkedRow, CR_FILTERED, 0);
2377 if (nNonFilteredRow > nLastMarkedRow)
2378 return;
2379
2380 SCROW nRowsSkipped = nNonFilteredRow - nEndRow - 1;
2381 nDy += nRowsSkipped;
2382
2383 nBegRow = nNonFilteredRow;
2384 nEndRow = lcl_getLastNonFilteredRow(rFlags, nBegRow, nLastMarkedRow, nRowCount);
2385
2386 if (!bSkipAttrForEmpty)
2387 DeleteArea(nCol1, nBegRow, nCol2, nEndRow, rMark, nDelFlag);
2388
2389 CopyBlockFromClip(nCol1, nBegRow, nCol2, nEndRow, rMark, nDx, nDy, &aCBFCP);
2390 nRowCount -= nEndRow - nBegRow + 1;
2391 }
2392
2393 if (rClipParam.meDirection == ScClipParam::Row)
2394 // Begin row for the next range being pasted.
2395 nBegRow = rFlags.GetFirstForCondition(nEndRow+1, nLastMarkedRow, CR_FILTERED, 0);
2396 else
2397 nBegRow = nRow1;
2398
2399 if (rClipParam.meDirection == ScClipParam::Column)
2400 nCol1 += p->aEnd.Col() - p->aStart.Col() + 1;
2401 }
2402
2403 for (SCTAB i = 0; i <= MAXTAB; i++)
2404 if (pTab[i] && rMark.GetTableSelect(i))
2405 pTab[i]->DecRecalcLevel();
2406
2407 bInsertingFromOtherDoc = sal_False;
2408
2409 ScRangeList aRanges;
2410 aRanges.Append(aDestRange);
2411 SCCOL nCols = aDestRange.aEnd.Col() - aDestRange.aStart.Col() + 1;
2412 SCROW nRows = aDestRange.aEnd.Row() - aDestRange.aStart.Row() + 1;
2413 UpdateRangeNamesInFormulas(aClipRangeNames, aRanges, rMark, nCols-1, nRows-1);
2414
2415 // Listener aufbauen nachdem alles inserted wurde
2416 StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
2417 aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
2418 // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
2419 BroadcastFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
2420 aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
2421
2422 if (bResetCut)
2423 pClipDoc->GetClipParam().mbCutMode = false;
2424 SetAutoCalc( bOldAutoCalc );
2425 }
2426
SetClipArea(const ScRange & rArea,sal_Bool bCut)2427 void ScDocument::SetClipArea( const ScRange& rArea, sal_Bool bCut )
2428 {
2429 if (bIsClip)
2430 {
2431 ScClipParam& rClipParam = GetClipParam();
2432 rClipParam.maRanges.RemoveAll();
2433 rClipParam.maRanges.Append(rArea);
2434 rClipParam.mbCutMode = bCut;
2435 }
2436 else
2437 {
2438 DBG_ERROR("SetClipArea: kein Clip");
2439 }
2440 }
2441
2442
GetClipArea(SCCOL & nClipX,SCROW & nClipY,sal_Bool bIncludeFiltered)2443 void ScDocument::GetClipArea(SCCOL& nClipX, SCROW& nClipY, sal_Bool bIncludeFiltered)
2444 {
2445 if (!bIsClip)
2446 {
2447 DBG_ERROR("GetClipArea: kein Clip");
2448 return;
2449 }
2450
2451 ScRangeList& rClipRanges = GetClipParam().maRanges;
2452 if (!rClipRanges.Count())
2453 // No clip range. Bail out.
2454 return;
2455
2456 ScRangePtr p = rClipRanges.First();
2457 SCCOL nStartCol = p->aStart.Col();
2458 SCCOL nEndCol = p->aEnd.Col();
2459 SCROW nStartRow = p->aStart.Row();
2460 SCROW nEndRow = p->aEnd.Row();
2461 for (p = rClipRanges.Next(); p; p = rClipRanges.Next())
2462 {
2463 if (p->aStart.Col() < nStartCol)
2464 nStartCol = p->aStart.Col();
2465 if (p->aStart.Row() < nStartRow)
2466 nStartRow = p->aStart.Row();
2467 if (p->aEnd.Col() > nEndCol)
2468 nEndCol = p->aEnd.Col();
2469 if (p->aEnd.Row() < nEndRow)
2470 nEndRow = p->aEnd.Row();
2471 }
2472
2473 nClipX = nEndCol - nStartCol;
2474
2475 if ( bIncludeFiltered )
2476 nClipY = nEndRow - nStartRow;
2477 else
2478 {
2479 // count non-filtered rows
2480 // count on first used table in clipboard
2481 SCTAB nCountTab = 0;
2482 while ( nCountTab < MAXTAB && !pTab[nCountTab] )
2483 ++nCountTab;
2484
2485 SCROW nResult = CountNonFilteredRows(nStartRow, nEndRow, nCountTab);
2486
2487 if ( nResult > 0 )
2488 nClipY = nResult - 1;
2489 else
2490 nClipY = 0; // always return at least 1 row
2491 }
2492 }
2493
2494
GetClipStart(SCCOL & nClipX,SCROW & nClipY)2495 void ScDocument::GetClipStart(SCCOL& nClipX, SCROW& nClipY)
2496 {
2497 if (bIsClip)
2498 {
2499 ScRangeList& rClipRanges = GetClipParam().maRanges;
2500 if (rClipRanges.Count())
2501 {
2502 nClipX = rClipRanges.First()->aStart.Col();
2503 nClipY = rClipRanges.First()->aStart.Row();
2504 }
2505 }
2506 else
2507 {
2508 DBG_ERROR("GetClipStart: kein Clip");
2509 }
2510 }
2511
2512
HasClipFilteredRows()2513 sal_Bool ScDocument::HasClipFilteredRows()
2514 {
2515 // count on first used table in clipboard
2516 SCTAB nCountTab = 0;
2517 while ( nCountTab < MAXTAB && !pTab[nCountTab] )
2518 ++nCountTab;
2519
2520 ScRangeList& rClipRanges = GetClipParam().maRanges;
2521 if (!rClipRanges.Count())
2522 return false;
2523
2524 for (ScRange* p = rClipRanges.First(); p; p = rClipRanges.Next())
2525 {
2526 bool bAnswer = pTab[nCountTab]->HasFilteredRows(p->aStart.Row(), p->aEnd.Row());
2527 if (bAnswer)
2528 return true;
2529 }
2530 return false;
2531 }
2532
2533
MixDocument(const ScRange & rRange,sal_uInt16 nFunction,sal_Bool bSkipEmpty,ScDocument * pSrcDoc)2534 void ScDocument::MixDocument( const ScRange& rRange, sal_uInt16 nFunction, sal_Bool bSkipEmpty,
2535 ScDocument* pSrcDoc )
2536 {
2537 SCTAB nTab1 = rRange.aStart.Tab();
2538 SCTAB nTab2 = rRange.aEnd.Tab();
2539 for (SCTAB i = nTab1; i <= nTab2; i++)
2540 if (pTab[i] && pSrcDoc->pTab[i])
2541 pTab[i]->MixData( rRange.aStart.Col(), rRange.aStart.Row(),
2542 rRange.aEnd.Col(), rRange.aEnd.Row(),
2543 nFunction, bSkipEmpty, pSrcDoc->pTab[i] );
2544 }
2545
2546
FillTab(const ScRange & rSrcArea,const ScMarkData & rMark,sal_uInt16 nFlags,sal_uInt16 nFunction,sal_Bool bSkipEmpty,sal_Bool bAsLink)2547 void ScDocument::FillTab( const ScRange& rSrcArea, const ScMarkData& rMark,
2548 sal_uInt16 nFlags, sal_uInt16 nFunction,
2549 sal_Bool bSkipEmpty, sal_Bool bAsLink )
2550 {
2551 sal_uInt16 nDelFlags = nFlags;
2552 if (nDelFlags & IDF_CONTENTS)
2553 nDelFlags |= IDF_CONTENTS; // immer alle Inhalte oder keine loeschen!
2554
2555 SCTAB nSrcTab = rSrcArea.aStart.Tab();
2556
2557 if (ValidTab(nSrcTab) && pTab[nSrcTab])
2558 {
2559 SCCOL nStartCol = rSrcArea.aStart.Col();
2560 SCROW nStartRow = rSrcArea.aStart.Row();
2561 SCCOL nEndCol = rSrcArea.aEnd.Col();
2562 SCROW nEndRow = rSrcArea.aEnd.Row();
2563 ScDocument* pMixDoc = NULL;
2564 sal_Bool bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS );
2565
2566 sal_Bool bOldAutoCalc = GetAutoCalc();
2567 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden
2568
2569 SCTAB nCount = GetTableCount();
2570 for (SCTAB i=0; i<nCount; i++)
2571 if ( i!=nSrcTab && pTab[i] && rMark.GetTableSelect(i) )
2572 {
2573 if (bDoMix)
2574 {
2575 if (!pMixDoc)
2576 {
2577 pMixDoc = new ScDocument( SCDOCMODE_UNDO );
2578 pMixDoc->InitUndo( this, i, i );
2579 }
2580 else
2581 pMixDoc->AddUndoTab( i, i );
2582 pTab[i]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow,
2583 IDF_CONTENTS, sal_False, pMixDoc->pTab[i] );
2584 }
2585 pTab[i]->DeleteArea( nStartCol,nStartRow, nEndCol,nEndRow, nDelFlags);
2586 pTab[nSrcTab]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow,
2587 nFlags, sal_False, pTab[i], NULL, bAsLink );
2588
2589 if (bDoMix)
2590 pTab[i]->MixData( nStartCol,nStartRow, nEndCol,nEndRow,
2591 nFunction, bSkipEmpty, pMixDoc->pTab[i] );
2592 }
2593
2594 delete pMixDoc;
2595
2596 SetAutoCalc( bOldAutoCalc );
2597 }
2598 else
2599 {
2600 DBG_ERROR("falsche Tabelle");
2601 }
2602 }
2603
2604
FillTabMarked(SCTAB nSrcTab,const ScMarkData & rMark,sal_uInt16 nFlags,sal_uInt16 nFunction,sal_Bool bSkipEmpty,sal_Bool bAsLink)2605 void ScDocument::FillTabMarked( SCTAB nSrcTab, const ScMarkData& rMark,
2606 sal_uInt16 nFlags, sal_uInt16 nFunction,
2607 sal_Bool bSkipEmpty, sal_Bool bAsLink )
2608 {
2609 sal_uInt16 nDelFlags = nFlags;
2610 if (nDelFlags & IDF_CONTENTS)
2611 nDelFlags |= IDF_CONTENTS; // immer alle Inhalte oder keine loeschen!
2612
2613 if (ValidTab(nSrcTab) && pTab[nSrcTab])
2614 {
2615 ScDocument* pMixDoc = NULL;
2616 sal_Bool bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS );
2617
2618 sal_Bool bOldAutoCalc = GetAutoCalc();
2619 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden
2620
2621 ScRange aArea;
2622 rMark.GetMultiMarkArea( aArea );
2623 SCCOL nStartCol = aArea.aStart.Col();
2624 SCROW nStartRow = aArea.aStart.Row();
2625 SCCOL nEndCol = aArea.aEnd.Col();
2626 SCROW nEndRow = aArea.aEnd.Row();
2627
2628 SCTAB nCount = GetTableCount();
2629 for (SCTAB i=0; i<nCount; i++)
2630 if ( i!=nSrcTab && pTab[i] && rMark.GetTableSelect(i) )
2631 {
2632 if (bDoMix)
2633 {
2634 if (!pMixDoc)
2635 {
2636 pMixDoc = new ScDocument( SCDOCMODE_UNDO );
2637 pMixDoc->InitUndo( this, i, i );
2638 }
2639 else
2640 pMixDoc->AddUndoTab( i, i );
2641 pTab[i]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow,
2642 IDF_CONTENTS, sal_True, pMixDoc->pTab[i], &rMark );
2643 }
2644
2645 pTab[i]->DeleteSelection( nDelFlags, rMark );
2646 pTab[nSrcTab]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow,
2647 nFlags, sal_True, pTab[i], &rMark, bAsLink );
2648
2649 if (bDoMix)
2650 pTab[i]->MixMarked( rMark, nFunction, bSkipEmpty, pMixDoc->pTab[i] );
2651 }
2652
2653 delete pMixDoc;
2654
2655 SetAutoCalc( bOldAutoCalc );
2656 }
2657 else
2658 {
2659 DBG_ERROR("falsche Tabelle");
2660 }
2661 }
2662
2663
PutCell(SCCOL nCol,SCROW nRow,SCTAB nTab,ScBaseCell * pCell,sal_Bool bForceTab)2664 void ScDocument::PutCell( SCCOL nCol, SCROW nRow, SCTAB nTab, ScBaseCell* pCell, sal_Bool bForceTab )
2665 {
2666 if (VALIDTAB(nTab))
2667 {
2668 if ( bForceTab && !pTab[nTab] )
2669 {
2670 sal_Bool bExtras = !bIsUndo; // Spaltenbreiten, Zeilenhoehen, Flags
2671
2672 pTab[nTab] = new ScTable(this, nTab,
2673 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")),
2674 bExtras, bExtras);
2675 ++nMaxTableNumber;
2676 }
2677
2678 if (pTab[nTab])
2679 pTab[nTab]->PutCell( nCol, nRow, pCell );
2680 }
2681 }
2682
2683
PutCell(const ScAddress & rPos,ScBaseCell * pCell,sal_Bool bForceTab)2684 void ScDocument::PutCell( const ScAddress& rPos, ScBaseCell* pCell, sal_Bool bForceTab )
2685 {
2686 SCTAB nTab = rPos.Tab();
2687 if ( bForceTab && !pTab[nTab] )
2688 {
2689 sal_Bool bExtras = !bIsUndo; // Spaltenbreiten, Zeilenhoehen, Flags
2690
2691 pTab[nTab] = new ScTable(this, nTab,
2692 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")),
2693 bExtras, bExtras);
2694 ++nMaxTableNumber;
2695 }
2696
2697 if (pTab[nTab])
2698 pTab[nTab]->PutCell( rPos, pCell );
2699 }
2700
2701
SetString(SCCOL nCol,SCROW nRow,SCTAB nTab,const String & rString,SvNumberFormatter * pFormatter,bool bDetectNumberFormat)2702 sal_Bool ScDocument::SetString( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rString,
2703 SvNumberFormatter* pFormatter, bool bDetectNumberFormat )
2704 {
2705 if ( ValidTab(nTab) && pTab[nTab] )
2706 return pTab[nTab]->SetString( nCol, nRow, nTab, rString, pFormatter, bDetectNumberFormat );
2707 else
2708 return sal_False;
2709 }
2710
2711
SetValue(SCCOL nCol,SCROW nRow,SCTAB nTab,const double & rVal)2712 void ScDocument::SetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rVal )
2713 {
2714 if (VALIDTAB(nTab))
2715 if (pTab[nTab])
2716 pTab[nTab]->SetValue( nCol, nRow, rVal );
2717 }
2718
2719
GetString(SCCOL nCol,SCROW nRow,SCTAB nTab,String & rString)2720 void ScDocument::GetString( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rString )
2721 {
2722 if ( VALIDTAB(nTab) && pTab[nTab] )
2723 pTab[nTab]->GetString( nCol, nRow, rString );
2724 else
2725 rString.Erase();
2726 }
2727
FillDPCache(ScDPTableDataCache * pCache,SCTAB nTab,SCCOL nStartCol,SCCOL nEndCol,SCROW nStartRow,SCROW nEndRow)2728 void ScDocument::FillDPCache( ScDPTableDataCache * pCache, SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow )
2729 {
2730 if ( VALIDTAB(nTab) && pTab[nTab] )
2731 pTab[nTab]->FillDPCache( pCache, nStartCol, nEndCol, nStartRow, nEndRow );
2732 }
2733
GetInputString(SCCOL nCol,SCROW nRow,SCTAB nTab,String & rString)2734 void ScDocument::GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rString )
2735 {
2736 if ( VALIDTAB(nTab) && pTab[nTab] )
2737 pTab[nTab]->GetInputString( nCol, nRow, rString );
2738 else
2739 rString.Erase();
2740 }
2741
2742
GetStringForFormula(const ScAddress & rPos,rtl::OUString & rString)2743 sal_uInt16 ScDocument::GetStringForFormula( const ScAddress& rPos, rtl::OUString& rString )
2744 {
2745 // Used in formulas (add-in parameters etc), so it must use the same semantics as
2746 // ScInterpreter::GetCellString: always format values as numbers.
2747 // The return value is the error code.
2748
2749 sal_uInt16 nErr = 0;
2750 String aStr;
2751 ScBaseCell* pCell = GetCell( rPos );
2752 if (pCell)
2753 {
2754 SvNumberFormatter* pFormatter = GetFormatTable();
2755 switch (pCell->GetCellType())
2756 {
2757 case CELLTYPE_STRING:
2758 static_cast<ScStringCell*>(pCell)->GetString(aStr);
2759 break;
2760 case CELLTYPE_EDIT:
2761 static_cast<ScEditCell*>(pCell)->GetString(aStr);
2762 break;
2763 case CELLTYPE_FORMULA:
2764 {
2765 ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
2766 nErr = pFCell->GetErrCode();
2767 if (pFCell->IsValue())
2768 {
2769 double fVal = pFCell->GetValue();
2770 sal_uInt32 nIndex = pFormatter->GetStandardFormat(
2771 NUMBERFORMAT_NUMBER,
2772 ScGlobal::eLnge);
2773 pFormatter->GetInputLineString(fVal, nIndex, aStr);
2774 }
2775 else
2776 pFCell->GetString(aStr);
2777 }
2778 break;
2779 case CELLTYPE_VALUE:
2780 {
2781 double fVal = static_cast<ScValueCell*>(pCell)->GetValue();
2782 sal_uInt32 nIndex = pFormatter->GetStandardFormat(
2783 NUMBERFORMAT_NUMBER,
2784 ScGlobal::eLnge);
2785 pFormatter->GetInputLineString(fVal, nIndex, aStr);
2786 }
2787 break;
2788 default:
2789 ;
2790 }
2791 }
2792 rString = aStr;
2793 return nErr;
2794 }
2795
2796
GetValue(SCCOL nCol,SCROW nRow,SCTAB nTab,double & rValue)2797 void ScDocument::GetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, double& rValue )
2798 {
2799 if ( VALIDTAB(nTab) && pTab[nTab] )
2800 rValue = pTab[nTab]->GetValue( nCol, nRow );
2801 else
2802 rValue = 0.0;
2803 }
2804
2805
GetValue(const ScAddress & rPos)2806 double ScDocument::GetValue( const ScAddress& rPos )
2807 {
2808 SCTAB nTab = rPos.Tab();
2809 if ( pTab[nTab] )
2810 return pTab[nTab]->GetValue( rPos );
2811 return 0.0;
2812 }
2813
2814
GetNumberFormat(SCCOL nCol,SCROW nRow,SCTAB nTab,sal_uInt32 & rFormat)2815 void ScDocument::GetNumberFormat( SCCOL nCol, SCROW nRow, SCTAB nTab,
2816 sal_uInt32& rFormat )
2817 {
2818 if (VALIDTAB(nTab))
2819 if (pTab[nTab])
2820 {
2821 rFormat = pTab[nTab]->GetNumberFormat( nCol, nRow );
2822 return ;
2823 }
2824 rFormat = 0;
2825 }
2826
2827
GetNumberFormat(const ScAddress & rPos) const2828 sal_uInt32 ScDocument::GetNumberFormat( const ScAddress& rPos ) const
2829 {
2830 SCTAB nTab = rPos.Tab();
2831 if ( pTab[nTab] )
2832 return pTab[nTab]->GetNumberFormat( rPos );
2833 return 0;
2834 }
2835
2836
GetNumberFormatInfo(short & nType,sal_uLong & nIndex,const ScAddress & rPos,const ScBaseCell * pCell) const2837 void ScDocument::GetNumberFormatInfo( short& nType, sal_uLong& nIndex,
2838 const ScAddress& rPos, const ScBaseCell* pCell ) const
2839 {
2840 SCTAB nTab = rPos.Tab();
2841 if ( pTab[nTab] )
2842 {
2843 nIndex = pTab[nTab]->GetNumberFormat( rPos );
2844 if ( (nIndex % SV_COUNTRY_LANGUAGE_OFFSET) == 0 && pCell &&
2845 pCell->GetCellType() == CELLTYPE_FORMULA )
2846 static_cast<const ScFormulaCell*>(pCell)->GetFormatInfo( nType, nIndex );
2847 else
2848 nType = GetFormatTable()->GetType( nIndex );
2849 }
2850 else
2851 {
2852 nType = NUMBERFORMAT_UNDEFINED;
2853 nIndex = 0;
2854 }
2855 }
2856
2857
GetFormula(SCCOL nCol,SCROW nRow,SCTAB nTab,String & rFormula,sal_Bool bAsciiExport) const2858 void ScDocument::GetFormula( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rFormula,
2859 sal_Bool bAsciiExport ) const
2860 {
2861 if ( VALIDTAB(nTab) && pTab[nTab] )
2862 pTab[nTab]->GetFormula( nCol, nRow, rFormula, bAsciiExport );
2863 else
2864 rFormula.Erase();
2865 }
2866
2867
GetCellType(const ScAddress & rPos) const2868 CellType ScDocument::GetCellType( const ScAddress& rPos ) const
2869 {
2870 SCTAB nTab = rPos.Tab();
2871 if ( pTab[nTab] )
2872 return pTab[nTab]->GetCellType( rPos );
2873 return CELLTYPE_NONE;
2874 }
2875
2876
GetCellType(SCCOL nCol,SCROW nRow,SCTAB nTab,CellType & rCellType) const2877 void ScDocument::GetCellType( SCCOL nCol, SCROW nRow, SCTAB nTab,
2878 CellType& rCellType ) const
2879 {
2880 if (ValidTab(nTab) && pTab[nTab])
2881 rCellType = pTab[nTab]->GetCellType( nCol, nRow );
2882 else
2883 rCellType = CELLTYPE_NONE;
2884 }
2885
2886
GetCell(SCCOL nCol,SCROW nRow,SCTAB nTab,ScBaseCell * & rpCell) const2887 void ScDocument::GetCell( SCCOL nCol, SCROW nRow, SCTAB nTab,
2888 ScBaseCell*& rpCell ) const
2889 {
2890 if (ValidTab(nTab) && pTab[nTab])
2891 rpCell = pTab[nTab]->GetCell( nCol, nRow );
2892 else
2893 {
2894 DBG_ERROR("GetCell ohne Tabelle");
2895 rpCell = NULL;
2896 }
2897 }
2898
2899
GetCell(const ScAddress & rPos) const2900 ScBaseCell* ScDocument::GetCell( const ScAddress& rPos ) const
2901 {
2902 SCTAB nTab = rPos.Tab();
2903 if (ValidTab(nTab) && pTab[nTab])
2904 return pTab[nTab]->GetCell( rPos );
2905
2906 DBG_ERROR("GetCell ohne Tabelle");
2907 return NULL;
2908 }
2909
2910
HasStringData(SCCOL nCol,SCROW nRow,SCTAB nTab) const2911 sal_Bool ScDocument::HasStringData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
2912 {
2913 if ( VALIDTAB(nTab) && pTab[nTab] )
2914 return pTab[nTab]->HasStringData( nCol, nRow );
2915 else
2916 return sal_False;
2917 }
2918
2919
HasValueData(SCCOL nCol,SCROW nRow,SCTAB nTab) const2920 sal_Bool ScDocument::HasValueData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
2921 {
2922 if ( VALIDTAB(nTab) && pTab[nTab] )
2923 return pTab[nTab]->HasValueData( nCol, nRow );
2924 else
2925 return sal_False;
2926 }
2927
2928
HasStringCells(const ScRange & rRange) const2929 sal_Bool ScDocument::HasStringCells( const ScRange& rRange ) const
2930 {
2931 // sal_True, wenn String- oder Editzellen im Bereich
2932
2933 SCCOL nStartCol = rRange.aStart.Col();
2934 SCROW nStartRow = rRange.aStart.Row();
2935 SCTAB nStartTab = rRange.aStart.Tab();
2936 SCCOL nEndCol = rRange.aEnd.Col();
2937 SCROW nEndRow = rRange.aEnd.Row();
2938 SCTAB nEndTab = rRange.aEnd.Tab();
2939
2940 for ( SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++ )
2941 if ( pTab[nTab] && pTab[nTab]->HasStringCells( nStartCol, nStartRow, nEndCol, nEndRow ) )
2942 return sal_True;
2943
2944 return sal_False;
2945 }
2946
2947
HasSelectionData(SCCOL nCol,SCROW nRow,SCTAB nTab) const2948 sal_Bool ScDocument::HasSelectionData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
2949 {
2950 sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue();
2951 if( nValidation )
2952 {
2953 const ScValidationData* pData = GetValidationEntry( nValidation );
2954 if( pData && pData->HasSelectionList() )
2955 return sal_True;
2956 }
2957 return HasStringCells( ScRange( nCol, 0, nTab, nCol, MAXROW, nTab ) );
2958 }
2959
2960
GetNote(const ScAddress & rPos)2961 ScPostIt* ScDocument::GetNote( const ScAddress& rPos )
2962 {
2963 ScTable* pTable = ValidTab( rPos.Tab() ) ? pTab[ rPos.Tab() ] : 0;
2964 return pTable ? pTable->GetNote( rPos.Col(), rPos.Row() ) : 0;
2965 }
2966
2967
TakeNote(const ScAddress & rPos,ScPostIt * & rpNote)2968 void ScDocument::TakeNote( const ScAddress& rPos, ScPostIt*& rpNote )
2969 {
2970 if( ValidTab( rPos.Tab() ) && pTab[ rPos.Tab() ] )
2971 pTab[ rPos.Tab() ]->TakeNote( rPos.Col(), rPos.Row(), rpNote );
2972 else
2973 DELETEZ( rpNote );
2974 }
2975
2976
ReleaseNote(const ScAddress & rPos)2977 ScPostIt* ScDocument::ReleaseNote( const ScAddress& rPos )
2978 {
2979 ScTable* pTable = ValidTab( rPos.Tab() ) ? pTab[ rPos.Tab() ] : 0;
2980 return pTable ? pTable->ReleaseNote( rPos.Col(), rPos.Row() ) : 0;
2981 }
2982
2983
GetOrCreateNote(const ScAddress & rPos)2984 ScPostIt* ScDocument::GetOrCreateNote( const ScAddress& rPos )
2985 {
2986 ScPostIt* pNote = GetNote( rPos );
2987 if( !pNote )
2988 {
2989 pNote = new ScPostIt( *this, rPos, false );
2990 TakeNote( rPos, pNote );
2991 }
2992 return pNote;
2993 }
2994
2995
DeleteNote(const ScAddress & rPos)2996 void ScDocument::DeleteNote( const ScAddress& rPos )
2997 {
2998 if( ValidTab( rPos.Tab() ) && pTab[ rPos.Tab() ] )
2999 pTab[ rPos.Tab() ]->DeleteNote( rPos.Col(), rPos.Row() );
3000 }
3001
3002
InitializeNoteCaptions(SCTAB nTab,bool bForced)3003 void ScDocument::InitializeNoteCaptions( SCTAB nTab, bool bForced )
3004 {
3005 if( ValidTab( nTab ) && pTab[ nTab ] )
3006 pTab[ nTab ]->InitializeNoteCaptions( bForced );
3007 }
3008
InitializeAllNoteCaptions(bool bForced)3009 void ScDocument::InitializeAllNoteCaptions( bool bForced )
3010 {
3011 for( SCTAB nTab = 0; nTab < GetTableCount(); ++nTab )
3012 InitializeNoteCaptions( nTab, bForced );
3013 }
3014
SetDirty()3015 void ScDocument::SetDirty()
3016 {
3017 sal_Bool bOldAutoCalc = GetAutoCalc();
3018 bAutoCalc = sal_False; // keine Mehrfachberechnung
3019 { // scope for bulk broadcast
3020 ScBulkBroadcast aBulkBroadcast( GetBASM());
3021 for (SCTAB i=0; i<=MAXTAB; i++)
3022 if (pTab[i]) pTab[i]->SetDirty();
3023 }
3024
3025 // Charts werden zwar auch ohne AutoCalc im Tracking auf Dirty gesetzt,
3026 // wenn alle Formeln dirty sind, werden die Charts aber nicht mehr erwischt
3027 // (#45205#) - darum alle Charts nochmal explizit
3028 if (pChartListenerCollection)
3029 pChartListenerCollection->SetDirty();
3030
3031 SetAutoCalc( bOldAutoCalc );
3032 }
3033
3034
SetDirty(const ScRange & rRange)3035 void ScDocument::SetDirty( const ScRange& rRange )
3036 {
3037 sal_Bool bOldAutoCalc = GetAutoCalc();
3038 bAutoCalc = sal_False; // keine Mehrfachberechnung
3039 { // scope for bulk broadcast
3040 ScBulkBroadcast aBulkBroadcast( GetBASM());
3041 SCTAB nTab2 = rRange.aEnd.Tab();
3042 for (SCTAB i=rRange.aStart.Tab(); i<=nTab2; i++)
3043 if (pTab[i]) pTab[i]->SetDirty( rRange );
3044 }
3045 SetAutoCalc( bOldAutoCalc );
3046 }
3047
3048
SetTableOpDirty(const ScRange & rRange)3049 void ScDocument::SetTableOpDirty( const ScRange& rRange )
3050 {
3051 sal_Bool bOldAutoCalc = GetAutoCalc();
3052 bAutoCalc = sal_False; // no multiple recalculation
3053 SCTAB nTab2 = rRange.aEnd.Tab();
3054 for (SCTAB i=rRange.aStart.Tab(); i<=nTab2; i++)
3055 if (pTab[i]) pTab[i]->SetTableOpDirty( rRange );
3056 SetAutoCalc( bOldAutoCalc );
3057 }
3058
3059
InterpretDirtyCells(const ScRangeList & rRanges)3060 void ScDocument::InterpretDirtyCells( const ScRangeList& rRanges )
3061 {
3062 sal_uLong nRangeCount = rRanges.Count();
3063 for (sal_uLong nPos=0; nPos<nRangeCount; nPos++)
3064 {
3065 ScCellIterator aIter( this, *rRanges.GetObject(nPos) );
3066 ScBaseCell* pCell = aIter.GetFirst();
3067 while (pCell)
3068 {
3069 if (pCell->GetCellType() == CELLTYPE_FORMULA)
3070 {
3071 if ( static_cast<ScFormulaCell*>(pCell)->GetDirty() && GetAutoCalc() )
3072 static_cast<ScFormulaCell*>(pCell)->Interpret();
3073 }
3074 pCell = aIter.GetNext();
3075 }
3076 }
3077 }
3078
3079
AddTableOpFormulaCell(ScFormulaCell * pCell)3080 void ScDocument::AddTableOpFormulaCell( ScFormulaCell* pCell )
3081 {
3082 ScInterpreterTableOpParams* p = aTableOpList.Last();
3083 if ( p && p->bCollectNotifications )
3084 {
3085 if ( p->bRefresh )
3086 { // refresh pointers only
3087 p->aNotifiedFormulaCells.push_back( pCell );
3088 }
3089 else
3090 { // init both, address and pointer
3091 p->aNotifiedFormulaCells.push_back( pCell );
3092 p->aNotifiedFormulaPos.push_back( pCell->aPos );
3093 }
3094 }
3095 }
3096
3097
CalcAll()3098 void ScDocument::CalcAll()
3099 {
3100 ClearLookupCaches(); // Ensure we don't deliver zombie data.
3101 sal_Bool bOldAutoCalc = GetAutoCalc();
3102 SetAutoCalc( sal_True );
3103 SCTAB i;
3104 for (i=0; i<=MAXTAB; i++)
3105 if (pTab[i]) pTab[i]->SetDirtyVar();
3106 for (i=0; i<=MAXTAB; i++)
3107 if (pTab[i]) pTab[i]->CalcAll();
3108 ClearFormulaTree();
3109 SetAutoCalc( bOldAutoCalc );
3110 }
3111
3112
CompileAll()3113 void ScDocument::CompileAll()
3114 {
3115 if ( pCondFormList )
3116 pCondFormList->CompileAll();
3117
3118 for (SCTAB i=0; i<=MAXTAB; i++)
3119 if (pTab[i]) pTab[i]->CompileAll();
3120 SetDirty();
3121 }
3122
3123
CompileXML()3124 void ScDocument::CompileXML()
3125 {
3126 sal_Bool bOldAutoCalc = GetAutoCalc();
3127 SetAutoCalc( sal_False );
3128 ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString(
3129 STR_PROGRESS_CALCULATING ), GetXMLImportedFormulaCount() );
3130
3131 // #b6355215# set AutoNameCache to speed up automatic name lookup
3132 DBG_ASSERT( !pAutoNameCache, "AutoNameCache already set" );
3133 pAutoNameCache = new ScAutoNameCache( this );
3134
3135 for (SCTAB i=0; i<=MAXTAB; i++)
3136 if (pTab[i]) pTab[i]->CompileXML( aProgress );
3137
3138 DELETEZ( pAutoNameCache ); // valid only during CompileXML, where cell contents don't change
3139
3140 if ( pCondFormList )
3141 pCondFormList->CompileXML();
3142 if ( pValidationList )
3143 pValidationList->CompileXML();
3144
3145 SetDirty();
3146 SetAutoCalc( bOldAutoCalc );
3147 }
3148
3149
CalcAfterLoad()3150 void ScDocument::CalcAfterLoad()
3151 {
3152 SCTAB i;
3153
3154 if (bIsClip) // Excel-Dateien werden aus dem Clipboard in ein Clip-Doc geladen
3155 return; // dann wird erst beim Einfuegen in das richtige Doc berechnet
3156
3157 bCalcingAfterLoad = sal_True;
3158 for ( i = 0; i <= MAXTAB; i++)
3159 if (pTab[i]) pTab[i]->CalcAfterLoad();
3160 for (i=0; i<=MAXTAB; i++)
3161 if (pTab[i]) pTab[i]->SetDirtyAfterLoad();
3162 bCalcingAfterLoad = sal_False;
3163
3164 SetDetectiveDirty(sal_False); // noch keine wirklichen Aenderungen
3165
3166 // #i112436# If formula cells are already dirty, they don't broadcast further changes.
3167 // So the source ranges of charts must be interpreted even if they are not visible,
3168 // similar to ScMyShapeResizer::CreateChartListener for loading own files (i104899).
3169 if (pChartListenerCollection)
3170 {
3171 sal_uInt16 nChartCount = pChartListenerCollection->GetCount();
3172 for ( sal_uInt16 nIndex = 0; nIndex < nChartCount; nIndex++ )
3173 {
3174 ScChartListener* pChartListener = static_cast<ScChartListener*>(pChartListenerCollection->At(nIndex));
3175 InterpretDirtyCells(*pChartListener->GetRangeList());
3176 }
3177 }
3178 }
3179
3180
GetErrCode(const ScAddress & rPos) const3181 sal_uInt16 ScDocument::GetErrCode( const ScAddress& rPos ) const
3182 {
3183 SCTAB nTab = rPos.Tab();
3184 if ( pTab[nTab] )
3185 return pTab[nTab]->GetErrCode( rPos );
3186 return 0;
3187 }
3188
3189
ResetChanged(const ScRange & rRange)3190 void ScDocument::ResetChanged( const ScRange& rRange )
3191 {
3192 SCTAB nStartTab = rRange.aStart.Tab();
3193 SCTAB nEndTab = rRange.aEnd.Tab();
3194 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
3195 if (pTab[nTab])
3196 pTab[nTab]->ResetChanged( rRange );
3197 }
3198
3199 //
3200 // Spaltenbreiten / Zeilenhoehen --------------------------------------
3201 //
3202
3203
SetColWidth(SCCOL nCol,SCTAB nTab,sal_uInt16 nNewWidth)3204 void ScDocument::SetColWidth( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth )
3205 {
3206 if ( ValidTab(nTab) && pTab[nTab] )
3207 pTab[nTab]->SetColWidth( nCol, nNewWidth );
3208 }
3209
SetColWidthOnly(SCCOL nCol,SCTAB nTab,sal_uInt16 nNewWidth)3210 void ScDocument::SetColWidthOnly( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth )
3211 {
3212 if ( ValidTab(nTab) && pTab[nTab] )
3213 pTab[nTab]->SetColWidthOnly( nCol, nNewWidth );
3214 }
3215
SetRowHeight(SCROW nRow,SCTAB nTab,sal_uInt16 nNewHeight)3216 void ScDocument::SetRowHeight( SCROW nRow, SCTAB nTab, sal_uInt16 nNewHeight )
3217 {
3218 if ( ValidTab(nTab) && pTab[nTab] )
3219 pTab[nTab]->SetRowHeight( nRow, nNewHeight );
3220 }
3221
3222
SetRowHeightRange(SCROW nStartRow,SCROW nEndRow,SCTAB nTab,sal_uInt16 nNewHeight)3223 void ScDocument::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight )
3224 {
3225 if ( ValidTab(nTab) && pTab[nTab] )
3226 pTab[nTab]->SetRowHeightRange
3227 ( nStartRow, nEndRow, nNewHeight, 1.0, 1.0 );
3228 }
3229
SetRowHeightOnly(SCROW nStartRow,SCROW nEndRow,SCTAB nTab,sal_uInt16 nNewHeight)3230 void ScDocument::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight )
3231 {
3232 if ( ValidTab(nTab) && pTab[nTab] )
3233 pTab[nTab]->SetRowHeightOnly( nStartRow, nEndRow, nNewHeight );
3234 }
3235
SetManualHeight(SCROW nStartRow,SCROW nEndRow,SCTAB nTab,sal_Bool bManual)3236 void ScDocument::SetManualHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_Bool bManual )
3237 {
3238 if ( ValidTab(nTab) && pTab[nTab] )
3239 pTab[nTab]->SetManualHeight( nStartRow, nEndRow, bManual );
3240 }
3241
3242
GetColWidth(SCCOL nCol,SCTAB nTab) const3243 sal_uInt16 ScDocument::GetColWidth( SCCOL nCol, SCTAB nTab ) const
3244 {
3245 if ( ValidTab(nTab) && pTab[nTab] )
3246 return pTab[nTab]->GetColWidth( nCol );
3247 DBG_ERROR("Falsche Tabellennummer");
3248 return 0;
3249 }
3250
3251
GetOriginalWidth(SCCOL nCol,SCTAB nTab) const3252 sal_uInt16 ScDocument::GetOriginalWidth( SCCOL nCol, SCTAB nTab ) const
3253 {
3254 if ( ValidTab(nTab) && pTab[nTab] )
3255 return pTab[nTab]->GetOriginalWidth( nCol );
3256 DBG_ERROR("Falsche Tabellennummer");
3257 return 0;
3258 }
3259
3260
GetCommonWidth(SCCOL nEndCol,SCTAB nTab) const3261 sal_uInt16 ScDocument::GetCommonWidth( SCCOL nEndCol, SCTAB nTab ) const
3262 {
3263 if ( ValidTab(nTab) && pTab[nTab] )
3264 return pTab[nTab]->GetCommonWidth( nEndCol );
3265 DBG_ERROR("Wrong table number");
3266 return 0;
3267 }
3268
3269
GetOriginalHeight(SCROW nRow,SCTAB nTab) const3270 sal_uInt16 ScDocument::GetOriginalHeight( SCROW nRow, SCTAB nTab ) const
3271 {
3272 if ( ValidTab(nTab) && pTab[nTab] )
3273 return pTab[nTab]->GetOriginalHeight( nRow );
3274 DBG_ERROR("Wrong table number");
3275 return 0;
3276 }
3277
3278
GetRowHeight(SCROW nRow,SCTAB nTab,bool bHiddenAsZero) const3279 sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, bool bHiddenAsZero ) const
3280 {
3281 if ( ValidTab(nTab) && pTab[nTab] )
3282 return pTab[nTab]->GetRowHeight( nRow, NULL, NULL, bHiddenAsZero );
3283 DBG_ERROR("Wrong sheet number");
3284 return 0;
3285 }
3286
3287
GetRowHeight(SCROW nRow,SCTAB nTab,SCROW * pStartRow,SCROW * pEndRow,bool bHiddenAsZero) const3288 sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const
3289 {
3290 if ( ValidTab(nTab) && pTab[nTab] )
3291 return pTab[nTab]->GetRowHeight( nRow, pStartRow, pEndRow, bHiddenAsZero );
3292 DBG_ERROR("Wrong sheet number");
3293 return 0;
3294 }
3295
3296
GetRowHeight(SCROW nStartRow,SCROW nEndRow,SCTAB nTab) const3297 sal_uLong ScDocument::GetRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const
3298 {
3299 if (nStartRow == nEndRow)
3300 return GetRowHeight( nStartRow, nTab); // faster for a single row
3301
3302 // check bounds because this method replaces former for(i=start;i<=end;++i) loops
3303 if (nStartRow > nEndRow)
3304 return 0;
3305
3306 if ( ValidTab(nTab) && pTab[nTab] )
3307 return pTab[nTab]->GetRowHeight( nStartRow, nEndRow);
3308
3309 DBG_ERROR("wrong sheet number");
3310 return 0;
3311 }
3312
GetRowForHeight(SCTAB nTab,sal_uLong nHeight) const3313 SCROW ScDocument::GetRowForHeight( SCTAB nTab, sal_uLong nHeight ) const
3314 {
3315 return pTab[nTab]->GetRowForHeight(nHeight);
3316 }
3317
GetScaledRowHeight(SCROW nStartRow,SCROW nEndRow,SCTAB nTab,double fScale) const3318 sal_uLong ScDocument::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow,
3319 SCTAB nTab, double fScale ) const
3320 {
3321 // faster for a single row
3322 if (nStartRow == nEndRow)
3323 return (sal_uLong) (GetRowHeight( nStartRow, nTab) * fScale);
3324
3325 // check bounds because this method replaces former for(i=start;i<=end;++i) loops
3326 if (nStartRow > nEndRow)
3327 return 0;
3328
3329 if ( ValidTab(nTab) && pTab[nTab] )
3330 return pTab[nTab]->GetScaledRowHeight( nStartRow, nEndRow, fScale);
3331
3332 DBG_ERROR("wrong sheet number");
3333 return 0;
3334 }
3335
GetHiddenRowCount(SCROW nRow,SCTAB nTab) const3336 SCROW ScDocument::GetHiddenRowCount( SCROW nRow, SCTAB nTab ) const
3337 {
3338 if ( ValidTab(nTab) && pTab[nTab] )
3339 return pTab[nTab]->GetHiddenRowCount( nRow );
3340 DBG_ERROR("Falsche Tabellennummer");
3341 return 0;
3342 }
3343
3344
GetColOffset(SCCOL nCol,SCTAB nTab) const3345 sal_uLong ScDocument::GetColOffset( SCCOL nCol, SCTAB nTab ) const
3346 {
3347 if ( ValidTab(nTab) && pTab[nTab] )
3348 return pTab[nTab]->GetColOffset( nCol );
3349 DBG_ERROR("Falsche Tabellennummer");
3350 return 0;
3351 }
3352
3353
GetRowOffset(SCROW nRow,SCTAB nTab) const3354 sal_uLong ScDocument::GetRowOffset( SCROW nRow, SCTAB nTab ) const
3355 {
3356 if ( ValidTab(nTab) && pTab[nTab] )
3357 return pTab[nTab]->GetRowOffset( nRow );
3358 DBG_ERROR("Falsche Tabellennummer");
3359 return 0;
3360 }
3361
3362
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)3363 sal_uInt16 ScDocument::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, OutputDevice* pDev,
3364 double nPPTX, double nPPTY,
3365 const Fraction& rZoomX, const Fraction& rZoomY,
3366 sal_Bool bFormula, const ScMarkData* pMarkData,
3367 sal_Bool bSimpleTextImport )
3368 {
3369 if ( ValidTab(nTab) && pTab[nTab] )
3370 return pTab[nTab]->GetOptimalColWidth( nCol, pDev, nPPTX, nPPTY,
3371 rZoomX, rZoomY, bFormula, pMarkData, bSimpleTextImport );
3372 DBG_ERROR("Falsche Tabellennummer");
3373 return 0;
3374 }
3375
3376
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)3377 long ScDocument::GetNeededSize( SCCOL nCol, SCROW nRow, SCTAB nTab,
3378 OutputDevice* pDev,
3379 double nPPTX, double nPPTY,
3380 const Fraction& rZoomX, const Fraction& rZoomY,
3381 sal_Bool bWidth, sal_Bool bTotalSize )
3382 {
3383 if ( ValidTab(nTab) && pTab[nTab] )
3384 return pTab[nTab]->GetNeededSize
3385 ( nCol, nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, bTotalSize );
3386 DBG_ERROR("Falsche Tabellennummer");
3387 return 0;
3388 }
3389
3390
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)3391 sal_Bool ScDocument::SetOptimalHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nExtra,
3392 OutputDevice* pDev,
3393 double nPPTX, double nPPTY,
3394 const Fraction& rZoomX, const Fraction& rZoomY,
3395 sal_Bool bShrink )
3396 {
3397 //! MarkToMulti();
3398 if ( ValidTab(nTab) && pTab[nTab] )
3399 return pTab[nTab]->SetOptimalHeight( nStartRow, nEndRow, nExtra,
3400 pDev, nPPTX, nPPTY, rZoomX, rZoomY, bShrink );
3401 DBG_ERROR("Falsche Tabellennummer");
3402 return sal_False;
3403 }
3404
3405
UpdateAllRowHeights(OutputDevice * pDev,double nPPTX,double nPPTY,const Fraction & rZoomX,const Fraction & rZoomY,const ScMarkData * pTabMark)3406 void ScDocument::UpdateAllRowHeights( OutputDevice* pDev, double nPPTX, double nPPTY,
3407 const Fraction& rZoomX, const Fraction& rZoomY, const ScMarkData* pTabMark )
3408 {
3409 // one progress across all (selected) sheets
3410
3411 sal_uLong nCellCount = 0;
3412 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ )
3413 if ( pTab[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) )
3414 nCellCount += pTab[nTab]->GetWeightedCount();
3415
3416 ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING), nCellCount );
3417
3418 sal_uLong nProgressStart = 0;
3419 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ )
3420 if ( pTab[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) )
3421 {
3422 pTab[nTab]->SetOptimalHeight( 0, MAXROW, 0,
3423 pDev, nPPTX, nPPTY, rZoomX, rZoomY, sal_False, &aProgress, nProgressStart );
3424 nProgressStart += pTab[nTab]->GetWeightedCount();
3425 }
3426 }
3427
3428
3429 //
3430 // Spalten-/Zeilen-Flags ----------------------------------------------
3431 //
3432
ShowCol(SCCOL nCol,SCTAB nTab,sal_Bool bShow)3433 void ScDocument::ShowCol(SCCOL nCol, SCTAB nTab, sal_Bool bShow)
3434 {
3435 if ( ValidTab(nTab) && pTab[nTab] )
3436 pTab[nTab]->ShowCol( nCol, bShow );
3437 }
3438
3439
ShowRow(SCROW nRow,SCTAB nTab,sal_Bool bShow)3440 void ScDocument::ShowRow(SCROW nRow, SCTAB nTab, sal_Bool bShow)
3441 {
3442 if ( ValidTab(nTab) && pTab[nTab] )
3443 pTab[nTab]->ShowRow( nRow, bShow );
3444 }
3445
3446
ShowRows(SCROW nRow1,SCROW nRow2,SCTAB nTab,sal_Bool bShow)3447 void ScDocument::ShowRows(SCROW nRow1, SCROW nRow2, SCTAB nTab, sal_Bool bShow)
3448 {
3449 if ( ValidTab(nTab) && pTab[nTab] )
3450 pTab[nTab]->ShowRows( nRow1, nRow2, bShow );
3451 }
3452
3453
SetColFlags(SCCOL nCol,SCTAB nTab,sal_uInt8 nNewFlags)3454 void ScDocument::SetColFlags( SCCOL nCol, SCTAB nTab, sal_uInt8 nNewFlags )
3455 {
3456 if ( ValidTab(nTab) && pTab[nTab] )
3457 pTab[nTab]->SetColFlags( nCol, nNewFlags );
3458 }
3459
3460
SetRowFlags(SCROW nRow,SCTAB nTab,sal_uInt8 nNewFlags)3461 void ScDocument::SetRowFlags( SCROW nRow, SCTAB nTab, sal_uInt8 nNewFlags )
3462 {
3463 if ( ValidTab(nTab) && pTab[nTab] )
3464 pTab[nTab]->SetRowFlags( nRow, nNewFlags );
3465 }
3466
3467
SetRowFlags(SCROW nStartRow,SCROW nEndRow,SCTAB nTab,sal_uInt8 nNewFlags)3468 void ScDocument::SetRowFlags( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt8 nNewFlags )
3469 {
3470 if ( ValidTab(nTab) && pTab[nTab] )
3471 pTab[nTab]->SetRowFlags( nStartRow, nEndRow, nNewFlags );
3472 }
3473
3474
GetColFlags(SCCOL nCol,SCTAB nTab) const3475 sal_uInt8 ScDocument::GetColFlags( SCCOL nCol, SCTAB nTab ) const
3476 {
3477 if ( ValidTab(nTab) && pTab[nTab] )
3478 return pTab[nTab]->GetColFlags( nCol );
3479 DBG_ERROR("Falsche Tabellennummer");
3480 return 0;
3481 }
3482
GetRowFlags(SCROW nRow,SCTAB nTab) const3483 sal_uInt8 ScDocument::GetRowFlags( SCROW nRow, SCTAB nTab ) const
3484 {
3485 if ( ValidTab(nTab) && pTab[nTab] )
3486 return pTab[nTab]->GetRowFlags( nRow );
3487 DBG_ERROR("Falsche Tabellennummer");
3488 return 0;
3489 }
3490
GetRowFlagsArrayModifiable(SCTAB nTab)3491 ScBitMaskCompressedArray< SCROW, sal_uInt8> & ScDocument::GetRowFlagsArrayModifiable(
3492 SCTAB nTab )
3493 {
3494 return const_cast< ScBitMaskCompressedArray< SCROW, sal_uInt8> & >(
3495 GetRowFlagsArray( nTab));
3496 }
3497
GetRowFlagsArray(SCTAB nTab) const3498 const ScBitMaskCompressedArray< SCROW, sal_uInt8> & ScDocument::GetRowFlagsArray(
3499 SCTAB nTab ) const
3500 {
3501 const ScBitMaskCompressedArray< SCROW, sal_uInt8> * pFlags;
3502 if ( ValidTab(nTab) && pTab[nTab] )
3503 pFlags = pTab[nTab]->GetRowFlagsArray();
3504 else
3505 {
3506 DBG_ERROR("wrong sheet number");
3507 pFlags = 0;
3508 }
3509 if (!pFlags)
3510 {
3511 DBG_ERROR("no row flags at sheet");
3512 static ScBitMaskCompressedArray< SCROW, sal_uInt8> aDummy( MAXROW, 0);
3513 pFlags = &aDummy;
3514 }
3515 return *pFlags;
3516 }
3517
GetAllRowBreaks(set<SCROW> & rBreaks,SCTAB nTab,bool bPage,bool bManual) const3518 void ScDocument::GetAllRowBreaks(set<SCROW>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const
3519 {
3520 if (!ValidTab(nTab) || !pTab[nTab])
3521 return;
3522
3523 pTab[nTab]->GetAllRowBreaks(rBreaks, bPage, bManual);
3524 }
3525
GetAllColBreaks(set<SCCOL> & rBreaks,SCTAB nTab,bool bPage,bool bManual) const3526 void ScDocument::GetAllColBreaks(set<SCCOL>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const
3527 {
3528 if (!ValidTab(nTab) || !pTab[nTab])
3529 return;
3530
3531 pTab[nTab]->GetAllColBreaks(rBreaks, bPage, bManual);
3532 }
3533
HasRowBreak(SCROW nRow,SCTAB nTab) const3534 ScBreakType ScDocument::HasRowBreak(SCROW nRow, SCTAB nTab) const
3535 {
3536 ScBreakType nType = BREAK_NONE;
3537 if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow))
3538 return nType;
3539
3540 if (pTab[nTab]->HasRowPageBreak(nRow))
3541 nType |= BREAK_PAGE;
3542
3543 if (pTab[nTab]->HasRowManualBreak(nRow))
3544 nType |= BREAK_MANUAL;
3545
3546 return nType;
3547 }
3548
HasColBreak(SCCOL nCol,SCTAB nTab) const3549 ScBreakType ScDocument::HasColBreak(SCCOL nCol, SCTAB nTab) const
3550 {
3551 ScBreakType nType = BREAK_NONE;
3552 if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol))
3553 return nType;
3554
3555 if (pTab[nTab]->HasColPageBreak(nCol))
3556 nType |= BREAK_PAGE;
3557
3558 if (pTab[nTab]->HasColManualBreak(nCol))
3559 nType |= BREAK_MANUAL;
3560
3561 return nType;
3562 }
3563
SetRowBreak(SCROW nRow,SCTAB nTab,bool bPage,bool bManual)3564 void ScDocument::SetRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual)
3565 {
3566 if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow))
3567 return;
3568
3569 pTab[nTab]->SetRowBreak(nRow, bPage, bManual);
3570 }
3571
SetColBreak(SCCOL nCol,SCTAB nTab,bool bPage,bool bManual)3572 void ScDocument::SetColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual)
3573 {
3574 if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol))
3575 return;
3576
3577 pTab[nTab]->SetColBreak(nCol, bPage, bManual);
3578 }
3579
RemoveRowBreak(SCROW nRow,SCTAB nTab,bool bPage,bool bManual)3580 void ScDocument::RemoveRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual)
3581 {
3582 if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow))
3583 return;
3584
3585 pTab[nTab]->RemoveRowBreak(nRow, bPage, bManual);
3586 }
3587
RemoveColBreak(SCCOL nCol,SCTAB nTab,bool bPage,bool bManual)3588 void ScDocument::RemoveColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual)
3589 {
3590 if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol))
3591 return;
3592
3593 pTab[nTab]->RemoveColBreak(nCol, bPage, bManual);
3594 }
3595
GetRowBreakData(SCTAB nTab) const3596 Sequence<TablePageBreakData> ScDocument::GetRowBreakData(SCTAB nTab) const
3597 {
3598 if (!ValidTab(nTab) || !pTab[nTab])
3599 return Sequence<TablePageBreakData>();
3600
3601 return pTab[nTab]->GetRowBreakData();
3602 }
3603
RowHidden(SCROW nRow,SCTAB nTab,SCROW * pFirstRow,SCROW * pLastRow)3604 bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow)
3605 {
3606 if (!ValidTab(nTab) || !pTab[nTab])
3607 return false;
3608
3609 return pTab[nTab]->RowHidden(nRow, pFirstRow, pLastRow);
3610 }
3611
RowHidden(SCROW nRow,SCTAB nTab,SCROW & rLastRow)3612 bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW& rLastRow)
3613 {
3614 if (!ValidTab(nTab) || !pTab[nTab])
3615 {
3616 rLastRow = nRow;
3617 return false;
3618 }
3619
3620 return pTab[nTab]->RowHidden(nRow, rLastRow);
3621 }
3622
3623
HasHiddenRows(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3624 bool ScDocument::HasHiddenRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3625 {
3626 if (!ValidTab(nTab) || !pTab[nTab])
3627 return false;
3628
3629 return pTab[nTab]->HasHiddenRows(nStartRow, nEndRow);
3630 }
3631
ColHidden(SCCOL nCol,SCTAB nTab,SCCOL & rLastCol)3632 bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL& rLastCol)
3633 {
3634 if (!ValidTab(nTab) || !pTab[nTab])
3635 {
3636 rLastCol = nCol;
3637 return false;
3638 }
3639
3640 return pTab[nTab]->ColHidden(nCol, rLastCol);
3641 }
3642
ColHidden(SCCOL nCol,SCTAB nTab,SCCOL * pFirstCol,SCCOL * pLastCol)3643 bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol)
3644 {
3645 if (!ValidTab(nTab) || !pTab[nTab])
3646 {
3647 if (pFirstCol)
3648 *pFirstCol = nCol;
3649 if (pLastCol)
3650 *pLastCol = nCol;
3651 return false;
3652 }
3653
3654 return pTab[nTab]->ColHidden(nCol, pFirstCol, pLastCol);
3655 }
3656
SetRowHidden(SCROW nStartRow,SCROW nEndRow,SCTAB nTab,bool bHidden)3657 void ScDocument::SetRowHidden(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHidden)
3658 {
3659 if (!ValidTab(nTab) || !pTab[nTab])
3660 return;
3661
3662 pTab[nTab]->SetRowHidden(nStartRow, nEndRow, bHidden);
3663 }
3664
SetColHidden(SCCOL nStartCol,SCCOL nEndCol,SCTAB nTab,bool bHidden)3665 void ScDocument::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bHidden)
3666 {
3667 if (!ValidTab(nTab) || !pTab[nTab])
3668 return;
3669
3670 pTab[nTab]->SetColHidden(nStartCol, nEndCol, bHidden);
3671 }
3672
FirstVisibleRow(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3673 SCROW ScDocument::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3674 {
3675 if (!ValidTab(nTab) || !pTab[nTab])
3676 return ::std::numeric_limits<SCROW>::max();;
3677
3678 return pTab[nTab]->FirstVisibleRow(nStartRow, nEndRow);
3679 }
3680
LastVisibleRow(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3681 SCROW ScDocument::LastVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3682 {
3683 if (!ValidTab(nTab) || !pTab[nTab])
3684 return ::std::numeric_limits<SCROW>::max();;
3685
3686 return pTab[nTab]->LastVisibleRow(nStartRow, nEndRow);
3687 }
3688
CountVisibleRows(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3689 SCROW ScDocument::CountVisibleRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3690 {
3691 if (!ValidTab(nTab) || !pTab[nTab])
3692 return 0;
3693
3694 return pTab[nTab]->CountVisibleRows(nStartRow, nEndRow);
3695 }
3696
RowFiltered(SCROW nRow,SCTAB nTab,SCROW * pFirstRow,SCROW * pLastRow)3697 bool ScDocument::RowFiltered(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow)
3698 {
3699 if (!ValidTab(nTab) || !pTab[nTab])
3700 return false;
3701
3702 return pTab[nTab]->RowFiltered(nRow, pFirstRow, pLastRow);
3703 }
3704
HasFilteredRows(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3705 bool ScDocument::HasFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3706 {
3707 if (!ValidTab(nTab) || !pTab[nTab])
3708 return false;
3709
3710 return pTab[nTab]->HasFilteredRows(nStartRow, nEndRow);
3711 }
3712
ColFiltered(SCCOL nCol,SCTAB nTab,SCCOL * pFirstCol,SCCOL * pLastCol)3713 bool ScDocument::ColFiltered(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol)
3714 {
3715 if (!ValidTab(nTab) || !pTab[nTab])
3716 return false;
3717
3718 return pTab[nTab]->ColFiltered(nCol, pFirstCol, pLastCol);
3719 }
3720
SetRowFiltered(SCROW nStartRow,SCROW nEndRow,SCTAB nTab,bool bFiltered)3721 void ScDocument::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bFiltered)
3722 {
3723 if (!ValidTab(nTab) || !pTab[nTab])
3724 return;
3725
3726 pTab[nTab]->SetRowFiltered(nStartRow, nEndRow, bFiltered);
3727 }
3728
SetColFiltered(SCCOL nStartCol,SCCOL nEndCol,SCTAB nTab,bool bFiltered)3729 void ScDocument::SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bFiltered)
3730 {
3731 if (!ValidTab(nTab) || !pTab[nTab])
3732 return;
3733
3734 pTab[nTab]->SetColFiltered(nStartCol, nEndCol, bFiltered);
3735 }
3736
FirstNonFilteredRow(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3737 SCROW ScDocument::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3738 {
3739 if (!ValidTab(nTab) || !pTab[nTab])
3740 return ::std::numeric_limits<SCROW>::max();;
3741
3742 return pTab[nTab]->FirstNonFilteredRow(nStartRow, nEndRow);
3743 }
3744
LastNonFilteredRow(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3745 SCROW ScDocument::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3746 {
3747 if (!ValidTab(nTab) || !pTab[nTab])
3748 return ::std::numeric_limits<SCROW>::max();;
3749
3750 return pTab[nTab]->LastNonFilteredRow(nStartRow, nEndRow);
3751 }
3752
CountNonFilteredRows(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3753 SCROW ScDocument::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3754 {
3755 if (!ValidTab(nTab) || !pTab[nTab])
3756 return 0;
3757
3758 return pTab[nTab]->CountNonFilteredRows(nStartRow, nEndRow);
3759 }
3760
SyncColRowFlags()3761 void ScDocument::SyncColRowFlags()
3762 {
3763 for (SCTAB i = 0; i <= nMaxTableNumber; ++i)
3764 {
3765 if (!ValidTab(i) || !pTab[i])
3766 continue;
3767
3768 pTab[i]->SyncColRowFlags();
3769 }
3770 }
3771
GetLastFlaggedRow(SCTAB nTab) const3772 SCROW ScDocument::GetLastFlaggedRow( SCTAB nTab ) const
3773 {
3774 if ( ValidTab(nTab) && pTab[nTab] )
3775 return pTab[nTab]->GetLastFlaggedRow();
3776 return 0;
3777 }
3778
3779
GetLastChangedCol(SCTAB nTab) const3780 SCCOL ScDocument::GetLastChangedCol( SCTAB nTab ) const
3781 {
3782 if ( ValidTab(nTab) && pTab[nTab] )
3783 return pTab[nTab]->GetLastChangedCol();
3784 return 0;
3785 }
3786
GetLastChangedRow(SCTAB nTab) const3787 SCROW ScDocument::GetLastChangedRow( SCTAB nTab ) const
3788 {
3789 if ( ValidTab(nTab) && pTab[nTab] )
3790 return pTab[nTab]->GetLastChangedRow();
3791 return 0;
3792 }
3793
3794
GetNextDifferentChangedCol(SCTAB nTab,SCCOL nStart) const3795 SCCOL ScDocument::GetNextDifferentChangedCol( SCTAB nTab, SCCOL nStart) const
3796 {
3797 if ( ValidTab(nTab) && pTab[nTab] )
3798 {
3799 sal_uInt8 nStartFlags = pTab[nTab]->GetColFlags(nStart);
3800 sal_uInt16 nStartWidth = pTab[nTab]->GetOriginalWidth(nStart);
3801 for (SCCOL nCol = nStart + 1; nCol <= MAXCOL; nCol++)
3802 {
3803 if (((nStartFlags & CR_MANUALBREAK) != (pTab[nTab]->GetColFlags(nCol) & CR_MANUALBREAK)) ||
3804 (nStartWidth != pTab[nTab]->GetOriginalWidth(nCol)) ||
3805 ((nStartFlags & CR_HIDDEN) != (pTab[nTab]->GetColFlags(nCol) & CR_HIDDEN)) )
3806 return nCol;
3807 }
3808 return MAXCOL+1;
3809 }
3810 return 0;
3811 }
3812
GetNextDifferentChangedRow(SCTAB nTab,SCROW nStart,bool bCareManualSize) const3813 SCROW ScDocument::GetNextDifferentChangedRow( SCTAB nTab, SCROW nStart, bool bCareManualSize) const
3814 {
3815 const ScBitMaskCompressedArray< SCROW, sal_uInt8> * pRowFlagsArray;
3816 if ( ValidTab(nTab) && pTab[nTab] && ((pRowFlagsArray = pTab[nTab]->GetRowFlagsArray()) != NULL) &&
3817 pTab[nTab]->mpRowHeights && pTab[nTab]->mpHiddenRows )
3818 {
3819 size_t nIndex; // ignored
3820 SCROW nFlagsEndRow;
3821 SCROW nHiddenEndRow;
3822 SCROW nHeightEndRow;
3823 sal_uInt8 nFlags;
3824 bool bHidden;
3825 sal_uInt16 nHeight;
3826 sal_uInt8 nStartFlags = nFlags = pRowFlagsArray->GetValue( nStart, nIndex, nFlagsEndRow);
3827 bool bStartHidden = bHidden = pTab[nTab]->RowHidden( nStart, NULL, &nHiddenEndRow);
3828 sal_uInt16 nStartHeight = nHeight = pTab[nTab]->GetRowHeight( nStart, NULL, &nHeightEndRow, false);
3829 SCROW nRow;
3830 while ((nRow = std::min( nHiddenEndRow, std::min( nFlagsEndRow, nHeightEndRow)) + 1) <= MAXROW)
3831 {
3832 if (nFlagsEndRow < nRow)
3833 nFlags = pRowFlagsArray->GetValue( nRow, nIndex, nFlagsEndRow);
3834 if (nHiddenEndRow < nRow)
3835 bHidden = pTab[nTab]->RowHidden( nRow, NULL, &nHiddenEndRow);
3836 if (nHeightEndRow < nRow)
3837 nHeight = pTab[nTab]->GetRowHeight( nRow, NULL, &nHeightEndRow, false);
3838 if ( ((nStartFlags & CR_MANUALBREAK) != (nFlags & CR_MANUALBREAK)) ||
3839 ((nStartFlags & CR_MANUALSIZE) != (nFlags & CR_MANUALSIZE)) ||
3840 (bStartHidden != bHidden) ||
3841 (bCareManualSize && (nStartFlags & CR_MANUALSIZE) && (nStartHeight != nHeight)) ||
3842 (!bCareManualSize && ((nStartHeight != nHeight))))
3843 return nRow;
3844 }
3845 return MAXROW+1;
3846 }
3847 return 0;
3848 }
3849
GetColDefault(SCTAB nTab,SCCOL nCol,SCROW nLastRow,SCROW & nDefault)3850 sal_Bool ScDocument::GetColDefault( SCTAB nTab, SCCOL nCol, SCROW nLastRow, SCROW& nDefault)
3851 {
3852 sal_Bool bRet(sal_False);
3853 nDefault = 0;
3854 ScDocAttrIterator aDocAttrItr(this, nTab, nCol, 0, nCol, nLastRow);
3855 SCCOL nColumn;
3856 SCROW nStartRow;
3857 SCROW nEndRow;
3858 const ScPatternAttr* pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow);
3859 if (nEndRow < nLastRow)
3860 {
3861 ScDefaultAttrSet aSet;
3862 ScDefaultAttrSet::iterator aItr = aSet.end();
3863 while (pAttr)
3864 {
3865 ScDefaultAttr aAttr(pAttr);
3866 aItr = aSet.find(aAttr);
3867 if (aItr == aSet.end())
3868 {
3869 aAttr.nCount = static_cast<SCSIZE>(nEndRow - nStartRow + 1);
3870 aAttr.nFirst = nStartRow;
3871 aSet.insert(aAttr);
3872 }
3873 else
3874 {
3875 aAttr.nCount = aItr->nCount + static_cast<SCSIZE>(nEndRow - nStartRow + 1);
3876 aAttr.nFirst = aItr->nFirst;
3877 aSet.erase(aItr);
3878 aSet.insert(aAttr);
3879 }
3880 pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow);
3881 }
3882 ScDefaultAttrSet::iterator aDefaultItr = aSet.begin();
3883 aItr = aDefaultItr;
3884 aItr++;
3885 while (aItr != aSet.end())
3886 {
3887 // for entries with equal count, use the one with the lowest start row,
3888 // don't use the random order of pointer comparisons
3889 if ( aItr->nCount > aDefaultItr->nCount ||
3890 ( aItr->nCount == aDefaultItr->nCount && aItr->nFirst < aDefaultItr->nFirst ) )
3891 aDefaultItr = aItr;
3892 aItr++;
3893 }
3894 nDefault = aDefaultItr->nFirst;
3895 bRet = sal_True;
3896 }
3897 else
3898 bRet = sal_True;
3899 return bRet;
3900 }
3901
GetRowDefault(SCTAB,SCROW,SCCOL,SCCOL &)3902 sal_Bool ScDocument::GetRowDefault( SCTAB /* nTab */, SCROW /* nRow */, SCCOL /* nLastCol */, SCCOL& /* nDefault */ )
3903 {
3904 sal_Bool bRet(sal_False);
3905 return bRet;
3906 }
3907
StripHidden(SCCOL & rX1,SCROW & rY1,SCCOL & rX2,SCROW & rY2,SCTAB nTab)3908 void ScDocument::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab )
3909 {
3910 if ( ValidTab(nTab) && pTab[nTab] )
3911 pTab[nTab]->StripHidden( rX1, rY1, rX2, rY2 );
3912 }
3913
3914
ExtendHidden(SCCOL & rX1,SCROW & rY1,SCCOL & rX2,SCROW & rY2,SCTAB nTab)3915 void ScDocument::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab )
3916 {
3917 if ( ValidTab(nTab) && pTab[nTab] )
3918 pTab[nTab]->ExtendHidden( rX1, rY1, rX2, rY2 );
3919 }
3920
3921 //
3922 // Attribute ----------------------------------------------------------
3923 //
3924
GetAttr(SCCOL nCol,SCROW nRow,SCTAB nTab,sal_uInt16 nWhich) const3925 const SfxPoolItem* ScDocument::GetAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich ) const
3926 {
3927 if ( ValidTab(nTab) && pTab[nTab] )
3928 {
3929 const SfxPoolItem* pTemp = pTab[nTab]->GetAttr( nCol, nRow, nWhich );
3930 if (pTemp)
3931 return pTemp;
3932 else
3933 {
3934 DBG_ERROR( "Attribut Null" );
3935 }
3936 }
3937 return &xPoolHelper->GetDocPool()->GetDefaultItem( nWhich );
3938 }
3939
3940
GetPattern(SCCOL nCol,SCROW nRow,SCTAB nTab) const3941 const ScPatternAttr* ScDocument::GetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
3942 {
3943 if ( ValidTab(nTab) && pTab[nTab] )
3944 return pTab[nTab]->GetPattern( nCol, nRow );
3945 return NULL;
3946 }
3947
3948
GetMostUsedPattern(SCCOL nCol,SCROW nStartRow,SCROW nEndRow,SCTAB nTab) const3949 const ScPatternAttr* ScDocument::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const
3950 {
3951 if ( ValidTab(nTab) && pTab[nTab] )
3952 return pTab[nTab]->GetMostUsedPattern( nCol, nStartRow, nEndRow );
3953 return NULL;
3954 }
3955
3956
ApplyAttr(SCCOL nCol,SCROW nRow,SCTAB nTab,const SfxPoolItem & rAttr)3957 void ScDocument::ApplyAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, const SfxPoolItem& rAttr )
3958 {
3959 if ( ValidTab(nTab) && pTab[nTab] )
3960 pTab[nTab]->ApplyAttr( nCol, nRow, rAttr );
3961 }
3962
3963
ApplyPattern(SCCOL nCol,SCROW nRow,SCTAB nTab,const ScPatternAttr & rAttr)3964 void ScDocument::ApplyPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr )
3965 {
3966 if ( ValidTab(nTab) && pTab[nTab] )
3967 pTab[nTab]->ApplyPattern( nCol, nRow, rAttr );
3968 }
3969
3970
ApplyPatternArea(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,const ScMarkData & rMark,const ScPatternAttr & rAttr)3971 void ScDocument::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow,
3972 SCCOL nEndCol, SCROW nEndRow,
3973 const ScMarkData& rMark,
3974 const ScPatternAttr& rAttr )
3975 {
3976 for (SCTAB i=0; i <= MAXTAB; i++)
3977 if (pTab[i])
3978 if (rMark.GetTableSelect(i))
3979 pTab[i]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr );
3980 }
3981
3982
ApplyPatternAreaTab(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,SCTAB nTab,const ScPatternAttr & rAttr)3983 void ScDocument::ApplyPatternAreaTab( SCCOL nStartCol, SCROW nStartRow,
3984 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr& rAttr )
3985 {
3986 if (VALIDTAB(nTab))
3987 if (pTab[nTab])
3988 pTab[nTab]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr );
3989 }
3990
ApplyPooledPatternAreaTab(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,SCTAB nTab,const ScPatternAttr & rPooledAttr,const ScPatternAttr & rAttr)3991 void ScDocument::ApplyPooledPatternAreaTab( SCCOL nStartCol, SCROW nStartRow,
3992 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr& rPooledAttr, const ScPatternAttr& rAttr )
3993 {
3994 if (VALIDTAB(nTab))
3995 if (pTab[nTab])
3996 pTab[nTab]->ApplyPooledPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rPooledAttr, rAttr );
3997 }
3998
ApplyPatternIfNumberformatIncompatible(const ScRange & rRange,const ScMarkData & rMark,const ScPatternAttr & rPattern,short nNewType)3999 void ScDocument::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
4000 const ScMarkData& rMark, const ScPatternAttr& rPattern, short nNewType )
4001 {
4002 for (SCTAB i=0; i <= MAXTAB; i++)
4003 if (pTab[i])
4004 if (rMark.GetTableSelect(i))
4005 pTab[i]->ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType );
4006 }
4007
4008
ApplyStyle(SCCOL nCol,SCROW nRow,SCTAB nTab,const ScStyleSheet & rStyle)4009 void ScDocument::ApplyStyle( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScStyleSheet& rStyle)
4010 {
4011 if (VALIDTAB(nTab))
4012 if (pTab[nTab])
4013 pTab[nTab]->ApplyStyle( nCol, nRow, rStyle );
4014 }
4015
4016
ApplyStyleArea(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,const ScMarkData & rMark,const ScStyleSheet & rStyle)4017 void ScDocument::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow,
4018 SCCOL nEndCol, SCROW nEndRow,
4019 const ScMarkData& rMark,
4020 const ScStyleSheet& rStyle)
4021 {
4022 for (SCTAB i=0; i <= MAXTAB; i++)
4023 if (pTab[i])
4024 if (rMark.GetTableSelect(i))
4025 pTab[i]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle );
4026 }
4027
4028
ApplyStyleAreaTab(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,SCTAB nTab,const ScStyleSheet & rStyle)4029 void ScDocument::ApplyStyleAreaTab( SCCOL nStartCol, SCROW nStartRow,
4030 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScStyleSheet& rStyle)
4031 {
4032 if (VALIDTAB(nTab))
4033 if (pTab[nTab])
4034 pTab[nTab]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle );
4035 }
4036
4037
ApplySelectionStyle(const ScStyleSheet & rStyle,const ScMarkData & rMark)4038 void ScDocument::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
4039 {
4040 // ApplySelectionStyle needs multi mark
4041 if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
4042 {
4043 ScRange aRange;
4044 rMark.GetMarkArea( aRange );
4045 ApplyStyleArea( aRange.aStart.Col(), aRange.aStart.Row(),
4046 aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rStyle );
4047 }
4048 else
4049 {
4050 for (SCTAB i=0; i<=MAXTAB; i++)
4051 if ( pTab[i] && rMark.GetTableSelect(i) )
4052 pTab[i]->ApplySelectionStyle( rStyle, rMark );
4053 }
4054 }
4055
4056
ApplySelectionLineStyle(const ScMarkData & rMark,const SvxBorderLine * pLine,sal_Bool bColorOnly)4057 void ScDocument::ApplySelectionLineStyle( const ScMarkData& rMark,
4058 const SvxBorderLine* pLine, sal_Bool bColorOnly )
4059 {
4060 if ( bColorOnly && !pLine )
4061 return;
4062
4063 for (SCTAB i=0; i<=MAXTAB; i++)
4064 if (pTab[i])
4065 if (rMark.GetTableSelect(i))
4066 pTab[i]->ApplySelectionLineStyle( rMark, pLine, bColorOnly );
4067 }
4068
4069
GetStyle(SCCOL nCol,SCROW nRow,SCTAB nTab) const4070 const ScStyleSheet* ScDocument::GetStyle( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
4071 {
4072 if ( VALIDTAB(nTab) && pTab[nTab] )
4073 return pTab[nTab]->GetStyle(nCol, nRow);
4074 else
4075 return NULL;
4076 }
4077
4078
GetSelectionStyle(const ScMarkData & rMark) const4079 const ScStyleSheet* ScDocument::GetSelectionStyle( const ScMarkData& rMark ) const
4080 {
4081 sal_Bool bEqual = sal_True;
4082 sal_Bool bFound;
4083
4084 const ScStyleSheet* pStyle = NULL;
4085 const ScStyleSheet* pNewStyle;
4086
4087 if ( rMark.IsMultiMarked() )
4088 for (SCTAB i=0; i<=MAXTAB && bEqual; i++)
4089 if (pTab[i] && rMark.GetTableSelect(i))
4090 {
4091 pNewStyle = pTab[i]->GetSelectionStyle( rMark, bFound );
4092 if (bFound)
4093 {
4094 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
4095 bEqual = sal_False; // unterschiedliche
4096 pStyle = pNewStyle;
4097 }
4098 }
4099 if ( rMark.IsMarked() )
4100 {
4101 ScRange aRange;
4102 rMark.GetMarkArea( aRange );
4103 for (SCTAB i=aRange.aStart.Tab(); i<=aRange.aEnd.Tab() && bEqual; i++)
4104 if (pTab[i] && rMark.GetTableSelect(i))
4105 {
4106 pNewStyle = pTab[i]->GetAreaStyle( bFound,
4107 aRange.aStart.Col(), aRange.aStart.Row(),
4108 aRange.aEnd.Col(), aRange.aEnd.Row() );
4109 if (bFound)
4110 {
4111 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
4112 bEqual = sal_False; // unterschiedliche
4113 pStyle = pNewStyle;
4114 }
4115 }
4116 }
4117
4118 return bEqual ? pStyle : NULL;
4119 }
4120
4121
StyleSheetChanged(const SfxStyleSheetBase * pStyleSheet,sal_Bool bRemoved,OutputDevice * pDev,double nPPTX,double nPPTY,const Fraction & rZoomX,const Fraction & rZoomY)4122 void ScDocument::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, sal_Bool bRemoved,
4123 OutputDevice* pDev,
4124 double nPPTX, double nPPTY,
4125 const Fraction& rZoomX, const Fraction& rZoomY )
4126 {
4127 for (SCTAB i=0; i <= MAXTAB; i++)
4128 if (pTab[i])
4129 pTab[i]->StyleSheetChanged
4130 ( pStyleSheet, bRemoved, pDev, nPPTX, nPPTY, rZoomX, rZoomY );
4131
4132 if ( pStyleSheet && pStyleSheet->GetName() == ScGlobal::GetRscString(STR_STYLENAME_STANDARD) )
4133 {
4134 // update attributes for all note objects
4135 ScDetectiveFunc::UpdateAllComments( *this );
4136 }
4137 }
4138
4139
IsStyleSheetUsed(const ScStyleSheet & rStyle,sal_Bool bGatherAllStyles) const4140 sal_Bool ScDocument::IsStyleSheetUsed( const ScStyleSheet& rStyle, sal_Bool bGatherAllStyles ) const
4141 {
4142 if ( bStyleSheetUsageInvalid || rStyle.GetUsage() == ScStyleSheet::UNKNOWN )
4143 {
4144 if ( bGatherAllStyles )
4145 {
4146 SfxStyleSheetIterator aIter( xPoolHelper->GetStylePool(),
4147 SFX_STYLE_FAMILY_PARA );
4148 for ( const SfxStyleSheetBase* pStyle = aIter.First(); pStyle;
4149 pStyle = aIter.Next() )
4150 {
4151 const ScStyleSheet* pScStyle = PTR_CAST( ScStyleSheet, pStyle );
4152 if ( pScStyle )
4153 pScStyle->SetUsage( ScStyleSheet::NOTUSED );
4154 }
4155 }
4156
4157 sal_Bool bIsUsed = sal_False;
4158
4159 for ( SCTAB i=0; i<=MAXTAB; i++ )
4160 {
4161 if ( pTab[i] )
4162 {
4163 if ( pTab[i]->IsStyleSheetUsed( rStyle, bGatherAllStyles ) )
4164 {
4165 if ( !bGatherAllStyles )
4166 return sal_True;
4167 bIsUsed = sal_True;
4168 }
4169 }
4170 }
4171
4172 if ( bGatherAllStyles )
4173 bStyleSheetUsageInvalid = sal_False;
4174
4175 return bIsUsed;
4176 }
4177
4178 return rStyle.GetUsage() == ScStyleSheet::USED;
4179 }
4180
4181
ApplyFlagsTab(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,SCTAB nTab,sal_Int16 nFlags)4182 sal_Bool ScDocument::ApplyFlagsTab( SCCOL nStartCol, SCROW nStartRow,
4183 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags )
4184 {
4185 if (VALIDTAB(nTab))
4186 if (pTab[nTab])
4187 return pTab[nTab]->ApplyFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags );
4188
4189 DBG_ERROR("ApplyFlags: falsche Tabelle");
4190 return sal_False;
4191 }
4192
4193
RemoveFlagsTab(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,SCTAB nTab,sal_Int16 nFlags)4194 sal_Bool ScDocument::RemoveFlagsTab( SCCOL nStartCol, SCROW nStartRow,
4195 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags )
4196 {
4197 if (VALIDTAB(nTab))
4198 if (pTab[nTab])
4199 return pTab[nTab]->RemoveFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags );
4200
4201 DBG_ERROR("RemoveFlags: falsche Tabelle");
4202 return sal_False;
4203 }
4204
4205
SetPattern(SCCOL nCol,SCROW nRow,SCTAB nTab,const ScPatternAttr & rAttr,sal_Bool bPutToPool)4206 void ScDocument::SetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr,
4207 sal_Bool bPutToPool )
4208 {
4209 if (VALIDTAB(nTab))
4210 if (pTab[nTab])
4211 pTab[nTab]->SetPattern( nCol, nRow, rAttr, bPutToPool );
4212 }
4213
4214
SetPattern(const ScAddress & rPos,const ScPatternAttr & rAttr,sal_Bool bPutToPool)4215 void ScDocument::SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr,
4216 sal_Bool bPutToPool )
4217 {
4218 SCTAB nTab = rPos.Tab();
4219 if (pTab[nTab])
4220 pTab[nTab]->SetPattern( rPos, rAttr, bPutToPool );
4221 }
4222
4223
CreateSelectionPattern(const ScMarkData & rMark,sal_Bool bDeep)4224 ScPatternAttr* ScDocument::CreateSelectionPattern( const ScMarkData& rMark, sal_Bool bDeep )
4225 {
4226 ScMergePatternState aState;
4227
4228 if ( rMark.IsMultiMarked() ) // multi selection
4229 {
4230 for (SCTAB i=0; i<=MAXTAB; i++)
4231 if (pTab[i] && rMark.GetTableSelect(i))
4232 pTab[i]->MergeSelectionPattern( aState, rMark, bDeep );
4233 }
4234 if ( rMark.IsMarked() ) // simle selection
4235 {
4236 ScRange aRange;
4237 rMark.GetMarkArea(aRange);
4238 for (SCTAB i=0; i<=MAXTAB; i++)
4239 if (pTab[i] && rMark.GetTableSelect(i))
4240 pTab[i]->MergePatternArea( aState,
4241 aRange.aStart.Col(), aRange.aStart.Row(),
4242 aRange.aEnd.Col(), aRange.aEnd.Row(), bDeep );
4243 }
4244
4245 DBG_ASSERT( aState.pItemSet, "SelectionPattern Null" );
4246 if (aState.pItemSet)
4247 return new ScPatternAttr( aState.pItemSet );
4248 else
4249 return new ScPatternAttr( GetPool() ); // empty
4250 }
4251
4252
GetSelectionPattern(const ScMarkData & rMark,sal_Bool bDeep)4253 const ScPatternAttr* ScDocument::GetSelectionPattern( const ScMarkData& rMark, sal_Bool bDeep )
4254 {
4255 delete pSelectionAttr;
4256 pSelectionAttr = CreateSelectionPattern( rMark, bDeep );
4257 return pSelectionAttr;
4258 }
4259
4260
GetSelectionFrame(const ScMarkData & rMark,SvxBoxItem & rLineOuter,SvxBoxInfoItem & rLineInner)4261 void ScDocument::GetSelectionFrame( const ScMarkData& rMark,
4262 SvxBoxItem& rLineOuter,
4263 SvxBoxInfoItem& rLineInner )
4264 {
4265 rLineOuter.SetLine(NULL, BOX_LINE_TOP);
4266 rLineOuter.SetLine(NULL, BOX_LINE_BOTTOM);
4267 rLineOuter.SetLine(NULL, BOX_LINE_LEFT);
4268 rLineOuter.SetLine(NULL, BOX_LINE_RIGHT);
4269 rLineOuter.SetDistance(0);
4270
4271 rLineInner.SetLine(NULL, BOXINFO_LINE_HORI);
4272 rLineInner.SetLine(NULL, BOXINFO_LINE_VERT);
4273 rLineInner.SetTable(sal_True);
4274 rLineInner.SetDist(sal_True);
4275 rLineInner.SetMinDist(sal_False);
4276
4277 ScLineFlags aFlags;
4278
4279 if (rMark.IsMarked())
4280 {
4281 ScRange aRange;
4282 rMark.GetMarkArea(aRange);
4283 rLineInner.EnableHor( aRange.aStart.Row() != aRange.aEnd.Row() );
4284 rLineInner.EnableVer( aRange.aStart.Col() != aRange.aEnd.Col() );
4285 for (SCTAB i=0; i<=MAXTAB; i++)
4286 if (pTab[i] && rMark.GetTableSelect(i))
4287 pTab[i]->MergeBlockFrame( &rLineOuter, &rLineInner, aFlags,
4288 aRange.aStart.Col(), aRange.aStart.Row(),
4289 aRange.aEnd.Col(), aRange.aEnd.Row() );
4290 }
4291
4292 // Don't care Status auswerten
4293
4294 rLineInner.SetValid( VALID_LEFT, ( aFlags.nLeft != SC_LINE_DONTCARE ) );
4295 rLineInner.SetValid( VALID_RIGHT, ( aFlags.nRight != SC_LINE_DONTCARE ) );
4296 rLineInner.SetValid( VALID_TOP, ( aFlags.nTop != SC_LINE_DONTCARE ) );
4297 rLineInner.SetValid( VALID_BOTTOM, ( aFlags.nBottom != SC_LINE_DONTCARE ) );
4298 rLineInner.SetValid( VALID_HORI, ( aFlags.nHori != SC_LINE_DONTCARE ) );
4299 rLineInner.SetValid( VALID_VERT, ( aFlags.nVert != SC_LINE_DONTCARE ) );
4300 }
4301
4302
HasAttrib(SCCOL nCol1,SCROW nRow1,SCTAB nTab1,SCCOL nCol2,SCROW nRow2,SCTAB nTab2,sal_uInt16 nMask)4303 bool ScDocument::HasAttrib( SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
4304 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt16 nMask )
4305 {
4306 if ( nMask & HASATTR_ROTATE )
4307 {
4308 // Attribut im Dokument ueberhaupt verwendet?
4309 // (wie in fillinfo)
4310
4311 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
4312
4313 sal_Bool bAnyItem = sal_False;
4314 sal_uInt32 nRotCount = pPool->GetItemCount2( ATTR_ROTATE_VALUE );
4315 for (sal_uInt32 nItem=0; nItem<nRotCount; nItem++)
4316 {
4317 const SfxPoolItem* pItem = pPool->GetItem2( ATTR_ROTATE_VALUE, nItem );
4318 if ( pItem )
4319 {
4320 // 90 or 270 degrees is former SvxOrientationItem - only look for other values
4321 // (see ScPatternAttr::GetCellOrientation)
4322 sal_Int32 nAngle = static_cast<const SfxInt32Item*>(pItem)->GetValue();
4323 if ( nAngle != 0 && nAngle != 9000 && nAngle != 27000 )
4324 {
4325 bAnyItem = sal_True;
4326 break;
4327 }
4328 }
4329 }
4330 if (!bAnyItem)
4331 nMask &= ~HASATTR_ROTATE;
4332 }
4333
4334 if ( nMask & HASATTR_RTL )
4335 {
4336 // first check if right-to left is in the pool at all
4337 // (the same item is used in cell and page format)
4338
4339 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
4340
4341 sal_Bool bHasRtl = sal_False;
4342 sal_uInt32 nDirCount = pPool->GetItemCount2( ATTR_WRITINGDIR );
4343 for (sal_uInt32 nItem=0; nItem<nDirCount; nItem++)
4344 {
4345 const SfxPoolItem* pItem = pPool->GetItem2( ATTR_WRITINGDIR, nItem );
4346 if ( pItem && ((const SvxFrameDirectionItem*)pItem)->GetValue() == FRMDIR_HORI_RIGHT_TOP )
4347 {
4348 bHasRtl = sal_True;
4349 break;
4350 }
4351 }
4352 if (!bHasRtl)
4353 nMask &= ~HASATTR_RTL;
4354 }
4355
4356 if (!nMask)
4357 return false;
4358
4359 bool bFound = false;
4360 for (SCTAB i=nTab1; i<=nTab2 && !bFound; i++)
4361 if (pTab[i])
4362 {
4363 if ( nMask & HASATTR_RTL )
4364 {
4365 if ( GetEditTextDirection(i) == EE_HTEXTDIR_R2L ) // sheet default
4366 bFound = true;
4367 }
4368 if ( nMask & HASATTR_RIGHTORCENTER )
4369 {
4370 // On a RTL sheet, don't start to look for the default left value
4371 // (which is then logically right), instead always assume sal_True.
4372 // That way, ScAttrArray::HasAttrib doesn't have to handle RTL sheets.
4373
4374 if ( IsLayoutRTL(i) )
4375 bFound = true;
4376 }
4377
4378 if ( !bFound )
4379 bFound = pTab[i]->HasAttrib( nCol1, nRow1, nCol2, nRow2, nMask );
4380 }
4381
4382 return bFound;
4383 }
4384
HasAttrib(const ScRange & rRange,sal_uInt16 nMask)4385 bool ScDocument::HasAttrib( const ScRange& rRange, sal_uInt16 nMask )
4386 {
4387 return HasAttrib( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
4388 rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(),
4389 nMask );
4390 }
4391
FindMaxRotCol(SCTAB nTab,RowInfo * pRowInfo,SCSIZE nArrCount,SCCOL nX1,SCCOL nX2) const4392 void ScDocument::FindMaxRotCol( SCTAB nTab, RowInfo* pRowInfo, SCSIZE nArrCount,
4393 SCCOL nX1, SCCOL nX2 ) const
4394 {
4395 if ( ValidTab(nTab) && pTab[nTab] )
4396 pTab[nTab]->FindMaxRotCol( pRowInfo, nArrCount, nX1, nX2 );
4397 else
4398 {
4399 DBG_ERRORFILE("FindMaxRotCol: falsche Tabelle");
4400 }
4401 }
4402
GetBorderLines(SCCOL nCol,SCROW nRow,SCTAB nTab,const SvxBorderLine ** ppLeft,const SvxBorderLine ** ppTop,const SvxBorderLine ** ppRight,const SvxBorderLine ** ppBottom) const4403 void ScDocument::GetBorderLines( SCCOL nCol, SCROW nRow, SCTAB nTab,
4404 const SvxBorderLine** ppLeft, const SvxBorderLine** ppTop,
4405 const SvxBorderLine** ppRight, const SvxBorderLine** ppBottom ) const
4406 {
4407 //! Seitengrenzen fuer Druck beruecksichtigen !!!!!
4408
4409 const SvxBoxItem* pThisAttr = (const SvxBoxItem*) GetEffItem( nCol, nRow, nTab, ATTR_BORDER );
4410 DBG_ASSERT(pThisAttr,"wo ist das Attribut?");
4411
4412 const SvxBorderLine* pLeftLine = pThisAttr->GetLeft();
4413 const SvxBorderLine* pTopLine = pThisAttr->GetTop();
4414 const SvxBorderLine* pRightLine = pThisAttr->GetRight();
4415 const SvxBorderLine* pBottomLine = pThisAttr->GetBottom();
4416
4417 if ( nCol > 0 )
4418 {
4419 const SvxBorderLine* pOther = ((const SvxBoxItem*)
4420 GetEffItem( nCol-1, nRow, nTab, ATTR_BORDER ))->GetRight();
4421 if ( ScHasPriority( pOther, pLeftLine ) )
4422 pLeftLine = pOther;
4423 }
4424 if ( nRow > 0 )
4425 {
4426 const SvxBorderLine* pOther = ((const SvxBoxItem*)
4427 GetEffItem( nCol, nRow-1, nTab, ATTR_BORDER ))->GetBottom();
4428 if ( ScHasPriority( pOther, pTopLine ) )
4429 pTopLine = pOther;
4430 }
4431 if ( nCol < MAXCOL )
4432 {
4433 const SvxBorderLine* pOther = ((const SvxBoxItem*)
4434 GetEffItem( nCol+1, nRow, nTab, ATTR_BORDER ))->GetLeft();
4435 if ( ScHasPriority( pOther, pRightLine ) )
4436 pRightLine = pOther;
4437 }
4438 if ( nRow < MAXROW )
4439 {
4440 const SvxBorderLine* pOther = ((const SvxBoxItem*)
4441 GetEffItem( nCol, nRow+1, nTab, ATTR_BORDER ))->GetTop();
4442 if ( ScHasPriority( pOther, pBottomLine ) )
4443 pBottomLine = pOther;
4444 }
4445
4446 if (ppLeft)
4447 *ppLeft = pLeftLine;
4448 if (ppTop)
4449 *ppTop = pTopLine;
4450 if (ppRight)
4451 *ppRight = pRightLine;
4452 if (ppBottom)
4453 *ppBottom = pBottomLine;
4454 }
4455
IsBlockEmpty(SCTAB nTab,SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,bool bIgnoreNotes) const4456 sal_Bool ScDocument::IsBlockEmpty( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
4457 SCCOL nEndCol, SCROW nEndRow, bool bIgnoreNotes ) const
4458 {
4459 if (VALIDTAB(nTab))
4460 if (pTab[nTab])
4461 return pTab[nTab]->IsBlockEmpty( nStartCol, nStartRow, nEndCol, nEndRow, bIgnoreNotes );
4462
4463 DBG_ERROR("Falsche Tabellennummer");
4464 return sal_False;
4465 }
4466
4467
LockTable(SCTAB nTab)4468 void ScDocument::LockTable(SCTAB nTab)
4469 {
4470 if ( ValidTab(nTab) && pTab[nTab] )
4471 pTab[nTab]->LockTable();
4472 else
4473 {
4474 DBG_ERROR("Falsche Tabellennummer");
4475 }
4476 }
4477
4478
UnlockTable(SCTAB nTab)4479 void ScDocument::UnlockTable(SCTAB nTab)
4480 {
4481 if ( ValidTab(nTab) && pTab[nTab] )
4482 pTab[nTab]->UnlockTable();
4483 else
4484 {
4485 DBG_ERROR("Falsche Tabellennummer");
4486 }
4487 }
4488
4489
IsBlockEditable(SCTAB nTab,SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,sal_Bool * pOnlyNotBecauseOfMatrix) const4490 sal_Bool ScDocument::IsBlockEditable( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
4491 SCCOL nEndCol, SCROW nEndRow,
4492 sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
4493 {
4494 // import into read-only document is possible
4495 if ( !bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly() )
4496 {
4497 if ( pOnlyNotBecauseOfMatrix )
4498 *pOnlyNotBecauseOfMatrix = sal_False;
4499 return sal_False;
4500 }
4501
4502 if (VALIDTAB(nTab))
4503 if (pTab[nTab])
4504 return pTab[nTab]->IsBlockEditable( nStartCol, nStartRow, nEndCol,
4505 nEndRow, pOnlyNotBecauseOfMatrix );
4506
4507 DBG_ERROR("Falsche Tabellennummer");
4508 if ( pOnlyNotBecauseOfMatrix )
4509 *pOnlyNotBecauseOfMatrix = sal_False;
4510 return sal_False;
4511 }
4512
4513
IsSelectionEditable(const ScMarkData & rMark,sal_Bool * pOnlyNotBecauseOfMatrix) const4514 sal_Bool ScDocument::IsSelectionEditable( const ScMarkData& rMark,
4515 sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
4516 {
4517 // import into read-only document is possible
4518 if ( !bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly() )
4519 {
4520 if ( pOnlyNotBecauseOfMatrix )
4521 *pOnlyNotBecauseOfMatrix = sal_False;
4522 return sal_False;
4523 }
4524
4525 ScRange aRange;
4526 rMark.GetMarkArea(aRange);
4527
4528 sal_Bool bOk = sal_True;
4529 sal_Bool bMatrix = ( pOnlyNotBecauseOfMatrix != NULL );
4530 for ( SCTAB i=0; i<=MAXTAB && (bOk || bMatrix); i++ )
4531 {
4532 if ( pTab[i] && rMark.GetTableSelect(i) )
4533 {
4534 if (rMark.IsMarked())
4535 {
4536 if ( !pTab[i]->IsBlockEditable( aRange.aStart.Col(),
4537 aRange.aStart.Row(), aRange.aEnd.Col(),
4538 aRange.aEnd.Row(), pOnlyNotBecauseOfMatrix ) )
4539 {
4540 bOk = sal_False;
4541 if ( pOnlyNotBecauseOfMatrix )
4542 bMatrix = *pOnlyNotBecauseOfMatrix;
4543 }
4544 }
4545 if (rMark.IsMultiMarked())
4546 {
4547 if ( !pTab[i]->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix ) )
4548 {
4549 bOk = sal_False;
4550 if ( pOnlyNotBecauseOfMatrix )
4551 bMatrix = *pOnlyNotBecauseOfMatrix;
4552 }
4553 }
4554 }
4555 }
4556
4557 if ( pOnlyNotBecauseOfMatrix )
4558 *pOnlyNotBecauseOfMatrix = ( !bOk && bMatrix );
4559
4560 return bOk;
4561 }
4562
4563
HasSelectedBlockMatrixFragment(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,const ScMarkData & rMark) const4564 sal_Bool ScDocument::HasSelectedBlockMatrixFragment( SCCOL nStartCol, SCROW nStartRow,
4565 SCCOL nEndCol, SCROW nEndRow,
4566 const ScMarkData& rMark ) const
4567 {
4568 sal_Bool bOk = sal_True;
4569 for (SCTAB i=0; i<=MAXTAB && bOk; i++)
4570 if (pTab[i])
4571 if (rMark.GetTableSelect(i))
4572 if (pTab[i]->HasBlockMatrixFragment( nStartCol, nStartRow, nEndCol, nEndRow ))
4573 bOk = sal_False;
4574
4575 return !bOk;
4576 }
4577
4578
GetMatrixFormulaRange(const ScAddress & rCellPos,ScRange & rMatrix)4579 sal_Bool ScDocument::GetMatrixFormulaRange( const ScAddress& rCellPos, ScRange& rMatrix )
4580 {
4581 // if rCell is part of a matrix formula, return its complete range
4582
4583 sal_Bool bRet = sal_False;
4584 ScBaseCell* pCell = GetCell( rCellPos );
4585 if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
4586 {
4587 ScAddress aOrigin = rCellPos;
4588 if ( ((ScFormulaCell*)pCell)->GetMatrixOrigin( aOrigin ) )
4589 {
4590 if ( aOrigin != rCellPos )
4591 pCell = GetCell( aOrigin );
4592 if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
4593 {
4594 SCCOL nSizeX;
4595 SCROW nSizeY;
4596 ((ScFormulaCell*)pCell)->GetMatColsRows(nSizeX,nSizeY);
4597 if ( !(nSizeX > 0 && nSizeY > 0) )
4598 {
4599 // GetMatrixEdge computes also dimensions of the matrix
4600 // if not already done (may occur if document is loaded
4601 // from old file format).
4602 // Needs an "invalid" initialized address.
4603 aOrigin.SetInvalid();
4604 ((ScFormulaCell*)pCell)->GetMatrixEdge(aOrigin);
4605 ((ScFormulaCell*)pCell)->GetMatColsRows(nSizeX,nSizeY);
4606 }
4607 if ( nSizeX > 0 && nSizeY > 0 )
4608 {
4609 ScAddress aEnd( aOrigin.Col() + nSizeX - 1,
4610 aOrigin.Row() + nSizeY - 1,
4611 aOrigin.Tab() );
4612
4613 rMatrix.aStart = aOrigin;
4614 rMatrix.aEnd = aEnd;
4615 bRet = sal_True;
4616 }
4617 }
4618 }
4619 }
4620 return bRet;
4621 }
4622
4623
ExtendOverlapped(SCCOL & rStartCol,SCROW & rStartRow,SCCOL nEndCol,SCROW nEndRow,SCTAB nTab)4624 sal_Bool ScDocument::ExtendOverlapped( SCCOL& rStartCol, SCROW& rStartRow,
4625 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
4626 {
4627 sal_Bool bFound = sal_False;
4628 if ( ValidColRow(rStartCol,rStartRow) && ValidColRow(nEndCol,nEndRow) && ValidTab(nTab) )
4629 {
4630 if (pTab[nTab])
4631 {
4632 SCCOL nCol;
4633 SCCOL nOldCol = rStartCol;
4634 SCROW nOldRow = rStartRow;
4635 for (nCol=nOldCol; nCol<=nEndCol; nCol++)
4636 while (((ScMergeFlagAttr*)GetAttr(nCol,rStartRow,nTab,ATTR_MERGE_FLAG))->
4637 IsVerOverlapped())
4638 --rStartRow;
4639
4640 //! weiterreichen ?
4641
4642 ScAttrArray* pAttrArray = pTab[nTab]->aCol[nOldCol].pAttrArray;
4643 SCSIZE nIndex;
4644 pAttrArray->Search( nOldRow, nIndex );
4645 SCROW nAttrPos = nOldRow;
4646 while (nAttrPos<=nEndRow)
4647 {
4648 DBG_ASSERT( nIndex < pAttrArray->nCount, "Falscher Index im AttrArray" );
4649
4650 if (((ScMergeFlagAttr&)pAttrArray->pData[nIndex].pPattern->
4651 GetItem(ATTR_MERGE_FLAG)).IsHorOverlapped())
4652 {
4653 SCROW nLoopEndRow = Min( nEndRow, pAttrArray->pData[nIndex].nRow );
4654 for (SCROW nAttrRow = nAttrPos; nAttrRow <= nLoopEndRow; nAttrRow++)
4655 {
4656 SCCOL nTempCol = nOldCol;
4657 do
4658 --nTempCol;
4659 while (((ScMergeFlagAttr*)GetAttr(nTempCol,nAttrRow,nTab,ATTR_MERGE_FLAG))
4660 ->IsHorOverlapped());
4661 if (nTempCol < rStartCol)
4662 rStartCol = nTempCol;
4663 }
4664 }
4665 nAttrPos = pAttrArray->pData[nIndex].nRow + 1;
4666 ++nIndex;
4667 }
4668 }
4669 }
4670 else
4671 {
4672 DBG_ERROR("ExtendOverlapped: falscher Bereich");
4673 }
4674
4675 return bFound;
4676 }
4677
4678
ExtendMergeSel(SCCOL nStartCol,SCROW nStartRow,SCCOL & rEndCol,SCROW & rEndRow,const ScMarkData & rMark,sal_Bool bRefresh,sal_Bool bAttrs)4679 sal_Bool ScDocument::ExtendMergeSel( SCCOL nStartCol, SCROW nStartRow,
4680 SCCOL& rEndCol, SCROW& rEndRow,
4681 const ScMarkData& rMark, sal_Bool bRefresh, sal_Bool bAttrs )
4682 {
4683 // use all selected sheets from rMark
4684
4685 sal_Bool bFound = sal_False;
4686 SCCOL nOldEndCol = rEndCol;
4687 SCROW nOldEndRow = rEndRow;
4688
4689 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++)
4690 if ( pTab[nTab] && rMark.GetTableSelect(nTab) )
4691 {
4692 SCCOL nThisEndCol = nOldEndCol;
4693 SCROW nThisEndRow = nOldEndRow;
4694 if ( ExtendMerge( nStartCol, nStartRow, nThisEndCol, nThisEndRow, nTab, bRefresh, bAttrs ) )
4695 bFound = sal_True;
4696 if ( nThisEndCol > rEndCol )
4697 rEndCol = nThisEndCol;
4698 if ( nThisEndRow > rEndRow )
4699 rEndRow = nThisEndRow;
4700 }
4701
4702 return bFound;
4703 }
4704
4705
ExtendMerge(SCCOL nStartCol,SCROW nStartRow,SCCOL & rEndCol,SCROW & rEndRow,SCTAB nTab,sal_Bool bRefresh,sal_Bool bAttrs)4706 sal_Bool ScDocument::ExtendMerge( SCCOL nStartCol, SCROW nStartRow,
4707 SCCOL& rEndCol, SCROW& rEndRow,
4708 SCTAB nTab, sal_Bool bRefresh, sal_Bool bAttrs )
4709 {
4710 sal_Bool bFound = sal_False;
4711 if ( ValidColRow(nStartCol,nStartRow) && ValidColRow(rEndCol,rEndRow) && ValidTab(nTab) )
4712 {
4713 if (pTab[nTab])
4714 bFound = pTab[nTab]->ExtendMerge( nStartCol, nStartRow, rEndCol, rEndRow, bRefresh, bAttrs );
4715
4716 if (bRefresh)
4717 RefreshAutoFilter( nStartCol, nStartRow, rEndCol, rEndRow, nTab );
4718 }
4719 else
4720 {
4721 DBG_ERROR("ExtendMerge: falscher Bereich");
4722 }
4723
4724 return bFound;
4725 }
4726
4727
ExtendMerge(ScRange & rRange,sal_Bool bRefresh,sal_Bool bAttrs)4728 sal_Bool ScDocument::ExtendMerge( ScRange& rRange, sal_Bool bRefresh, sal_Bool bAttrs )
4729 {
4730 sal_Bool bFound = sal_False;
4731 SCTAB nStartTab = rRange.aStart.Tab();
4732 SCTAB nEndTab = rRange.aEnd.Tab();
4733 SCCOL nEndCol = rRange.aEnd.Col();
4734 SCROW nEndRow = rRange.aEnd.Row();
4735
4736 PutInOrder( nStartTab, nEndTab );
4737 for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++ )
4738 {
4739 SCCOL nExtendCol = rRange.aEnd.Col();
4740 SCROW nExtendRow = rRange.aEnd.Row();
4741 if (ExtendMerge( rRange.aStart.Col(), rRange.aStart.Row(),
4742 nExtendCol, nExtendRow,
4743 nTab, bRefresh, bAttrs ) )
4744 {
4745 bFound = sal_True;
4746 if (nExtendCol > nEndCol) nEndCol = nExtendCol;
4747 if (nExtendRow > nEndRow) nEndRow = nExtendRow;
4748 }
4749 }
4750
4751 rRange.aEnd.SetCol(nEndCol);
4752 rRange.aEnd.SetRow(nEndRow);
4753
4754 return bFound;
4755 }
4756
ExtendTotalMerge(ScRange & rRange)4757 sal_Bool ScDocument::ExtendTotalMerge( ScRange& rRange )
4758 {
4759 // Bereich genau dann auf zusammengefasste Zellen erweitern, wenn
4760 // dadurch keine neuen nicht-ueberdeckten Zellen getroffen werden
4761
4762 sal_Bool bRet = sal_False;
4763 ScRange aExt = rRange;
4764 if (ExtendMerge(aExt))
4765 {
4766 if ( aExt.aEnd.Row() > rRange.aEnd.Row() )
4767 {
4768 ScRange aTest = aExt;
4769 aTest.aStart.SetRow( rRange.aEnd.Row() + 1 );
4770 if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) )
4771 aExt.aEnd.SetRow(rRange.aEnd.Row());
4772 }
4773 if ( aExt.aEnd.Col() > rRange.aEnd.Col() )
4774 {
4775 ScRange aTest = aExt;
4776 aTest.aStart.SetCol( rRange.aEnd.Col() + 1 );
4777 if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) )
4778 aExt.aEnd.SetCol(rRange.aEnd.Col());
4779 }
4780
4781 bRet = ( aExt.aEnd != rRange.aEnd );
4782 rRange = aExt;
4783 }
4784 return bRet;
4785 }
4786
ExtendOverlapped(ScRange & rRange)4787 sal_Bool ScDocument::ExtendOverlapped( ScRange& rRange )
4788 {
4789 sal_Bool bFound = sal_False;
4790 SCTAB nStartTab = rRange.aStart.Tab();
4791 SCTAB nEndTab = rRange.aEnd.Tab();
4792 SCCOL nStartCol = rRange.aStart.Col();
4793 SCROW nStartRow = rRange.aStart.Row();
4794
4795 PutInOrder( nStartTab, nEndTab );
4796 for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++ )
4797 {
4798 SCCOL nExtendCol = rRange.aStart.Col();
4799 SCROW nExtendRow = rRange.aStart.Row();
4800 ExtendOverlapped( nExtendCol, nExtendRow,
4801 rRange.aEnd.Col(), rRange.aEnd.Row(), nTab );
4802 if (nExtendCol < nStartCol)
4803 {
4804 nStartCol = nExtendCol;
4805 bFound = sal_True;
4806 }
4807 if (nExtendRow < nStartRow)
4808 {
4809 nStartRow = nExtendRow;
4810 bFound = sal_True;
4811 }
4812 }
4813
4814 rRange.aStart.SetCol(nStartCol);
4815 rRange.aStart.SetRow(nStartRow);
4816
4817 return bFound;
4818 }
4819
RefreshAutoFilter(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,SCTAB nTab)4820 sal_Bool ScDocument::RefreshAutoFilter( SCCOL nStartCol, SCROW nStartRow,
4821 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
4822 {
4823 sal_uInt16 nCount = pDBCollection->GetCount();
4824 sal_uInt16 i;
4825 ScDBData* pData;
4826 SCTAB nDBTab;
4827 SCCOL nDBStartCol;
4828 SCROW nDBStartRow;
4829 SCCOL nDBEndCol;
4830 SCROW nDBEndRow;
4831
4832 // Autofilter loeschen
4833
4834 sal_Bool bChange = RemoveFlagsTab( nStartCol,nStartRow, nEndCol,nEndRow, nTab, SC_MF_AUTO );
4835
4836 // Autofilter setzen
4837
4838 for (i=0; i<nCount; i++)
4839 {
4840 pData = (*pDBCollection)[i];
4841 if (pData->HasAutoFilter())
4842 {
4843 pData->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow );
4844 if ( nDBTab==nTab && nDBStartRow<=nEndRow && nDBEndRow>=nStartRow &&
4845 nDBStartCol<=nEndCol && nDBEndCol>=nStartCol )
4846 {
4847 if (ApplyFlagsTab( nDBStartCol,nDBStartRow, nDBEndCol,nDBStartRow,
4848 nDBTab, SC_MF_AUTO ))
4849 bChange = sal_True;
4850 }
4851 }
4852 }
4853 return bChange;
4854 }
4855
4856
IsHorOverlapped(SCCOL nCol,SCROW nRow,SCTAB nTab) const4857 sal_Bool ScDocument::IsHorOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
4858 {
4859 const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*)
4860 GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG );
4861 if (pAttr)
4862 return pAttr->IsHorOverlapped();
4863 else
4864 {
4865 DBG_ERROR("Overlapped: Attr==0");
4866 return sal_False;
4867 }
4868 }
4869
4870
IsVerOverlapped(SCCOL nCol,SCROW nRow,SCTAB nTab) const4871 sal_Bool ScDocument::IsVerOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
4872 {
4873 const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*)
4874 GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG );
4875 if (pAttr)
4876 return pAttr->IsVerOverlapped();
4877 else
4878 {
4879 DBG_ERROR("Overlapped: Attr==0");
4880 return sal_False;
4881 }
4882 }
4883
4884
ApplySelectionFrame(const ScMarkData & rMark,const SvxBoxItem * pLineOuter,const SvxBoxInfoItem * pLineInner)4885 void ScDocument::ApplySelectionFrame( const ScMarkData& rMark,
4886 const SvxBoxItem* pLineOuter,
4887 const SvxBoxInfoItem* pLineInner )
4888 {
4889 ScRangeList aRangeList;
4890 rMark.FillRangeListWithMarks( &aRangeList, sal_False );
4891 sal_uLong nRangeCount = aRangeList.Count();
4892 for (SCTAB i=0; i<=MAXTAB; i++)
4893 {
4894 if (pTab[i] && rMark.GetTableSelect(i))
4895 {
4896 for (sal_uLong j=0; j<nRangeCount; j++)
4897 {
4898 ScRange aRange = *aRangeList.GetObject(j);
4899 pTab[i]->ApplyBlockFrame( pLineOuter, pLineInner,
4900 aRange.aStart.Col(), aRange.aStart.Row(),
4901 aRange.aEnd.Col(), aRange.aEnd.Row() );
4902 }
4903 }
4904 }
4905 }
4906
4907
ApplyFrameAreaTab(const ScRange & rRange,const SvxBoxItem * pLineOuter,const SvxBoxInfoItem * pLineInner)4908 void ScDocument::ApplyFrameAreaTab( const ScRange& rRange,
4909 const SvxBoxItem* pLineOuter,
4910 const SvxBoxInfoItem* pLineInner )
4911 {
4912 SCTAB nStartTab = rRange.aStart.Tab();
4913 SCTAB nEndTab = rRange.aStart.Tab();
4914 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4915 if (pTab[nTab])
4916 pTab[nTab]->ApplyBlockFrame( pLineOuter, pLineInner,
4917 rRange.aStart.Col(), rRange.aStart.Row(),
4918 rRange.aEnd.Col(), rRange.aEnd.Row() );
4919 }
4920
4921
ApplySelectionPattern(const ScPatternAttr & rAttr,const ScMarkData & rMark)4922 void ScDocument::ApplySelectionPattern( const ScPatternAttr& rAttr, const ScMarkData& rMark )
4923 {
4924 const SfxItemSet* pSet = &rAttr.GetItemSet();
4925 sal_Bool bSet = sal_False;
4926 sal_uInt16 i;
4927 for (i=ATTR_PATTERN_START; i<=ATTR_PATTERN_END && !bSet; i++)
4928 if (pSet->GetItemState(i) == SFX_ITEM_SET)
4929 bSet = sal_True;
4930
4931 if (bSet)
4932 {
4933 // ApplySelectionCache needs multi mark
4934 if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
4935 {
4936 ScRange aRange;
4937 rMark.GetMarkArea( aRange );
4938 ApplyPatternArea( aRange.aStart.Col(), aRange.aStart.Row(),
4939 aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rAttr );
4940 }
4941 else
4942 {
4943 SfxItemPoolCache aCache( xPoolHelper->GetDocPool(), pSet );
4944 for (SCTAB nTab=0; nTab<=MAXTAB; nTab++)
4945 if (pTab[nTab])
4946 if (rMark.GetTableSelect(nTab))
4947 pTab[nTab]->ApplySelectionCache( &aCache, rMark );
4948 }
4949 }
4950 }
4951
4952
ChangeSelectionIndent(sal_Bool bIncrement,const ScMarkData & rMark)4953 void ScDocument::ChangeSelectionIndent( sal_Bool bIncrement, const ScMarkData& rMark )
4954 {
4955 for (SCTAB i=0; i<=MAXTAB; i++)
4956 if (pTab[i] && rMark.GetTableSelect(i))
4957 pTab[i]->ChangeSelectionIndent( bIncrement, rMark );
4958 }
4959
4960
ClearSelectionItems(const sal_uInt16 * pWhich,const ScMarkData & rMark)4961 void ScDocument::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark )
4962 {
4963 for (SCTAB i=0; i<=MAXTAB; i++)
4964 if (pTab[i] && rMark.GetTableSelect(i))
4965 pTab[i]->ClearSelectionItems( pWhich, rMark );
4966 }
4967
4968
DeleteSelection(sal_uInt16 nDelFlag,const ScMarkData & rMark)4969 void ScDocument::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark )
4970 {
4971 for (SCTAB i=0; i<=MAXTAB; i++)
4972 if (pTab[i] && rMark.GetTableSelect(i))
4973 pTab[i]->DeleteSelection( nDelFlag, rMark );
4974 }
4975
4976
DeleteSelectionTab(SCTAB nTab,sal_uInt16 nDelFlag,const ScMarkData & rMark)4977 void ScDocument::DeleteSelectionTab( SCTAB nTab, sal_uInt16 nDelFlag, const ScMarkData& rMark )
4978 {
4979 if (ValidTab(nTab) && pTab[nTab])
4980 pTab[nTab]->DeleteSelection( nDelFlag, rMark );
4981 else
4982 {
4983 DBG_ERROR("Falsche Tabelle");
4984 }
4985 }
4986
4987
GetDefPattern() const4988 ScPatternAttr* ScDocument::GetDefPattern() const
4989 {
4990 return (ScPatternAttr*) &xPoolHelper->GetDocPool()->GetDefaultItem(ATTR_PATTERN);
4991 }
4992
4993
GetPool()4994 ScDocumentPool* ScDocument::GetPool()
4995 {
4996 return xPoolHelper->GetDocPool();
4997 }
4998
4999
5000
GetStyleSheetPool() const5001 ScStyleSheetPool* ScDocument::GetStyleSheetPool() const
5002 {
5003 return xPoolHelper->GetStylePool();
5004 }
5005
5006
GetEmptyLinesInBlock(SCCOL nStartCol,SCROW nStartRow,SCTAB nStartTab,SCCOL nEndCol,SCROW nEndRow,SCTAB nEndTab,ScDirection eDir)5007 SCSIZE ScDocument::GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
5008 SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, ScDirection eDir )
5009 {
5010 PutInOrder(nStartCol, nEndCol);
5011 PutInOrder(nStartRow, nEndRow);
5012 PutInOrder(nStartTab, nEndTab);
5013 if (VALIDTAB(nStartTab))
5014 {
5015 if (pTab[nStartTab])
5016 return pTab[nStartTab]->GetEmptyLinesInBlock(nStartCol, nStartRow, nEndCol, nEndRow, eDir);
5017 else
5018 return 0;
5019 }
5020 else
5021 return 0;
5022 }
5023
5024
FindAreaPos(SCCOL & rCol,SCROW & rRow,SCTAB nTab,SCsCOL nMovX,SCsROW nMovY)5025 void ScDocument::FindAreaPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY )
5026 {
5027 if (ValidTab(nTab) && pTab[nTab])
5028 pTab[nTab]->FindAreaPos( rCol, rRow, nMovX, nMovY );
5029 }
5030
5031
GetNextPos(SCCOL & rCol,SCROW & rRow,SCTAB nTab,SCsCOL nMovX,SCsROW nMovY,sal_Bool bMarked,sal_Bool bUnprotected,const ScMarkData & rMark)5032 void ScDocument::GetNextPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY,
5033 sal_Bool bMarked, sal_Bool bUnprotected, const ScMarkData& rMark )
5034 {
5035 DBG_ASSERT( !nMovX || !nMovY, "GetNextPos: nur X oder Y" );
5036
5037 ScMarkData aCopyMark = rMark;
5038 aCopyMark.SetMarking(sal_False);
5039 aCopyMark.MarkToMulti();
5040
5041 if (ValidTab(nTab) && pTab[nTab])
5042 pTab[nTab]->GetNextPos( rCol, rRow, nMovX, nMovY, bMarked, bUnprotected, aCopyMark );
5043 }
5044
5045 //
5046 // Datei-Operationen
5047 //
5048
5049
UpdStlShtPtrsFrmNms()5050 void ScDocument::UpdStlShtPtrsFrmNms()
5051 {
5052 ScPatternAttr::pDoc = this;
5053
5054 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
5055
5056 sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN);
5057 ScPatternAttr* pPattern;
5058 for (sal_uInt32 i=0; i<nCount; i++)
5059 {
5060 pPattern = (ScPatternAttr*)pPool->GetItem2(ATTR_PATTERN, i);
5061 if (pPattern)
5062 pPattern->UpdateStyleSheet();
5063 }
5064 ((ScPatternAttr&)pPool->GetDefaultItem(ATTR_PATTERN)).UpdateStyleSheet();
5065 }
5066
5067
StylesToNames()5068 void ScDocument::StylesToNames()
5069 {
5070 ScPatternAttr::pDoc = this;
5071
5072 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
5073
5074 sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN);
5075 ScPatternAttr* pPattern;
5076 for (sal_uInt32 i=0; i<nCount; i++)
5077 {
5078 pPattern = (ScPatternAttr*)pPool->GetItem2(ATTR_PATTERN, i);
5079 if (pPattern)
5080 pPattern->StyleToName();
5081 }
5082 ((ScPatternAttr&)pPool->GetDefaultItem(ATTR_PATTERN)).StyleToName();
5083 }
5084
5085
GetCellCount() const5086 sal_uLong ScDocument::GetCellCount() const
5087 {
5088 sal_uLong nCellCount = 0L;
5089
5090 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ )
5091 if ( pTab[nTab] )
5092 nCellCount += pTab[nTab]->GetCellCount();
5093
5094 return nCellCount;
5095 }
5096
GetCellCount(SCTAB nTab,SCCOL nCol) const5097 SCSIZE ScDocument::GetCellCount(SCTAB nTab, SCCOL nCol) const
5098 {
5099 if (!ValidTab(nTab) || !pTab[nTab])
5100 return 0;
5101
5102 return pTab[nTab]->GetCellCount(nCol);
5103 }
5104
GetCodeCount() const5105 sal_uLong ScDocument::GetCodeCount() const
5106 {
5107 sal_uLong nCodeCount = 0;
5108
5109 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ )
5110 if ( pTab[nTab] )
5111 nCodeCount += pTab[nTab]->GetCodeCount();
5112
5113 return nCodeCount;
5114 }
5115
5116
GetWeightedCount() const5117 sal_uLong ScDocument::GetWeightedCount() const
5118 {
5119 sal_uLong nCellCount = 0L;
5120
5121 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ )
5122 if ( pTab[nTab] )
5123 nCellCount += pTab[nTab]->GetWeightedCount();
5124
5125 return nCellCount;
5126 }
5127
5128
PageStyleModified(SCTAB nTab,const String & rNewName)5129 void ScDocument::PageStyleModified( SCTAB nTab, const String& rNewName )
5130 {
5131 if ( ValidTab(nTab) && pTab[nTab] )
5132 pTab[nTab]->PageStyleModified( rNewName );
5133 }
5134
5135
SetPageStyle(SCTAB nTab,const String & rName)5136 void ScDocument::SetPageStyle( SCTAB nTab, const String& rName )
5137 {
5138 if ( ValidTab(nTab) && pTab[nTab] )
5139 pTab[nTab]->SetPageStyle( rName );
5140 }
5141
5142
GetPageStyle(SCTAB nTab) const5143 const String& ScDocument::GetPageStyle( SCTAB nTab ) const
5144 {
5145 if ( ValidTab(nTab) && pTab[nTab] )
5146 return pTab[nTab]->GetPageStyle();
5147
5148 return EMPTY_STRING;
5149 }
5150
5151
SetPageSize(SCTAB nTab,const Size & rSize)5152 void ScDocument::SetPageSize( SCTAB nTab, const Size& rSize )
5153 {
5154 if ( ValidTab(nTab) && pTab[nTab] )
5155 pTab[nTab]->SetPageSize( rSize );
5156 }
5157
GetPageSize(SCTAB nTab) const5158 Size ScDocument::GetPageSize( SCTAB nTab ) const
5159 {
5160 if ( ValidTab(nTab) && pTab[nTab] )
5161 return pTab[nTab]->GetPageSize();
5162
5163 DBG_ERROR("falsche Tab");
5164 return Size();
5165 }
5166
5167
SetRepeatArea(SCTAB nTab,SCCOL nStartCol,SCCOL nEndCol,SCROW nStartRow,SCROW nEndRow)5168 void ScDocument::SetRepeatArea( SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow )
5169 {
5170 if ( ValidTab(nTab) && pTab[nTab] )
5171 pTab[nTab]->SetRepeatArea( nStartCol, nEndCol, nStartRow, nEndRow );
5172 }
5173
InvalidatePageBreaks(SCTAB nTab)5174 void ScDocument::InvalidatePageBreaks(SCTAB nTab)
5175 {
5176 if (ValidTab(nTab) && pTab[nTab])
5177 pTab[nTab]->InvalidatePageBreaks();
5178 }
5179
UpdatePageBreaks(SCTAB nTab,const ScRange * pUserArea)5180 void ScDocument::UpdatePageBreaks( SCTAB nTab, const ScRange* pUserArea )
5181 {
5182 if ( ValidTab(nTab) && pTab[nTab] )
5183 pTab[nTab]->UpdatePageBreaks( pUserArea );
5184 }
5185
RemoveManualBreaks(SCTAB nTab)5186 void ScDocument::RemoveManualBreaks( SCTAB nTab )
5187 {
5188 if ( ValidTab(nTab) && pTab[nTab] )
5189 pTab[nTab]->RemoveManualBreaks();
5190 }
5191
HasManualBreaks(SCTAB nTab) const5192 sal_Bool ScDocument::HasManualBreaks( SCTAB nTab ) const
5193 {
5194 if ( ValidTab(nTab) && pTab[nTab] )
5195 return pTab[nTab]->HasManualBreaks();
5196
5197 DBG_ERROR("falsche Tab");
5198 return sal_False;
5199 }
5200
5201
GetDocStat(ScDocStat & rDocStat)5202 void ScDocument::GetDocStat( ScDocStat& rDocStat )
5203 {
5204 rDocStat.nTableCount = GetTableCount();
5205 rDocStat.aDocName = aDocName;
5206 rDocStat.nCellCount = GetCellCount();
5207 }
5208
5209
HasPrintRange()5210 sal_Bool ScDocument::HasPrintRange()
5211 {
5212 sal_Bool bResult = sal_False;
5213
5214 for ( SCTAB i=0; !bResult && i<nMaxTableNumber; i++ )
5215 if ( pTab[i] )
5216 bResult = pTab[i]->IsPrintEntireSheet() || (pTab[i]->GetPrintRangeCount() > 0);
5217
5218 return bResult;
5219 }
5220
5221
IsPrintEntireSheet(SCTAB nTab) const5222 sal_Bool ScDocument::IsPrintEntireSheet( SCTAB nTab ) const
5223 {
5224 return (ValidTab(nTab) ) && pTab[nTab] && pTab[nTab]->IsPrintEntireSheet();
5225 }
5226
5227
GetPrintRangeCount(SCTAB nTab)5228 sal_uInt16 ScDocument::GetPrintRangeCount( SCTAB nTab )
5229 {
5230 if (ValidTab(nTab) && pTab[nTab])
5231 return pTab[nTab]->GetPrintRangeCount();
5232
5233 return 0;
5234 }
5235
5236
GetPrintRange(SCTAB nTab,sal_uInt16 nPos)5237 const ScRange* ScDocument::GetPrintRange( SCTAB nTab, sal_uInt16 nPos )
5238 {
5239 if (ValidTab(nTab) && pTab[nTab])
5240 return pTab[nTab]->GetPrintRange(nPos);
5241
5242 return NULL;
5243 }
5244
5245
GetRepeatColRange(SCTAB nTab)5246 const ScRange* ScDocument::GetRepeatColRange( SCTAB nTab )
5247 {
5248 if (ValidTab(nTab) && pTab[nTab])
5249 return pTab[nTab]->GetRepeatColRange();
5250
5251 return NULL;
5252 }
5253
5254
GetRepeatRowRange(SCTAB nTab)5255 const ScRange* ScDocument::GetRepeatRowRange( SCTAB nTab )
5256 {
5257 if (ValidTab(nTab) && pTab[nTab])
5258 return pTab[nTab]->GetRepeatRowRange();
5259
5260 return NULL;
5261 }
5262
5263
ClearPrintRanges(SCTAB nTab)5264 void ScDocument::ClearPrintRanges( SCTAB nTab )
5265 {
5266 if (ValidTab(nTab) && pTab[nTab])
5267 pTab[nTab]->ClearPrintRanges();
5268 }
5269
5270
AddPrintRange(SCTAB nTab,const ScRange & rNew)5271 void ScDocument::AddPrintRange( SCTAB nTab, const ScRange& rNew )
5272 {
5273 if (ValidTab(nTab) && pTab[nTab])
5274 pTab[nTab]->AddPrintRange( rNew );
5275 }
5276
5277
5278 //UNUSED2009-05 void ScDocument::SetPrintRange( SCTAB nTab, const ScRange& rNew )
5279 //UNUSED2009-05 {
5280 //UNUSED2009-05 if (ValidTab(nTab) && pTab[nTab])
5281 //UNUSED2009-05 pTab[nTab]->SetPrintRange( rNew );
5282 //UNUSED2009-05 }
5283
5284
SetPrintEntireSheet(SCTAB nTab)5285 void ScDocument::SetPrintEntireSheet( SCTAB nTab )
5286 {
5287 if (ValidTab(nTab) && pTab[nTab])
5288 pTab[nTab]->SetPrintEntireSheet();
5289 }
5290
5291
SetRepeatColRange(SCTAB nTab,const ScRange * pNew)5292 void ScDocument::SetRepeatColRange( SCTAB nTab, const ScRange* pNew )
5293 {
5294 if (ValidTab(nTab) && pTab[nTab])
5295 pTab[nTab]->SetRepeatColRange( pNew );
5296 }
5297
5298
SetRepeatRowRange(SCTAB nTab,const ScRange * pNew)5299 void ScDocument::SetRepeatRowRange( SCTAB nTab, const ScRange* pNew )
5300 {
5301 if (ValidTab(nTab) && pTab[nTab])
5302 pTab[nTab]->SetRepeatRowRange( pNew );
5303 }
5304
5305
CreatePrintRangeSaver() const5306 ScPrintRangeSaver* ScDocument::CreatePrintRangeSaver() const
5307 {
5308 SCTAB nCount = GetTableCount();
5309 ScPrintRangeSaver* pNew = new ScPrintRangeSaver( nCount );
5310 for (SCTAB i=0; i<nCount; i++)
5311 if (pTab[i])
5312 pTab[i]->FillPrintSaver( pNew->GetTabData(i) );
5313 return pNew;
5314 }
5315
5316
RestorePrintRanges(const ScPrintRangeSaver & rSaver)5317 void ScDocument::RestorePrintRanges( const ScPrintRangeSaver& rSaver )
5318 {
5319 SCTAB nCount = rSaver.GetTabCount();
5320 for (SCTAB i=0; i<nCount; i++)
5321 if (pTab[i])
5322 pTab[i]->RestorePrintRanges( rSaver.GetTabData(i) );
5323 }
5324
5325
NeedPageResetAfterTab(SCTAB nTab) const5326 sal_Bool ScDocument::NeedPageResetAfterTab( SCTAB nTab ) const
5327 {
5328 // Die Seitennummern-Zaehlung faengt bei einer Tabelle neu an, wenn eine
5329 // andere Vorlage als bei der vorherigen gesetzt ist (nur Namen vergleichen)
5330 // und eine Seitennummer angegeben ist (nicht 0)
5331
5332 if ( nTab < MAXTAB && pTab[nTab] && pTab[nTab+1] )
5333 {
5334 String aNew = pTab[nTab+1]->GetPageStyle();
5335 if ( aNew != pTab[nTab]->GetPageStyle() )
5336 {
5337 SfxStyleSheetBase* pStyle = xPoolHelper->GetStylePool()->Find( aNew, SFX_STYLE_FAMILY_PAGE );
5338 if ( pStyle )
5339 {
5340 const SfxItemSet& rSet = pStyle->GetItemSet();
5341 sal_uInt16 nFirst = ((const SfxUInt16Item&)rSet.Get(ATTR_PAGE_FIRSTPAGENO)).GetValue();
5342 if ( nFirst != 0 )
5343 return sal_True; // Seitennummer in neuer Vorlage angegeben
5344 }
5345 }
5346 }
5347
5348 return sal_False; // sonst nicht
5349 }
5350
GetUndoManager()5351 SfxUndoManager* ScDocument::GetUndoManager()
5352 {
5353 if (!mpUndoManager)
5354 {
5355 // to support enhanced text edit for draw objects, use an SdrUndoManager
5356 mpUndoManager = new SdrUndoManager;
5357 }
5358
5359 return mpUndoManager;
5360 }
5361
GetRowBreakIterator(SCTAB nTab) const5362 ScRowBreakIterator* ScDocument::GetRowBreakIterator(SCTAB nTab) const
5363 {
5364 if (ValidTab(nTab) && pTab[nTab])
5365 return new ScRowBreakIterator(pTab[nTab]->maRowPageBreaks);
5366 return NULL;
5367 }
5368
EnableUndo(bool bVal)5369 void ScDocument::EnableUndo( bool bVal )
5370 {
5371 GetUndoManager()->EnableUndo(bVal);
5372 if( pDrawLayer ) pDrawLayer->EnableUndo(bVal);
5373 mbUndoEnabled = bVal;
5374 }
5375
IsInVBAMode() const5376 bool ScDocument::IsInVBAMode() const
5377 {
5378 bool bResult = false;
5379 if ( pShell )
5380 {
5381 com::sun::star::uno::Reference< com::sun::star::script::vba::XVBACompatibility > xVBA( pShell->GetBasicContainer(), com::sun::star::uno::UNO_QUERY );
5382 bResult = xVBA.is() && xVBA->getVBACompatibilityMode();
5383 }
5384 return bResult;
5385 }
5386