LibreOffice Module sc (master)  1
table2.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <algorithm>
21 #include <memory>
22 #include <table.hxx>
23 #include <patattr.hxx>
24 #include <docpool.hxx>
25 #include <formulacell.hxx>
26 #include <document.hxx>
27 #include <drwlayer.hxx>
28 #include <olinetab.hxx>
29 #include <stlpool.hxx>
30 #include <attarray.hxx>
31 #include <markdata.hxx>
32 #include <dociter.hxx>
33 #include <conditio.hxx>
34 #include <chartlis.hxx>
35 #include <fillinfo.hxx>
36 #include <bcaslot.hxx>
37 #include <postit.hxx>
38 #include <sheetevents.hxx>
39 #include <segmenttree.hxx>
40 #include <dbdata.hxx>
41 #include <tokenarray.hxx>
42 #include <clipcontext.hxx>
43 #include <types.hxx>
44 #include <editutil.hxx>
45 #include <mtvcellfunc.hxx>
46 #include <refupdatecontext.hxx>
47 #include <scopetools.hxx>
48 #include <tabprotection.hxx>
49 #include <columnspanset.hxx>
50 #include <rowheightcontext.hxx>
51 #include <listenercontext.hxx>
52 #include <compressedarray.hxx>
53 #include <refdata.hxx>
54 #include <docsh.hxx>
55 
56 #include <scitems.hxx>
57 #include <editeng/boxitem.hxx>
58 #include <editeng/editobj.hxx>
59 #include <o3tl/safeint.hxx>
60 #include <o3tl/unit_conversion.hxx>
61 #include <osl/diagnose.h>
62 #include <sal/log.hxx>
63 #include <svl/poolcach.hxx>
64 #include <unotools/charclass.hxx>
65 #include <math.h>
66 
67 namespace {
68 
69 class ColumnRegroupFormulaCells
70 {
71  ScColContainer& mrCols;
72  std::vector<ScAddress>* mpGroupPos;
73 
74 public:
75  ColumnRegroupFormulaCells( ScColContainer& rCols, std::vector<ScAddress>* pGroupPos ) :
76  mrCols(rCols), mpGroupPos(pGroupPos) {}
77 
78  void operator() (SCCOL nCol)
79  {
80  mrCols[nCol].RegroupFormulaCells(mpGroupPos);
81  }
82 };
83 
84 }
85 
86 sal_uInt16 ScTable::GetTextWidth(SCCOL nCol, SCROW nRow) const
87 {
88  return aCol[nCol].GetTextWidth(nRow);
89 }
90 
91 bool ScTable::SetOutlineTable( const ScOutlineTable* pNewOutline )
92 {
93  sal_uInt16 nOldSizeX = 0;
94  sal_uInt16 nOldSizeY = 0;
95  sal_uInt16 nNewSizeX = 0;
96  sal_uInt16 nNewSizeY = 0;
97 
98  if (pOutlineTable)
99  {
100  nOldSizeX = pOutlineTable->GetColArray().GetDepth();
101  nOldSizeY = pOutlineTable->GetRowArray().GetDepth();
102  pOutlineTable.reset();
103  }
104 
105  if (pNewOutline)
106  {
107  pOutlineTable.reset(new ScOutlineTable( *pNewOutline ));
108  nNewSizeX = pOutlineTable->GetColArray().GetDepth();
109  nNewSizeY = pOutlineTable->GetRowArray().GetDepth();
110  }
111 
112  return ( nNewSizeX != nOldSizeX || nNewSizeY != nOldSizeY ); // changed size?
113 }
114 
116 {
117  if (!pOutlineTable)
118  pOutlineTable.reset(new ScOutlineTable);
119 }
120 
121 void ScTable::SetSheetEvents( std::unique_ptr<ScSheetEvents> pNew )
122 {
123  pSheetEvents = std::move(pNew);
124 
125  SetCalcNotification( false ); // discard notifications before the events were set
126 
127  SetStreamValid(false);
128 }
129 
131 {
132  bCalcNotification = bSet;
133 }
134 
135 bool ScTable::TestInsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize ) const
136 {
137  if ( nStartCol==0 && nEndCol==rDocument.MaxCol() && pOutlineTable )
138  if (!pOutlineTable->TestInsertRow(nSize))
139  return false;
140 
141  SCCOL maxCol = ClampToAllocatedColumns(nEndCol);
142  for (SCCOL i=nStartCol; i<=maxCol; i++)
143  if (!aCol[i].TestInsertRow(nStartRow, nSize))
144  return false;
145 
146  if( maxCol != nEndCol )
147  if (!aDefaultColData.TestInsertRow(nSize))
148  return false;
149 
150  return true;
151 }
152 
153 void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize )
154 {
155  if (nStartCol==0 && nEndCol==rDocument.MaxCol())
156  {
157  if (mpRowHeights && pRowFlags)
158  {
159  mpRowHeights->insertSegment(nStartRow, nSize);
160  CRFlags nNewFlags = pRowFlags->Insert( nStartRow, nSize);
161  // only copy manual size flag, clear all others
162  if (nNewFlags != CRFlags::NONE && (nNewFlags != CRFlags::ManualSize))
163  pRowFlags->SetValue( nStartRow, nStartRow + nSize - 1,
164  nNewFlags & CRFlags::ManualSize);
165  }
166 
167  if (pOutlineTable)
168  pOutlineTable->InsertRow( nStartRow, nSize );
169 
170  mpFilteredRows->insertSegment(nStartRow, nSize);
171  mpHiddenRows->insertSegment(nStartRow, nSize);
172 
173  if (!maRowManualBreaks.empty())
174  {
175  // Copy all breaks up to nStartRow (non-inclusive).
176  ::std::set<SCROW>::iterator itr1 = maRowManualBreaks.lower_bound(nStartRow);
177  ::std::set<SCROW> aNewBreaks(maRowManualBreaks.begin(), itr1);
178 
179  // Copy all breaks from nStartRow (inclusive) to the last element,
180  // but add nSize to each value.
181  ::std::set<SCROW>::iterator itr2 = maRowManualBreaks.end();
182  for (; itr1 != itr2; ++itr1)
183  aNewBreaks.insert(static_cast<SCROW>(*itr1 + nSize));
184 
185  maRowManualBreaks.swap(aNewBreaks);
186  }
187  }
188 
189  for (SCCOL j : GetAllocatedColumnsRange(nStartCol, nEndCol))
190  aCol[j].InsertRow( nStartRow, nSize );
191  aDefaultColData.InsertRow( nStartRow, nSize );
192 
193  mpCondFormatList->InsertRow(nTab, nStartCol, nEndCol, nStartRow, nSize);
194 
196 
197  // TODO: In the future we may want to check if the table has been
198  // really modified before setting the stream invalid.
199  SetStreamValid(false);
200 }
201 
203  const sc::ColumnSet& rRegroupCols, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize,
204  bool* pUndoOutline, std::vector<ScAddress>* pGroupPos )
205 {
206  if (nStartCol==0 && nEndCol==rDocument.MaxCol())
207  {
208  if (pRowFlags)
209  pRowFlags->Remove( nStartRow, nSize);
210 
211  if (mpRowHeights)
212  mpRowHeights->removeSegment(nStartRow, nStartRow+nSize);
213 
214  if (pOutlineTable)
215  if (pOutlineTable->DeleteRow( nStartRow, nSize ))
216  if (pUndoOutline)
217  *pUndoOutline = true;
218 
219  mpFilteredRows->removeSegment(nStartRow, nStartRow+nSize);
220  mpHiddenRows->removeSegment(nStartRow, nStartRow+nSize);
221 
222  if (!maRowManualBreaks.empty())
223  {
224  // Erase all manual breaks between nStartRow and nStartRow + nSize - 1 (inclusive).
225  std::set<SCROW>::iterator itr1 = maRowManualBreaks.lower_bound(nStartRow);
226  std::set<SCROW>::iterator itr2 = maRowManualBreaks.upper_bound(static_cast<SCROW>(nStartRow + nSize - 1));
227  maRowManualBreaks.erase(itr1, itr2);
228 
229  // Copy all breaks from the 1st element up to nStartRow to the new container.
230  itr1 = maRowManualBreaks.lower_bound(nStartRow);
231  ::std::set<SCROW> aNewBreaks(maRowManualBreaks.begin(), itr1);
232 
233  // Copy all breaks from nStartRow to the last element, but subtract each value by nSize.
234  itr2 = maRowManualBreaks.end();
235  for (; itr1 != itr2; ++itr1)
236  aNewBreaks.insert(static_cast<SCROW>(*itr1 - nSize));
237 
238  maRowManualBreaks.swap(aNewBreaks);
239  }
240  }
241 
242  { // scope for bulk broadcast
243  ScBulkBroadcast aBulkBroadcast( rDocument.GetBASM(), SfxHintId::ScDataChanged);
244  for (SCCOL j=nStartCol; j<=ClampToAllocatedColumns(nEndCol); j++)
245  aCol[j].DeleteRow(nStartRow, nSize, pGroupPos);
246  }
247 
248  std::vector<SCCOL> aRegroupCols;
249  rRegroupCols.getColumns(nTab, aRegroupCols);
250  std::for_each(
251  aRegroupCols.begin(), aRegroupCols.end(), ColumnRegroupFormulaCells(aCol, pGroupPos));
252 
254 
255  // TODO: In the future we may want to check if the table has been
256  // really modified before setting the stream invalid.
257  SetStreamValid(false);
258 }
259 
260 bool ScTable::TestInsertCol( SCROW nStartRow, SCROW nEndRow, SCSIZE nSize ) const
261 {
262  if ( nSize > o3tl::make_unsigned(rDocument.MaxCol()) )
263  return false;
264 
265  if ( nStartRow==0 && nEndRow==rDocument.MaxRow() && pOutlineTable
266  && ! pOutlineTable->TestInsertCol(nSize) )
267  return false;
268 
269  auto range = GetAllocatedColumnsRange( rDocument.MaxCol() - static_cast<SCCOL>(nSize) + 1, rDocument.MaxCol() );
270  for (auto it = range.rbegin(); it != range.rend(); ++it )
271  if (! aCol[*it].TestInsertCol(nStartRow, nEndRow))
272  return false;
273 
274  return true;
275 }
276 
278  const sc::ColumnSet& rRegroupCols, SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE nSize )
279 {
280  if (nStartRow==0 && nEndRow==rDocument.MaxRow())
281  {
282  if (mpColWidth && mpColFlags)
283  {
284  mpColWidth->InsertPreservingSize(nStartCol, nSize, STD_COL_WIDTH);
285  // The inserted columns have the same widths as the columns, which were selected for insert.
286  for (SCSIZE i=0; i < std::min(rDocument.MaxCol()-nSize-nStartCol, nSize); ++i)
287  mpColWidth->SetValue(nStartCol + i, mpColWidth->GetValue(nStartCol+i+nSize));
288  mpColFlags->InsertPreservingSize(nStartCol, nSize, CRFlags::NONE);
289  }
290  if (pOutlineTable)
291  pOutlineTable->InsertCol( nStartCol, nSize );
292 
293  mpHiddenCols->insertSegment(nStartCol, static_cast<SCCOL>(nSize));
294  mpFilteredCols->insertSegment(nStartCol, static_cast<SCCOL>(nSize));
295 
296  if (!maColManualBreaks.empty())
297  {
298  // Copy all breaks up to nStartCol (non-inclusive).
299  ::std::set<SCCOL>::iterator itr1 = maColManualBreaks.lower_bound(nStartCol);
300  ::std::set<SCCOL> aNewBreaks(maColManualBreaks.begin(), itr1);
301 
302  // Copy all breaks from nStartCol (inclusive) to the last element,
303  // but add nSize to each value.
304  ::std::set<SCCOL>::iterator itr2 = maColManualBreaks.end();
305  for (; itr1 != itr2; ++itr1)
306  aNewBreaks.insert(static_cast<SCCOL>(*itr1 + nSize));
307 
308  maColManualBreaks.swap(aNewBreaks);
309  }
310  }
311 
312  // Make sure there are enough columns at the end.
313  CreateColumnIfNotExists(std::min<SCCOL>(rDocument.MaxCol(), std::max(nStartCol, aCol.size()) + nSize - 1 ));
314  if ((nStartRow == 0) && (nEndRow == rDocument.MaxRow()))
315  {
316  // Move existing columns back, this will swap last empty columns in the inserted place.
317  for (SCCOL nCol = aCol.size() - 1 - nSize; nCol >= nStartCol; --nCol)
318  aCol[nCol].SwapCol(aCol[nCol+nSize]);
319  }
320  else
321  {
322  for (SCSIZE i=0; static_cast<SCCOL>(i+nSize)+nStartCol < aCol.size(); i++)
323  aCol[aCol.size() - 1 - nSize - i].MoveTo(nStartRow, nEndRow, aCol[aCol.size() - 1 - i]);
324  }
325 
326  std::vector<SCCOL> aRegroupCols;
327  rRegroupCols.getColumns(nTab, aRegroupCols);
328  std::for_each(aRegroupCols.begin(), aRegroupCols.end(), ColumnRegroupFormulaCells(aCol, nullptr));
329 
330  if (nStartCol>0) // copy old attributes
331  {
332  sal_uInt16 nWhichArray[2];
333  nWhichArray[0] = ATTR_MERGE;
334  nWhichArray[1] = 0;
335 
337  for (SCSIZE i=0; i<nSize; i++)
338  {
339  aCol[nStartCol-1].CopyToColumn(aCxt, nStartRow, nEndRow, InsertDeleteFlags::ATTRIB,
340  false, aCol[nStartCol+i] );
341  aCol[nStartCol+i].RemoveFlags( nStartRow, nEndRow,
343  aCol[nStartCol+i].ClearItems( nStartRow, nEndRow, nWhichArray );
344  }
345  }
346 
347  mpCondFormatList->InsertCol(nTab, nStartRow, nEndRow, nStartCol, nSize);
348 
350 
351  // TODO: In the future we may want to check if the table has been
352  // really modified before setting the stream invalid.
353  SetStreamValid(false);
354 }
355 
357  const sc::ColumnSet& rRegroupCols, SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE nSize, bool* pUndoOutline )
358 {
359  if (nStartRow==0 && nEndRow==rDocument.MaxRow())
360  {
361  if (mpColWidth && mpColFlags)
362  {
363  assert( nStartCol + nSize <= o3tl::make_unsigned(rDocument.MaxCol()+1) ); // moving 0 if ==rDocument.MaxCol()+1 is correct
364  mpColWidth->RemovePreservingSize(nStartCol, nSize, STD_COL_WIDTH);
365  mpColFlags->RemovePreservingSize(nStartCol, nSize, CRFlags::NONE);
366  }
367  if (pOutlineTable)
368  if (pOutlineTable->DeleteCol( nStartCol, nSize ))
369  if (pUndoOutline)
370  *pUndoOutline = true;
371 
372  SCCOL nRmSize = nStartCol + static_cast<SCCOL>(nSize);
373  mpHiddenCols->removeSegment(nStartCol, nRmSize);
374  mpFilteredCols->removeSegment(nStartCol, nRmSize);
375 
376  if (!maColManualBreaks.empty())
377  {
378  // Erase all manual breaks between nStartCol and nStartCol + nSize - 1 (inclusive).
379  std::set<SCCOL>::iterator itr1 = maColManualBreaks.lower_bound(nStartCol);
380  std::set<SCCOL>::iterator itr2 = maColManualBreaks.upper_bound(static_cast<SCCOL>(nStartCol + nSize - 1));
381  maColManualBreaks.erase(itr1, itr2);
382 
383  // Copy all breaks from the 1st element up to nStartCol to the new container.
384  itr1 = maColManualBreaks.lower_bound(nStartCol);
385  ::std::set<SCCOL> aNewBreaks(maColManualBreaks.begin(), itr1);
386 
387  // Copy all breaks from nStartCol to the last element, but subtract each value by nSize.
388  itr2 = maColManualBreaks.end();
389  for (; itr1 != itr2; ++itr1)
390  aNewBreaks.insert(static_cast<SCCOL>(*itr1 - nSize));
391 
392  maColManualBreaks.swap(aNewBreaks);
393  }
394  }
395 
396  for (SCCOL col = nStartCol; col <= ClampToAllocatedColumns(nStartCol + nSize - 1); ++col)
397  aCol[col].DeleteArea(nStartRow, nEndRow, InsertDeleteFlags::ALL, false);
398 
399  if ((nStartRow == 0) && (nEndRow == rDocument.MaxRow()))
400  {
401  for (SCCOL nCol = nStartCol + nSize; nCol < aCol.size(); ++nCol)
402  aCol[nCol].SwapCol(aCol[nCol - nSize]);
403  }
404  else
405  {
406  for (SCSIZE i=0; static_cast<SCCOL>(i+nSize)+nStartCol < aCol.size(); i++)
407  aCol[nStartCol + nSize + i].MoveTo(nStartRow, nEndRow, aCol[nStartCol + i]);
408  }
409 
410  std::vector<SCCOL> aRegroupCols;
411  rRegroupCols.getColumns(nTab, aRegroupCols);
412  std::for_each(aRegroupCols.begin(), aRegroupCols.end(), ColumnRegroupFormulaCells(aCol, nullptr));
413 
415 
416  // TODO: In the future we may want to check if the table has been
417  // really modified before setting the stream invalid.
418  SetStreamValid(false);
419 }
420 
422  SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, InsertDeleteFlags nDelFlag,
423  bool bBroadcast, sc::ColumnSpanSet* pBroadcastSpans )
424 {
425  if ( nCol2 >= aCol.size() ) nCol2 = aCol.size() - 1;
426  if (nRow2 > rDocument.MaxRow()) nRow2 = rDocument.MaxRow();
427  if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
428  {
429  { // scope for bulk broadcast
430  ScBulkBroadcast aBulkBroadcast( rDocument.GetBASM(), SfxHintId::ScDataChanged);
431  for (SCCOL i = nCol1; i <= nCol2; i++)
432  aCol[i].DeleteArea(nRow1, nRow2, nDelFlag, bBroadcast, pBroadcastSpans);
433  }
434 
435  // Do not set protected cell in a protected table
436 
437  if ( IsProtected() && (nDelFlag & InsertDeleteFlags::ATTRIB) )
438  {
439  ScPatternAttr aPattern(rDocument.GetPool());
440  aPattern.GetItemSet().Put( ScProtectionAttr( false ) );
441  ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern );
442  }
443 
444  if( nDelFlag & InsertDeleteFlags::ATTRIB )
445  mpCondFormatList->DeleteArea( nCol1, nRow1, nCol2, nRow2 );
446  }
447 
448  // TODO: In the future we may want to check if the table has been
449  // really modified before setting the stream invalid.
450  SetStreamValid(false);
451 }
452 
453 void ScTable::DeleteSelection( InsertDeleteFlags nDelFlag, const ScMarkData& rMark, bool bBroadcast )
454 {
455  { // scope for bulk broadcast
456  ScBulkBroadcast aBulkBroadcast( rDocument.GetBASM(), SfxHintId::ScDataChanged);
457  for (SCCOL i=0; i < aCol.size(); i++)
458  aCol[i].DeleteSelection(nDelFlag, rMark, bBroadcast);
459  }
460 
461  ScRangeList aRangeList;
462  rMark.FillRangeListWithMarks(&aRangeList, false);
463 
464  for (size_t i = 0; i < aRangeList.size(); ++i)
465  {
466  const ScRange & rRange = aRangeList[i];
467 
468  if((nDelFlag & InsertDeleteFlags::ATTRIB) && rRange.aStart.Tab() == nTab)
469  mpCondFormatList->DeleteArea( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row() );
470  }
471 
472  // Do not set protected cell in a protected sheet
473 
474  if ( IsProtected() && (nDelFlag & InsertDeleteFlags::ATTRIB) )
475  {
476  ScDocumentPool* pPool = rDocument.GetPool();
478  aSet.Put( ScProtectionAttr( false ) );
479  SfxItemPoolCache aCache( pPool, &aSet );
480  ApplySelectionCache( &aCache, rMark );
481  }
482 
483  // TODO: In the future we may want to check if the table has been
484  // really modified before setting the stream invalid.
485  SetStreamValid(false);
486 }
487 
488 // pTable = Clipboard
490  sc::CopyToClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
491  ScTable* pTable )
492 {
493  if (!ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2))
494  return;
495 
496  // copy content
497  //local range names need to be copied first for formula cells
498  if (!pTable->mpRangeName && mpRangeName)
499  pTable->mpRangeName.reset( new ScRangeName(*mpRangeName) );
500 
501  nCol2 = ClampToAllocatedColumns(nCol2);
502 
503  for ( SCCOL i = nCol1; i <= nCol2; i++)
504  aCol[i].CopyToClip(rCxt, nRow1, nRow2, pTable->CreateColumnIfNotExists(i)); // notes are handled at column level
505 
506  // copy widths/heights, and only "hidden", "filtered" and "manual" flags
507  // also for all preceding columns/rows, to have valid positions for drawing objects
508 
509  if (mpColWidth && pTable->mpColWidth)
510  pTable->mpColWidth->CopyFrom(*mpColWidth, 0, nCol2);
511 
512  pTable->CopyColHidden(*this, 0, nCol2);
513  pTable->CopyColFiltered(*this, 0, nCol2);
514  if (pDBDataNoName)
515  pTable->SetAnonymousDBData(std::unique_ptr<ScDBData>(new ScDBData(*pDBDataNoName)));
516 
517  if (pRowFlags && pTable->pRowFlags && mpRowHeights && pTable->mpRowHeights)
518  {
519  pTable->pRowFlags->CopyFromAnded( *pRowFlags, 0, nRow2, CRFlags::ManualSize);
520  pTable->CopyRowHeight(*this, 0, nRow2, 0);
521  }
522 
523  pTable->CopyRowHidden(*this, 0, nRow2);
524  pTable->CopyRowFiltered(*this, 0, nRow2);
525 
526  // If necessary replace formulas with values
527 
528  if ( IsProtected() )
529  for (SCCOL i = nCol1; i <= nCol2; i++)
530  pTable->aCol[i].RemoveProtected(nRow1, nRow2);
531 
533 }
534 
536  sc::CopyToClipContext& rCxt, const ScRangeList& rRanges, ScTable* pTable )
537 {
538  for ( size_t i = 0, nListSize = rRanges.size(); i < nListSize; ++i )
539  {
540  const ScRange & r = rRanges[ i ];
541  CopyToClip( rCxt, r.aStart.Col(), r.aStart.Row(), r.aEnd.Col(), r.aEnd.Row(), pTable);
542  }
543 }
544 
546  SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const SvNumberFormatterMergeMap& rMap, ScTable* pDestTab )
547 {
548  if (nCol1 > nCol2 || nRow1 > nRow2)
549  return;
550 
551  const SCCOL nFirstUnallocated = std::clamp<SCCOL>(GetAllocatedColumnsCount(), nCol1, nCol2 + 1);
552  if (nFirstUnallocated > nCol1)
553  pDestTab->CreateColumnIfNotExists(nFirstUnallocated - 1);
554 
555  for (SCCOL i = nCol1; i < nFirstUnallocated; ++i)
556  {
557  ScColumn& rSrcCol = aCol[i];
558  ScColumn& rDestCol = pDestTab->aCol[i];
559  rSrcCol.CopyStaticToDocument(nRow1, nRow2, rMap, rDestCol);
560  }
561 
562  // Maybe copy this table's default attrs to dest not limiting to already allocated in dest?
563  const SCCOL nLastInDest = std::min<SCCOL>(pDestTab->GetAllocatedColumnsCount() - 1, nCol2);
564  for (SCCOL i = nFirstUnallocated; i <= nLastInDest; ++i)
565  {
566  ScColumn& rDestCol = pDestTab->aCol[i];
567  rDestCol.maCellTextAttrs.set_empty(nRow1, nRow2);
568  rDestCol.maCells.set_empty(nRow1, nRow2);
569  for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
570  {
571  sal_uInt32 nNumFmt = aDefaultColData.GetPattern(nRow)->GetNumberFormat(
573  SvNumberFormatterMergeMap::const_iterator itNum = rMap.find(nNumFmt);
574  if (itNum != rMap.end())
575  nNumFmt = itNum->second;
576 
577  rDestCol.SetNumberFormat(nRow, nNumFmt);
578  }
579  rDestCol.CellStorageModified();
580  }
581 }
582 
583 void ScTable::CopyCellToDocument(SCCOL nSrcCol, SCROW nSrcRow, SCCOL nDestCol, SCROW nDestRow, ScTable& rDestTab )
584 {
585  if (!ValidColRow(nSrcCol, nSrcRow) || !ValidColRow(nDestCol, nDestRow))
586  return;
587 
588  if (nSrcCol >= GetAllocatedColumnsCount())
589  {
590  if (nDestCol < rDestTab.GetAllocatedColumnsCount())
591  {
592  ScColumn& rDestCol = rDestTab.aCol[nDestCol];
593  rDestCol.maCells.set_empty(nDestRow, nDestRow);
594  rDestCol.maCellTextAttrs.set_empty(nDestRow, nDestRow);
595  rDestCol.maCellNotes.set_empty(nDestRow, nDestRow);
596  rDestCol.CellStorageModified();
597  }
598  return;
599  }
600 
601  ScColumn& rSrcCol = aCol[nSrcCol];
602  ScColumn& rDestCol = rDestTab.CreateColumnIfNotExists(nDestCol);
603  rSrcCol.CopyCellToDocument(nSrcRow, nDestRow, rDestCol);
604 }
605 
606 namespace {
607 
608 bool CheckAndDeduplicateCondFormat(ScDocument& rDocument, ScConditionalFormat* pOldFormat, const ScConditionalFormat* pNewFormat, SCTAB nTab)
609 {
610  if (!pOldFormat)
611  return false;
612 
613  if (pOldFormat->EqualEntries(*pNewFormat, true))
614  {
615  const ScRangeList& rNewRangeList = pNewFormat->GetRange();
616  ScRangeList& rDstRangeList = pOldFormat->GetRangeList();
617  for (size_t i = 0; i < rNewRangeList.size(); ++i)
618  {
619  rDstRangeList.Join(rNewRangeList[i]);
620  }
621  rDocument.AddCondFormatData(rNewRangeList, nTab, pOldFormat->GetKey());
622  return true;
623  }
624 
625  return false;
626 }
627 
628 }
629 
630 void ScTable::CopyConditionalFormat( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
631  SCCOL nDx, SCROW nDy, const ScTable* pTable)
632 {
633  ScRange aOldRange( nCol1 - nDx, nRow1 - nDy, pTable->nTab, nCol2 - nDx, nRow2 - nDy, pTable->nTab);
634  ScRange aNewRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
635  bool bSameDoc = rDocument.GetStyleSheetPool() == pTable->rDocument.GetStyleSheetPool();
636 
637  for(const auto& rxCondFormat : *pTable->mpCondFormatList)
638  {
639  const ScRangeList& rCondFormatRange = rxCondFormat->GetRange();
640  if(!rCondFormatRange.Intersects( aOldRange ))
641  continue;
642 
643  ScRangeList aIntersectedRange = rCondFormatRange.GetIntersectedRange(aOldRange);
644  std::unique_ptr<ScConditionalFormat> pNewFormat = rxCondFormat->Clone(&rDocument);
645 
646  pNewFormat->SetRange(aIntersectedRange);
647  sc::RefUpdateContext aRefCxt(rDocument);
648  aRefCxt.meMode = URM_COPY;
649  aRefCxt.maRange = aNewRange;
650  aRefCxt.mnColDelta = nDx;
651  aRefCxt.mnRowDelta = nDy;
652  aRefCxt.mnTabDelta = nTab - pTable->nTab;
653  pNewFormat->UpdateReference(aRefCxt, true);
654 
655  if (bSameDoc && pTable->nTab == nTab && CheckAndDeduplicateCondFormat(rDocument, mpCondFormatList->GetFormat(rxCondFormat->GetKey()), pNewFormat.get(), nTab))
656  {
657  continue;
658  }
659  sal_uLong nMax = 0;
660  bool bDuplicate = false;
661  for(const auto& rxCond : *mpCondFormatList)
662  {
663  // Check if there is the same format in the destination
664  // If there is, then simply expand its range
665  if (CheckAndDeduplicateCondFormat(rDocument, rxCond.get(), pNewFormat.get(), nTab))
666  {
667  bDuplicate = true;
668  break;
669  }
670 
671  if (rxCond->GetKey() > nMax)
672  nMax = rxCond->GetKey();
673  }
674  // Do not add duplicate entries
675  if (bDuplicate)
676  {
677  continue;
678  }
679 
680  pNewFormat->SetKey(nMax + 1);
681  auto pNewFormatTmp = pNewFormat.get();
682  mpCondFormatList->InsertNew(std::move(pNewFormat));
683 
684  if(!bSameDoc)
685  {
686  for(size_t i = 0, n = pNewFormatTmp->size();
687  i < n; ++i)
688  {
689  OUString aStyleName;
690  const ScFormatEntry* pEntry = pNewFormatTmp->GetEntry(i);
691  if(pEntry->GetType() == ScFormatEntry::Type::Condition ||
693  aStyleName = static_cast<const ScCondFormatEntry*>(pEntry)->GetStyle();
694  else if(pEntry->GetType() == ScFormatEntry::Type::Date)
695  aStyleName = static_cast<const ScCondDateFormatEntry*>(pEntry)->GetStyleName();
696 
697  if(!aStyleName.isEmpty())
698  {
699  if(rDocument.GetStyleSheetPool()->Find(aStyleName, SfxStyleFamily::Para))
700  continue;
701 
702  rDocument.GetStyleSheetPool()->CopyStyleFrom(
703  pTable->rDocument.GetStyleSheetPool(), aStyleName, SfxStyleFamily::Para );
704  }
705  }
706  }
707 
708  rDocument.AddCondFormatData( pNewFormatTmp->GetRange(), nTab, pNewFormatTmp->GetKey() );
709  }
710 }
711 
713 {
714  if (!ValidCol(nCol))
715  return false;
716 
718  return true;
719 }
720 
721 // pTable is source
722 
724  sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
725  SCCOL nDx, SCROW nDy, ScTable* pTable )
726 {
727  if (nCol2 > rDocument.MaxCol())
728  nCol2 = rDocument.MaxCol();
729  if (nRow2 > rDocument.MaxRow())
730  nRow2 = rDocument.MaxRow();
731 
732  if (!(ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2)))
733  return;
734 
736  for ( SCCOL i = nCol1; i <= nCol2; i++)
737  {
738  pTable->CreateColumnIfNotExists(i - nDx);
739  aCol[i].CopyFromClip(rCxt, nRow1, nRow2, nDy, pTable->aCol[i - nDx]); // notes are handles at column level
740  }
741 
743  {
744  // make sure that there are no old references to the cond formats
745  sal_uInt16 nWhichArray[2];
746  nWhichArray[0] = ATTR_CONDITIONAL;
747  nWhichArray[1] = 0;
748  for ( SCCOL i = nCol1; i <= nCol2; ++i)
749  aCol[i].ClearItems(nRow1, nRow2, nWhichArray);
750  }
751 
753  return;
754 
755  if (nRow1==0 && nRow2==rDocument.MaxRow() && mpColWidth && pTable->mpColWidth)
756  mpColWidth->CopyFrom(*pTable->mpColWidth, nCol1, nCol2, nCol1 - nDx);
757 
758  if (nCol1==0 && nCol2==rDocument.MaxCol() && mpRowHeights && pTable->mpRowHeights &&
759  pRowFlags && pTable->pRowFlags)
760  {
761  CopyRowHeight(*pTable, nRow1, nRow2, -nDy);
762  // Must copy CRFlags::ManualSize bit too, otherwise pRowHeight doesn't make sense
763  for (SCROW j=nRow1; j<=nRow2; j++)
764  {
765  if ( pTable->pRowFlags->GetValue(j-nDy) & CRFlags::ManualSize )
766  pRowFlags->OrValue( j, CRFlags::ManualSize);
767  else
768  pRowFlags->AndValue( j, ~CRFlags::ManualSize);
769  }
770  }
771 
772  // Do not set protected cell in a protected sheet
774  {
775  ScPatternAttr aPattern(rDocument.GetPool());
776  aPattern.GetItemSet().Put( ScProtectionAttr( false ) );
777  ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern );
778  }
779 
780  // create deep copies for conditional formatting
781  CopyConditionalFormat( nCol1, nRow1, nCol2, nRow2, nDx, nDy, pTable);
782 }
783 
785  sc::MixDocContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
786  ScPasteFunc nFunction, bool bSkipEmpty, const ScTable* pSrcTab )
787 {
788  for (SCCOL i=nCol1; i<=nCol2; i++)
789  aCol[i].MixData(rCxt, nRow1, nRow2, nFunction, bSkipEmpty, pSrcTab->aCol[i]);
790 }
791 
792 // Selection form this document
794  sc::MixDocContext& rCxt, const ScMarkData& rMark, ScPasteFunc nFunction,
795  bool bSkipEmpty, const ScTable* pSrcTab )
796 {
797  for (SCCOL i=0; i < aCol.size(); i++)
798  aCol[i].MixMarked(rCxt, rMark, nFunction, bSkipEmpty, pSrcTab->aCol[i]);
799 }
800 
801 namespace {
802 
803 class TransClipHandler
804 {
805  ScTable& mrClipTab;
806  const ScTable& mrSrcTab;
807  SCTAB mnSrcTab;
808  SCCOL mnCol1;
809  SCCOL mnSrcCol;
810  size_t mnTopRow;
811  size_t mnEndRow;
812  SCROW mnTransRow;
813  SCROW mnFilteredRows = 0;
814  SCROW mnRowDestOffset = 0;
815  bool mbAsLink;
816  bool mbWasCut;
817  bool mbIncludeFiltered;
819 
820  ScAddress getDestPos(size_t nRow) const
821  {
822  return ScAddress(static_cast<SCCOL>(mnCol1 + nRow - mnTopRow), mnTransRow,
823  mrClipTab.GetTab());
824  }
825 
826  ScFormulaCell* createRefCell(size_t nSrcRow, const ScAddress& rDestPos) const
827  {
828  ScAddress aSrcPos(mnSrcCol, nSrcRow, mnSrcTab);
829  ScSingleRefData aRef;
830  aRef.InitAddress(aSrcPos); // Absolute reference.
831  aRef.SetFlag3D(true);
832 
833  ScTokenArray aArr(mrClipTab.GetDoc());
834  aArr.AddSingleReference(aRef);
835  return new ScFormulaCell(mrClipTab.GetDoc(), rDestPos, aArr);
836  }
837 
838  void setLink(size_t nRow)
839  {
840  SCCOL nTransCol = mnCol1 + nRow - mnTopRow - mnFilteredRows + mnRowDestOffset;
841  mrClipTab.SetFormulaCell(nTransCol, mnTransRow,
842  createRefCell(nRow, getDestPos(nRow)));
843  }
844 
845 public:
846  TransClipHandler(ScTable& rClipTab, const ScTable& rSrcTab, SCTAB nSrcTab, SCCOL nCol1,
847  SCCOL nSrcCol, size_t nTopRow, size_t nEndRow, SCROW nCombinedStartRow,
848  SCROW nRowDestOffset, bool bAsLink, bool bWasCut,
849  const InsertDeleteFlags& nFlags, const bool bIncludeFiltered,
850  std::vector<SCROW>& rFilteredRows)
851  : mrClipTab(rClipTab)
852  , mrSrcTab(rSrcTab)
853  , mnSrcTab(nSrcTab)
854  , mnCol1(nCol1)
855  , mnSrcCol(nSrcCol)
856  , mnTopRow(nTopRow)
857  , mnEndRow(nEndRow)
858  , mnTransRow(nSrcCol - nCol1 + nCombinedStartRow)
859  , mnRowDestOffset(nRowDestOffset)
860  , mbAsLink(bAsLink)
861  , mbWasCut(bWasCut)
862  , mbIncludeFiltered(bIncludeFiltered)
863  , mnFlags(nFlags)
864  {
865  // Create list of filtered rows.
866  if (!mbIncludeFiltered)
867  {
868  for (SCROW curRow = nTopRow; curRow <= static_cast<SCROW>(mnEndRow); ++curRow)
869  {
870  // maybe this loop could be optimized
871  bool bFiltered = mrSrcTab.RowFiltered(curRow, nullptr, nullptr);
872  if (bFiltered)
873  rFilteredRows.push_back(curRow);
874  }
875  }
876  }
877 
878  void operator() (size_t nRow, double fVal)
879  {
880  bool bFiltered = mrSrcTab.RowFiltered(nRow, nullptr, nullptr);
881  if (!mbIncludeFiltered && bFiltered)
882  {
883  mnFilteredRows++;
884  return;
885  }
886 
887  if (mbAsLink)
888  {
889  setLink(nRow);
890  return;
891  }
892 
893  SCCOL nTransCol = mnCol1 + nRow - mnTopRow - mnFilteredRows + mnRowDestOffset;
894  mrClipTab.SetValue(nTransCol, mnTransRow, fVal);
895  }
896 
897  void operator() (size_t nRow, const svl::SharedString& rStr)
898  {
899  bool bFiltered = mrSrcTab.RowFiltered(nRow, nullptr, nullptr);
900  if (!mbIncludeFiltered && bFiltered)
901  {
902  mnFilteredRows++;
903  return;
904  }
905 
906  if (mbAsLink)
907  {
908  setLink(nRow);
909  return;
910  }
911 
912  SCCOL nTransCol = mnCol1 + nRow - mnTopRow - mnFilteredRows + mnRowDestOffset;
913  mrClipTab.SetRawString(nTransCol, mnTransRow, rStr);
914  }
915 
916  void operator() (size_t nRow, const EditTextObject* p)
917  {
918  bool bFiltered = mrSrcTab.RowFiltered(nRow, nullptr, nullptr);
919  if (!mbIncludeFiltered && bFiltered)
920  {
921  mnFilteredRows++;
922  return;
923  }
924 
925  if (mbAsLink)
926  {
927  setLink(nRow);
928  return;
929  }
930 
931  SCCOL nTransCol = mnCol1 + nRow - mnTopRow - mnFilteredRows + mnRowDestOffset;
932  mrClipTab.SetEditText(nTransCol, mnTransRow, ScEditUtil::Clone(*p, mrClipTab.GetDoc()));
933  }
934 
935  void operator() (size_t nRow, const ScFormulaCell* p)
936  {
937  bool bFiltered = mrSrcTab.RowFiltered(nRow, nullptr, nullptr);
938  if (!mbIncludeFiltered && bFiltered)
939  {
940  mnFilteredRows++;
941  return;
942  }
943 
944  if (mbAsLink)
945  {
946  setLink(nRow);
947  return;
948  }
949 
950  ScFormulaCell* pNew = new ScFormulaCell(*p, mrClipTab.GetDoc(),
951  getDestPos(nRow - mnFilteredRows + mnRowDestOffset),
953 
954  // rotate reference
955  // for Cut, the references are later adjusted through UpdateTranspose
956 
957  if (!mbWasCut)
958  pNew->TransposeReference();
959 
960  SCCOL nTransCol = mnCol1 + nRow - mnTopRow - mnFilteredRows + mnRowDestOffset;
961  mrClipTab.SetFormulaCell(nTransCol, mnTransRow, pNew);
962  }
963 
964  // empty cells
965  void operator()(const int /*type*/, size_t nRow, size_t nDataSize)
966  {
967  for (size_t curRow = nRow; curRow < nRow + nDataSize; ++curRow)
968  {
969  bool bFiltered = mrSrcTab.RowFiltered(curRow, nullptr, nullptr);
970  if (!mbIncludeFiltered && bFiltered)
971  {
972  mnFilteredRows++;
973  continue;
974  }
975 
976  if (mbAsLink && mnFlags == InsertDeleteFlags::ALL)
977  {
978  // with InsertDeleteFlags::ALL, also create links (formulas) for empty cells
979  setLink(nRow);
980  continue;
981  }
982  }
983  }
984 };
985 }
986 
987 void ScTable::TransposeClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
988  SCROW nCombinedStartRow, SCROW nRowDestOffset, ScTable* pTransClip,
989  InsertDeleteFlags nFlags, bool bAsLink, bool bIncludeFiltered)
990 {
991  bool bWasCut = rDocument.IsCutMode();
992 
993  for (SCCOL nCol=nCol1; nCol<=nCol2; nCol++)
994  {
995  std::vector<SCROW> aFilteredRows;
996 
997  TransClipHandler aFunc(*pTransClip, *this, nTab, nCol1, nCol, nRow1, nRow2,
998  nCombinedStartRow, nRowDestOffset, bAsLink, bWasCut, nFlags,
999  bIncludeFiltered, aFilteredRows);
1000 
1001  const sc::CellStoreType& rCells = aCol[nCol].maCells;
1002 
1003  // Loop through all rows by iterator and call aFunc operators
1004  sc::ParseAll(rCells.begin(), rCells, nRow1, nRow2, aFunc,
1005  aFunc);
1006 
1007  // Attributes
1008  if (nFlags & InsertDeleteFlags::ATTRIB)
1009  TransposeColPatterns(pTransClip, nCol1, nCol, nRow1, nRow2, nCombinedStartRow,
1010  bIncludeFiltered, aFilteredRows, nRowDestOffset);
1011 
1012  // Cell Notes - fdo#68381 paste cell notes on Transpose
1013  if ((nFlags & InsertDeleteFlags::NOTE) && rDocument.HasColNotes(nCol, nTab))
1014  TransposeColNotes(pTransClip, nCol1, nCol, nRow1, nRow2, nCombinedStartRow,
1015  bIncludeFiltered, nRowDestOffset);
1016  }
1017 }
1018 
1019 static void lcl_SetTransposedPatternInRows(ScTable* pTransClip, SCROW nAttrRow1, SCROW nAttrRow2,
1020  SCCOL nCol1, SCROW nRow1, SCROW nCombinedStartRow, SCCOL nCol,
1021  const ScPatternAttr& rPatternAttr, bool bIncludeFiltered,
1022  const std::vector<SCROW>& rFilteredRows,
1023  SCROW nRowDestOffset)
1024 {
1025  for (SCROW nRow = nAttrRow1; nRow <= nAttrRow2; nRow++)
1026  {
1027  size_t nFilteredRowAdjustment = 0;
1028  if (!bIncludeFiltered)
1029  {
1030  // aFilteredRows is sorted thus lower_bound() can be used.
1031  // lower_bound() has a logarithmic complexity O(log(n))
1032  auto itRow1 = std::lower_bound(rFilteredRows.begin(), rFilteredRows.end(), nRow1);
1033  auto itRow = std::lower_bound(rFilteredRows.begin(), rFilteredRows.end(), nRow);
1034  bool bRefRowIsFiltered = itRow != rFilteredRows.end() && *itRow == nRow;
1035  if (bRefRowIsFiltered)
1036  continue;
1037 
1038  // How many filtered rows are between the formula cell and the reference?
1039  // distance() has a constant complexity O(1) for vectors
1040  nFilteredRowAdjustment = std::distance(itRow1, itRow);
1041  }
1042 
1043  pTransClip->SetPattern(
1044  static_cast<SCCOL>(nCol1 + nRow - nRow1 - nFilteredRowAdjustment + nRowDestOffset),
1045  static_cast<SCROW>(nCombinedStartRow + nCol - nCol1), rPatternAttr);
1046  }
1047 }
1048 
1049 void ScTable::TransposeColPatterns(ScTable* pTransClip, SCCOL nCol1, SCCOL nCol, SCROW nRow1,
1050  SCROW nRow2, SCROW nCombinedStartRow, bool bIncludeFiltered,
1051  const std::vector<SCROW>& rFilteredRows, SCROW nRowDestOffset)
1052 {
1053  SCROW nAttrRow1 = {}; // spurious -Werror=maybe-uninitialized
1054  SCROW nAttrRow2 = {}; // spurious -Werror=maybe-uninitialized
1055  const ScPatternAttr* pPattern;
1056  std::unique_ptr<ScAttrIterator> pAttrIter(aCol[nCol].CreateAttrIterator( nRow1, nRow2 ));
1057  while ( (pPattern = pAttrIter->Next( nAttrRow1, nAttrRow2 )) != nullptr )
1058  {
1059  if ( !IsDefaultItem( pPattern ) )
1060  {
1061  const SfxItemSet& rSet = pPattern->GetItemSet();
1062  if ( rSet.GetItemState( ATTR_MERGE, false ) == SfxItemState::DEFAULT &&
1063  rSet.GetItemState( ATTR_MERGE_FLAG, false ) == SfxItemState::DEFAULT &&
1064  rSet.GetItemState( ATTR_BORDER, false ) == SfxItemState::DEFAULT )
1065  {
1066  // Set pattern in cells from nAttrRow1 to nAttrRow2
1067  // no borders or merge items involved - use pattern as-is
1068  lcl_SetTransposedPatternInRows(pTransClip, nAttrRow1, nAttrRow2, nCol1, nRow1,
1069  nCombinedStartRow, nCol, *pPattern,
1070  bIncludeFiltered, rFilteredRows, nRowDestOffset);
1071  }
1072  else
1073  {
1074  // transpose borders and merge values, remove merge flags (refreshed after pasting)
1075  ScPatternAttr aNewPattern( *pPattern );
1076  SfxItemSet& rNewSet = aNewPattern.GetItemSet();
1077 
1078  const SvxBoxItem& rOldBox = rSet.Get(ATTR_BORDER);
1079  if ( rOldBox.GetTop() || rOldBox.GetBottom() || rOldBox.GetLeft() || rOldBox.GetRight() )
1080  {
1081  SvxBoxItem aNew( ATTR_BORDER );
1082  aNew.SetLine( rOldBox.GetLine( SvxBoxItemLine::TOP ), SvxBoxItemLine::LEFT );
1083  aNew.SetLine( rOldBox.GetLine( SvxBoxItemLine::LEFT ), SvxBoxItemLine::TOP );
1084  aNew.SetLine( rOldBox.GetLine( SvxBoxItemLine::BOTTOM ), SvxBoxItemLine::RIGHT );
1085  aNew.SetLine( rOldBox.GetLine( SvxBoxItemLine::RIGHT ), SvxBoxItemLine::BOTTOM );
1086  aNew.SetDistance( rOldBox.GetDistance( SvxBoxItemLine::TOP ), SvxBoxItemLine::LEFT );
1087  aNew.SetDistance( rOldBox.GetDistance( SvxBoxItemLine::LEFT ), SvxBoxItemLine::TOP );
1088  aNew.SetDistance( rOldBox.GetDistance( SvxBoxItemLine::BOTTOM ), SvxBoxItemLine::RIGHT );
1089  aNew.SetDistance( rOldBox.GetDistance( SvxBoxItemLine::RIGHT ), SvxBoxItemLine::BOTTOM );
1090  rNewSet.Put( aNew );
1091  }
1092 
1093  const ScMergeAttr& rOldMerge = rSet.Get(ATTR_MERGE);
1094  if (rOldMerge.IsMerged())
1095  rNewSet.Put( ScMergeAttr( std::min(
1096  static_cast<SCCOL>(rOldMerge.GetRowMerge()),
1097  static_cast<SCCOL>(rDocument.MaxCol()+1 - (nAttrRow2-nRow1))),
1098  std::min(
1099  static_cast<SCROW>(rOldMerge.GetColMerge()),
1100  static_cast<SCROW>(rDocument.MaxRow()+1 - (nCol-nCol1)))));
1101  const ScMergeFlagAttr& rOldFlag = rSet.Get(ATTR_MERGE_FLAG);
1102  if (rOldFlag.IsOverlapped())
1103  {
1104  ScMF nNewFlags = rOldFlag.GetValue() & ~ScMF( ScMF::Hor | ScMF::Ver );
1105  if ( nNewFlags != ScMF::NONE )
1106  rNewSet.Put( ScMergeFlagAttr( nNewFlags ) );
1107  else
1108  rNewSet.ClearItem( ATTR_MERGE_FLAG );
1109  }
1110 
1111  // Set pattern in cells from nAttrRow1 to nAttrRow2
1112  lcl_SetTransposedPatternInRows(pTransClip, nAttrRow1, nAttrRow2, nCol1, nRow1,
1113  nCombinedStartRow, nCol, aNewPattern,
1114  bIncludeFiltered, rFilteredRows, nRowDestOffset);
1115  }
1116  }
1117  }
1118 }
1119 
1120 void ScTable::TransposeColNotes(ScTable* pTransClip, SCCOL nCol1, SCCOL nCol, SCROW nRow1,
1121  SCROW nRow2, SCROW nCombinedStartRow, bool bIncludeFiltered,
1122  SCROW nRowDestOffset)
1123 {
1124  sc::CellNoteStoreType::const_iterator itBlk = aCol[nCol].maCellNotes.begin(), itBlkEnd = aCol[nCol].maCellNotes.end();
1125 
1126  // Locate the top row position.
1127  size_t nOffsetInBlock = 0;
1128  size_t nBlockStart = 0, nBlockEnd = 0, nRowPos = static_cast<size_t>(nRow1);
1129  for (; itBlk != itBlkEnd; ++itBlk, nBlockStart = nBlockEnd)
1130  {
1131  nBlockEnd = nBlockStart + itBlk->size;
1132  if (nBlockStart <= nRowPos && nRowPos < nBlockEnd)
1133  {
1134  // Found.
1135  nOffsetInBlock = nRowPos - nBlockStart;
1136  break;
1137  }
1138  }
1139 
1140  if (itBlk == itBlkEnd)
1141  // Specified range found
1142  return;
1143 
1144  nRowPos = static_cast<size_t>(nRow2); // End row position.
1145  SCCOL nFilteredRows = 0;
1146 
1147  // Keep processing until we hit the end row position.
1148  sc::cellnote_block::const_iterator itData, itDataEnd;
1149  for (; itBlk != itBlkEnd; ++itBlk, nBlockStart = nBlockEnd, nOffsetInBlock = 0)
1150  {
1151  nBlockEnd = nBlockStart + itBlk->size;
1152 
1153  if (itBlk->data)
1154  {
1155  itData = sc::cellnote_block::begin(*itBlk->data);
1156  std::advance(itData, nOffsetInBlock);
1157 
1158  // selected area is smaller than the iteration block
1159  if (nBlockStart <= nRowPos && nRowPos < nBlockEnd)
1160  {
1161  // This block contains the end row. Only process partially.
1162  size_t nOffsetEnd = nRowPos - nBlockStart + 1;
1163  itDataEnd = sc::cellnote_block::begin(*itBlk->data);
1164  std::advance(itDataEnd, nOffsetEnd);
1165  size_t curRow = nBlockStart + nOffsetInBlock;
1166  for (; itData != itDataEnd; ++itData, ++curRow)
1167  {
1168  bool bFiltered = this->RowFiltered(curRow, nullptr, nullptr);
1169  if (!bIncludeFiltered && bFiltered)
1170  {
1171  nFilteredRows++;
1172  continue;
1173  }
1174 
1175  ScAddress aDestPos(
1176  static_cast<SCCOL>(nCol1 + curRow - nRow1 - nFilteredRows + nRowDestOffset),
1177  static_cast<SCROW>(nCombinedStartRow + nCol - nCol1), pTransClip->nTab);
1178  pTransClip->rDocument.ReleaseNote(aDestPos);
1179  ScPostIt* pNote = *itData;
1180  if (pNote)
1181  {
1182  std::unique_ptr<ScPostIt> pClonedNote = pNote->Clone( ScAddress(nCol, curRow, nTab), pTransClip->rDocument, aDestPos, true );
1183  pTransClip->rDocument.SetNote(aDestPos, std::move(pClonedNote));
1184  }
1185  }
1186  break; // we reached the last valid block
1187  }
1188  else
1189  {
1190  itDataEnd = sc::cellnote_block::end(*itBlk->data);
1191  size_t curRow = nBlockStart + nOffsetInBlock;
1192  for (; itData != itDataEnd; ++itData, ++curRow)
1193  {
1194  bool bFiltered = this->RowFiltered(curRow, nullptr, nullptr);
1195  if (!bIncludeFiltered && bFiltered)
1196  {
1197  nFilteredRows++;
1198  continue;
1199  }
1200 
1201  ScAddress aDestPos(
1202  static_cast<SCCOL>(nCol1 + curRow - nRow1 - nFilteredRows + nRowDestOffset),
1203  static_cast<SCROW>(nCombinedStartRow + nCol - nCol1), pTransClip->nTab);
1204  pTransClip->rDocument.ReleaseNote(aDestPos);
1205  ScPostIt* pNote = *itData;
1206  if (pNote)
1207  {
1208  std::unique_ptr<ScPostIt> pClonedNote = pNote->Clone( ScAddress(nCol, curRow, nTab), pTransClip->rDocument, aDestPos, true );
1209  pTransClip->rDocument.SetNote(aDestPos, std::move(pClonedNote));
1210  }
1211  }
1212  }
1213  }
1214  else // remove dest notes for rows without notes
1215  {
1216  for (size_t curRow = nBlockStart + nOffsetInBlock;
1217  curRow <= nBlockEnd && curRow <= nRowPos; ++curRow)
1218  {
1219  bool bFiltered = this->RowFiltered(curRow, nullptr, nullptr);
1220  if (!bIncludeFiltered && bFiltered && curRow < nBlockEnd)
1221  {
1222  nFilteredRows++;
1223  continue;
1224  }
1225 
1226  ScAddress aDestPos(
1227  static_cast<SCCOL>(nCol1 + curRow - nRow1 - nFilteredRows + nRowDestOffset),
1228  static_cast<SCROW>(nCombinedStartRow + nCol - nCol1), pTransClip->nTab);
1229  pTransClip->rDocument.ReleaseNote(aDestPos);
1230  }
1231  }
1232  }
1233 }
1234 
1236 {
1237  if (!ValidCol(nCol))
1238  return nullptr;
1239 
1240  return &CreateColumnIfNotExists(nCol);
1241 }
1242 
1244 {
1245  if (!ValidCol(nCol) || nCol >= GetAllocatedColumnsCount())
1246  return nullptr;
1247 
1248  return &aCol[nCol];
1249 }
1250 
1252 {
1253  std::shared_ptr<const sc::ColumnSet> pColSet = rCxt.getColumnSet();
1254  if (!pColSet)
1255  {
1256  for (SCCOL i=0; i < aCol.size(); i++)
1257  aCol[i].StartListeners(rCxt, bAll);
1258  }
1259  else if (pColSet->hasTab( nTab))
1260  {
1261  std::vector<SCCOL> aColumns;
1262  pColSet->getColumns( nTab, aColumns);
1263  for (auto i : aColumns)
1264  {
1265  if (0 <= i && i < aCol.size())
1266  aCol[i].StartListeners(rCxt, bAll);
1267  }
1268  }
1269 }
1270 
1272  sc::StartListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
1273 {
1274  nCol2 = ClampToAllocatedColumns(nCol2);
1275  for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
1276  aCol[nCol].AttachFormulaCells(rCxt, nRow1, nRow2);
1277 }
1278 
1280  sc::EndListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
1281 {
1282  nCol2 = ClampToAllocatedColumns(nCol2);
1283  for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
1284  aCol[nCol].DetachFormulaCells(rCxt, nRow1, nRow2);
1285 }
1286 
1288  SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sc::ColumnSpanSet& rBroadcastSpans )
1289 {
1290  if ( nCol2 >= aCol.size() ) nCol2 = aCol.size() - 1;
1291  if (nCol2 > rDocument.MaxCol()) nCol2 = rDocument.MaxCol();
1292  if (nRow2 > rDocument.MaxRow()) nRow2 = rDocument.MaxRow();
1293  if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
1294  for (SCCOL i = nCol1; i <= nCol2; i++)
1295  aCol[i].SetDirtyFromClip(nRow1, nRow2, rBroadcastSpans);
1296 }
1297 
1300  SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
1301 {
1302  if ( nCol2 >= aCol.size() ) nCol2 = aCol.size() - 1;
1303  if (nCol2 > rDocument.MaxCol()) nCol2 = rDocument.MaxCol();
1304  if (nRow2 > rDocument.MaxRow()) nRow2 = rDocument.MaxRow();
1305  if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
1306  for (SCCOL i = nCol1; i <= nCol2; i++)
1307  aCol[i].StartListeningFormulaCells(rStartCxt, rEndCxt, nRow1, nRow2);
1308 }
1309 
1311  sc::CopyToDocContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1312  InsertDeleteFlags nFlags, bool bMarked, ScTable* pDestTab, const ScMarkData* pMarkData,
1313  bool bAsLink, bool bColRowFlags, bool bGlobalNamesToLocal, bool bCopyCaptions )
1314 {
1315  if (!ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2))
1316  return;
1317 
1318  bool bIsUndoDoc = pDestTab->rDocument.IsUndo();
1319 
1320  if (bIsUndoDoc && (nFlags & InsertDeleteFlags::CONTENTS))
1321  {
1322  // Copying formulas may create sheet-local named expressions on the
1323  // destination sheet. Add existing to Undo first.
1324  pDestTab->SetRangeName( std::unique_ptr<ScRangeName>( new ScRangeName( *GetRangeName())));
1325  }
1326 
1327  if (nFlags != InsertDeleteFlags::NONE)
1328  {
1329  InsertDeleteFlags nTempFlags( nFlags &
1331  // tdf#102364 - in some pathological cases CopyToTable() replacing cells with new cells
1332  // can lead to repetitive splitting and rejoining of the same formula group, which can get
1333  // quadratically expensive with large groups. So do the grouping just once at the end.
1334  sc::DelayFormulaGroupingSwitch delayGrouping( pDestTab->rDocument, true );
1335  for (SCCOL i = nCol1; i <= ClampToAllocatedColumns(nCol2); i++)
1336  aCol[i].CopyToColumn(rCxt, nRow1, nRow2, bIsUndoDoc ? nFlags : nTempFlags, bMarked,
1337  pDestTab->CreateColumnIfNotExists(i), pMarkData, bAsLink, bGlobalNamesToLocal);
1338  }
1339 
1340  if (!bColRowFlags) // Column widths/Row heights/Flags
1341  return;
1342 
1343  if(bIsUndoDoc && (nFlags & InsertDeleteFlags::ATTRIB))
1344  {
1345  pDestTab->mpCondFormatList.reset(new ScConditionalFormatList(pDestTab->rDocument, *mpCondFormatList));
1346  }
1347 
1348  if (pDBDataNoName)
1349  {
1350  std::unique_ptr<ScDBData> pNewDBData(new ScDBData(*pDBDataNoName));
1351  SCCOL aCol1, aCol2;
1352  SCROW aRow1, aRow2;
1353  SCTAB aTab;
1354  pNewDBData->GetArea(aTab, aCol1, aRow1, aCol2, aRow2);
1355  pNewDBData->MoveTo(pDestTab->nTab, aCol1, aRow1, aCol2, aRow2);
1356  pDestTab->SetAnonymousDBData(std::move(pNewDBData));
1357  }
1358  // Charts have to be adjusted when hide/show
1360 
1361  bool bFlagChange = false;
1362 
1363  bool bWidth = (nRow1==0 && nRow2==rDocument.MaxRow() && mpColWidth && pDestTab->mpColWidth);
1364  bool bHeight = (nCol1==0 && nCol2==rDocument.MaxCol() && mpRowHeights && pDestTab->mpRowHeights);
1365 
1366  if (bWidth || bHeight)
1367  {
1368  if (bWidth)
1369  {
1370  auto destTabColWidthIt = pDestTab->mpColWidth->begin() + nCol1;
1371  auto thisTabColWidthIt = mpColWidth->begin() + nCol1;
1372  pDestTab->mpColWidth->CopyFrom(*mpColWidth, nCol1, nCol2);
1373  pDestTab->mpColFlags->CopyFrom(*mpColFlags, nCol1, nCol2);
1374  for (SCCOL i = nCol1; i <= nCol2; ++i)
1375  {
1376  bool bThisHidden = ColHidden(i);
1377  bool bHiddenChange = (pDestTab->ColHidden(i) != bThisHidden);
1378  bool bChange = bHiddenChange || (*destTabColWidthIt != *thisTabColWidthIt);
1379  pDestTab->SetColHidden(i, i, bThisHidden);
1380  //TODO: collect changes?
1381  if (bHiddenChange && pCharts)
1382  pCharts->SetRangeDirty(ScRange( i, 0, nTab, i, rDocument.MaxRow(), nTab ));
1383 
1384  if (bChange)
1385  bFlagChange = true;
1386 
1387  ++destTabColWidthIt;
1388  ++thisTabColWidthIt;
1389  }
1390  pDestTab->SetColManualBreaks( std::set(maColManualBreaks) );
1391  }
1392 
1393  if (bHeight)
1394  {
1395  bool bChange = pDestTab->GetRowHeight(nRow1, nRow2) != GetRowHeight(nRow1, nRow2);
1396 
1397  if (bChange)
1398  bFlagChange = true;
1399 
1400  pDestTab->CopyRowHeight(*this, nRow1, nRow2, 0);
1401  pDestTab->pRowFlags->CopyFrom(*pRowFlags, nRow1, nRow2);
1402 
1403  // Hidden flags.
1404  for (SCROW i = nRow1; i <= nRow2; ++i)
1405  {
1406  SCROW nLastRow;
1407  bool bHidden = RowHidden(i, nullptr, &nLastRow);
1408  if (nLastRow >= nRow2)
1409  // the last row shouldn't exceed the upper bound the caller specified.
1410  nLastRow = nRow2;
1411 
1412  bool bHiddenChanged = pDestTab->SetRowHidden(i, nLastRow, bHidden);
1413  if (bHiddenChanged && pCharts)
1414  // Hidden flags differ.
1415  pCharts->SetRangeDirty(ScRange(0, i, nTab, rDocument.MaxCol(), nLastRow, nTab));
1416 
1417  if (bHiddenChanged)
1418  bFlagChange = true;
1419 
1420  // Jump to the last row of the identical flag segment.
1421  i = nLastRow;
1422  }
1423 
1424  // Filtered flags.
1425  for (SCROW i = nRow1; i <= nRow2; ++i)
1426  {
1427  SCROW nLastRow;
1428  bool bFiltered = RowFiltered(i, nullptr, &nLastRow);
1429  if (nLastRow >= nRow2)
1430  // the last row shouldn't exceed the upper bound the caller specified.
1431  nLastRow = nRow2;
1432  pDestTab->SetRowFiltered(i, nLastRow, bFiltered);
1433  i = nLastRow;
1434  }
1435  pDestTab->SetRowManualBreaks( std::set(maRowManualBreaks) );
1436  }
1437  }
1438 
1439  if (bFlagChange)
1440  pDestTab->InvalidatePageBreaks();
1441 
1442  if(nFlags & InsertDeleteFlags::ATTRIB)
1443  {
1444  pDestTab->mpCondFormatList->DeleteArea(nCol1, nRow1, nCol2, nRow2);
1445  pDestTab->CopyConditionalFormat(nCol1, nRow1, nCol2, nRow2, 0, 0, this);
1446  }
1447 
1448  if(nFlags & InsertDeleteFlags::OUTLINE) // also only when bColRowFlags
1449  pDestTab->SetOutlineTable( pOutlineTable.get() );
1450 
1451  if (nFlags & InsertDeleteFlags::SPARKLINES)
1452  {
1453  CopySparklinesToTable(nCol1, nRow1, nCol2, nRow2, pDestTab);
1454  }
1455 
1456  if (!bIsUndoDoc && bCopyCaptions && (nFlags & (InsertDeleteFlags::NOTE | InsertDeleteFlags::ADDNOTES)))
1457  {
1458  bool bCloneCaption = (nFlags & InsertDeleteFlags::NOCAPTIONS) == InsertDeleteFlags::NONE;
1459  CopyCaptionsToTable( nCol1, nRow1, nCol2, nRow2, pDestTab, bCloneCaption);
1460  }
1461 }
1462 
1463 void ScTable::CopySparklinesToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScTable* pDestTab)
1464 {
1465  if (!ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2))
1466  return;
1467 
1468  nCol2 = ClampToAllocatedColumns(nCol2);
1469  for (SCCOL i = nCol1; i <= nCol2; i++)
1470  {
1471  aCol[i].CopyCellSparklinesToDocument(nRow1, nRow2, pDestTab->CreateColumnIfNotExists(i));
1472  }
1473 }
1474 
1475 void ScTable::CopyCaptionsToTable( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScTable* pDestTab,
1476  bool bCloneCaption )
1477 {
1478  if (!ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2))
1479  return;
1480 
1481  nCol2 = ClampToAllocatedColumns(nCol2);
1482  for (SCCOL i = nCol1; i <= nCol2; i++)
1483  {
1484  aCol[i].CopyCellNotesToDocument(nRow1, nRow2, pDestTab->CreateColumnIfNotExists(i), bCloneCaption);
1485  pDestTab->aCol[i].UpdateNoteCaptions(nRow1, nRow2);
1486  }
1487 }
1488 
1490  sc::CopyToDocContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1491  InsertDeleteFlags nFlags, bool bMarked, ScTable* pDestTab )
1492 {
1493  if (!(ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2)))
1494  return;
1495 
1496  bool bWidth = (nRow1==0 && nRow2==rDocument.MaxRow() && mpColWidth && pDestTab->mpColWidth);
1497  bool bHeight = (nCol1==0 && nCol2==rDocument.MaxCol() && mpRowHeights && pDestTab->mpRowHeights);
1498 
1499  if ((nFlags & InsertDeleteFlags::CONTENTS) && mpRangeName)
1500  {
1501  // Undo sheet-local named expressions created during copying
1502  // formulas. If mpRangeName is not set then the Undo wasn't even
1503  // set to an empty ScRangeName map so don't "undo" that.
1504  pDestTab->SetRangeName( std::unique_ptr<ScRangeName>( new ScRangeName( *GetRangeName())));
1505  if (!pDestTab->rDocument.IsClipOrUndo())
1506  {
1507  ScDocShell* pDocSh = static_cast<ScDocShell*>(pDestTab->rDocument.GetDocumentShell());
1508  if (pDocSh)
1509  pDocSh->SetAreasChangedNeedBroadcast();
1510  }
1511 
1512  }
1513 
1514  for ( SCCOL i = 0; i < aCol.size(); i++)
1515  {
1516  auto& rDestCol = pDestTab->CreateColumnIfNotExists(i);
1517  if ( i >= nCol1 && i <= nCol2 )
1518  aCol[i].UndoToColumn(rCxt, nRow1, nRow2, nFlags, bMarked, rDestCol);
1519  else
1520  aCol[i].CopyToColumn(rCxt, 0, rDocument.MaxRow(), InsertDeleteFlags::FORMULA, false, rDestCol);
1521  }
1522 
1523  if (nFlags & InsertDeleteFlags::ATTRIB)
1524  pDestTab->mpCondFormatList.reset(new ScConditionalFormatList(pDestTab->rDocument, *mpCondFormatList));
1525 
1526  if (!(bWidth||bHeight))
1527  return;
1528 
1529  if (bWidth)
1530  {
1531  pDestTab->mpColWidth->CopyFrom(*mpColWidth, nCol1, nCol2);
1532  pDestTab->SetColManualBreaks( std::set(maColManualBreaks) );
1533  }
1534  if (bHeight)
1535  {
1536  pDestTab->CopyRowHeight(*this, nRow1, nRow2, 0);
1537  pDestTab->SetRowManualBreaks( std::set(maRowManualBreaks) );
1538  }
1539 }
1540 
1541 void ScTable::CopyUpdated( const ScTable* pPosTab, ScTable* pDestTab ) const
1542 {
1543  pDestTab->CreateColumnIfNotExists(aCol.size()-1);
1544  for (SCCOL i=0; i < aCol.size(); i++)
1545  aCol[i].CopyUpdated( pPosTab->FetchColumn(i), pDestTab->aCol[i] );
1546 }
1547 
1549 {
1550  bTableAreaValid = false;
1551  bTableAreaVisibleValid = false;
1552 }
1553 
1555 {
1556  mbPageBreaksValid = false;
1557 }
1558 
1559 void ScTable::CopyScenarioTo( ScTable* pDestTab ) const
1560 {
1561  OSL_ENSURE( bScenario, "bScenario == FALSE" );
1562 
1563  for (SCCOL i=0; i < aCol.size(); i++)
1565 }
1566 
1567 void ScTable::CopyScenarioFrom( const ScTable* pSrcTab )
1568 {
1569  OSL_ENSURE( bScenario, "bScenario == FALSE" );
1570 
1571  SCCOL nEndCol = pSrcTab->aCol.size();
1572  CreateColumnIfNotExists(nEndCol);
1573  for (SCCOL i=0; i < nEndCol; i++)
1574  aCol[i].CopyScenarioFrom( pSrcTab->aCol[i] );
1575 }
1576 
1577 void ScTable::MarkScenarioIn( ScMarkData& rDestMark, ScScenarioFlags nNeededBits ) const
1578 {
1579  OSL_ENSURE( bScenario, "bScenario == FALSE" );
1580 
1581  if ( ( nScenarioFlags & nNeededBits ) != nNeededBits ) // Are all Bits set?
1582  return;
1583 
1584  for (SCCOL i=0; i < aCol.size(); i++)
1585  aCol[i].MarkScenarioIn( rDestMark );
1586 }
1587 
1588 bool ScTable::HasScenarioRange( const ScRange& rRange ) const
1589 {
1590  OSL_ENSURE( bScenario, "bScenario == FALSE" );
1591 
1592  ScRange aTabRange = rRange;
1593  aTabRange.aStart.SetTab( nTab );
1594  aTabRange.aEnd.SetTab( nTab );
1595 
1596  const ScRangeList* pList = GetScenarioRanges();
1597 
1598  if (pList)
1599  {
1600  for ( size_t j = 0, n = pList->size(); j < n; j++ )
1601  {
1602  const ScRange & rR = (*pList)[j];
1603  if ( rR.Intersects( aTabRange ) )
1604  return true;
1605  }
1606  }
1607 
1608  return false;
1609 }
1610 
1612 {
1613  pScenarioRanges.reset();
1614 }
1615 
1617 {
1618  OSL_ENSURE( bScenario, "bScenario == FALSE" );
1619 
1620  if (!pScenarioRanges)
1621  {
1622  const_cast<ScTable*>(this)->pScenarioRanges.reset(new ScRangeList);
1623  ScMarkData aMark(rDocument.GetSheetLimits());
1624  MarkScenarioIn( aMark, ScScenarioFlags::NONE ); // always
1625  aMark.FillRangeListWithMarks( pScenarioRanges.get(), false );
1626  }
1627  return pScenarioRanges.get();
1628 }
1629 
1630 bool ScTable::TestCopyScenarioTo( const ScTable* pDestTab ) const
1631 {
1632  OSL_ENSURE( bScenario, "bScenario == FALSE" );
1633 
1634  if (!pDestTab->IsProtected())
1635  return true;
1636 
1637  bool bOk = true;
1638  for (SCCOL i=0; i < aCol.size() && bOk; i++)
1639  bOk = aCol[i].TestCopyScenarioTo( pDestTab->aCol[i] );
1640  return bOk;
1641 }
1642 
1643 bool ScTable::SetString( SCCOL nCol, SCROW nRow, SCTAB nTabP, const OUString& rString,
1644  const ScSetStringParam * pParam )
1645 {
1646  if (!ValidColRow(nCol,nRow))
1647  {
1648  return false;
1649  }
1650 
1651  return CreateColumnIfNotExists(nCol).SetString(
1652  nRow, nTabP, rString, rDocument.GetAddressConvention(), pParam);
1653 }
1654 
1655 bool ScTable::SetEditText( SCCOL nCol, SCROW nRow, std::unique_ptr<EditTextObject> pEditText )
1656 {
1657  if (!ValidColRow(nCol, nRow))
1658  {
1659  return false;
1660  }
1661 
1662  CreateColumnIfNotExists(nCol).SetEditText(nRow, std::move(pEditText));
1663  return true;
1664 }
1665 
1666 void ScTable::SetEditText( SCCOL nCol, SCROW nRow, const EditTextObject& rEditText, const SfxItemPool* pEditPool )
1667 {
1668  if (!ValidColRow(nCol, nRow))
1669  return;
1670 
1671  CreateColumnIfNotExists(nCol).SetEditText(nRow, rEditText, pEditPool);
1672 }
1673 
1674 SCROW ScTable::GetFirstEditTextRow( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) const
1675 {
1676  if (!ValidCol(nCol1) || !ValidCol(nCol2) || nCol2 < nCol1)
1677  return -1;
1678 
1679  if (!ValidRow(nRow1) || !ValidRow(nRow2) || nRow2 < nRow1)
1680  return -1;
1681 
1682  nCol2 = ClampToAllocatedColumns(nCol2);
1683  SCROW nFirst = rDocument.MaxRow()+1;
1684  for (SCCOL i = nCol1; i <= nCol2; ++i)
1685  {
1686  const ScColumn& rCol = aCol[i];
1687  SCROW nThisFirst = -1;
1688  if (const_cast<ScColumn&>(rCol).HasEditCells(nRow1, nRow2, nThisFirst))
1689  {
1690  if (nThisFirst == nRow1)
1691  return nRow1;
1692 
1693  if (nThisFirst < nFirst)
1694  nFirst = nThisFirst;
1695  }
1696  }
1697 
1698  return nFirst == (rDocument.MaxRow()+1) ? -1 : nFirst;
1699 }
1700 
1702 {
1703  if (!ValidColRow(nCol, nRow) || nCol >= GetAllocatedColumnsCount())
1704  return;
1705 
1706  aCol[nCol].Delete(nRow);
1707 }
1708 
1710  SCCOL nCol, SCROW nRow, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram )
1711 {
1712  if (!ValidColRow(nCol, nRow))
1713  return;
1714 
1715  CreateColumnIfNotExists(nCol).SetFormula(nRow, rArray, eGram);
1716 }
1717 
1719  SCCOL nCol, SCROW nRow, const OUString& rFormula, formula::FormulaGrammar::Grammar eGram )
1720 {
1721  if (!ValidColRow(nCol, nRow))
1722  return;
1723 
1724  CreateColumnIfNotExists(nCol).SetFormula(nRow, rFormula, eGram);
1725 }
1726 
1728 {
1729  if (!ValidColRow(nCol, nRow))
1730  {
1731  delete pCell;
1732  return nullptr;
1733  }
1734 
1736 }
1737 
1738 bool ScTable::SetFormulaCells( SCCOL nCol, SCROW nRow, std::vector<ScFormulaCell*>& rCells )
1739 {
1740  if (!ValidCol(nCol))
1741  return false;
1742 
1743  return CreateColumnIfNotExists(nCol).SetFormulaCells(nRow, rCells);
1744 }
1745 
1747 {
1748  if (!ValidColRow(nCol, nRow) || nCol >= GetAllocatedColumnsCount())
1749  return svl::SharedString();
1750 
1751  return aCol[nCol].GetSharedString(nRow);
1752 }
1753 
1754 void ScTable::SetValue( SCCOL nCol, SCROW nRow, const double& rVal )
1755 {
1756  if (ValidColRow(nCol, nRow))
1757  CreateColumnIfNotExists(nCol).SetValue(nRow, rVal);
1758 }
1759 
1760 void ScTable::SetRawString( SCCOL nCol, SCROW nRow, const svl::SharedString& rStr )
1761 {
1762  if (ValidColRow(nCol, nRow))
1763  CreateColumnIfNotExists(nCol).SetRawString(nRow, rStr);
1764 }
1765 
1766 OUString ScTable::GetString( SCCOL nCol, SCROW nRow, const ScInterpreterContext* pContext ) const
1767 {
1768  if (ValidColRow(nCol,nRow) && nCol < GetAllocatedColumnsCount())
1769  return aCol[nCol].GetString( nRow, pContext );
1770  else
1771  return OUString();
1772 }
1773 
1774 double* ScTable::GetValueCell( SCCOL nCol, SCROW nRow )
1775 {
1776  if (!ValidColRow(nCol, nRow))
1777  return nullptr;
1778 
1779  return CreateColumnIfNotExists(nCol).GetValueCell(nRow);
1780 }
1781 
1782 OUString ScTable::GetInputString( SCCOL nCol, SCROW nRow, const svl::SharedString** pShared, bool bForceSystemLocale ) const
1783 {
1784  if (ValidColRow(nCol, nRow) && nCol < GetAllocatedColumnsCount())
1785  return aCol[nCol].GetInputString( nRow, pShared, bForceSystemLocale );
1786  else
1787  return OUString();
1788 }
1789 
1790 double ScTable::GetValue( SCCOL nCol, SCROW nRow ) const
1791 {
1792  if (ValidColRow(nCol, nRow) && nCol < GetAllocatedColumnsCount())
1793  return aCol[nCol].GetValue( nRow );
1794  return 0.0;
1795 }
1796 
1798 {
1799  if (!ValidColRow(nCol, nRow) || nCol >= GetAllocatedColumnsCount())
1800  return nullptr;
1801 
1802  return aCol[nCol].GetEditText(nRow);
1803 }
1804 
1806 {
1807  if (!ValidColRow(nCol, nRow) || nCol >= GetAllocatedColumnsCount())
1808  return;
1809 
1810  return aCol[nCol].RemoveEditTextCharAttribs(nRow, rAttr);
1811 }
1812 
1813 OUString ScTable::GetFormula( SCCOL nCol, SCROW nRow ) const
1814 {
1815  if (ValidColRow(nCol, nRow) && nCol < GetAllocatedColumnsCount())
1816  return aCol[nCol].GetFormula( nRow );
1817  else
1818  return OUString();
1819 }
1820 
1822 {
1823  if (!ValidColRow(nCol, nRow) || nCol >= GetAllocatedColumnsCount())
1824  return nullptr;
1825 
1826  return aCol[nCol].GetFormulaCell(nRow);
1827 }
1828 
1830 {
1831  if (!ValidColRow(nCol, nRow) || nCol >= GetAllocatedColumnsCount())
1832  return nullptr;
1833 
1834  return aCol[nCol].GetFormulaCell(nRow);
1835 }
1836 
1837 // Sparklines
1838 
1839 std::shared_ptr<sc::Sparkline> ScTable::GetSparkline(SCCOL nCol, SCROW nRow)
1840 {
1841  if (!ValidCol(nCol) || nCol >= GetAllocatedColumnsCount())
1842  return std::shared_ptr<sc::Sparkline>();
1843 
1844  sc::SparklineCell* pSparklineCell = aCol[nCol].GetSparklineCell(nRow);
1845  if (!pSparklineCell)
1846  return std::shared_ptr<sc::Sparkline>();
1847 
1848  return pSparklineCell->getSparkline();
1849 }
1850 
1851 sc::Sparkline* ScTable::CreateSparkline(SCCOL nCol, SCROW nRow, std::shared_ptr<sc::SparklineGroup> const& pSparklineGroup)
1852 {
1853  if (!ValidCol(nCol))
1854  return nullptr;
1855 
1856  ScColumn& rColumn = CreateColumnIfNotExists(nCol);
1857 
1858  std::shared_ptr<sc::Sparkline> pSparkline(new sc::Sparkline(nCol, nRow, pSparklineGroup));
1859  rColumn.CreateSparklineCell(nRow, pSparkline);
1860 
1861  return pSparkline.get();
1862 }
1863 
1865 {
1866  if (!ValidCol(nCol) || nCol >= GetAllocatedColumnsCount())
1867  return false;
1868 
1869  aCol[nCol].DeleteSparkline(nRow);
1870 
1871  return true;
1872 }
1873 
1875 {
1876  return maSparklineList;
1877 }
1878 
1879 // Notes
1880 
1881 std::unique_ptr<ScPostIt> ScTable::ReleaseNote( SCCOL nCol, SCROW nRow )
1882 {
1883  if (!ValidCol(nCol) || nCol >= GetAllocatedColumnsCount())
1884  return nullptr;
1885 
1886  return aCol[nCol].ReleaseNote(nRow);
1887 }
1888 
1890 {
1891  if (!ValidCol(nCol) || nCol >= GetAllocatedColumnsCount())
1892  return nullptr;
1893  return aCol[nCol].GetCellNote(nRow);
1894 }
1895 
1896 void ScTable::SetNote( SCCOL nCol, SCROW nRow, std::unique_ptr<ScPostIt> pNote )
1897 {
1898  if (!ValidColRow(nCol, nRow))
1899  return;
1900 
1901  CreateColumnIfNotExists(nCol).SetCellNote(nRow, std::move(pNote));
1902 }
1903 
1904 size_t ScTable::GetNoteCount( SCCOL nCol ) const
1905 {
1906  if (!ValidCol(nCol) || nCol >= GetAllocatedColumnsCount())
1907  return 0;
1908 
1909  return aCol[nCol].GetNoteCount();
1910 }
1911 
1912 SCROW ScTable::GetNotePosition( SCCOL nCol, size_t nIndex ) const
1913 {
1914  if (!ValidCol(nCol) || nCol >= GetAllocatedColumnsCount())
1915  return -1;
1916 
1917  return aCol[nCol].GetNotePosition(nIndex);
1918 }
1919 
1921 {
1922  for (SCCOL i = 0; i < aCol.size(); ++i)
1924 }
1925 
1926 void ScTable::ForgetNoteCaptions( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bPreserveData )
1927 {
1928  if (!ValidCol(nCol1) || !ValidCol(nCol2))
1929  return;
1930  if ( nCol2 >= aCol.size() ) nCol2 = aCol.size() - 1;
1931  for (SCCOL i = nCol1; i <= nCol2; ++i)
1932  aCol[i].ForgetNoteCaptions(nRow1, nRow2, bPreserveData);
1933 }
1934 
1935 void ScTable::GetAllNoteEntries( std::vector<sc::NoteEntry>& rNotes ) const
1936 {
1937  for (SCCOL nCol = 0; nCol < aCol.size(); ++nCol)
1938  aCol[nCol].GetAllNoteEntries(rNotes);
1939 }
1940 
1941 void ScTable::GetNotesInRange( const ScRange& rRange, std::vector<sc::NoteEntry>& rNotes ) const
1942 {
1943  SCROW nStartRow = rRange.aStart.Row();
1944  SCROW nEndRow = rRange.aEnd.Row();
1945  SCCOL nEndCol = ClampToAllocatedColumns(rRange.aEnd.Col());
1946  for (SCCOL nCol = rRange.aStart.Col(); nCol <= nEndCol; ++nCol)
1947  {
1948  aCol[nCol].GetNotesInRange(nStartRow, nEndRow, rNotes);
1949  }
1950 }
1951 
1952 CommentCaptionState ScTable::GetAllNoteCaptionsState(const ScRange& rRange, std::vector<sc::NoteEntry>& rNotes )
1953 {
1954  SCROW nStartRow = rRange.aStart.Row();
1955  SCROW nEndRow = rRange.aEnd.Row();
1956  bool bIsFirstNoteShownState = true; // because of error: -Werror=maybe-uninitialized
1957  bool bFirstControl = true;
1958 
1959  ScTable* pTab = rDocument.FetchTable(nTab);
1960  assert(pTab);
1961  const SCCOL nEndCol = pTab->ClampToAllocatedColumns(rRange.aEnd.Col());
1962  for (SCCOL nCol = rRange.aStart.Col(); nCol <= nEndCol; ++nCol)
1963  {
1964  if (bFirstControl && rDocument.HasColNotes(nCol, nTab)) // detect status of first note caption
1965  {
1966  aCol[nCol].GetNotesInRange(nStartRow, nEndRow, rNotes);
1967  bIsFirstNoteShownState = rNotes.begin()->mpNote->IsCaptionShown();
1968  bFirstControl = false;
1969  }
1970 
1971  if (rDocument.HasColNotes(nCol, nTab))
1972  {
1973  aCol[nCol].GetNotesInRange(nStartRow, nEndRow, rNotes);
1974 
1975  bool bIsMixedState = std::any_of(rNotes.begin(), rNotes.end(), [bIsFirstNoteShownState](const sc::NoteEntry& rNote) {
1976  // compare the first note caption with others
1977  return bIsFirstNoteShownState != rNote.mpNote->IsCaptionShown(); });
1978  if (bIsMixedState)
1980  }
1981  }
1982  return bIsFirstNoteShownState ? CommentCaptionState::ALLSHOWN : CommentCaptionState::ALLHIDDEN;
1983 }
1984 
1986 {
1987  for (auto const & pCol : aCol)
1988  pCol->GetUnprotectedCells(0, rDocument.MaxRow(), rRangeList);
1989 }
1990 
1991 bool ScTable::ContainsNotesInRange( const ScRange& rRange ) const
1992 {
1993  SCROW nStartRow = rRange.aStart.Row();
1994  SCROW nEndRow = rRange.aEnd.Row();
1995  SCCOL nEndCol = ClampToAllocatedColumns(rRange.aEnd.Col());
1996  for (SCCOL nCol = rRange.aStart.Col(); nCol <= nEndCol; ++nCol)
1997  {
1998  bool bContainsNote = !aCol[nCol].IsNotesEmptyBlock(nStartRow, nEndRow);
1999  if(bContainsNote)
2000  return true;
2001  }
2002 
2003  return false;
2004 }
2005 
2007 {
2008  if (ValidColRow(nCol, nRow) && nCol < GetAllocatedColumnsCount())
2009  return aCol[nCol].GetCellType( nRow );
2010  return CELLTYPE_NONE;
2011 }
2012 
2014 {
2015  if (!ValidColRow(nCol, nRow) || nCol >= GetAllocatedColumnsCount())
2016  return ScRefCellValue();
2017 
2018  return aCol[nCol].GetCellValue(nRow);
2019 }
2020 
2022 {
2023  if (!ValidColRow(nCol, nRow) || nCol >= GetAllocatedColumnsCount())
2024  return ScRefCellValue();
2025 
2026  return aCol[nCol].GetCellValue(rBlockPos, nRow);
2027 }
2028 
2029 void ScTable::GetFirstDataPos(SCCOL& rCol, SCROW& rRow) const
2030 {
2031  rCol = 0;
2032  rRow = rDocument.MaxRow()+1;
2033  while (rCol < (aCol.size() - 1) && aCol[rCol].IsEmptyData() )
2034  ++rCol;
2035  SCCOL nCol = rCol;
2036  while (nCol < aCol.size() && rRow > 0)
2037  {
2038  if (!aCol[nCol].IsEmptyData())
2039  rRow = ::std::min( rRow, aCol[nCol].GetFirstDataPos());
2040  ++nCol;
2041  }
2042 }
2043 
2044 void ScTable::GetLastDataPos(SCCOL& rCol, SCROW& rRow) const
2045 {
2046  rCol = aCol.size() - 1;
2047  rRow = 0;
2048  while (aCol[rCol].IsEmptyData() && (rCol > 0))
2049  rCol--;
2050  SCCOL nCol = rCol;
2051  while (nCol >= 0 && rRow < rDocument.MaxRow())
2052  rRow = ::std::max( rRow, aCol[nCol--].GetLastDataPos());
2053 }
2054 
2055 bool ScTable::HasData( SCCOL nCol, SCROW nRow ) const
2056 {
2057  if (ValidColRow(nCol, nRow) && nCol < GetAllocatedColumnsCount())
2058  return aCol[nCol].HasDataAt( nRow );
2059  else
2060  return false;
2061 }
2062 
2063 bool ScTable::HasStringData( SCCOL nCol, SCROW nRow ) const
2064 {
2065  if (ValidColRow(nCol, nRow) && nCol < GetAllocatedColumnsCount())
2066  return aCol[nCol].HasStringData( nRow );
2067  else
2068  return false;
2069 }
2070 
2071 bool ScTable::HasValueData( SCCOL nCol, SCROW nRow ) const
2072 {
2073  if (ValidColRow(nCol, nRow) && nCol < GetAllocatedColumnsCount())
2074  return aCol[nCol].HasValueData( nRow );
2075  else
2076  return false;
2077 }
2078 
2079 bool ScTable::HasStringCells( SCCOL nStartCol, SCROW nStartRow,
2080  SCCOL nEndCol, SCROW nEndRow ) const
2081 {
2082  if (ValidCol(nEndCol))
2083  {
2084  nEndCol = ClampToAllocatedColumns(nEndCol);
2085  for (SCCOL nCol = nStartCol; nCol <= nEndCol; nCol++)
2086  if (aCol[nCol].HasStringCells(nStartRow, nEndRow))
2087  return true;
2088  }
2089 
2090  return false;
2091 }
2092 
2094 {
2095  for (SCCOL i=0; i < aCol.size(); i++)
2096  aCol[i].SetDirtyVar();
2097 }
2098 
2100 {
2101  sc::AutoCalcSwitch aACSwitch(rDocument, false);
2102 
2103  for (SCCOL i = 0; i < aCol.size(); i++)
2105 }
2106 
2108 {
2109  sc::AutoCalcSwitch aACSwitch(rDocument, false);
2110 
2111  for (SCCOL i=0; i < aCol.size(); i++)
2112  aCol[i].SetAllFormulasDirty(rCxt);
2113 }
2114 
2116 {
2117  sc::AutoCalcSwitch aSwitch(rDocument, false);
2118  SCCOL nCol2 = rRange.aEnd.Col();
2119  nCol2 = ClampToAllocatedColumns(nCol2);
2120  for (SCCOL i=rRange.aStart.Col(); i<=nCol2; i++)
2121  aCol[i].SetDirty(rRange.aStart.Row(), rRange.aEnd.Row(), eMode);
2122 }
2123 
2124 void ScTable::SetTableOpDirty( const ScRange& rRange )
2125 {
2126  sc::AutoCalcSwitch aSwitch(rDocument, false);
2127  const SCCOL nCol2 = ClampToAllocatedColumns(rRange.aEnd.Col());
2128  for (SCCOL i=rRange.aStart.Col(); i<=nCol2; i++)
2129  aCol[i].SetTableOpDirty( rRange );
2130 }
2131 
2133 {
2134  sc::AutoCalcSwitch aSwitch(rDocument, false);
2135  for (SCCOL i=0; i < aCol.size(); i++)
2137 }
2138 
2140 {
2141  sc::AutoCalcSwitch aSwitch(rDocument, false);
2142  ScBulkBroadcast aBulkBroadcast( rDocument.GetBASM(), SfxHintId::ScDataChanged);
2143  for (SCCOL i=0; i < aCol.size(); i++)
2145 }
2146 
2148 {
2149  sc::AutoCalcSwitch aSwitch(rDocument, false);
2150  for (SCCOL i = 0; i < aCol.size(); ++i)
2152 }
2153 
2154 bool ScTable::BroadcastBroadcasters( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SfxHintId nHint )
2155 {
2156  bool bBroadcasted = false;
2157  sc::AutoCalcSwitch aSwitch(rDocument, false);
2158  nCol2 = ClampToAllocatedColumns(nCol2);
2159  for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
2160  bBroadcasted |= aCol[nCol].BroadcastBroadcasters( nRow1, nRow2, nHint);
2161  return bBroadcasted;
2162 }
2163 
2164 void ScTable::SetLoadingMedium(bool bLoading)
2165 {
2166  mpRowHeights->enableTreeSearch(!bLoading);
2167 }
2168 
2170 {
2171  for (SCCOL i=0; i < aCol.size(); i++)
2172  aCol[i].CalcAll();
2173 
2174  mpCondFormatList->CalcAll();
2175 }
2176 
2178 {
2179  for (SCCOL i = 0; i < aCol.size(); ++i)
2180  aCol[i].CompileAll(rCxt);
2181 
2182  if(mpCondFormatList)
2183  mpCondFormatList->CompileAll();
2184 }
2185 
2187 {
2188  if (mpRangeName)
2189  mpRangeName->CompileUnresolvedXML(rCxt);
2190 
2191  for (SCCOL i=0; i < aCol.size(); i++)
2192  {
2193  aCol[i].CompileXML(rCxt, rProgress);
2194  }
2195 
2196  if(mpCondFormatList)
2197  mpCondFormatList->CompileXML();
2198 }
2199 
2201 {
2202  bool bCompiled = false;
2203  for (SCCOL i = 0; i < aCol.size(); ++i)
2204  {
2205  if (aCol[i].CompileErrorCells(rCxt, nErrCode))
2206  bCompiled = true;
2207  }
2208 
2209  return bCompiled;
2210 }
2211 
2212 void ScTable::CalcAfterLoad( sc::CompileFormulaContext& rCxt, bool bStartListening )
2213 {
2214  for (SCCOL i = 0; i < aCol.size(); ++i)
2215  aCol[i].CalcAfterLoad(rCxt, bStartListening);
2216 }
2217 
2218 void ScTable::ResetChanged( const ScRange& rRange )
2219 {
2220  SCCOL nStartCol = rRange.aStart.Col();
2221  SCROW nStartRow = rRange.aStart.Row();
2222  SCCOL nEndCol = ClampToAllocatedColumns(rRange.aEnd.Col());
2223  SCROW nEndRow = rRange.aEnd.Row();
2224 
2225  for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
2226  aCol[nCol].ResetChanged(nStartRow, nEndRow);
2227 }
2228 
2229 // Attribute
2230 
2231 const SfxPoolItem* ScTable::GetAttr( SCCOL nCol, SCROW nRow, sal_uInt16 nWhich ) const
2232 {
2233  if (!ValidColRow(nCol, nRow))
2234  return nullptr;
2235  return &ColumnData(nCol).GetAttr( nRow, nWhich );
2236 }
2237 
2238 const SfxPoolItem* ScTable::GetAttr( SCCOL nCol, SCROW nRow, sal_uInt16 nWhich, SCROW& nStartRow, SCROW& nEndRow ) const
2239 {
2240  if (!ValidColRow(nCol, nRow))
2241  return nullptr;
2242  return &ColumnData(nCol).GetAttr( nRow, nWhich, nStartRow, nEndRow );
2243 }
2244 
2245 sal_uInt32 ScTable::GetNumberFormat( const ScInterpreterContext& rContext, const ScAddress& rPos ) const
2246 {
2247  if (ValidColRow(rPos.Col(), rPos.Row()))
2248  return ColumnData(rPos.Col()).GetNumberFormat(rContext, rPos.Row());
2249  return 0;
2250 }
2251 
2252 sal_uInt32 ScTable::GetNumberFormat( SCCOL nCol, SCROW nRow ) const
2253 {
2254  return GetNumberFormat(rDocument.GetNonThreadedContext(), ScAddress(nCol, nRow, nTab));
2255 }
2256 
2257 sal_uInt32 ScTable::GetNumberFormat( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const
2258 {
2259  if (!ValidCol(nCol) || !ValidRow(nStartRow) || !ValidRow(nEndRow))
2260  return 0;
2261 
2262  return ColumnData(nCol).GetNumberFormat(nStartRow, nEndRow);
2263 }
2264 
2265 void ScTable::SetNumberFormat( SCCOL nCol, SCROW nRow, sal_uInt32 nNumberFormat )
2266 {
2267  if (!ValidColRow(nCol, nRow))
2268  return;
2269 
2270  CreateColumnIfNotExists(nCol).SetNumberFormat(nRow, nNumberFormat);
2271 }
2272 
2273 const ScPatternAttr* ScTable::GetPattern( SCCOL nCol, SCROW nRow ) const
2274 {
2275  if (!ValidColRow(nCol,nRow))
2276  return nullptr;
2277  return ColumnData(nCol).GetPattern( nRow );
2278 }
2279 
2280 const ScPatternAttr* ScTable::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const
2281 {
2282  if ( ValidColRow( nCol, nStartRow ) && ValidRow( nEndRow ) && (nStartRow <= nEndRow))
2283  return ColumnData(nCol).GetMostUsedPattern( nStartRow, nEndRow );
2284  return nullptr;
2285 }
2286 
2287 bool ScTable::HasAttrib( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, HasAttrFlags nMask ) const
2288 {
2289  for(SCCOL nCol = nCol1; nCol <= nCol2 && nCol < aCol.size(); ++nCol )
2290  if( aCol[nCol].HasAttrib( nRow1, nRow2, nMask ))
2291  return true;
2292  if( nCol2 >= aCol.size())
2293  return aDefaultColData.HasAttrib( nRow1, nRow2, nMask );
2294  return false;
2295 }
2296 
2297 bool ScTable::HasAttrib( SCCOL nCol, SCROW nRow, HasAttrFlags nMask, SCROW* nStartRow, SCROW* nEndRow ) const
2298 {
2299  return ColumnData(nCol).HasAttrib( nRow, nMask, nStartRow, nEndRow );
2300 }
2301 
2302 bool ScTable::HasAttribSelection( const ScMarkData& rMark, HasAttrFlags nMask ) const
2303 {
2304  std::vector<sc::ColRowSpan> aSpans = rMark.GetMarkedColSpans();
2305 
2306  for (const sc::ColRowSpan & aSpan : aSpans)
2307  {
2308  for (SCCOLROW j = aSpan.mnStart; j <= aSpan.mnEnd; ++j)
2309  {
2310  if (aCol[j].HasAttribSelection(rMark, nMask))
2311  return true;
2312  }
2313  }
2314  return false;
2315 }
2316 
2317 bool ScTable::ExtendMerge( SCCOL nStartCol, SCROW nStartRow,
2318  SCCOL& rEndCol, SCROW& rEndRow,
2319  bool bRefresh )
2320 {
2321  if (!(ValidCol(nStartCol) && ValidCol(rEndCol)))
2322  {
2323  OSL_FAIL("ScTable::ExtendMerge: invalid column number");
2324  return false;
2325  }
2326  if( rEndCol >= aCol.size())
2327  assert( !aDefaultColData.GetAttr( nStartRow, ATTR_MERGE ).IsMerged());
2328  bool bFound = false;
2329  SCCOL nOldEndX = ClampToAllocatedColumns(rEndCol);
2330  SCROW nOldEndY = rEndRow;
2331  for (SCCOL i=nStartCol; i<=nOldEndX; i++)
2332  bFound |= aCol[i].ExtendMerge( i, nStartRow, nOldEndY, rEndCol, rEndRow, bRefresh );
2333  return bFound;
2334 }
2335 
2336 void ScTable::SetMergedCells( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
2337 {
2338  ScMergeAttr aAttr(nCol2-nCol1+1, nRow2-nRow1+1);
2339  ApplyAttr(nCol1, nRow1, aAttr);
2340 
2341  if (nCol1 < nCol2)
2342  ApplyFlags(nCol1+1, nRow1, nCol2, nRow2, ScMF::Hor);
2343 
2344  if (nRow1 < nRow2)
2345  ApplyFlags(nCol1, nRow1+1, nCol1, nRow2, ScMF::Ver);
2346 
2347  if (nCol1 < nCol2 && nRow1 < nRow2)
2348  ApplyFlags(nCol1+1, nRow1+1, nCol2, nRow2, ScMF::Hor | ScMF::Ver);
2349 }
2350 
2351 bool ScTable::IsBlockEmpty( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) const
2352 {
2353  if (!(ValidCol(nCol1) && ValidCol(nCol2)))
2354  {
2355  OSL_FAIL("ScTable::IsBlockEmpty: invalid column number");
2356  return false;
2357  }
2358  nCol2 = ClampToAllocatedColumns(nCol2);
2359  bool bEmpty = true;
2360  for (SCCOL i=nCol1; i<=nCol2 && bEmpty; i++)
2361  {
2362  bEmpty = aCol[i].IsEmptyData( nRow1, nRow2 );
2363  if (bEmpty)
2364  {
2365  bEmpty = aCol[i].IsSparklinesEmptyBlock(nRow1, nRow2);
2366  }
2367  if (bEmpty)
2368  {
2369  bEmpty = aCol[i].IsNotesEmptyBlock(nRow1, nRow2);
2370  }
2371  }
2372  return bEmpty;
2373 }
2374 
2375 SCSIZE ScTable::FillMaxRot( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2,
2376  SCCOL nCol, SCROW nAttrRow1, SCROW nAttrRow2, SCSIZE nArrY,
2377  const ScPatternAttr* pPattern, const SfxItemSet* pCondSet )
2378 {
2379  // Return value = new nArrY
2380 
2381  ScRotateDir nRotDir = pPattern->GetRotateDir( pCondSet );
2382  if ( nRotDir != ScRotateDir::NONE )
2383  {
2384  bool bHit = true;
2385  if ( nCol+1 < nX1 ) // column to the left
2386  bHit = ( nRotDir != ScRotateDir::Left );
2387  else if ( nCol > nX2+1 ) // column to the right
2388  bHit = ( nRotDir != ScRotateDir::Right ); // ScRotateDir::Standard may now also be extended to the left
2389 
2390  if ( bHit )
2391  {
2392  double nFactor = 0.0;
2393  if ( nCol > nX2+1 )
2394  {
2395  Degree100 nRotVal = pPattern->
2396  GetItem( ATTR_ROTATE_VALUE, pCondSet ).GetValue();
2397  double nRealOrient = toRadians(nRotVal);
2398  double nCos = cos( nRealOrient );
2399  double nSin = sin( nRealOrient );
2400  //TODO: limit !!!
2401  //TODO: additional factor for varying PPT X/Y !!!
2402 
2403  // for ScRotateDir::Left this gives a negative value,
2404  // if the mode is considered
2405  nFactor = -fabs( nCos / nSin );
2406  }
2407 
2408  for ( SCROW nRow = nAttrRow1; nRow <= nAttrRow2; nRow++ )
2409  {
2410  if (!RowHidden(nRow))
2411  {
2412  bool bHitOne = true;
2413  if ( nCol > nX2+1 )
2414  {
2415  // Does the rotated cell extend into the visible range?
2416 
2417  SCCOL nTouchedCol = nCol;
2418  tools::Long nWidth = static_cast<tools::Long>(mpRowHeights->getValue(nRow) * nFactor);
2419  OSL_ENSURE(nWidth <= 0, "Wrong direction");
2420  while ( nWidth < 0 && nTouchedCol > 0 )
2421  {
2422  --nTouchedCol;
2423  nWidth += GetColWidth( nTouchedCol );
2424  }
2425  if ( nTouchedCol > nX2 )
2426  bHitOne = false;
2427  }
2428 
2429  if (bHitOne)
2430  {
2431  while ( nArrY<nArrCount && pRowInfo[nArrY].nRowNo < nRow )
2432  ++nArrY;
2433  if ( nArrY<nArrCount && pRowInfo[nArrY].nRowNo == nRow )
2434  pRowInfo[nArrY].nRotMaxCol = nCol;
2435  }
2436  }
2437  }
2438  }
2439  }
2440 
2441  return nArrY;
2442 }
2443 
2444 void ScTable::FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2 )
2445 {
2446  if ( !mpColWidth || !mpRowHeights || !mpColFlags || !pRowFlags )
2447  {
2448  OSL_FAIL( "Row/column info missing" );
2449  return;
2450  }
2451 
2452  // nRotMaxCol is initialized to SC_ROTMAX_NONE, nRowNo is already set
2453 
2454  SCROW nY1 = pRowInfo[0].nRowNo;
2455  SCROW nY2 = pRowInfo[nArrCount-1].nRowNo;
2456 
2457  for (SCCOL nCol : GetColumnsRange(0, rDocument.MaxCol()))
2458  {
2459  if (!ColHidden(nCol))
2460  {
2461  SCSIZE nArrY = 0;
2462  ScDocAttrIterator aIter( rDocument, nTab, nCol, nY1, nCol, nY2 );
2463  SCCOL nAttrCol;
2464  SCROW nAttrRow1, nAttrRow2;
2465  const ScPatternAttr* pPattern = aIter.GetNext( nAttrCol, nAttrRow1, nAttrRow2 );
2466  while ( pPattern )
2467  {
2468  if ( const ScCondFormatItem* pCondItem = pPattern->GetItemSet().GetItemIfSet( ATTR_CONDITIONAL ) )
2469  {
2470  // Run through all formats, so that each cell does not have to be
2471  // handled individually
2472 
2473  const ScCondFormatIndexes& rCondFormatData = pCondItem->GetCondFormatData();
2474  ScStyleSheetPool* pStylePool = rDocument.GetStyleSheetPool();
2475  if (mpCondFormatList && pStylePool && !rCondFormatData.empty())
2476  {
2477  for(const auto& rItem : rCondFormatData)
2478  {
2479  const ScConditionalFormat* pFormat = mpCondFormatList->GetFormat(rItem);
2480  if ( pFormat )
2481  {
2482  size_t nEntryCount = pFormat->size();
2483  for (size_t nEntry=0; nEntry<nEntryCount; nEntry++)
2484  {
2485  const ScFormatEntry* pEntry = pFormat->GetEntry(nEntry);
2486  if(pEntry->GetType() != ScFormatEntry::Type::Condition &&
2488  continue;
2489 
2490  OUString aStyleName = static_cast<const ScCondFormatEntry*>(pEntry)->GetStyle();
2491  if (!aStyleName.isEmpty())
2492  {
2493  SfxStyleSheetBase* pStyleSheet =
2494  pStylePool->Find( aStyleName, SfxStyleFamily::Para );
2495  if ( pStyleSheet )
2496  {
2497  FillMaxRot( pRowInfo, nArrCount, nX1, nX2,
2498  nCol, nAttrRow1, nAttrRow2,
2499  nArrY, pPattern, &pStyleSheet->GetItemSet() );
2500  // not changing nArrY
2501  }
2502  }
2503  }
2504  }
2505  }
2506  }
2507  }
2508 
2509  nArrY = FillMaxRot( pRowInfo, nArrCount, nX1, nX2,
2510  nCol, nAttrRow1, nAttrRow2,
2511  nArrY, pPattern, nullptr );
2512 
2513  pPattern = aIter.GetNext( nAttrCol, nAttrRow1, nAttrRow2 );
2514  }
2515  }
2516  }
2517 }
2518 
2519 bool ScTable::HasBlockMatrixFragment( const SCCOL nCol1, SCROW nRow1, const SCCOL nCol2, SCROW nRow2,
2520  bool bNoMatrixAtAll ) const
2521 {
2522  using namespace sc;
2523 
2524  if ( !IsColValid( nCol1 ) )
2525  return false;
2526 
2527  const SCCOL nMaxCol2 = std::min<SCCOL>( nCol2, aCol.size() - 1 );
2528 
2529  MatrixEdge nEdges = MatrixEdge::Nothing;
2530 
2531  if ( nCol1 == nMaxCol2 )
2532  { // left and right column
2534  nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, n, bNoMatrixAtAll );
2535  if ((nEdges != MatrixEdge::Nothing) && (((nEdges & n)!=n) || (nEdges & (MatrixEdge::Inside|MatrixEdge::Open))))
2536  return true; // left or right edge is missing or open
2537  }
2538  else
2539  { // left column
2540  nEdges = aCol[nCol1].GetBlockMatrixEdges(nRow1, nRow2, MatrixEdge::Left, bNoMatrixAtAll);
2541  if ((nEdges != MatrixEdge::Nothing) && ((!(nEdges & MatrixEdge::Left)) || (nEdges & (MatrixEdge::Inside|MatrixEdge::Open))))
2542  return true; // left edge missing or open
2543  // right column
2544  nEdges = aCol[nMaxCol2].GetBlockMatrixEdges(nRow1, nRow2, MatrixEdge::Right, bNoMatrixAtAll);
2545  if ((nEdges != MatrixEdge::Nothing) && ((!(nEdges & MatrixEdge::Right)) || (nEdges & (MatrixEdge::Inside|MatrixEdge::Open))))
2546  return true; // right edge is missing or open
2547  }
2548 
2549  if (bNoMatrixAtAll)
2550  {
2551  for (SCCOL i=nCol1; i<=nMaxCol2; i++)
2552  {
2553  nEdges = aCol[i].GetBlockMatrixEdges( nRow1, nRow2, MatrixEdge::Nothing, bNoMatrixAtAll);
2554  if (nEdges != MatrixEdge::Nothing
2555  && (nEdges != (MatrixEdge::Top | MatrixEdge::Left | MatrixEdge::Bottom | MatrixEdge::Right)))
2556  return true;
2557  }
2558  }
2559  else if ( nRow1 == nRow2 )
2560  { // Row on top and on bottom
2561  bool bOpen = false;
2562  const MatrixEdge n = MatrixEdge::Bottom | MatrixEdge::Top;
2563  for ( SCCOL i=nCol1; i<=nMaxCol2; i++)
2564  {
2565  nEdges = aCol[i].GetBlockMatrixEdges( nRow1, nRow1, n, bNoMatrixAtAll );
2566  if (nEdges != MatrixEdge::Nothing)
2567  {
2568  if ( (nEdges & n) != n )
2569  return true; // Top or bottom edge missing
2570  if (nEdges & MatrixEdge::Left)
2571  bOpen = true; // left edge open, continue
2572  else if ( !bOpen )
2573  return true; // Something exist that has not been opened
2574  if (nEdges & MatrixEdge::Right)
2575  bOpen = false; // Close right edge
2576  }
2577  }
2578  if ( bOpen )
2579  return true;
2580  }
2581  else
2582  {
2583  int j;
2584  MatrixEdge n;
2585  SCROW nR;
2586  // first top row, then bottom row
2587  for ( j=0, n = MatrixEdge::Top, nR=nRow1; j<2;
2588  j++, n = MatrixEdge::Bottom, nR=nRow2)
2589  {
2590  bool bOpen = false;
2591  for ( SCCOL i=nCol1; i<=nMaxCol2; i++)
2592  {
2593  nEdges = aCol[i].GetBlockMatrixEdges( nR, nR, n, bNoMatrixAtAll );
2594  if ( nEdges != MatrixEdge::Nothing)
2595  {
2596  // in top row no top edge respectively
2597  // in bottom row no bottom edge
2598  if ( (nEdges & n) != n )
2599  return true;
2600  if (nEdges & MatrixEdge::Left)
2601  bOpen = true; // open left edge, continue
2602  else if ( !bOpen )
2603  return true; // Something exist that has not been opened
2604  if (nEdges & MatrixEdge::Right)
2605  bOpen = false; // Close right edge
2606  }
2607  }
2608  if ( bOpen )
2609  return true;
2610  }
2611  }
2612  return false;
2613 }
2614 
2616 {
2617  std::vector<sc::ColRowSpan> aSpans = rMark.GetMarkedColSpans();
2618  ScRangeList rangeList = rMark.GetMarkedRanges();
2619 
2620  for (const sc::ColRowSpan & aSpan : aSpans)
2621  {
2622  SCCOL nEndCol = ClampToAllocatedColumns(aSpan.mnEnd);
2623  for ( SCCOLROW j=aSpan.mnStart; j<=nEndCol; j++ )
2624  {
2625  if ( aCol[j].HasSelectionMatrixFragment(rMark, rangeList) )
2626  return true;
2627  }
2628  }
2629  return false;
2630 }
2631 
2632 bool ScTable::IsBlockEditable( SCCOL nCol1, SCROW nRow1, SCCOL nCol2,
2633  SCROW nRow2, bool* pOnlyNotBecauseOfMatrix /* = NULL */,
2634  bool bNoMatrixAtAll ) const
2635 {
2636  if ( !ValidColRow( nCol2, nRow2 ) )
2637  {
2638  SAL_WARN("sc", "IsBlockEditable: invalid column or row " << nCol2 << " " << nRow2);
2639  if (pOnlyNotBecauseOfMatrix)
2640  *pOnlyNotBecauseOfMatrix = false;
2641  return false;
2642  }
2643 
2644  bool bIsEditable = true;
2645  if ( nLockCount )
2646  bIsEditable = false;
2647  else if ( IsProtected() && !rDocument.IsScenario(nTab) )
2648  {
2649  bIsEditable = !HasAttrib( nCol1, nRow1, nCol2, nRow2, HasAttrFlags::Protected );
2650  if (!bIsEditable)
2651  {
2652  // An enhanced protection permission may override the attribute.
2653  if (pTabProtection)
2654  bIsEditable = pTabProtection->isBlockEditable( ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab));
2655  }
2656  if (bIsEditable)
2657  {
2658  // If Sheet is protected and cells are not protected then
2659  // check the active scenario protect flag if this range is
2660  // on the active scenario range. Note the 'copy back' must also
2661  // be set to apply protection.
2662  sal_uInt16 nScenTab = nTab+1;
2663  while(rDocument.IsScenario(nScenTab))
2664  {
2665  ScRange aEditRange(nCol1, nRow1, nScenTab, nCol2, nRow2, nScenTab);
2666  if(rDocument.IsActiveScenario(nScenTab) && rDocument.HasScenarioRange(nScenTab, aEditRange))
2667  {
2668  ScScenarioFlags nFlags;
2669  rDocument.GetScenarioFlags(nScenTab,nFlags);
2670  bIsEditable = !((nFlags & ScScenarioFlags::Protected) && (nFlags & ScScenarioFlags::TwoWay));
2671  break;
2672  }
2673  nScenTab++;
2674  }
2675  }
2676  }
2677  else if (rDocument.IsScenario(nTab))
2678  {
2679  // Determine if the preceding sheet is protected
2680  SCTAB nActualTab = nTab;
2681  do
2682  {
2683  nActualTab--;
2684  }
2685  while(rDocument.IsScenario(nActualTab));
2686 
2687  if(rDocument.IsTabProtected(nActualTab))
2688  {
2689  ScRange aEditRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
2690  if(rDocument.HasScenarioRange(nTab, aEditRange))
2691  {
2692  ScScenarioFlags nFlags;
2693  rDocument.GetScenarioFlags(nTab,nFlags);
2694  bIsEditable = !(nFlags & ScScenarioFlags::Protected);
2695  }
2696  }
2697  }
2698  if ( bIsEditable )
2699  {
2700  if (HasBlockMatrixFragment( nCol1, nRow1, nCol2, nRow2, bNoMatrixAtAll))
2701  {
2702  bIsEditable = false;
2703  if ( pOnlyNotBecauseOfMatrix )
2704  *pOnlyNotBecauseOfMatrix = true;
2705  }
2706  else if ( pOnlyNotBecauseOfMatrix )
2707  *pOnlyNotBecauseOfMatrix = false;
2708  }
2709  else if ( pOnlyNotBecauseOfMatrix )
2710  *pOnlyNotBecauseOfMatrix = false;
2711  return bIsEditable;
2712 }
2713 
2715  bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
2716 {
2717  bool bIsEditable = true;
2718  if ( nLockCount )
2719  bIsEditable = false;
2720  else if ( IsProtected() && !rDocument.IsScenario(nTab) )
2721  {
2722  ScRangeList aRanges;
2723  rMark.FillRangeListWithMarks( &aRanges, false );
2724  bIsEditable = !HasAttribSelection( rMark, HasAttrFlags::Protected );
2725  if (!bIsEditable)
2726  {
2727  // An enhanced protection permission may override the attribute.
2728  if (pTabProtection)
2729  bIsEditable = pTabProtection->isSelectionEditable( aRanges);
2730  }
2731  if (bIsEditable)
2732  {
2733  // If Sheet is protected and cells are not protected then
2734  // check the active scenario protect flag if this area is
2735  // in the active scenario range.
2736  SCTAB nScenTab = nTab+1;
2737  while(rDocument.IsScenario(nScenTab) && bIsEditable)
2738  {
2739  if(rDocument.IsActiveScenario(nScenTab))
2740  {
2741  for (size_t i=0, nRange = aRanges.size(); (i < nRange) && bIsEditable; i++ )
2742  {
2743  const ScRange & rRange = aRanges[ i ];
2744  if(rDocument.HasScenarioRange(nScenTab, rRange))
2745  {
2746  ScScenarioFlags nFlags;
2747  rDocument.GetScenarioFlags(nScenTab,nFlags);
2748  bIsEditable = !((nFlags & ScScenarioFlags::Protected) && (nFlags & ScScenarioFlags::TwoWay));
2749  }
2750  }
2751  }
2752  nScenTab++;
2753  }
2754  }
2755  }
2756  else if (rDocument.IsScenario(nTab))
2757  {
2758  // Determine if the preceding sheet is protected
2759  SCTAB nActualTab = nTab;
2760  do
2761  {
2762  nActualTab--;
2763  }
2764  while(rDocument.IsScenario(nActualTab));
2765 
2766  if(rDocument.IsTabProtected(nActualTab))
2767  {
2768  ScRangeList aRanges;
2769  rMark.FillRangeListWithMarks( &aRanges, false );
2770  for (size_t i = 0, nRange = aRanges.size(); (i < nRange) && bIsEditable; i++)
2771  {
2772  const ScRange & rRange = aRanges[ i ];
2773  if(rDocument.HasScenarioRange(nTab, rRange))
2774  {
2775  ScScenarioFlags nFlags;
2776  rDocument.GetScenarioFlags(nTab,nFlags);
2777  bIsEditable = !(nFlags & ScScenarioFlags::Protected);
2778  }
2779  }
2780  }
2781  }
2782  if ( bIsEditable )
2783  {
2784  if ( HasSelectionMatrixFragment( rMark ) )
2785  {
2786  bIsEditable = false;
2787  if ( pOnlyNotBecauseOfMatrix )
2788  *pOnlyNotBecauseOfMatrix = true;
2789  }
2790  else if ( pOnlyNotBecauseOfMatrix )
2791  *pOnlyNotBecauseOfMatrix = false;
2792  }
2793  else if ( pOnlyNotBecauseOfMatrix )
2794  *pOnlyNotBecauseOfMatrix = false;
2795  return bIsEditable;
2796 }
2797 
2799 {
2800  ++nLockCount;
2801 }
2802 
2804 {
2805  if (nLockCount)
2806  --nLockCount;
2807  else
2808  {
2809  OSL_FAIL("UnlockTable without LockTable");
2810  }
2811 }
2812 
2813 void ScTable::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, bool bDeep ) const
2814 {
2815  std::vector<sc::ColRowSpan> aSpans = rMark.GetMarkedColSpans();
2816 
2817  for (const sc::ColRowSpan & rSpan : aSpans)
2818  {
2819  SCCOL maxCol = ClampToAllocatedColumns(rSpan.mnEnd);
2820  for (SCCOL i = rSpan.mnStart; i <= maxCol; ++i)
2821  {
2822  aCol[i].MergeSelectionPattern( rState, rMark, bDeep );
2823  }
2824  }
2825 }
2826 
2828  SCCOL nCol2, SCROW nRow2, bool bDeep ) const
2829 {
2830  const SCCOL nEndCol = ClampToAllocatedColumns(nCol2);
2831  for (SCCOL i=nCol1; i<=nEndCol; i++)
2832  aCol[i].MergePatternArea( rState, nRow1, nRow2, bDeep );
2833  if (nEndCol != nCol2)
2834  aDefaultColData.MergePatternArea( rState, nRow1, nRow2, bDeep );
2835 }
2836 
2837 void ScTable::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner, ScLineFlags& rFlags,
2838  SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) const
2839 {
2840  if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2841  {
2842  PutInOrder(nStartCol, nEndCol);
2843  PutInOrder(nStartRow, nEndRow);
2844  nEndCol = ClampToAllocatedColumns(nEndCol);
2845  for (SCCOL i=nStartCol; i<=nEndCol; i++)
2846  aCol[i].MergeBlockFrame( pLineOuter, pLineInner, rFlags,
2847  nStartRow, nEndRow, (i==nStartCol), nEndCol-i );
2848  }
2849 }
2850 
2851 void ScTable::ApplyBlockFrame(const SvxBoxItem& rLineOuter, const SvxBoxInfoItem* pLineInner,
2852  SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow)
2853 {
2854  if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2855  {
2856  PutInOrder(nStartCol, nEndCol);
2857  PutInOrder(nStartRow, nEndRow);
2858  nEndCol = ClampToAllocatedColumns(nEndCol);
2859  for (SCCOL i=nStartCol; i<=nEndCol; i++)
2860  aCol[i].ApplyBlockFrame(rLineOuter, pLineInner,
2861  nStartRow, nEndRow, (i==nStartCol), nEndCol-i);
2862  }
2863 }
2864 
2865 void ScTable::ApplyPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr )
2866 {
2867  if (ValidColRow(nCol,nRow))
2868  CreateColumnIfNotExists(nCol).ApplyPattern( nRow, rAttr );
2869 }
2870 
2871 void ScTable::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
2872  const ScPatternAttr& rAttr, ScEditDataArray* pDataArray,
2873  bool* const pIsChanged )
2874 {
2875  if (!ValidColRow(nStartCol, nStartRow) || !ValidColRow(nEndCol, nEndRow))
2876  return;
2877  PutInOrder(nStartCol, nEndCol);
2878  PutInOrder(nStartRow, nEndRow);
2879  SCCOL maxCol = nEndCol;
2880  if( nEndCol == GetDoc().MaxCol())
2881  {
2882  // For the same unallocated columns until the end we can change just the default.
2883  maxCol = std::max( nStartCol, aCol.size()) - 1;
2884  if( maxCol >= 0 )
2885  CreateColumnIfNotExists(maxCol); // Allocate needed different columns before changing the default.
2886  aDefaultColData.ApplyPatternArea(nStartRow, nEndRow, rAttr, pDataArray, pIsChanged);
2887  }
2888  for (SCCOL i = nStartCol; i <= maxCol; i++)
2889  CreateColumnIfNotExists(i).ApplyPatternArea(nStartRow, nEndRow, rAttr, pDataArray, pIsChanged);
2890 }
2891 
2892 void ScTable::SetAttrEntries( SCCOL nStartCol, SCCOL nEndCol, std::vector<ScAttrEntry> && vNewData)
2893 {
2894  if (!ValidCol(nStartCol) || !ValidCol(nEndCol))
2895  return;
2896  if ( nEndCol == rDocument.MaxCol() )
2897  {
2898  if ( nStartCol < aCol.size() )
2899  {
2900  // If we would like set all columns to same attrs, then change only attrs for not existing columns
2901  nEndCol = aCol.size() - 1;
2902  for (SCCOL i = nStartCol; i <= nEndCol; i++)
2903  // [-loplugin:redundantfcast] false positive:
2904  aCol[i].SetAttrEntries( std::vector<ScAttrEntry>(vNewData));
2905  aDefaultColData.SetAttrEntries(std::move(vNewData));
2906  }
2907  else
2908  {
2909  CreateColumnIfNotExists( nStartCol - 1 );
2910  aDefaultColData.SetAttrEntries(std::move(vNewData));
2911  }
2912  }
2913  else
2914  {
2915  CreateColumnIfNotExists( nEndCol );
2916  for (SCCOL i = nStartCol; i < nEndCol; i++) // all but last need a copy
2917  // [-loplugin:redundantfcast] false positive:
2918  aCol[i].SetAttrEntries( std::vector<ScAttrEntry>(vNewData));
2919  aCol[nEndCol].SetAttrEntries( std::move(vNewData));
2920  }
2921 }
2922 
2923 
2924 
2926  const ScPatternAttr& rPattern, SvNumFormatType nNewType )
2927 {
2928  SCCOL nEndCol = rRange.aEnd.Col();
2929  for ( SCCOL nCol = rRange.aStart.Col(); nCol <= nEndCol; nCol++ )
2930  {
2931  aCol[nCol].ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType );
2932  }
2933 }
2934 
2935 void ScTable::AddCondFormatData( const ScRangeList& rRangeList, sal_uInt32 nIndex )
2936 {
2937  size_t n = rRangeList.size();
2938  for(size_t i = 0; i < n; ++i)
2939  {
2940  const ScRange & rRange = rRangeList[i];
2941  SCCOL nColStart = rRange.aStart.Col();
2942  SCCOL nColEnd = rRange.aEnd.Col();
2943  SCROW nRowStart = rRange.aStart.Row();
2944  SCROW nRowEnd = rRange.aEnd.Row();
2945  for(SCCOL nCol = nColStart; nCol <= nColEnd; ++nCol)
2946  {
2947  CreateColumnIfNotExists(nCol).AddCondFormat(nRowStart, nRowEnd, nIndex);
2948  }
2949  }
2950 }
2951 
2952 void ScTable::RemoveCondFormatData( const ScRangeList& rRangeList, sal_uInt32 nIndex )
2953 {
2954  size_t n = rRangeList.size();
2955  for(size_t i = 0; i < n; ++i)
2956  {
2957  const ScRange & rRange = rRangeList[i];
2958  SCCOL nColStart = rRange.aStart.Col();
2959  SCCOL nColEnd = ClampToAllocatedColumns(rRange.aEnd.Col());
2960  SCROW nRowStart = rRange.aStart.Row();
2961  SCROW nRowEnd = rRange.aEnd.Row();
2962  for(SCCOL nCol = nColStart; nCol <= nColEnd; ++nCol)
2963  {
2964  aCol[nCol].RemoveCondFormat(nRowStart, nRowEnd, nIndex);
2965  }
2966  }
2967 }
2968 
2969 void ScTable::SetPatternAreaCondFormat( SCCOL nCol, SCROW nStartRow, SCROW nEndRow,
2970  const ScPatternAttr& rAttr, const ScCondFormatIndexes& rCondFormatIndexes )
2971 {
2972  CreateColumnIfNotExists(nCol).SetPatternArea( nStartRow, nEndRow, rAttr);
2973 
2974  for (const auto& rIndex : rCondFormatIndexes)
2975  {
2976  ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(rIndex);
2977  if (pCondFormat)
2978  {
2979  ScRangeList aRange = pCondFormat->GetRange();
2980  aRange.Join( ScRange( nCol, nStartRow, nTab, nCol, nEndRow, nTab));
2981  pCondFormat->SetRange(aRange);
2982  }
2983  }
2984 }
2985 
2986 void ScTable::ApplyStyle( SCCOL nCol, SCROW nRow, const ScStyleSheet* rStyle )
2987 {
2988  if (ValidColRow(nCol,nRow))
2989  // If column not exists then we need to create it
2990  CreateColumnIfNotExists( nCol ).ApplyStyle( nRow, rStyle );
2991 }
2992 
2993 void ScTable::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScStyleSheet& rStyle )
2994 {
2995  if (!(ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow)))
2996  return;
2997 
2998  PutInOrder(nStartCol, nEndCol);
2999  PutInOrder(nStartRow, nEndRow);
3000  if ( nEndCol == rDocument.MaxCol() )
3001  {
3002  if ( nStartCol < aCol.size() )
3003  {
3004  // If we would like set all columns to specific style, then change only default style for not existing columns
3005  nEndCol = aCol.size() - 1;
3006  for (SCCOL i = nStartCol; i <= nEndCol; i++)
3007  aCol[i].ApplyStyleArea(nStartRow, nEndRow, rStyle);
3008  aDefaultColData.ApplyStyleArea(nStartRow, nEndRow, rStyle );
3009  }
3010  else
3011  {
3012  CreateColumnIfNotExists( nStartCol - 1 );
3013  aDefaultColData.ApplyStyleArea(nStartRow, nEndRow, rStyle );
3014  }
3015  }
3016  else
3017  {
3018  CreateColumnIfNotExists( nEndCol );
3019  for (SCCOL i = nStartCol; i <= nEndCol; i++)
3020  aCol[i].ApplyStyleArea(nStartRow, nEndRow, rStyle);
3021  }
3022 }
3023 
3024 void ScTable::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
3025 {
3026  for (SCCOL i=0; i < aCol.size(); i++)
3027  aCol[i].ApplySelectionStyle( rStyle, rMark );
3028 }
3029 
3031  const ::editeng::SvxBorderLine* pLine, bool bColorOnly )
3032 {
3033  if ( bColorOnly && !pLine )
3034  return;
3035 
3036  for (SCCOL i=0; i < aCol.size(); i++)
3037  aCol[i].ApplySelectionLineStyle( rMark, pLine, bColorOnly );
3038 }
3039 
3040 const ScStyleSheet* ScTable::GetStyle( SCCOL nCol, SCROW nRow ) const
3041 {
3042  if ( !ValidColRow( nCol, nRow ) )
3043  return nullptr;
3044  return ColumnData(nCol).GetStyle( nRow );
3045 }
3046 
3047 const ScStyleSheet* ScTable::GetSelectionStyle( const ScMarkData& rMark, bool& rFound ) const
3048 {
3049  rFound = false;
3050 
3051  bool bEqual = true;
3052  bool bColFound;
3053 
3054  const ScStyleSheet* pStyle = nullptr;
3055  const ScStyleSheet* pNewStyle;
3056 
3057  for (SCCOL i=0; i < aCol.size() && bEqual; i++)
3058  if (rMark.HasMultiMarks(i))
3059  {
3060  pNewStyle = aCol[i].GetSelectionStyle( rMark, bColFound );
3061  if (bColFound)
3062  {
3063  rFound = true;
3064  if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
3065  bEqual = false;
3066  pStyle = pNewStyle;
3067  }
3068  }
3069 
3070  return bEqual ? pStyle : nullptr;
3071 }
3072 
3073 const ScStyleSheet* ScTable::GetAreaStyle( bool& rFound, SCCOL nCol1, SCROW nRow1,
3074  SCCOL nCol2, SCROW nRow2 ) const
3075 {
3076  rFound = false;
3077 
3078  bool bEqual = true;
3079  bool bColFound;
3080 
3081  const ScStyleSheet* pStyle = nullptr;
3082  const ScStyleSheet* pNewStyle;
3083  nCol2 = ClampToAllocatedColumns(nCol2);
3084  for (SCCOL i=nCol1; i<=nCol2 && bEqual; i++)
3085  {
3086  pNewStyle = aCol[i].GetAreaStyle(bColFound, nRow1, nRow2);
3087  if (bColFound)
3088  {
3089  rFound = true;
3090  if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
3091  bEqual = false;
3092  pStyle = pNewStyle;
3093  }
3094  }
3095 
3096  return bEqual ? pStyle : nullptr;
3097 }
3098 
3099 bool ScTable::IsStyleSheetUsed( const ScStyleSheet& rStyle ) const
3100 {
3101  bool bIsUsed = false;
3102 
3103  for ( SCCOL i=0; i < aCol.size(); i++ )
3104  {
3105  if ( aCol[i].IsStyleSheetUsed( rStyle ) )
3106  {
3107  bIsUsed = true;
3108  }
3109  }
3110 
3111  return bIsUsed;
3112 }
3113 
3114 void ScTable::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, bool bRemoved,
3115  OutputDevice* pDev,
3116  double nPPTX, double nPPTY,
3117  const Fraction& rZoomX, const Fraction& rZoomY )
3118 {
3119  ScFlatBoolRowSegments aUsedRows(rDocument.MaxRow());
3120  for (SCCOL i = 0; i < aCol.size(); ++i)
3121  aCol[i].FindStyleSheet(pStyleSheet, aUsedRows, bRemoved);
3122 
3123  sc::RowHeightContext aCxt(rDocument.MaxRow(), nPPTX, nPPTY, rZoomX, rZoomY, pDev);
3124  SCROW nRow = 0;
3125  while (nRow <= rDocument.MaxRow())
3126  {
3128  if (!aUsedRows.getRangeData(nRow, aData))
3129  // search failed!
3130  return;
3131 
3132  SCROW nEndRow = aData.mnRow2;
3133  if (aData.mbValue)
3134  SetOptimalHeight(aCxt, nRow, nEndRow, true);
3135 
3136  nRow = nEndRow + 1;
3137  }
3138 }
3139 
3140 bool ScTable::ApplyFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
3141  ScMF nFlags )
3142 {
3143  bool bChanged = false;
3144  if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
3145  for (SCCOL i = nStartCol; i <= nEndCol; i++)
3146  bChanged |= CreateColumnIfNotExists(i).ApplyFlags(nStartRow, nEndRow, nFlags);
3147  return bChanged;
3148 }
3149 
3150 bool ScTable::RemoveFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
3151  ScMF nFlags )
3152 {
3153  if (!ValidColRow(nStartCol, nStartRow) || !ValidColRow(nEndCol, nEndRow))
3154  return false;
3155  bool bChanged = false;
3156  nEndCol = ClampToAllocatedColumns(nEndCol);
3157  for (SCCOL i = nStartCol; i <= nEndCol; i++)
3158  bChanged |= aCol[i].RemoveFlags(nStartRow, nEndRow, nFlags);
3159  return bChanged;
3160 }
3161 
3162 void ScTable::SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr )
3163 {
3164  if (ValidColRow(rPos.Col(),rPos.Row()))
3165  CreateColumnIfNotExists(rPos.Col()).SetPattern(rPos.Row(), rAttr);
3166 }
3167 
3168 const ScPatternAttr* ScTable::SetPattern( SCCOL nCol, SCROW nRow, std::unique_ptr<ScPatternAttr> pAttr )
3169 {
3170  if (ValidColRow(nCol,nRow))
3171  return CreateColumnIfNotExists(nCol).SetPattern(nRow, std::move(pAttr));
3172  return nullptr;
3173 }
3174 
3175 void ScTable::SetPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr )
3176 {
3177  if (ValidColRow(nCol,nRow))
3178  CreateColumnIfNotExists(nCol).SetPattern(nRow, rAttr);
3179 }
3180 
3181 void ScTable::ApplyAttr( SCCOL nCol, SCROW nRow, const SfxPoolItem& rAttr )
3182 {
3183  if (ValidColRow(nCol,nRow))
3184  CreateColumnIfNotExists(nCol).ApplyAttr( nRow, rAttr );
3185 }
3186 
3188  ScEditDataArray* pDataArray, bool* const pIsChanged )
3189 {
3190  if(!rMark.GetTableSelect(nTab))
3191  return;
3192  SCCOL lastChangeCol;
3193  if( rMark.GetArea().aEnd.Col() == GetDoc().MaxCol())
3194  {
3195  // For the same unallocated columns until the end we can change just the default.
3196  lastChangeCol = rMark.GetStartOfEqualColumns( GetDoc().MaxCol(), aCol.size()) - 1;
3197  if( lastChangeCol >= 0 )
3198  CreateColumnIfNotExists(lastChangeCol); // Allocate needed different columns before changing the default.
3199  aDefaultColData.ApplySelectionCache( pCache, rMark, pDataArray, pIsChanged, GetDoc().MaxCol());
3200  }
3201  else // need to allocate all columns affected
3202  {
3203  lastChangeCol = rMark.GetArea().aEnd.Col();
3204  CreateColumnIfNotExists(lastChangeCol);
3205  }
3206 
3207  for (SCCOL i=0; i <= lastChangeCol; i++)
3208  aCol[i].ApplySelectionCache( pCache, rMark, pDataArray, pIsChanged );
3209 }
3210 
3211 void ScTable::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
3212 {
3213  if(!rMark.GetTableSelect(nTab))
3214  return;
3215  SCCOL lastChangeCol;
3216  if( rMark.GetArea().aEnd.Col() == GetDoc().MaxCol())
3217  {
3218  // For the same unallocated columns until the end we can change just the default.
3219  lastChangeCol = rMark.GetStartOfEqualColumns( GetDoc().MaxCol(), aCol.size()) - 1;
3220  if( lastChangeCol >= 0 )
3221  CreateColumnIfNotExists(lastChangeCol); // Allocate needed different columns before changing the default.
3222  aDefaultColData.ChangeSelectionIndent( bIncrement, rMark, GetDoc().MaxCol());
3223  }
3224  else
3225  {
3226  lastChangeCol = rMark.GetArea().aEnd.Col();
3227  CreateColumnIfNotExists(lastChangeCol);
3228  }
3229 
3230  for (SCCOL i=0; i <= lastChangeCol; i++)
3231  aCol[i].ChangeSelectionIndent( bIncrement, rMark );
3232 }
3233 
3234 void ScTable::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark )
3235 {
3236  if(!rMark.GetTableSelect(nTab))
3237  return;
3238  SCCOL lastChangeCol;
3239  if( rMark.GetArea().aEnd.Col() == GetDoc().MaxCol())
3240  {
3241  // For the same unallocated columns until the end we can change just the default.
3242  lastChangeCol = rMark.GetStartOfEqualColumns( GetDoc().MaxCol(), aCol.size()) - 1;
3243  if( lastChangeCol >= 0 )
3244  CreateColumnIfNotExists(lastChangeCol); // Allocate needed different columns before changing the default.
3245  aDefaultColData.ClearSelectionItems( pWhich, rMark, GetDoc().MaxCol());
3246  }
3247  else
3248  {
3249  lastChangeCol = rMark.GetArea().aEnd.Col();
3250  CreateColumnIfNotExists(lastChangeCol);
3251  }
3252 
3253  for (SCCOL i=0; i <= lastChangeCol; i++)
3254  aCol[i].ClearSelectionItems( pWhich, rMark );
3255 }
3256 
3257 // Column widths / Row heights
3258 
3259 void ScTable::SetColWidth( SCCOL nCol, sal_uInt16 nNewWidth )
3260 {
3261  if (ValidCol(nCol) && mpColWidth)
3262  {
3263  if (!nNewWidth)
3264  {
3265  nNewWidth = STD_COL_WIDTH;
3266  }
3267 
3268  if ( nNewWidth != mpColWidth->GetValue(nCol) )
3269  {
3270  mpColWidth->SetValue(nCol, nNewWidth);
3272  }
3273  }
3274  else
3275  {
3276  OSL_FAIL("Invalid column number or no widths");
3277  }
3278 }
3279 
3280 void ScTable::SetColWidthOnly( SCCOL nCol, sal_uInt16 nNewWidth )
3281 {
3282  if (!ValidCol(nCol) || !mpColWidth)
3283  return;
3284 
3285  if (!nNewWidth)
3286  nNewWidth = STD_COL_WIDTH;
3287 
3288  if (nNewWidth != mpColWidth->GetValue(nCol))
3289  mpColWidth->SetValue(nCol, nNewWidth);
3290 }
3291 
3292 void ScTable::SetRowHeight( SCROW nRow, sal_uInt16 nNewHeight )
3293 {
3294  if (ValidRow(nRow) && mpRowHeights)
3295  {
3296  if (!nNewHeight)
3297  {
3298  OSL_FAIL("SetRowHeight: Row height zero");
3299  nNewHeight = ScGlobal::nStdRowHeight;
3300  }
3301 
3302  sal_uInt16 nOldHeight = mpRowHeights->getValue(nRow);
3303  if ( nNewHeight != nOldHeight )
3304  {
3305  mpRowHeights->setValue(nRow, nRow, nNewHeight);
3307  }
3308  }
3309  else
3310  {
3311  OSL_FAIL("Invalid row number or no heights");
3312  }
3313 }
3314 
3315 namespace {
3316 
3321 bool lcl_pixelSizeChanged(
3322  ScFlatUInt16RowSegments& rRowHeights, SCROW nStartRow, SCROW nEndRow,
3323  sal_uInt16 nNewHeight, double nPPTY, bool bApi)
3324 {
3325  tools::Long nNewPix = static_cast<tools::Long>(nNewHeight * nPPTY);
3326 
3327  ScFlatUInt16RowSegments::ForwardIterator aFwdIter(rRowHeights);
3328  for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
3329  {
3330  sal_uInt16 nHeight;
3331  if (!aFwdIter.getValue(nRow, nHeight))
3332  break;
3333 
3334  if (nHeight != nNewHeight)
3335  {
3336  tools::Long nOldPix = static_cast<tools::Long>(nHeight * nPPTY);
3337 
3338  // Heuristic: Don't bother when handling interactive input, if changing just one row and
3339  // the height will shrink.
3340  bool bChanged = (nNewPix != nOldPix) && (bApi || nEndRow - nStartRow > 0 || nNewPix > nOldPix);
3341  if (bChanged)
3342  return true;
3343  }
3344 
3345  // Skip ahead to the last position of the current range.
3346  nRow = aFwdIter.getLastPos();
3347  }
3348  return false;
3349 }
3350 
3351 }
3352 
3353 bool ScTable::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight,
3354  double nPPTY, bool bApi )
3355 {
3356  bool bChanged = false;
3357  if (ValidRow(nStartRow) && ValidRow(nEndRow) && mpRowHeights)
3358  {
3359  if (!nNewHeight)
3360  {
3361  OSL_FAIL("SetRowHeight: Row height zero");
3362  nNewHeight = ScGlobal::nStdRowHeight;
3363  }
3364 
3365  bool bSingle = false; // true = process every row for its own
3366  ScDrawLayer* pDrawLayer = rDocument.GetDrawLayer();
3367  if (pDrawLayer)
3368  if (pDrawLayer->HasObjectsInRows( nTab, nStartRow, nEndRow ))
3369  bSingle = true;
3370 
3371  if (bSingle)
3372  {
3374  if (mpRowHeights->getRangeData(nStartRow, aData) &&
3375  nNewHeight == aData.mnValue && nEndRow <= aData.mnRow2)
3376  {
3377  bSingle = false; // no difference in this range
3378  }
3379  }
3380 
3381  // No idea why 20 is used here
3382  if (!bSingle || nEndRow - nStartRow < 20)
3383  {
3384  bChanged = lcl_pixelSizeChanged(*mpRowHeights, nStartRow, nEndRow, nNewHeight, nPPTY, bApi);
3385  if (bChanged)
3386  mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
3387  }
3388  else
3389  {
3390  SCROW nMid = (nStartRow + nEndRow) / 2;
3391  // No idea why nPPTY is ignored in these recursive calls and instead 1.0 is used
3392  if (SetRowHeightRange(nStartRow, nMid, nNewHeight, 1.0, bApi))
3393  bChanged = true;
3394  if (SetRowHeightRange(nMid + 1, nEndRow, nNewHeight, 1.0, bApi))
3395  bChanged = true;
3396  }
3397 
3398  if (bChanged)
3400  }
3401  else
3402  {
3403  OSL_FAIL("Invalid row number or no heights");
3404  }
3405 
3406  return bChanged;
3407 }
3408 
3409 void ScTable::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight )
3410 {
3411  if (!ValidRow(nStartRow) || !ValidRow(nEndRow) || !mpRowHeights)
3412  return;
3413 
3414  if (!nNewHeight)
3415  nNewHeight = ScGlobal::nStdRowHeight;
3416 
3417  mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
3418 }
3419 
3420 void ScTable::SetManualHeight( SCROW nStartRow, SCROW nEndRow, bool bManual )
3421 {
3422  if (ValidRow(nStartRow) && ValidRow(nEndRow) && pRowFlags)
3423  {
3424  if (bManual)
3425  pRowFlags->OrValue( nStartRow, nEndRow, CRFlags::ManualSize);
3426  else
3427  pRowFlags->AndValue( nStartRow, nEndRow, ~CRFlags::ManualSize);
3428  }
3429  else
3430  {
3431  OSL_FAIL("Invalid row number or no column flags");
3432  }
3433 }
3434 
3435 sal_uInt16 ScTable::GetColWidth( SCCOL nCol, bool bHiddenAsZero ) const
3436 {
3437  OSL_ENSURE(ValidCol(nCol),"wrong column number");
3438 
3439  if (ValidCol(nCol) && mpColFlags && mpColWidth)
3440  {
3441  if (bHiddenAsZero && ColHidden(nCol))
3442  return 0;
3443  else
3444  return mpColWidth->GetValue(nCol);
3445  }
3446  else
3447  return sal_uInt16(STD_COL_WIDTH);
3448 }
3449 
3450 tools::Long ScTable::GetColWidth( SCCOL nStartCol, SCCOL nEndCol ) const
3451 {
3452  if (!ValidCol(nStartCol) || !ValidCol(nEndCol) || nStartCol > nEndCol)
3453  return 0;
3454 
3455  tools::Long nW = 0;
3456  bool bHidden = false;
3457  SCCOL nLastHiddenCol = -1;
3458  auto colWidthIt = mpColWidth->begin() + nStartCol;
3459  for (SCCOL nCol = nStartCol; nCol <= nEndCol; (++nCol <= nEndCol) ? ++colWidthIt : (void)false)
3460  {
3461  if (nCol > nLastHiddenCol)
3462  bHidden = ColHidden(nCol, nullptr, &nLastHiddenCol);
3463 
3464  if (bHidden)
3465  continue;
3466 
3467  nW += *colWidthIt;
3468  }
3469  return nW;
3470 }
3471 
3472 sal_uInt16 ScTable::GetOriginalWidth( SCCOL nCol ) const // always the set value
3473 {
3474  OSL_ENSURE(ValidCol(nCol),"wrong column number");
3475 
3476  if (ValidCol(nCol) && mpColWidth)
3477  return mpColWidth->GetValue(nCol);
3478  else
3479  return sal_uInt16(STD_COL_WIDTH);
3480 }
3481 
3482 sal_uInt16 ScTable::GetCommonWidth( SCCOL nEndCol ) const
3483 {
3484  // get the width that is used in the largest continuous column range (up to nEndCol)
3485 
3486  if ( !ValidCol(nEndCol) )
3487  {
3488  OSL_FAIL("wrong column");
3489  nEndCol = rDocument.MaxCol();
3490  }
3491 
3492  sal_uInt16 nMaxWidth = 0;
3493  sal_uInt16 nMaxCount = 0;
3494  SCCOL nRangeStart = 0;
3495  while ( nRangeStart <= nEndCol )
3496  {
3497  // skip hidden columns
3498  while ( nRangeStart <= nEndCol && ColHidden(nRangeStart) )
3499  ++nRangeStart;
3500  if ( nRangeStart <= nEndCol )
3501  {
3502  sal_uInt16 nThisCount = 0;
3503  auto colWidthIt = mpColWidth->begin() + nRangeStart;
3504  sal_uInt16 nThisWidth = *colWidthIt;
3505  SCCOL nRangeEnd = nRangeStart;
3506  while ( nRangeEnd <= nEndCol && *colWidthIt == nThisWidth )
3507  {
3508  ++nThisCount;
3509  ++nRangeEnd;
3510  ++colWidthIt;
3511 
3512  // skip hidden columns
3513  while ( nRangeEnd <= nEndCol && ColHidden(nRangeEnd) )
3514  {
3515  ++nRangeEnd;
3516  ++colWidthIt;
3517  }
3518  }
3519 
3520  if ( nThisCount > nMaxCount )
3521  {
3522  nMaxCount = nThisCount;
3523  nMaxWidth = nThisWidth;
3524  }
3525 
3526  nRangeStart = nRangeEnd; // next range
3527  }
3528  }
3529 
3530  return nMaxWidth;
3531 }
3532 
3533 sal_uInt16 ScTable::GetRowHeight( SCROW nRow, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const
3534 {
3535  SAL_WARN_IF(!ValidRow(nRow), "sc", "Invalid row number " << nRow);
3536 
3537  if (ValidRow(nRow) && mpRowHeights)
3538  {
3539  if (bHiddenAsZero && RowHidden( nRow, pStartRow, pEndRow))
3540  return 0;
3541  else
3542  {
3544  if (!mpRowHeights->getRangeData(nRow, aData))
3545  {
3546  if (pStartRow)
3547  *pStartRow = nRow;
3548  if (pEndRow)
3549  *pEndRow = nRow;
3550  // TODO: What should we return in case the search fails?
3551  return 0;
3552  }
3553 
3554  // If bHiddenAsZero, pStartRow and pEndRow were initialized to
3555  // boundaries of a non-hidden segment. Assume that the previous and
3556  // next segment are hidden then and limit the current height
3557  // segment.
3558  if (pStartRow)
3559  *pStartRow = (bHiddenAsZero ? std::max( *pStartRow, aData.mnRow1) : aData.mnRow1);
3560  if (pEndRow)
3561  *pEndRow = (bHiddenAsZero ? std::min( *pEndRow, aData.mnRow2) : aData.mnRow2);
3562  return aData.mnValue;
3563  }
3564  }
3565  else
3566  {
3567  if (pStartRow)
3568  *pStartRow = nRow;
3569  if (pEndRow)
3570  *pEndRow = nRow;
3571  return ScGlobal::nStdRowHeight;
3572  }
3573 }
3574 
3575 tools::Long ScTable::GetRowHeight( SCROW nStartRow, SCROW nEndRow, bool bHiddenAsZero ) const
3576 {
3577  OSL_ENSURE(ValidRow(nStartRow) && ValidRow(nEndRow),"wrong row number");
3578 
3579  if (ValidRow(nStartRow) && ValidRow(nEndRow) && mpRowHeights)
3580  {
3581  tools::Long nHeight = 0;
3582  SCROW nRow = nStartRow;
3583  while (nRow <= nEndRow)
3584  {
3585  SCROW nLastRow = -1;
3586  if (!( ( RowHidden(nRow, nullptr, &nLastRow) ) && bHiddenAsZero ) )
3587  {
3588  if (nLastRow > nEndRow)
3589  nLastRow = nEndRow;
3590  nHeight += mpRowHeights->getSumValue(nRow, nLastRow);
3591  }
3592  nRow = nLastRow + 1;
3593  }
3594  return nHeight;
3595  }
3596  else
3597  return (nEndRow - nStartRow + 1) * static_cast<tools::Long>(ScGlobal::nStdRowHeight);
3598 }
3599 
3600 tools::Long ScTable::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, double fScale, const tools::Long* pnMaxHeight ) const
3601 {
3602  OSL_ENSURE(ValidRow(nStartRow) && ValidRow(nEndRow),"wrong row number");
3603 
3604  if (ValidRow(nStartRow) && ValidRow(nEndRow) && mpRowHeights)
3605  {
3606  tools::Long nHeight = 0;
3607  SCROW nRow = nStartRow;
3608  while (nRow <= nEndRow)
3609  {
3610  SCROW nLastRow = -1;
3611  if (!RowHidden(nRow, nullptr, &nLastRow))
3612  {
3613  if (nLastRow > nEndRow)
3614  nLastRow = nEndRow;
3615 
3616  // #i117315# can't use getSumValue, because individual values must be rounded
3618  while (nRow <= nLastRow)
3619  {
3620  sal_uInt16 nRowVal;
3621  if (!aSegmentIter.getValue(nRow, nRowVal))
3622  return nHeight; // shouldn't happen
3623 
3624  SCROW nSegmentEnd = std::min( nLastRow, aSegmentIter.getLastPos() );
3625 
3626  // round-down a single height value, multiply resulting (pixel) values
3627  const tools::Long nOneHeight = static_cast<tools::Long>( nRowVal * fScale );
3628  // sometimes scaling results in zero height
3629  if (nOneHeight)
3630  {
3631  SCROW nRowsInSegment = nSegmentEnd + 1 - nRow;
3632  if (pnMaxHeight)
3633  {
3634  nRowsInSegment = std::min(nRowsInSegment, static_cast<SCROW>(*pnMaxHeight / nOneHeight + 1));
3635  nHeight += nOneHeight * nRowsInSegment;
3636  if (nHeight > *pnMaxHeight)
3637  return nHeight;
3638  }
3639  else
3640  nHeight += nOneHeight * nRowsInSegment;
3641  }
3642 
3643  nRow = nSegmentEnd + 1;
3644  }
3645  }
3646  nRow = nLastRow + 1;
3647  }
3648  return nHeight;
3649  }
3650  else
3651  {
3652  const tools::Long nOneHeight = static_cast<tools::Long>(ScGlobal::nStdRowHeight * fScale);
3653  SCROW nRowsInSegment = nEndRow - nStartRow + 1;
3654  if (pnMaxHeight)
3655  {
3656  nRowsInSegment = std::min(nRowsInSegment, static_cast<SCROW>(*pnMaxHeight / nOneHeight + 1));
3657  return nOneHeight * nRowsInSegment;
3658  }
3659  else
3660  return static_cast<tools::Long>(nRowsInSegment * nOneHeight);
3661  }
3662 }
3663 
3664 sal_uInt16 ScTable::GetOriginalHeight( SCROW nRow ) const // non-0 even if hidden
3665 {
3666  OSL_ENSURE(ValidRow(nRow),"wrong row number");
3667 
3668  if (ValidRow(nRow) && mpRowHeights)
3669  return mpRowHeights->getValue(nRow);
3670  else
3671  return ScGlobal::nStdRowHeight;
3672 }
3673 
3674 // Column/Row -Flags
3675 
3677 {
3678  if (!ValidRow(nRow))
3679  return 0;
3680 
3681  SCROW nLastRow = -1;
3682  if (!RowHidden(nRow, nullptr, &nLastRow) || !ValidRow(nLastRow))
3683  return 0;
3684 
3685  return nLastRow - nRow + 1;
3686 }
3687 
3688 //TODO: combine ShowRows / DBShowRows
3689 
3690 void ScTable::ShowCol(SCCOL nCol, bool bShow)
3691 {
3692  if (ValidCol(nCol))
3693  {
3694  bool bWasVis = !ColHidden(nCol);
3695  if (bWasVis != bShow)
3696  {
3697  SetColHidden(nCol, nCol, !bShow);
3698 
3700  if ( pCharts )
3701  pCharts->SetRangeDirty(ScRange( nCol, 0, nTab, nCol, rDocument.MaxRow(), nTab ));
3702  }
3703  }
3704  else
3705  {
3706  OSL_FAIL("Invalid column number or no flags");
3707  }
3708 }
3709 
3710 void ScTable::ShowRow(SCROW nRow, bool bShow)
3711 {
3712  if (ValidRow(nRow) && pRowFlags)
3713  {
3714  bool bWasVis = !RowHidden(nRow);
3715  if (bWasVis != bShow)
3716  {
3717  SetRowHidden(nRow, nRow, !bShow);
3718  if (bShow)
3719  SetRowFiltered(nRow, nRow, false);
3721  if ( pCharts )
3722  pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, rDocument.MaxCol(), nRow, nTab ));
3723 
3725  }
3726  }
3727  else
3728  {
3729  OSL_FAIL("Invalid row number or no flags");
3730  }
3731 }
3732 
3733 void ScTable::DBShowRow(SCROW nRow, bool bShow)
3734 {
3735  if (ValidRow(nRow) && pRowFlags)
3736  {
3737  // Always set filter flag; unchanged when Hidden
3738  bool bChanged = SetRowHidden(nRow, nRow, !bShow);
3739  SetRowFiltered(nRow, nRow, !bShow);
3740 
3741  if (bChanged)
3742  {
3744  if ( pCharts )
3745  pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, rDocument.MaxCol(), nRow, nTab ));
3746 
3747  if (pOutlineTable)
3748  UpdateOutlineRow( nRow, nRow, bShow );
3749 
3751  }
3752  }
3753  else
3754  {
3755  OSL_FAIL("Invalid row number or no flags");
3756  }
3757 }
3758 
3759 void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
3760 {
3761  SCROW nStartRow = nRow1;
3762  while (nStartRow <= nRow2)
3763  {
3764  SCROW nEndRow = -1;
3765  bool bWasVis = !RowHiddenLeaf(nStartRow, nullptr, &nEndRow);
3766  if (nEndRow > nRow2)
3767  nEndRow = nRow2;
3768 
3769  bool bChanged = ( bWasVis != bShow );
3770 
3771  SetRowHidden(nStartRow, nEndRow, !bShow);
3772  SetRowFiltered(nStartRow, nEndRow, !bShow);
3773 
3774  if ( bChanged )
3775  {
3777  if ( pCharts )
3778  pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, rDocument.MaxCol(), nEndRow, nTab ));
3779  }
3780 
3781  nStartRow = nEndRow + 1;
3782  }
3783 
3784  // #i12341# For Show/Hide rows, the outlines are updated separately from the outside.
3785  // For filtering, the changes aren't visible to the caller, so UpdateOutlineRow has
3786  // to be done here.
3787  if (pOutlineTable)
3788  UpdateOutlineRow( nRow1, nRow2, bShow );
3789 }
3790 
3791 void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
3792 {
3793  SCROW nStartRow = nRow1;
3794 
3795  // #i116164# if there are no drawing objects within the row range, a single HeightChanged call is enough
3796  ScDrawLayer* pDrawLayer = rDocument.GetDrawLayer();
3797  bool bHasObjects = pDrawLayer && pDrawLayer->HasObjectsInRows( nTab, nRow1, nRow2 );
3798 
3799  while (nStartRow <= nRow2)
3800  {
3801  SCROW nEndRow = -1;
3802  bool bWasVis = !RowHiddenLeaf(nStartRow, nullptr, &nEndRow);
3803  if (nEndRow > nRow2)
3804  nEndRow = nRow2;
3805 
3806  bool bChanged = ( bWasVis != bShow );
3807 
3808  SetRowHidden(nStartRow, nEndRow, !bShow);
3809  if (bShow)
3810  SetRowFiltered(nStartRow, nEndRow, false);
3811 
3812  if ( bChanged )
3813  {
3815  if ( pCharts )
3816  pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, rDocument.MaxCol(), nEndRow, nTab ));
3817 
3819  }
3820 
3821  nStartRow = nEndRow + 1;
3822  }
3823 
3824  if ( !bHasObjects )
3825  {
3826  // #i116164# set the flags for the whole range at once
3827  SetRowHidden(nRow1, nRow2, !bShow);
3828  if (bShow)
3829  SetRowFiltered(nRow1, nRow2, false);
3830  }
3831 }
3832 
3833 bool ScTable::IsDataFiltered(SCCOL nColStart, SCROW nRowStart, SCCOL nColEnd, SCROW nRowEnd) const
3834 {
3835  assert(nColStart <= nColEnd && nRowStart <= nRowEnd
3836  && "range must be normalized to obtain a valid result");
3837  for (SCROW i = nRowStart; i <= nRowEnd; ++i)
3838  {
3839  if (RowHidden(i))
3840  return true;
3841  }
3842  for (SCCOL i = nColStart; i <= nColEnd; ++i)
3843  {
3844  if (ColHidden(i))
3845  return true;
3846  }
3847  return false;
3848 }
3849 
3850 bool ScTable::IsDataFiltered(const ScRange& rRange) const
3851 {
3852  ScRange aNormalized(rRange.aStart, rRange.aEnd);
3853  return IsDataFiltered(aNormalized.aStart.Col(), aNormalized.aStart.Row(),
3854  aNormalized.aEnd.Col(), aNormalized.aEnd.Row());
3855 }
3856 
3857 void ScTable::SetRowFlags( SCROW nRow, CRFlags nNewFlags )
3858 {
3859  if (ValidRow(nRow) && pRowFlags)
3860  pRowFlags->SetValue( nRow, nNewFlags);
3861  else
3862  {
3863  OSL_FAIL("Invalid row number or no flags");
3864  }
3865 }
3866 
3867 void ScTable::SetRowFlags( SCROW nStartRow, SCROW nEndRow, CRFlags nNewFlags )
3868 {
3869  if (ValidRow(nStartRow) && ValidRow(nEndRow) && pRowFlags)
3870  pRowFlags->SetValue( nStartRow, nEndRow, nNewFlags);
3871  else
3872  {
3873  OSL_FAIL("Invalid row number(s) or no flags");
3874  }
3875 }
3876 
3878 {
3879  if (ValidCol(nCol) && mpColFlags)
3880  return mpColFlags->GetValue(nCol);
3881  else
3882  return CRFlags::NONE;
3883 }
3884 
3886 {
3887  if (ValidRow(nRow) && pRowFlags)
3888  return pRowFlags->GetValue(nRow);
3889  else
3890  return CRFlags::NONE;
3891 }
3892 
3894 {
3895  SCROW nLastFound = 0;
3896  if (pRowFlags)
3897  {
3898  SCROW nRow = pRowFlags->GetLastAnyBitAccess( CRFlags::All );
3899  if (ValidRow(nRow))
3900  nLastFound = nRow;
3901  }
3902 
3903  if (!maRowManualBreaks.empty())
3904  nLastFound = ::std::max(nLastFound, *maRowManualBreaks.rbegin());
3905 
3906  if (mpHiddenRows)
3907  {
3908  SCROW nRow = mpHiddenRows->findLastTrue();
3909  if (ValidRow(nRow))
3910  nLastFound = ::std::max(nLastFound, nRow);
3911  }
3912 
3913  if (mpFilteredRows)
3914  {
3915  SCROW nRow = mpFilteredRows->findLastTrue();
3916  if (ValidRow(nRow))
3917  nLastFound = ::std::max(nLastFound, nRow);
3918  }
3919 
3920  return nLastFound;
3921 }
3922 
3924 {
3925  if ( !mpColFlags )
3926  return 0;
3927 
3928  SCCOL nLastFound = 0;
3929  auto colWidthIt = mpColWidth->begin() + 1;
3930  for (SCCOL nCol = 1; nCol <= GetDoc().MaxCol(); (++nCol <= GetDoc().MaxCol()) ? ++colWidthIt : (void)false)
3931  if ((mpColFlags->GetValue(nCol) & CRFlags::All) || (*colWidthIt != STD_COL_WIDTH))
3932  nLastFound = nCol;
3933 
3934  return nLastFound;
3935 }
3936 
3938 {
3939  if ( !pRowFlags )
3940  return 0;
3941 
3942  SCROW nLastFlags = GetLastFlaggedRow();
3943 
3944  // Find the last row position where the height is NOT the standard row
3945  // height.
3946  // KOHEI: Test this to make sure it does what it's supposed to.
3947  SCROW nLastHeight = mpRowHeights->findLastTrue(ScGlobal::nStdRowHeight);
3948  if (!ValidRow(nLastHeight))
3949  nLastHeight = 0;
3950 
3951  return std::max( nLastFlags, nLastHeight);
3952 }
3953 
3954 bool ScTable::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, bool bShow )
3955 {
3956  if (pOutlineTable && mpColFlags)
3957  {
3958  return pOutlineTable->GetColArray().ManualAction( nStartCol, nEndCol, bShow, *this, true );
3959  }
3960  else
3961  return false;
3962 }
3963 
3964 bool ScTable::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, bool bShow )
3965 {
3966  if (pOutlineTable && pRowFlags)
3967  return pOutlineTable->GetRowArray().ManualAction( nStartRow, nEndRow, bShow, *this, false );
3968  else
3969  return false;
3970 }
3971 
3972 void ScTable::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 )
3973 {
3974  // Column-wise expansion
3975 
3976  while (rX1 > 0 && ColHidden(rX1-1))
3977  --rX1;
3978 
3979  while (rX2 < rDocument.MaxCol() && ColHidden(rX2+1))
3980  ++rX2;
3981 
3982  // Row-wise expansion
3983 
3984  if (rY1 > 0)
3985  {
3987  if (mpHiddenRows->getRangeData(rY1-1, aData) && aData.mbValue)
3988  {
3989  SCROW nStartRow = aData.mnRow1;
3990  if (ValidRow(nStartRow))
3991  rY1 = nStartRow;
3992  }
3993  }
3994  if (rY2 < rDocument.MaxRow())
3995  {
3996  SCROW nEndRow = -1;
3997  if (RowHidden(rY2+1, nullptr, &nEndRow) && ValidRow(nEndRow))
3998  rY2 = nEndRow;
3999  }
4000 }
4001 
4002 void ScTable::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 )
4003 {
4004  while ( rX2>rX1 && ColHidden(rX2) )
4005  --rX2;
4006  while ( rX2>rX1 && ColHidden(rX1) )
4007  ++rX1;
4008 
4009  if (rY1 < rY2)
4010  {
4012  if (mpHiddenRows->getRangeData(rY2, aData) && aData.mbValue)
4013  {
4014  SCROW nStartRow = aData.mnRow1;
4015  if (ValidRow(nStartRow) && nStartRow >= rY1)
4016  rY2 = nStartRow;
4017  }
4018  }
4019 
4020  if (rY1 < rY2)
4021  {
4022  SCROW nEndRow = -1;
4023  if (RowHidden(rY1, nullptr, &nEndRow) && ValidRow(nEndRow) && nEndRow <= rY2)
4024  rY1 = nEndRow;
4025  }
4026 }
4027 
4028 // Auto-Outline
4029 
4030 template< typename T >
4031 static short DiffSign( T a, T b )
4032 {
4033  return (a<b) ? -1 :
4034  (a>b) ? 1 : 0;
4035 }
4036 
4037 namespace {
4038 
4039 class OutlineArrayFinder
4040 {
4041  ScRange maRef;
4042  SCCOL mnCol;
4043  SCTAB mnTab;
4045  bool mbSizeChanged;
4046 
4047 public:
4048  OutlineArrayFinder(const ScRange& rRef, SCCOL nCol, SCTAB nTab, ScOutlineArray* pArray, bool bSizeChanged) :
4049  maRef(rRef), mnCol(nCol), mnTab(nTab), mpArray(pArray),
4050  mbSizeChanged(bSizeChanged) {}
4051 
4052  bool operator() (size_t nRow, const ScFormulaCell* pCell)
4053  {
4054  SCROW nRow2 = static_cast<SCROW>(nRow);
4055 
4056  if (!pCell->HasRefListExpressibleAsOneReference(maRef))
4057  return false;
4058 
4059  if (maRef.aStart.Row() != nRow2 || maRef.aEnd.Row() != nRow2 ||
4060  maRef.aStart.Tab() != mnTab || maRef.aEnd.Tab() != mnTab)
4061  return false;
4062 
4063  if (DiffSign(maRef.aStart.Col(), mnCol) != DiffSign(maRef.aEnd.Col(), mnCol))
4064  return false;
4065 
4066  return mpArray->Insert(maRef.aStart.Col(), maRef.aEnd.Col(), mbSizeChanged);
4067  }
4068 };
4069 
4070 }
4071 
4072 void ScTable::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
4073 {
4074  typedef mdds::flat_segment_tree<SCROW, bool> UsedRowsType;
4075 
4076  bool bSizeChanged = false;
4077 
4078  SCCOL nCol;
4079  SCROW nRow;
4080  bool bFound;
4081  ScRange aRef;
4082 
4083  nEndCol = ClampToAllocatedColumns(nEndCol);
4084 
4086 
4087  // Rows
4088 
4089  UsedRowsType aUsed(0, rDocument.MaxRow()+1, false);
4090  for (nCol=nStartCol; nCol<=nEndCol; nCol++)
4091  aCol[nCol].FindUsed(nStartRow, nEndRow, aUsed);
4092  aUsed.build_tree();
4093 
4094  ScOutlineArray& rRowArray = pOutlineTable->GetRowArray();
4095  for (nRow=nStartRow; nRow<=nEndRow; nRow++)
4096  {
4097  bool bUsed = false;
4098  SCROW nLastRow = nRow;
4099  aUsed.search_tree(nRow, bUsed, nullptr, &nLastRow);
4100  if (!bUsed)
4101  {
4102  nRow = nLastRow;
4103  continue;
4104  }
4105 
4106  bFound = false;
4107  for (nCol=nStartCol; nCol<=nEndCol && !bFound; nCol++)
4108  {
4109  ScRefCellValue aCell = aCol[nCol].GetCellValue(nRow);
4110 
4111  if (aCell.meType != CELLTYPE_FORMULA)
4112  continue;
4113 
4115  continue;
4116 
4117  if ( aRef.aStart.Col() == nCol && aRef.aEnd.Col() == nCol &&
4118  aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab &&
4119  DiffSign( aRef.aStart.Row(), nRow ) ==
4120  DiffSign( aRef.aEnd.Row(), nRow ) )
4121  {
4122  if (rRowArray.Insert( aRef.aStart.Row(), aRef.aEnd.Row(), bSizeChanged ))
4123  {
4124  bFound = true;
4125  }
4126  }
4127  }
4128  }
4129 
4130  // Column
4131  ScOutlineArray& rColArray = pOutlineTable->GetColArray();
4132  for (nCol=nStartCol; nCol<=nEndCol; nCol++)
4133  {
4134  if (aCol[nCol].IsEmptyData())
4135  continue;
4136 
4137  OutlineArrayFinder aFunc(aRef, nCol, nTab, &rColArray, bSizeChanged);
4138  sc::FindFormula(aCol[nCol].maCells, nStartRow, nEndRow, aFunc);
4139  }
4140 }
4141 
4142  // CopyData - for Query in other range
4143 
4144 void ScTable::CopyData( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
4145  SCCOL nDestCol, SCROW nDestRow, SCTAB nDestTab )
4146 {
4147  //TODO: if used for multiple rows, optimize after columns!
4148 
4149  ScAddress aSrc( nStartCol, nStartRow, nTab );
4150  ScAddress aDest( nDestCol, nDestRow, nDestTab );
4151  ScRange aRange( aSrc, aDest );
4152  bool bThisTab = ( nDestTab == nTab );
4153  SCROW nDestY = nDestRow;
4154  for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++)
4155  {
4156  aSrc.SetRow( nRow );
4157  aDest.SetRow( nDestY );
4158  SCCOL nDestX = nDestCol;
4159  for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
4160  {
4161  aSrc.SetCol( nCol );
4162  aDest.SetCol( nDestX );
4163  ScCellValue aCell;
4164  aCell.assign(rDocument, ScAddress(nCol, nRow, nTab));
4165 
4166  if (aCell.meType == CELLTYPE_FORMULA)
4167  {
4168  sc::RefUpdateContext aCxt(rDocument);
4169  aCxt.meMode = URM_COPY;
4170  aCxt.maRange = aRange;
4171  aCxt.mnColDelta = nDestCol - nStartCol;
4172  aCxt.mnRowDelta = nDestRow - nStartRow;
4173  aCxt.mnTabDelta = nDestTab - nTab;
4174  aCell.mpFormula->UpdateReference(aCxt);
4175  aCell.mpFormula->aPos = aDest;
4176  }
4177 
4178  if (bThisTab)
4179  {
4180  aCell.release(CreateColumnIfNotExists(nDestX), nDestY);
4181  SetPattern( nDestX, nDestY, *GetPattern( nCol, nRow ) );
4182  }
4183  else
4184  {
4185  aCell.release(rDocument, aDest);
4186  rDocument.SetPattern( aDest, *GetPattern( nCol, nRow ) );
4187  }
4188 
4189  ++nDestX;
4190  }
4191  ++nDestY;
4192  }
4193 }
4194 
4196 {
4197  ScRange aRef;
4198 
4199  if (pCell->HasOneReference(aRef))
4200  {
4201  if (aRef.aStart.Col()==aRef.aEnd.Col() && aRef.aStart.Tab()==aRef.aEnd.Tab())
4202  {
4203  SCROW nEndRow;
4204  if (!RowFiltered(aRef.aStart.Row(), nullptr, &nEndRow))
4205  // row not filtered.
4206  nEndRow = ::std::numeric_limits<SCROW>::max();
4207 
4208  if (!ValidRow(nEndRow) || nEndRow < aRef.aEnd.Row())
4209  return true; // at least partly visible
4210  return false; // completely invisible
4211  }
4212  }
4213 
4214  return true; // somehow different
4215 }
4216 
4218 {
4219  return ScGlobal::getCharClass().uppercase(GetInputString(nCol, nRow).trim());
4220 }
4221 
4222 // Calculate the size of the sheet and set the size on DrawPage
4223 
4224 void ScTable::SetDrawPageSize(bool bResetStreamValid, bool bUpdateNoteCaptionPos,
4225  ScObjectHandling eObjectHandling)
4226 {
4227  ScDrawLayer* pDrawLayer = rDocument.GetDrawLayer();
4228  if( pDrawLayer )
4229  {
4230  const sal_Int64 nMax = ::std::numeric_limits<tools::Long>::max();
4231  // #i113884# Avoid int32 overflow with possible negative results than can cause bad effects.
4232  // If the draw page size is smaller than all rows, only the bottom of the sheet is affected.
4233  tools::Long x = std::min(o3tl::convert(GetColOffset(rDocument.MaxCol() + 1),
4235  nMax);
4236  tools::Long y = std::min(o3tl::convert(GetRowOffset(rDocument.MaxRow() + 1),
4238  nMax);
4239 
4240  if ( IsLayoutRTL() ) // IsNegativePage
4241  x = -x;
4242 
4243  pDrawLayer->SetPageSize(static_cast<sal_uInt16>(nTab), Size(x, y), bUpdateNoteCaptionPos,
4244  eObjectHandling);
4245  }
4246 
4247  // #i102616# actions that modify the draw page size count as sheet modification
4248  // (exception: InitDrawLayer)
4249  if (bResetStreamValid)
4250  SetStreamValid(false);
4251 }
4252 
4253 void ScTable::SetRangeName(std::unique_ptr<ScRangeName> pNew)
4254 {
4255  mpRangeName = std::move(pNew);
4256 
4257  //fdo#39792: mark stream as invalid, otherwise new ScRangeName will not be written to file
4258  SetStreamValid(false);
4259 }
4260 
4262 {
4263  if (!mpRangeName)
4264  mpRangeName.reset(new ScRangeName);
4265  return mpRangeName.get();
4266 }
4267 
4268 tools::Long ScTable::GetRowOffset( SCROW nRow, bool bHiddenAsZero ) const
4269 {
4270  tools::Long n = 0;
4271  if ( mpHiddenRows && mpRowHeights )
4272  {
4273  if (nRow == 0)
4274  return 0;
4275  else if (nRow == 1)
4276  return GetRowHeight(0, nullptr, nullptr, bHiddenAsZero );
4277 
4278  n = GetTotalRowHeight(0, nRow-1, bHiddenAsZero);
4279 #if OSL_DEBUG_LEVEL > 0
4280  if (n == ::std::numeric_limits<tools::Long>::max())
4281  OSL_FAIL("ScTable::GetRowOffset: row heights overflow");
4282 #endif
4283  }
4284  else
4285  {
4286  OSL_FAIL("GetRowOffset: Data missing");
4287  }
4288  return n;
4289 }
4290 
4292 {
4293  tools::Long nSum = 0;
4294 
4296 
4297  ScFlatUInt16RowSegments::RangeData aRowHeightRange;
4298  aRowHeightRange.mnRow2 = -1;
4299  aRowHeightRange.mnValue = 1; // silence MSVC C4701
4300 
4301  for (SCROW nRow = 0; nRow <= rDocument.MaxRow(); ++nRow)
4302  {
4303  if (!mpHiddenRows->getRangeData(nRow, aData))
4304  // Failed to fetch the range data for whatever reason.
4305  break;
4306 
4307  if (aData.mbValue)
4308  {
4309  // This row is hidden. Skip ahead all hidden rows.
4310  nRow = aData.mnRow2;
4311  continue;
4312  }
4313 
4314  if (aRowHeightRange.mnRow2 < nRow)
4315  {
4316  if (!mpRowHeights->getRangeData(nRow, aRowHeightRange))
4317  // Failed to fetch the range data for whatever reason.
4318  break;
4319  }
4320 
4321  // find the last common row between hidden & height spans
4322  SCROW nLastCommon = std::min(aData.mnRow2, aRowHeightRange.mnRow2);
4323  assert (nLastCommon >= nRow);
4324  SCROW nCommon = nLastCommon - nRow + 1;
4325 
4326  // how much further to go ?
4327  tools::Long nPixelsLeft = nHeight - nSum;
4328  tools::Long nCommonPixels = static_cast<tools::Long>(aRowHeightRange.mnValue) * nCommon;
4329 
4330  // are we in the zone ?
4331  if (nCommonPixels > nPixelsLeft)
4332  {
4333  nRow += (nPixelsLeft + aRowHeightRange.mnValue - 1) / aRowHeightRange.mnValue;
4334 
4335  // FIXME: finding this next row is far from elegant,
4336  // we have a single caller, which subtracts one as well(!?)
4337  if (nRow >= rDocument.MaxRow())
4338  return rDocument.MaxRow();
4339 
4340  if (!mpHiddenRows->getRangeData(nRow, aData))
4341  // Failed to fetch the range data for whatever reason.
4342  break;
4343 
4344  if (aData.mbValue)
4345  // These rows are hidden.
4346  nRow = aData.mnRow2 + 1;
4347 
4348  return nRow <= rDocument.MaxRow() ? nRow : rDocument.MaxRow();
4349  }
4350 
4351  // skip the range and keep hunting
4352  nSum += nCommonPixels;
4353  nRow = nLastCommon;
4354  }
4355  return -1;
4356 }
4357 
4358 tools::Long ScTable::GetColOffset( SCCOL nCol, bool bHiddenAsZero ) const
4359 {
4360  tools::Long n = 0;
4361  if ( mpColWidth )
4362  {
4363  auto colWidthIt = mpColWidth->begin();
4364  for (SCCOL i = 0; i < nCol; (++i < nCol) ? ++colWidthIt : (void)false)
4365  if (!( bHiddenAsZero && ColHidden(i) ))
4366  n += *colWidthIt;
4367  }
4368  else
4369  {
4370  OSL_FAIL("GetColumnOffset: Data missing");
4371  }
4372  return n;
4373 }
4374 
4375 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr sal_Int32 STD_COL_WIDTH
Definition: global.hxx:86
If set, cloned formula cells will start to listen to the document.
void FindMaxRotCol(RowInfo *pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2)
Definition: table2.cxx:2444
void SetFormula(SCCOL nCol, SCROW nRow, const ScTokenArray &rArray, formula::FormulaGrammar::Grammar eGram)
Definition: table2.cxx:1709
void SetMergedCells(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: table2.cxx:2336
const ScRange & GetArea() const
Definition: markdata.hxx:85
void CellStorageModified()
Called whenever the state of cell array gets modified i.e.
Definition: column2.cxx:1647
void ApplyStyle(SCROW nRow, const ScStyleSheet *rStyle)
Definition: column.cxx:517
void CalcAfterLoad(sc::CompileFormulaContext &rCxt, bool bStartListening)
Definition: table2.cxx:2212
void CopyUpdated(const ScTable *pPosTab, ScTable *pDestTab) const
Definition: table2.cxx:1541
svl::SharedString GetSharedString(SCCOL nCol, SCROW nRow) const
Definition: table2.cxx:1746
constexpr double nPPTY
bool TestCopyScenarioTo(const ScTable *pDestTab) const
Definition: table2.cxx:1630
SCCOL GetColMerge() const
Definition: attrib.hxx:68
SCTAB nTab
Definition: table.hxx:207
SCROW mnRowDelta
Amount and direction of movement in the row direction.
const ScPatternAttr * GetPattern(SCCOL nCol, SCROW nRow) const
Definition: table2.cxx:2273
bool SetRowHeightRange(SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight, double nPPTY, bool bApi)
Definition: table2.cxx:3353
Temporarily switch on/off auto calculation mode.
Definition: scopetools.hxx:26
bool Intersects(const ScRange &) const
Definition: rangelst.cxx:1077
void CopySparklinesToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScTable *pDestTab)
Definition: table2.cxx:1463
SfxHintId
CellType meType
Definition: cellvalue.hxx:37
ScRotateDir GetRotateDir(const SfxItemSet *pCondSet) const
Definition: patattr.cxx:1371
ScFormulaCell * SetFormulaCell(SCCOL nCol, SCROW nRow, ScFormulaCell *pCell)
Takes ownership of pCell.
Definition: table2.cxx:1727
void ApplyStyleArea(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScStyleSheet &rStyle)
Definition: table2.cxx:2993
bool HasAttrib(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, HasAttrFlags nMask) const
Definition: table2.cxx:2287
bool HasScenarioRange(SCTAB nTab, const ScRange &rRange) const
Definition: documen3.cxx:867
ScAddress aStart
Definition: address.hxx:497
ScColumnsRange GetAllocatedColumnsRange(SCCOL begin, SCCOL end) const
Definition: table1.cxx:2696
ScRotateDir
Definition: fillinfo.hxx:40
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
SC_DLLPUBLIC bool IsTabProtected(SCTAB nTab) const
Definition: documen3.cxx:1913
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:42
void UnlockTable()
Definition: table2.cxx:2803
bool HasBlockMatrixFragment(const SCCOL nCol1, SCROW nRow1, const SCCOL nCol2, SCROW nRow2, bool bNoMatrixAtAll=false) const
Definition: table2.cxx:2519
void CompileAll(sc::CompileFormulaContext &rCxt)
Definition: table2.cxx:2177
Store parameters used in the ScDocument::SetString() method.
Definition: stringutil.hxx:34
bool SetOptimalHeight(sc::RowHeightContext &rCxt, SCROW nStartRow, SCROW nEndRow, bool bApi, ScProgress *pOuterProgress=nullptr, sal_uInt64 nProgressStart=0)
Definition: table1.cxx:456
void ForgetNoteCaptions(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bPreserveData)
Definition: table2.cxx:1926
void SetAllFormulasDirty(const sc::SetFormulaDirtyContext &rCxt)
Definition: table2.cxx:2107
void SetRowFlags(SCROW nRow, CRFlags nNewFlags)
Definition: table2.cxx:3857
void SetRowHeight(SCROW nRow, sal_uInt16 nNewHeight)
Definition: table2.cxx:3292
std::unique_ptr< ScFlatUInt16RowSegments > mpRowHeights
Definition: table.hxx:184
void CopyScenarioTo(ScTable *pDestTab) const
Definition: table2.cxx:1559
HasAttrFlags
Definition: global.hxx:183
constexpr TypedWhichId< SvxBoxItem > ATTR_BORDER(150)
void SetPatternAreaCondFormat(SCCOL nCol, SCROW nStartRow, SCROW nEndRow, const ScPatternAttr &rAttr, const ScCondFormatIndexes &rCondFormatIndexes)
Definition: table2.cxx:2969
Sparklines in a cell.
SCROW Row() const
Definition: address.hxx:274
Simple container to keep track of sheet - column pair.
Definition: columnset.hxx:23
sc::Sparkline * CreateSparkline(SCCOL nCol, SCROW nRow, std::shared_ptr< sc::SparklineGroup > const &pSparklineGroup)
Definition: table2.cxx:1851
Single reference (one address) into the sheet.
Definition: refdata.hxx:29
void ApplyPatternArea(SCROW nStartRow, SCROW nEndRow, const ScPatternAttr &rPatAttr, ScEditDataArray *pDataArray=nullptr, bool *const pIsChanged=nullptr)
Definition: column.cxx:483
ScTable * FetchTable(SCTAB nTab)
Definition: document.cxx:2536
bool IsDataFiltered(SCCOL nColStart, SCROW nRowStart, SCCOL nColEnd, SCROW nRowEnd) const
Definition: table2.cxx:3833
bool IsSelectionEditable(const ScMarkData &rMark, bool *pOnlyNotBecauseOfMatrix=nullptr) const
Definition: table2.cxx:2714
void SetRowHeightOnly(SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight)
Set specified row height to specified ranges.
Definition: table2.cxx:3409
const ScPatternAttr * GetPattern(SCROW nRow) const
Definition: column.hxx:954
SCTAB GetTab() const
Definition: table.hxx:285
SC_DLLPUBLIC bool IsActiveScenario(SCTAB nTab) const
Definition: documen3.cxx:880
size_t GetNoteCount(SCCOL nCol) const
Definition: table2.cxx:1904
ScRangeList & GetRangeList()
Definition: conditio.hxx:560
void ApplyPattern(SCCOL nCol, SCROW nRow, const ScPatternAttr &rAttr)
Definition: table2.cxx:2865
ScColumn * FetchColumn(SCCOL nCol)
Definition: table2.cxx:1235
ScObjectHandling
Definition: drwlayer.hxx:90
std::unique_ptr< ScPostIt > ReleaseNote(SCCOL nCol, SCROW nRow)
Definition: table2.cxx:1881
ScScenarioFlags
Definition: global.hxx:224
Tracks and gathers all created sparklines and sparkline groups.
const SfxPoolItem * GetItem(const SwTextAttr &rAttr, sal_uInt16 nWhich)
void CopyData(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCCOL nDestCol, SCROW nDestRow, SCTAB nDestTab)
Definition: table2.cxx:4144
bool Intersects(const ScRange &rRange) const
Definition: address.hxx:734
void TransposeReference()
SCCOL size() const
ScMF GetValue() const
Definition: attrib.hxx:97
sal_uIntPtr sal_uLong
long Long
SCROW GetRowForHeight(tools::Long nHeight) const
Get the last row such that the height of row 0 to the end row is as high as possible without exceedin...
Definition: table2.cxx:4291
bool TestInsertRow(SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize) const
Definition: table2.cxx:135
void SetCellNote(SCROW nRow, std::unique_ptr< ScPostIt > pNote)
Definition: column2.cxx:2187
Context for reference update during shifting, moving or copying of cell ranges.
void CopyRowFiltered(const ScTable &rTable, SCROW nStartRow, SCROW nEndRow)
Definition: table5.cxx:907
bool IsOverlapped() const
Definition: attrib.hxx:101
CellType GetCellType(const ScAddress &rPos) const
Definition: table.hxx:463
ScColumn & CreateColumnIfNotExists(const SCCOL nScCol)
Definition: table.hxx:289
constexpr Point convert(const Point &rPoint, o3tl::Length eFrom, o3tl::Length eTo)
void SetCalcNotification(bool bSet)
Definition: table2.cxx:130
void SetEditText(SCROW nRow, std::unique_ptr< EditTextObject > pEditText)
Definition: column3.cxx:2273
sal_Int64 n
const SfxPoolItem & GetAttr(SCROW nRow, sal_uInt16 nWhich) const
Definition: column.hxx:959
bool IsUndo() const
Definition: document.hxx:1588
void DetachFormulaCells(sc::EndListeningContext &rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: table2.cxx:1279
std::unique_ptr< ScFlatBoolColSegments > mpFilteredCols
Definition: table.hxx:190
const ScStyleSheet * GetSelectionStyle(const ScMarkData &rMark, bool &rFound) const
Definition: table2.cxx:3047
Rich-text attributes.
ScColumnVector::const_iterator end() const
bool HasScenarioRange(const ScRange &rRange) const
Definition: table2.cxx:1588
sal_Int32 mnCol
sal_uInt16 nLockCount
Definition: table.hxx:222
CommentCaptionState GetAllNoteCaptionsState(const ScRange &rRange, std::vector< sc::NoteEntry > &rNotes)
Definition: table2.cxx:1952
std::unordered_map< sal_uInt32, sal_uInt32 > SvNumberFormatterMergeMap
void FillRangeListWithMarks(ScRangeList *pList, bool bClear, SCTAB nForTab=-1) const
Create a range list of marks.
Definition: markdata.cxx:372
Store position data for column array storage.
sal_uInt16 GetDistance(SvxBoxItemLine nLine) const
bool mbPageBreaksValid
Definition: table.hxx:248
InsertDeleteFlags getInsertFlag() const
bool IsClipOrUndo() const
Definition: document.hxx:1587
void TransposeColPatterns(ScTable *pTransClip, SCCOL nCol1, SCCOL nCol, SCROW nRow1, SCROW nRow2, SCROW nCombinedStartRow, bool bIncludeFiltered, const std::vector< SCROW > &rFilteredRows, SCROW nRowDestOffset)
Transpose clipboard patterns.
Definition: table2.cxx:1049
bool HasObjectsInRows(SCTAB nTab, SCROW nStartRow, SCROW nEndRow)
Definition: drwlayer.cxx:1487
void CopyStaticToDocument(SCROW nRow1, SCROW nRow2, const SvNumberFormatterMergeMap &rMap, ScColumn &rDestCol)
Definition: column.cxx:972
bool CompileErrorCells(sc::CompileFormulaContext &rCxt, FormulaError nErrCode)
Definition: table2.cxx:2200
sal_uInt16 GetTextWidth(SCCOL nCol, SCROW nRow) const
Definition: table2.cxx:86
void GetFirstDataPos(SCCOL &rCol, SCROW &rRow) const
Definition: table2.cxx:2029
ScAddress aEnd
Definition: address.hxx:498
void SetManualHeight(SCROW nStartRow, SCROW nEndRow, bool bManual)
Definition: table2.cxx:3420
void SetColHidden(SCCOL nStartCol, SCCOL nEndCol, bool bHidden)
Definition: table5.cxx:622
ScPostIt * GetNote(SCCOL nCol, SCROW nRow)
Definition: table2.cxx:1889
void SetAttrEntries(std::vector< ScAttrEntry > &&vNewData)
Definition: column.hxx:1035
virtual SfxItemSet & GetItemSet()
This is very similar to ScCellValue, except that it references the original value instead of copying ...
Definition: cellvalue.hxx:103
void UndoToTable(sc::CopyToDocContext &rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, InsertDeleteFlags nFlags, bool bMarked, ScTable *pDestTab)
Definition: table2.cxx:1489
Sparkline data, used for rendering the content of a cell.
Definition: Sparkline.hxx:27
void DeleteRow(const sc::ColumnSet &rRegroupCols, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize, bool *pUndoOutline, std::vector< ScAddress > *pGroupPos)
Definition: table2.cxx:202
sal_uInt16 GetOriginalHeight(SCROW nRow) const
Definition: table2.cxx:3664
void RemoveEditTextCharAttribs(SCCOL nCol, SCROW nRow, const ScPatternAttr &rAttr)
Definition: table2.cxx:1805
const editeng::SvxBorderLine * GetRight() const
const ScStyleSheet * GetStyle(SCCOL nCol, SCROW nRow) const
Definition: table2.cxx:3040
void ChangeSelectionIndent(bool bIncrement, const ScMarkData &rMark, SCCOL nCol)
Definition: column.cxx:409
float x
void TransposeClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCROW nCombinedStartRow, SCROW nRowDestOffset, ScTable *pTransClip, InsertDeleteFlags nFlags, bool bAsLink, bool bIncludeFiltered)
Definition: table2.cxx:987
void MixData(sc::MixDocContext &rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScPasteFunc nFunction, bool bSkipEmpty, const ScTable *pSrcTab)
Definition: table2.cxx:784
bool HasData(SCCOL nCol, SCROW nRow) const
Definition: table2.cxx:2055
void SetDirtyAfterLoad()
Definition: table2.cxx:2132
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:494
void MergeBlockFrame(SvxBoxItem *pLineOuter, SvxBoxInfoItem *pLineInner, ScLineFlags &rFlags, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow) const
Definition: table2.cxx:2837
void ApplySelectionStyle(const ScStyleSheet &rStyle, const ScMarkData &rMark)
Definition: table2.cxx:3024
std::unique_ptr< ScRangeName > mpRangeName
Definition: table.hxx:229
SCROW nRowNo
Definition: fillinfo.hxx:233
constexpr TypedWhichId< ScMergeAttr > ATTR_MERGE(144)
bool bTableAreaVisibleValid
Definition: table.hxx:241
void ApplyAttr(SCCOL nCol, SCROW nRow, const SfxPoolItem &rAttr)
Definition: table2.cxx:3181
ScColumnData aDefaultColData
Definition: table.hxx:254
sc::SparklineList maSparklineList
Definition: table.hxx:232
Internal use only (d&d undo): do not delete caption objects of cell notes.
void MarkScenarioIn(ScMarkData &rMark, ScScenarioFlags nNeededBits) const
Definition: table2.cxx:1577
bool UpdateReference(const sc::RefUpdateContext &rCxt, ScDocument *pUndoDoc=nullptr, const ScAddress *pUndoCellPos=nullptr)
bool ValidRow(SCROW nRow) const
Definition: table.hxx:335
SC_DLLPUBLIC ScDocumentPool * GetPool()
Definition: document.cxx:6156
bool TestInsertRow(SCSIZE nSize) const
Definition: column.hxx:1040
void StartListeners(sc::StartListeningContext &rCxt, bool bAll)
Either start all formula cells as listeners unconditionally, or start those that are marked "needs li...
Definition: table2.cxx:1251
void SetStreamValid(bool bSet, bool bIgnoreLock=false)
Definition: table1.cxx:374
FuncFlags mnFlags
Information about all parameters.
OUString GetFormula(SCCOL nCol, SCROW nRow) const
Definition: table2.cxx:1813
void AttachFormulaCells(sc::StartListeningContext &rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: table2.cxx:1271
Store arbitrary cell value of any kind.
Definition: cellvalue.hxx:35
constexpr TypedWhichId< ScRotateValueItem > ATTR_ROTATE_VALUE(135)
void ResetChanged(const ScRange &rRange)
Definition: table2.cxx:2218
ScFormulaCell * SetFormulaCell(SCROW nRow, ScFormulaCell *pCell, sc::StartListeningType eListenType=sc::SingleCellListening, bool bInheritNumFormatIfNeeded=true)
Takes ownership of pCell.
Definition: column3.cxx:2371
const ScRangeList & GetRange() const
Definition: conditio.hxx:558
static void lcl_SetTransposedPatternInRows(ScTable *pTransClip, SCROW nAttrRow1, SCROW nAttrRow2, SCCOL nCol1, SCROW nRow1, SCROW nCombinedStartRow, SCCOL nCol, const ScPatternAttr &rPatternAttr, bool bIncludeFiltered, const std::vector< SCROW > &rFilteredRows, SCROW nRowDestOffset)
Definition: table2.cxx:1019
void SetNumberFormat(SCCOL nCol, SCROW nRow, sal_uInt32 nNumberFormat)
Definition: table2.cxx:2265
bool IsBlockEditable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool *pOnlyNotBecauseOfMatrix=nullptr, bool bNoMatrixAtAll=false) const
Definition: table2.cxx:2632
tools::Long GetScaledRowHeight(SCROW nStartRow, SCROW nEndRow, double fScale, const tools::Long *pnMaxHeight=nullptr) const
Definition: table2.cxx:3600
void InsertRow(SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize)
Definition: table2.cxx:153
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:42
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:891
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
Definition: address.hxx:44
void SetTableOpDirty(const ScRange &)
Definition: table2.cxx:2124
void SetAnonymousDBData(std::unique_ptr< ScDBData > pDBData)
Definition: table1.cxx:2435
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
Definition: types.hxx:23
Additional class containing cell annotation data.
Definition: postit.hxx:160
void TransposeColNotes(ScTable *pTransClip, SCCOL nCol1, SCCOL nCol, SCROW nRow1, SCROW nRow2, SCROW nCombinedStartRow, bool bIncludeFiltered, SCROW nRowDestOffset)
Transpose clipboard notes.
Definition: table2.cxx:1120
static short DiffSign(T a, T b)
Definition: table2.cxx:4031
bool UpdateOutlineCol(SCCOL nStartCol, SCCOL nEndCol, bool bShow)
Definition: table2.cxx:3954
void SetNumberFormat(SCROW nRow, sal_uInt32 nNumberFormat)
Definition: column2.cxx:3247
void MergePatternArea(ScMergePatternState &rState, SCROW nRow1, SCROW nRow2, bool bDeep) const
Definition: column.hxx:936
double * GetValueCell(SCCOL nCol, SCROW nRow)
Definition: table2.cxx:1774
sc::CellStoreType maCells
Definition: column.hxx:196
std::shared_ptr< sc::Sparkline > GetSparkline(SCCOL nCol, SCROW nRow)
Definition: table2.cxx:1839
const std::shared_ptr< const ColumnSet > & getColumnSet() const
void SetColWidthOnly(SCCOL nCol, sal_uInt16 nNewWidth)
Definition: table2.cxx:3280
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:110
SCTAB Tab() const
Definition: address.hxx:283
void CopyToClip(sc::CopyToClipContext &rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScTable *pTable)
Definition: table2.cxx:489
void StripHidden(SCCOL &rX1, SCROW &rY1, SCCOL &rX2, SCROW &rY2)
Definition: table2.cxx:4002
SCCOL GetLastChangedColFlagsWidth() const
Definition: table2.cxx:3923
void SetRowManualBreaks(::std::set< SCROW > &&rBreaks)
Definition: table5.cxx:318
void SetRow(SCROW nRowP)
Definition: address.hxx:287
void release(ScDocument &rDoc, const ScAddress &rPos)
Set cell value at specified position in specified document.
Definition: cellvalue.cxx:432
void CopyColHidden(const ScTable &rTable, SCCOL nStartCol, SCCOL nEndCol)
Definition: table5.cxx:656
bool SetRowHidden(SCROW nStartRow, SCROW nEndRow, bool bHidden)
Definition: table5.cxx:572
void SetColWidth(SCCOL nCol, sal_uInt16 nNewWidth)
Definition: table2.cxx:3259
const editeng::SvxBorderLine * GetLine(SvxBoxItemLine nLine) const
bool HasValueData(SCCOL nCol, SCROW nRow) const
Definition: table2.cxx:2071
bool SetFormulaCells(SCROW nRow, std::vector< ScFormulaCell * > &rCells)
Definition: column3.cxx:2409
ScColumnVector::const_iterator begin() const
void SetValue(SCCOL nCol, SCROW nRow, const double &rVal)
Definition: table2.cxx:1754
std::unique_ptr< ScOutlineTable > pOutlineTable
Definition: table.hxx:198
ScAddress aPos
void DoAutoOutline(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow)
Definition: table2.cxx:4072
void SetRangeName(std::unique_ptr< ScRangeName > pNew)
Definition: table2.cxx:4253
void SetPattern(const ScAddress &rPos, const ScPatternAttr &rAttr)
Definition: table2.cxx:3162
bool RemoveFlags(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScMF nFlags)
Definition: table2.cxx:3150
ScBroadcastAreaSlotMachine * GetBASM() const
Definition: document.hxx:2224
tools::Long GetRowOffset(SCROW nRow, bool bHiddenAsZero=true) const
Definition: table2.cxx:4268
void SetAttrEntries(SCCOL nStartCol, SCCOL nEndCol, std::vector< ScAttrEntry > &&vNewData)
Definition: table2.cxx:2892
void SetCol(SCCOL nColP)
Definition: address.hxx:291
size_t size() const
Definition: conditio.cxx:1771
sal_uInt16 GetOriginalWidth(SCCOL nCol) const
Definition: table2.cxx:3472
bool HasSelectionMatrixFragment(const ScMarkData &rMark) const
Definition: table2.cxx:2615
std::unique_ptr< ScBitMaskCompressedArray< SCCOL, CRFlags > > mpColFlags
Definition: table.hxx:186
void PutInOrder(T &nStart, T &nEnd)
Definition: address.hxx:150
bool IsLayoutRTL() const
Definition: table.hxx:344
float y
bool IsColValid(const SCCOL nScCol) const
Definition: table.hxx:322
constexpr OUStringLiteral aData
bool SetString(SCROW nRow, SCTAB nTab, const OUString &rString, formula::FormulaGrammar::AddressConvention eConv, const ScSetStringParam *pParam=nullptr)
Returns true if the cell format was set as well.
Definition: column3.cxx:2253
bool HasRefListExpressibleAsOneReference(ScRange &rRange) const
constexpr double nPPTX
bool SetOutlineTable(const ScOutlineTable *pNewOutline)
Definition: table2.cxx:91
static SC_DLLPUBLIC sal_uInt16 nStdRowHeight
Definition: global.hxx:581
sal_uInt32 GetKey() const
Definition: conditio.hxx:590
void SetRange(const ScRangeList &rRanges)
Definition: conditio.cxx:1745
std::unique_ptr< ScFlatBoolColSegments &