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