1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <scitems.hxx>
21 #include <attrib.hxx>
22 #include <formulacell.hxx>
23 #include <table.hxx>
24 #include <column.hxx>
25 #include <document.hxx>
26 #include <drwlayer.hxx>
27 #include <global.hxx>
28 #include <stlpool.hxx>
29 #include <tabprotection.hxx>
30 #include <globstr.hrc>
31 #include <scresid.hxx>
32 #include <segmenttree.hxx>
33 #include <columniterator.hxx>
34 #include <globalnames.hxx>
35 #include <scmod.hxx>
36 #include <printopt.hxx>
37 #include <bcaslot.hxx>
38 #include <compressedarray.hxx>
39 #include <userdat.hxx>
40
41 #include <com/sun/star/sheet/TablePageBreakData.hpp>
42
43 #include <osl/diagnose.h>
44
45 #include <algorithm>
46 #include <limits>
47
48 using ::com::sun::star::uno::Sequence;
49 using ::com::sun::star::sheet::TablePageBreakData;
50 using ::std::set;
51
UpdatePageBreaks(const ScRange * pUserArea)52 void ScTable::UpdatePageBreaks(const ScRange* pUserArea)
53 {
54 if (rDocument.IsImportingXML())
55 return;
56
57 // pUserArea != NULL -> print area is specified. We need to force-update
58 // the page breaks.
59
60 if (!pUserArea)
61 {
62 if (!bPageSizeValid)
63 return;
64
65 // Always update breaks if force breaks option has changed
66 if (mbPageBreaksValid && mbForceBreaks == SC_MOD()->GetPrintOptions().GetForceBreaks())
67 return;
68 }
69
70 SfxStyleSheetBase* pStyle
71 = rDocument.GetStyleSheetPool()->Find(aPageStyle, SfxStyleFamily::Page);
72 if (!pStyle)
73 {
74 OSL_FAIL("UpdatePageBreaks: Style not found");
75 return;
76 }
77 SfxItemSet* pStyleSet = &pStyle->GetItemSet();
78 const SfxPoolItem* pItem;
79
80 SCCOL nStartCol = 0;
81 SCROW nStartRow = 0;
82 SCCOL nEndCol = rDocument.MaxCol();
83 SCROW nEndRow = rDocument.MaxRow();
84 if (pUserArea)
85 {
86 nStartCol = pUserArea->aStart.Col();
87 nStartRow = pUserArea->aStart.Row();
88 nEndCol = pUserArea->aEnd.Col();
89 nEndRow = pUserArea->aEnd.Row();
90 }
91 else
92 {
93 sal_uInt16 nAreaCount = GetPrintRangeCount();
94 if (nAreaCount > 1)
95 {
96 // Show nothing, when multiple ranges
97
98 for (SCCOL nX : GetColumnsRange(0, rDocument.MaxCol()))
99 RemoveColBreak(nX, true, false);
100
101 RemoveRowPageBreaks(0, rDocument.MaxRow() - 1);
102
103 return;
104 }
105 else if (nAreaCount == 1)
106 {
107 const ScRange* pArea = GetPrintRange(0);
108 if (pArea)
109 {
110 nStartCol = pArea->aStart.Col();
111 nStartRow = pArea->aStart.Row();
112 nEndCol = pArea->aEnd.Col();
113 nEndRow = pArea->aEnd.Row();
114 }
115 } // otherwise show everything
116 }
117
118 // get bSkipColBreaks/bSkipRowBreaks flags:
119 // fdo#40788 - print range scale settings can cause manual breaks to be
120 // ignored (see below). This behaviour may now be set by the user.
121 mbForceBreaks = SC_MOD()->GetPrintOptions().GetForceBreaks();
122 bool bSkipColBreaks = false;
123 bool bSkipRowBreaks = false;
124
125 if (!mbForceBreaks)
126 {
127 if (pStyleSet->GetItemState(ATTR_PAGE_SCALETOPAGES, false, &pItem) == SfxItemState::SET)
128 {
129 OSL_ENSURE(dynamic_cast<const SfxUInt16Item*>(pItem) != nullptr, "invalid Item");
130 bSkipColBreaks = bSkipRowBreaks
131 = static_cast<const SfxUInt16Item*>(pItem)->GetValue() > 0;
132 }
133
134 if (!bSkipColBreaks
135 && pStyleSet->GetItemState(ATTR_PAGE_SCALETO, false, &pItem) == SfxItemState::SET)
136 {
137 // #i54993# when fitting to width or height, ignore only manual breaks in that direction
138 const ScPageScaleToItem* pScaleToItem = static_cast<const ScPageScaleToItem*>(pItem);
139 if (pScaleToItem->GetWidth() > 0)
140 bSkipColBreaks = true;
141 if (pScaleToItem->GetHeight() > 0)
142 bSkipRowBreaks = true;
143 }
144 }
145
146 tools::Long nPageSizeX = aPageSizeTwips.Width();
147 tools::Long nPageSizeY = aPageSizeTwips.Height();
148
149 // Beginning: Remove breaks
150
151 for (SCCOL nX : GetColumnsRange(0, nStartCol - 1))
152 RemoveColBreak(nX, true, false);
153 RemoveRowPageBreaks(0, nStartRow - 1);
154
155 if (nStartCol > 0)
156 SetColBreak(nStartCol, true, false); // AREABREAK
157 if (nStartRow > 0)
158 SetRowBreak(nStartRow, true, false); // AREABREAK
159
160 // Middle part: Distribute breaks
161
162 bool bRepeatCol = (nRepeatStartX != SCCOL_REPEAT_NONE);
163 bool bColFound = false;
164 tools::Long nSizeX = 0;
165 for (SCCOL nX = nStartCol; nX <= nEndCol; nX++)
166 {
167 bool bStartOfPage = false;
168 tools::Long nThisX = ColHidden(nX) ? 0 : mpColWidth->GetValue(nX);
169 bool bManualBreak = HasColManualBreak(nX);
170 if ((nSizeX + nThisX > nPageSizeX) || (bManualBreak && !bSkipColBreaks))
171 {
172 SetColBreak(nX, true, false);
173 nSizeX = 0;
174 bStartOfPage = true;
175 }
176 else if (nX != nStartCol)
177 RemoveColBreak(nX, true, false);
178 else
179 bStartOfPage = true;
180
181 if (bStartOfPage && bRepeatCol && nX > nRepeatStartX && !bColFound)
182 {
183 // subtract size of repeat columns from page size
184 for (SCCOL i = nRepeatStartX; i <= nRepeatEndX; i++)
185 nPageSizeX -= ColHidden(i) ? 0 : mpColWidth->GetValue(i);
186 while (nX <= nRepeatEndX)
187 RemoveColBreak(++nX, true, false);
188 bColFound = true;
189 }
190
191 nSizeX += nThisX;
192 }
193
194 // Remove all page breaks in range.
195 RemoveRowPageBreaks(nStartRow + 1, nEndRow);
196
197 // And set new page breaks.
198 bool bRepeatRow = (nRepeatStartY != SCROW_REPEAT_NONE);
199 bool bRowFound = false;
200 tools::Long nSizeY = 0;
201 ScFlatBoolRowSegments::ForwardIterator aIterHidden(*mpHiddenRows);
202 ScFlatUInt16RowSegments::ForwardIterator aIterHeights(*mpRowHeights);
203 SCROW nNextManualBreak = GetNextManualBreak(nStartRow); // -1 => no more manual breaks
204 for (SCROW nY = nStartRow; nY <= nEndRow; ++nY)
205 {
206 bool bStartOfPage = false;
207 bool bThisRowHidden = false;
208 const bool bHasValue = aIterHidden.getValue(nY, bThisRowHidden);
209 assert(bHasValue);
210 (void)bHasValue;
211 tools::Long nThisY = 0;
212 if (!bThisRowHidden)
213 {
214 sal_uInt16 nTmp;
215 const bool bHasHeight = aIterHeights.getValue(nY, nTmp);
216 assert(bHasHeight);
217 if (bHasHeight)
218 nThisY = static_cast<tools::Long>(nTmp);
219 }
220
221 bool bManualBreak = false;
222 if (nNextManualBreak >= 0)
223 {
224 bManualBreak = (nY == nNextManualBreak);
225 if (nY >= nNextManualBreak)
226 // Query the next manual break position.
227 nNextManualBreak = GetNextManualBreak(nY + 1);
228 }
229
230 if ((nSizeY + nThisY > nPageSizeY) || (bManualBreak && !bSkipRowBreaks))
231 {
232 SetRowBreak(nY, true, false);
233 nSizeY = 0;
234 bStartOfPage = true;
235 }
236 else if (nY != nStartRow)
237 ; // page break already removed
238 else
239 bStartOfPage = true;
240
241 if (bStartOfPage && bRepeatRow && nY > nRepeatStartY && !bRowFound)
242 {
243 // subtract size of repeat rows from page size
244 tools::ULong nHeights = GetTotalRowHeight(nRepeatStartY, nRepeatEndY);
245 #if OSL_DEBUG_LEVEL > 0
246 if (nHeights == ::std::numeric_limits<tools::ULong>::max())
247 OSL_FAIL("ScTable::UpdatePageBreaks: row heights overflow");
248 #endif
249 nPageSizeY -= nHeights;
250 if (nY <= nRepeatEndY)
251 RemoveRowPageBreaks(nY, nRepeatEndY);
252 bRowFound = true;
253 }
254
255 if (bThisRowHidden)
256 {
257 // Hidden row range. Skip them unless there is a manual break.
258 SCROW nLastCommon = aIterHidden.getLastPos();
259 if (nNextManualBreak >= 0)
260 nLastCommon = ::std::min(nLastCommon, nNextManualBreak - 1);
261 nY = nLastCommon;
262 }
263 else
264 {
265 // Visible row range.
266
267 SCROW nLastHidden = aIterHidden.getLastPos();
268 SCROW nLastHeight = aIterHeights.getLastPos();
269 SCROW nLastCommon = ::std::min(nLastHidden, nLastHeight);
270 if (nNextManualBreak >= 0)
271 nLastCommon = ::std::min(nLastCommon, nNextManualBreak - 1);
272
273 if (nLastCommon > nY)
274 {
275 tools::Long nMaxMultiple = static_cast<tools::Long>(nLastCommon - nY);
276 tools::Long nMultiple = (nPageSizeY - nSizeY) / nThisY;
277 if (nMultiple > nMaxMultiple)
278 nMultiple = nMaxMultiple;
279 if (nMultiple > 1)
280 {
281 nSizeY += nThisY * (nMultiple - 1);
282 nY += nMultiple - 1;
283 }
284 }
285 }
286
287 nSizeY += nThisY;
288 }
289
290 // End: Remove Break
291
292 if (nEndCol < rDocument.MaxCol())
293 {
294 SetColBreak(nEndCol + 1, true, false); // AREABREAK
295 for (SCCOL nCol : GetColumnsRange(nEndCol + 2, rDocument.MaxCol()))
296 RemoveColBreak(nCol, true, false);
297 }
298 if (nEndRow < rDocument.MaxRow())
299 {
300 SetRowBreak(nEndRow + 1, true, false); // AREABREAK
301 if (nEndRow + 2 <= rDocument.MaxRow())
302 RemoveRowPageBreaks(nEndRow + 2, rDocument.MaxRow());
303 }
304 mbPageBreaksValid
305 = !pUserArea; // #i116881# the valid flag can only apply to the "no user area" case
306 }
307
RemoveManualBreaks()308 void ScTable::RemoveManualBreaks()
309 {
310 maRowManualBreaks.clear();
311 maColManualBreaks.clear();
312 InvalidatePageBreaks();
313
314 SetStreamValid(false);
315 }
316
HasManualBreaks() const317 bool ScTable::HasManualBreaks() const
318 {
319 return !maRowManualBreaks.empty() || !maColManualBreaks.empty();
320 }
321
SetRowManualBreaks(const::std::set<SCROW> & rBreaks)322 void ScTable::SetRowManualBreaks(const ::std::set<SCROW>& rBreaks)
323 {
324 maRowManualBreaks = rBreaks;
325 InvalidatePageBreaks();
326 SetStreamValid(false);
327 }
328
SetColManualBreaks(const::std::set<SCCOL> & rBreaks)329 void ScTable::SetColManualBreaks(const ::std::set<SCCOL>& rBreaks)
330 {
331 maColManualBreaks = rBreaks;
332 InvalidatePageBreaks();
333 SetStreamValid(false);
334 }
335
GetAllRowBreaks(set<SCROW> & rBreaks,bool bPage,bool bManual) const336 void ScTable::GetAllRowBreaks(set<SCROW>& rBreaks, bool bPage, bool bManual) const
337 {
338 if (bPage)
339 rBreaks = maRowPageBreaks;
340
341 if (bManual)
342 {
343 using namespace std;
344 copy(maRowManualBreaks.begin(), maRowManualBreaks.end(),
345 inserter(rBreaks, rBreaks.begin()));
346 }
347 }
348
GetAllColBreaks(set<SCCOL> & rBreaks,bool bPage,bool bManual) const349 void ScTable::GetAllColBreaks(set<SCCOL>& rBreaks, bool bPage, bool bManual) const
350 {
351 if (bPage)
352 rBreaks = maColPageBreaks;
353
354 if (bManual)
355 {
356 using namespace std;
357 copy(maColManualBreaks.begin(), maColManualBreaks.end(),
358 inserter(rBreaks, rBreaks.begin()));
359 }
360 }
361
HasRowPageBreak(SCROW nRow) const362 bool ScTable::HasRowPageBreak(SCROW nRow) const
363 {
364 if (!ValidRow(nRow))
365 return false;
366
367 return maRowPageBreaks.find(nRow) != maRowPageBreaks.end();
368 }
369
HasColPageBreak(SCCOL nCol) const370 bool ScTable::HasColPageBreak(SCCOL nCol) const
371 {
372 if (!ValidCol(nCol))
373 return false;
374
375 return maColPageBreaks.find(nCol) != maColPageBreaks.end();
376 }
377
HasRowManualBreak(SCROW nRow) const378 bool ScTable::HasRowManualBreak(SCROW nRow) const
379 {
380 if (!ValidRow(nRow))
381 return false;
382
383 return maRowManualBreaks.find(nRow) != maRowManualBreaks.end();
384 }
385
HasColManualBreak(SCCOL nCol) const386 bool ScTable::HasColManualBreak(SCCOL nCol) const
387 {
388 if (!ValidCol(nCol))
389 return false;
390
391 return maColManualBreaks.find(nCol) != maColManualBreaks.end();
392 }
393
GetNextManualBreak(SCROW nRow) const394 SCROW ScTable::GetNextManualBreak(SCROW nRow) const
395 {
396 set<SCROW>::const_iterator itr = maRowManualBreaks.lower_bound(nRow);
397 return itr == maRowManualBreaks.end() ? -1 : *itr;
398 }
399
RemoveRowPageBreaks(SCROW nStartRow,SCROW nEndRow)400 void ScTable::RemoveRowPageBreaks(SCROW nStartRow, SCROW nEndRow)
401 {
402 using namespace std;
403
404 if (!ValidRow(nStartRow) || !ValidRow(nEndRow))
405 return;
406
407 set<SCROW>::iterator low = maRowPageBreaks.lower_bound(nStartRow);
408 set<SCROW>::iterator high = maRowPageBreaks.upper_bound(nEndRow);
409 maRowPageBreaks.erase(low, high);
410 }
411
RemoveRowBreak(SCROW nRow,bool bPage,bool bManual)412 void ScTable::RemoveRowBreak(SCROW nRow, bool bPage, bool bManual)
413 {
414 if (!ValidRow(nRow))
415 return;
416
417 if (bPage)
418 maRowPageBreaks.erase(nRow);
419
420 if (bManual)
421 {
422 maRowManualBreaks.erase(nRow);
423 InvalidatePageBreaks();
424 }
425 }
426
RemoveColBreak(SCCOL nCol,bool bPage,bool bManual)427 void ScTable::RemoveColBreak(SCCOL nCol, bool bPage, bool bManual)
428 {
429 if (!ValidCol(nCol))
430 return;
431
432 if (bPage)
433 maColPageBreaks.erase(nCol);
434
435 if (bManual)
436 {
437 maColManualBreaks.erase(nCol);
438 InvalidatePageBreaks();
439 }
440 }
441
SetRowBreak(SCROW nRow,bool bPage,bool bManual)442 void ScTable::SetRowBreak(SCROW nRow, bool bPage, bool bManual)
443 {
444 if (!ValidRow(nRow))
445 return;
446
447 if (bPage)
448 maRowPageBreaks.insert(nRow);
449
450 if (bManual)
451 {
452 maRowManualBreaks.insert(nRow);
453 InvalidatePageBreaks();
454 }
455 }
456
SetColBreak(SCCOL nCol,bool bPage,bool bManual)457 void ScTable::SetColBreak(SCCOL nCol, bool bPage, bool bManual)
458 {
459 if (!ValidCol(nCol))
460 return;
461
462 if (bPage)
463 maColPageBreaks.insert(nCol);
464
465 if (bManual)
466 {
467 maColManualBreaks.insert(nCol);
468 InvalidatePageBreaks();
469 }
470 }
471
GetRowBreakData() const472 Sequence<TablePageBreakData> ScTable::GetRowBreakData() const
473 {
474 using ::std::copy;
475 using ::std::inserter;
476
477 set<SCROW> aRowBreaks = maRowPageBreaks;
478 copy(maRowManualBreaks.begin(), maRowManualBreaks.end(),
479 inserter(aRowBreaks, aRowBreaks.begin()));
480
481 sal_Int32 i = 0;
482 Sequence<TablePageBreakData> aSeq(aRowBreaks.size());
483
484 for (const SCROW nRow : aRowBreaks)
485 {
486 TablePageBreakData aData;
487 aData.Position = nRow;
488 aData.ManualBreak = HasRowManualBreak(nRow);
489 aSeq[i] = aData;
490 ++i;
491 }
492
493 return aSeq;
494 }
495
RowHidden(SCROW nRow,SCROW * pFirstRow,SCROW * pLastRow) const496 bool ScTable::RowHidden(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) const
497 {
498 if (!ValidRow(nRow))
499 {
500 if (pFirstRow)
501 *pFirstRow = nRow;
502 if (pLastRow)
503 *pLastRow = nRow;
504 return true;
505 }
506
507 ScFlatBoolRowSegments::RangeData aData;
508 if (!mpHiddenRows->getRangeData(nRow, aData))
509 {
510 // search failed.
511 if (pFirstRow)
512 *pFirstRow = nRow;
513 if (pLastRow)
514 *pLastRow = nRow;
515 return true;
516 }
517
518 if (pFirstRow)
519 *pFirstRow = aData.mnRow1;
520 if (pLastRow)
521 *pLastRow = aData.mnRow2;
522
523 return aData.mbValue;
524 }
525
RowHiddenLeaf(SCROW nRow,SCROW * pFirstRow,SCROW * pLastRow) const526 bool ScTable::RowHiddenLeaf(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) const
527 {
528 if (!ValidRow(nRow))
529 {
530 if (pFirstRow)
531 *pFirstRow = nRow;
532 if (pLastRow)
533 *pLastRow = nRow;
534 return true;
535 }
536
537 ScFlatBoolRowSegments::RangeData aData;
538 if (!mpHiddenRows->getRangeDataLeaf(nRow, aData))
539 {
540 // search failed.
541 if (pFirstRow)
542 *pFirstRow = nRow;
543 if (pLastRow)
544 *pLastRow = nRow;
545 return true;
546 }
547
548 if (pFirstRow)
549 *pFirstRow = aData.mnRow1;
550 if (pLastRow)
551 *pLastRow = aData.mnRow2;
552
553 return aData.mbValue;
554 }
555
HasHiddenRows(SCROW nStartRow,SCROW nEndRow) const556 bool ScTable::HasHiddenRows(SCROW nStartRow, SCROW nEndRow) const
557 {
558 SCROW nRow = nStartRow;
559 while (nRow <= nEndRow)
560 {
561 SCROW nLastRow = -1;
562 bool bHidden = RowHidden(nRow, nullptr, &nLastRow);
563 if (bHidden)
564 return true;
565
566 nRow = nLastRow + 1;
567 }
568 return false;
569 }
570
ColHidden(SCCOL nCol,SCCOL * pFirstCol,SCCOL * pLastCol) const571 bool ScTable::ColHidden(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) const
572 {
573 if (!ValidCol(nCol))
574 return true;
575
576 ScFlatBoolColSegments::RangeData aData;
577 if (!mpHiddenCols->getRangeData(nCol, aData))
578 return true;
579
580 if (pFirstCol)
581 *pFirstCol = aData.mnCol1;
582 if (pLastCol)
583 *pLastCol = aData.mnCol2;
584
585 return aData.mbValue;
586 }
587
SetRowHidden(SCROW nStartRow,SCROW nEndRow,bool bHidden)588 bool ScTable::SetRowHidden(SCROW nStartRow, SCROW nEndRow, bool bHidden)
589 {
590 bool bChanged = false;
591 if (bHidden)
592 bChanged = mpHiddenRows->setTrue(nStartRow, nEndRow);
593 else
594 bChanged = mpHiddenRows->setFalse(nStartRow, nEndRow);
595
596 // Cell anchored objects might change visibility
597 ScDrawLayer* pDrawLayer = rDocument.GetDrawLayer();
598 if (pDrawLayer)
599 {
600 std::vector<SdrObject*> aRowDrawObjects;
601 aRowDrawObjects = pDrawLayer->GetObjectsAnchoredToRows(GetTab(), nStartRow, nEndRow);
602 for (auto aObj : aRowDrawObjects)
603 {
604 ScDrawObjData* pData = ScDrawLayer::GetObjData(aObj);
605 if (pData)
606 {
607 if (bHidden)
608 aObj->SetVisible(false);
609 else if (!GetDoc().ColHidden(pData->maStart.Col(), pData->maStart.Tab()))
610 {
611 // Only change visibility if object is not hidden by a hidden col
612 aObj->SetVisible(true);
613 }
614 }
615 }
616 }
617
618 if (bChanged)
619 {
620 SetStreamValid(false);
621
622 { // Scoped bulk broadcast.
623 // Only subtotal formula cells will accept the notification of
624 // SfxHintId::ScHiddenRowsChanged, leaving the bulk will track
625 // those and broadcast SfxHintId::ScDataChanged to notify all
626 // dependents.
627 ScBulkBroadcast aBulkBroadcast(rDocument.GetBASM(), SfxHintId::ScDataChanged);
628 for (SCCOL i = 0; i < aCol.size(); i++)
629 {
630 aCol[i].BroadcastRows(nStartRow, nEndRow, SfxHintId::ScHiddenRowsChanged);
631 }
632 }
633 }
634
635 return bChanged;
636 }
637
SetColHidden(SCCOL nStartCol,SCCOL nEndCol,bool bHidden)638 void ScTable::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, bool bHidden)
639 {
640 bool bChanged = false;
641 if (bHidden)
642 bChanged = mpHiddenCols->setTrue(nStartCol, nEndCol);
643 else
644 bChanged = mpHiddenCols->setFalse(nStartCol, nEndCol);
645
646 // Cell anchored objects might change visibility
647 ScDrawLayer* pDrawLayer = rDocument.GetDrawLayer();
648 if (pDrawLayer)
649 {
650 std::vector<SdrObject*> aColDrawObjects;
651 aColDrawObjects = pDrawLayer->GetObjectsAnchoredToCols(GetTab(), nStartCol, nEndCol);
652 for (auto aObj : aColDrawObjects)
653 {
654 ScDrawObjData* pData = ScDrawLayer::GetObjData(aObj);
655 if (pData)
656 {
657 if (bHidden)
658 aObj->SetVisible(false);
659 else if (!GetDoc().RowHidden(pData->maStart.Row(), pData->maStart.Tab()))
660 {
661 // Only change visibility if object is not hidden by a hidden row
662 aObj->SetVisible(true);
663 }
664 }
665 }
666 }
667
668 if (bChanged)
669 SetStreamValid(false);
670 }
671
CopyColHidden(const ScTable & rTable,SCCOL nStartCol,SCCOL nEndCol)672 void ScTable::CopyColHidden(const ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol)
673 {
674 SCCOL nCol = nStartCol;
675 while (nCol <= nEndCol)
676 {
677 SCCOL nLastCol = -1;
678 bool bHidden = rTable.ColHidden(nCol, nullptr, &nLastCol);
679 if (nLastCol > nEndCol)
680 nLastCol = nEndCol;
681
682 SetColHidden(nCol, nLastCol, bHidden);
683 nCol = nLastCol + 1;
684 }
685 }
686
CopyRowHidden(const ScTable & rTable,SCROW nStartRow,SCROW nEndRow)687 void ScTable::CopyRowHidden(const ScTable& rTable, SCROW nStartRow, SCROW nEndRow)
688 {
689 SCROW nRow = nStartRow;
690 while (nRow <= nEndRow)
691 {
692 SCROW nLastRow = -1;
693 bool bHidden = rTable.RowHidden(nRow, nullptr, &nLastRow);
694 if (nLastRow > nEndRow)
695 nLastRow = nEndRow;
696 SetRowHidden(nRow, nLastRow, bHidden);
697 nRow = nLastRow + 1;
698 }
699 }
700
CopyRowHeight(const ScTable & rSrcTable,SCROW nStartRow,SCROW nEndRow,SCROW nSrcOffset)701 void ScTable::CopyRowHeight(const ScTable& rSrcTable, SCROW nStartRow, SCROW nEndRow,
702 SCROW nSrcOffset)
703 {
704 SCROW nRow = nStartRow;
705 ScFlatUInt16RowSegments::RangeData aSrcData;
706 while (nRow <= nEndRow)
707 {
708 if (!rSrcTable.mpRowHeights->getRangeData(nRow + nSrcOffset, aSrcData))
709 // Something is wrong !
710 return;
711
712 SCROW nLastRow = aSrcData.mnRow2 - nSrcOffset;
713 if (nLastRow > nEndRow)
714 nLastRow = nEndRow;
715
716 mpRowHeights->setValue(nRow, nLastRow, aSrcData.mnValue);
717 nRow = nLastRow + 1;
718 }
719 }
720
FirstVisibleRow(SCROW nStartRow,SCROW nEndRow) const721 SCROW ScTable::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow) const
722 {
723 SCROW nRow = nStartRow;
724 ScFlatBoolRowSegments::RangeData aData;
725 while (nRow <= nEndRow)
726 {
727 if (!ValidRow(nRow))
728 break;
729
730 if (!mpHiddenRows->getRangeData(nRow, aData))
731 // failed to get range data.
732 break;
733
734 if (!aData.mbValue)
735 // visible row found
736 return nRow;
737
738 nRow = aData.mnRow2 + 1;
739 }
740
741 return ::std::numeric_limits<SCROW>::max();
742 }
743
LastVisibleRow(SCROW nStartRow,SCROW nEndRow) const744 SCROW ScTable::LastVisibleRow(SCROW nStartRow, SCROW nEndRow) const
745 {
746 SCROW nRow = nEndRow;
747 ScFlatBoolRowSegments::RangeData aData;
748 while (nRow >= nStartRow)
749 {
750 if (!ValidRow(nRow))
751 break;
752
753 if (!mpHiddenRows->getRangeData(nRow, aData))
754 // failed to get range data.
755 break;
756
757 if (!aData.mbValue)
758 // visible row found
759 return nRow;
760
761 nRow = aData.mnRow1 - 1;
762 }
763
764 return ::std::numeric_limits<SCROW>::max();
765 }
766
CountVisibleRows(SCROW nStartRow,SCROW nEndRow) const767 SCROW ScTable::CountVisibleRows(SCROW nStartRow, SCROW nEndRow) const
768 {
769 SCROW nCount = 0;
770 SCROW nRow = nStartRow;
771 ScFlatBoolRowSegments::RangeData aData;
772 while (nRow <= nEndRow)
773 {
774 if (!mpHiddenRows->getRangeData(nRow, aData))
775 break;
776
777 if (aData.mnRow2 > nEndRow)
778 aData.mnRow2 = nEndRow;
779
780 if (!aData.mbValue)
781 nCount += aData.mnRow2 - nRow + 1;
782
783 nRow = aData.mnRow2 + 1;
784 }
785 return nCount;
786 }
787
GetTotalRowHeight(SCROW nStartRow,SCROW nEndRow,bool bHiddenAsZero) const788 sal_uInt32 ScTable::GetTotalRowHeight(SCROW nStartRow, SCROW nEndRow, bool bHiddenAsZero) const
789 {
790 sal_uInt32 nHeight = 0;
791 SCROW nRow = nStartRow;
792 ScFlatBoolRowSegments::RangeData aData;
793 while (nRow <= nEndRow)
794 {
795 if (!mpHiddenRows->getRangeData(nRow, aData))
796 break;
797
798 if (aData.mnRow2 > nEndRow)
799 aData.mnRow2 = nEndRow;
800
801 if (!(bHiddenAsZero && aData.mbValue))
802 // visible row range.
803 nHeight += mpRowHeights->getSumValue(nRow, aData.mnRow2);
804
805 nRow = aData.mnRow2 + 1;
806 }
807
808 return nHeight;
809 }
810
LastHiddenColRow(SCCOLROW nPos,bool bCol) const811 SCCOLROW ScTable::LastHiddenColRow(SCCOLROW nPos, bool bCol) const
812 {
813 if (bCol)
814 {
815 SCCOL nCol = static_cast<SCCOL>(nPos);
816 if (ColHidden(nCol))
817 {
818 for (SCCOL i = nCol + 1; i <= rDocument.MaxCol(); ++i)
819 {
820 if (!ColHidden(i))
821 return i - 1;
822 }
823 }
824 }
825 else
826 {
827 SCROW nRow = static_cast<SCROW>(nPos);
828 SCROW nLastRow;
829 if (RowHidden(nRow, nullptr, &nLastRow))
830 return static_cast<SCCOLROW>(nLastRow);
831 }
832 return ::std::numeric_limits<SCCOLROW>::max();
833 }
834
RowFiltered(SCROW nRow,SCROW * pFirstRow,SCROW * pLastRow) const835 bool ScTable::RowFiltered(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) const
836 {
837 if (!ValidRow(nRow))
838 return false;
839
840 ScFlatBoolRowSegments::RangeData aData;
841 if (!mpFilteredRows->getRangeData(nRow, aData))
842 // search failed.
843 return false;
844
845 if (pFirstRow)
846 *pFirstRow = aData.mnRow1;
847 if (pLastRow)
848 *pLastRow = aData.mnRow2;
849
850 return aData.mbValue;
851 }
852
ColFiltered(SCCOL nCol,SCCOL * pFirstCol,SCCOL * pLastCol) const853 bool ScTable::ColFiltered(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) const
854 {
855 if (!ValidCol(nCol))
856 return false;
857
858 ScFlatBoolColSegments::RangeData aData;
859 if (!mpFilteredCols->getRangeData(nCol, aData))
860 // search failed.
861 return false;
862
863 if (pFirstCol)
864 *pFirstCol = aData.mnCol1;
865 if (pLastCol)
866 *pLastCol = aData.mnCol2;
867
868 return aData.mbValue;
869 }
870
HasFilteredRows(SCROW nStartRow,SCROW nEndRow) const871 bool ScTable::HasFilteredRows(SCROW nStartRow, SCROW nEndRow) const
872 {
873 SCROW nRow = nStartRow;
874 while (nRow <= nEndRow)
875 {
876 SCROW nLastRow = nRow;
877 bool bFiltered = RowFiltered(nRow, nullptr, &nLastRow);
878 if (bFiltered)
879 return true;
880
881 nRow = nLastRow + 1;
882 }
883 return false;
884 }
885
CopyColFiltered(const ScTable & rTable,SCCOL nStartCol,SCCOL nEndCol)886 void ScTable::CopyColFiltered(const ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol)
887 {
888 SCCOL nCol = nStartCol;
889 while (nCol <= nEndCol)
890 {
891 SCCOL nLastCol = -1;
892 bool bFiltered = rTable.ColFiltered(nCol, nullptr, &nLastCol);
893 if (nLastCol > nEndCol)
894 nLastCol = nEndCol;
895
896 SetColFiltered(nCol, nLastCol, bFiltered);
897 nCol = nLastCol + 1;
898 }
899 }
900
CopyRowFiltered(const ScTable & rTable,SCROW nStartRow,SCROW nEndRow)901 void ScTable::CopyRowFiltered(const ScTable& rTable, SCROW nStartRow, SCROW nEndRow)
902 {
903 SCROW nRow = nStartRow;
904 while (nRow <= nEndRow)
905 {
906 SCROW nLastRow = -1;
907 bool bFiltered = rTable.RowFiltered(nRow, nullptr, &nLastRow);
908 if (nLastRow > nEndRow)
909 nLastRow = nEndRow;
910 SetRowFiltered(nRow, nLastRow, bFiltered);
911 nRow = nLastRow + 1;
912 }
913 }
914
SetRowFiltered(SCROW nStartRow,SCROW nEndRow,bool bFiltered)915 void ScTable::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, bool bFiltered)
916 {
917 if (bFiltered)
918 mpFilteredRows->setTrue(nStartRow, nEndRow);
919 else
920 mpFilteredRows->setFalse(nStartRow, nEndRow);
921 }
922
SetColFiltered(SCCOL nStartCol,SCCOL nEndCol,bool bFiltered)923 void ScTable::SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, bool bFiltered)
924 {
925 if (bFiltered)
926 mpFilteredCols->setTrue(nStartCol, nEndCol);
927 else
928 mpFilteredCols->setFalse(nStartCol, nEndCol);
929 }
930
FirstNonFilteredRow(SCROW nStartRow,SCROW nEndRow) const931 SCROW ScTable::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow) const
932 {
933 SCROW nRow = nStartRow;
934 ScFlatBoolRowSegments::RangeData aData;
935 while (nRow <= nEndRow)
936 {
937 if (!ValidRow(nRow))
938 break;
939
940 if (!mpFilteredRows->getRangeData(nRow, aData))
941 // failed to get range data.
942 break;
943
944 if (!aData.mbValue)
945 // non-filtered row found
946 return nRow;
947
948 nRow = aData.mnRow2 + 1;
949 }
950
951 return ::std::numeric_limits<SCROW>::max();
952 }
953
LastNonFilteredRow(SCROW nStartRow,SCROW nEndRow) const954 SCROW ScTable::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow) const
955 {
956 SCROW nRow = nEndRow;
957 ScFlatBoolRowSegments::RangeData aData;
958 while (nRow >= nStartRow)
959 {
960 if (!ValidRow(nRow))
961 break;
962
963 if (!mpFilteredRows->getRangeData(nRow, aData))
964 // failed to get range data.
965 break;
966
967 if (!aData.mbValue)
968 // non-filtered row found
969 return nRow;
970
971 nRow = aData.mnRow1 - 1;
972 }
973
974 return ::std::numeric_limits<SCROW>::max();
975 }
976
CountNonFilteredRows(SCROW nStartRow,SCROW nEndRow) const977 SCROW ScTable::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow) const
978 {
979 SCROW nCount = 0;
980 SCROW nRow = nStartRow;
981 ScFlatBoolRowSegments::RangeData aData;
982 while (nRow <= nEndRow)
983 {
984 if (!mpFilteredRows->getRangeData(nRow, aData))
985 break;
986
987 if (aData.mnRow2 > nEndRow)
988 aData.mnRow2 = nEndRow;
989
990 if (!aData.mbValue)
991 nCount += aData.mnRow2 - nRow + 1;
992
993 nRow = aData.mnRow2 + 1;
994 }
995 return nCount;
996 }
997
IsManualRowHeight(SCROW nRow) const998 bool ScTable::IsManualRowHeight(SCROW nRow) const
999 {
1000 return bool(pRowFlags->GetValue(nRow) & CRFlags::ManualSize);
1001 }
1002
1003 namespace
1004 {
lcl_syncFlags(const ScDocument * pDocument,ScFlatBoolColSegments & rColSegments,const ScFlatBoolRowSegments & rRowSegments,ScBitMaskCompressedArray<SCCOL,CRFlags> * pColFlags,ScBitMaskCompressedArray<SCROW,CRFlags> * pRowFlags,const CRFlags nFlagMask)1005 void lcl_syncFlags(const ScDocument* pDocument, ScFlatBoolColSegments& rColSegments,
1006 const ScFlatBoolRowSegments& rRowSegments,
1007 ScBitMaskCompressedArray<SCCOL, CRFlags>* pColFlags,
1008 ScBitMaskCompressedArray<SCROW, CRFlags>* pRowFlags, const CRFlags nFlagMask)
1009 {
1010 using ::sal::static_int_cast;
1011
1012 CRFlags nFlagMaskComplement = ~nFlagMask;
1013
1014 pRowFlags->AndValue(0, pDocument->MaxRow(), nFlagMaskComplement);
1015 pColFlags->AndValue(0, pDocument->MaxCol() + 1, nFlagMaskComplement);
1016
1017 {
1018 // row hidden flags.
1019
1020 SCROW nRow = 0;
1021 ScFlatBoolRowSegments::RangeData aData;
1022 while (nRow <= pDocument->MaxRow())
1023 {
1024 if (!rRowSegments.getRangeData(nRow, aData))
1025 break;
1026
1027 if (aData.mbValue)
1028 pRowFlags->OrValue(nRow, aData.mnRow2, nFlagMask);
1029
1030 nRow = aData.mnRow2 + 1;
1031 }
1032 }
1033
1034 {
1035 // column hidden flags.
1036
1037 SCCOL nCol = 0;
1038 ScFlatBoolColSegments::RangeData aData;
1039 while (nCol <= pDocument->MaxCol())
1040 {
1041 if (!rColSegments.getRangeData(nCol, aData))
1042 break;
1043
1044 if (aData.mbValue)
1045 pColFlags->OrValue(nCol, aData.mnCol2, nFlagMask);
1046
1047 nCol = aData.mnCol2 + 1;
1048 }
1049 }
1050 }
1051 }
1052
SyncColRowFlags()1053 void ScTable::SyncColRowFlags()
1054 {
1055 CRFlags nManualBreakComplement = ~CRFlags::ManualBreak;
1056
1057 // Manual breaks.
1058 pRowFlags->AndValue(0, rDocument.MaxRow(), nManualBreakComplement);
1059 mpColFlags->AndValue(0, rDocument.MaxCol() + 1, nManualBreakComplement);
1060
1061 for (const auto& rBreakPos : maRowManualBreaks)
1062 pRowFlags->OrValue(rBreakPos, CRFlags::ManualBreak);
1063
1064 for (const auto& rBreakPos : maColManualBreaks)
1065 mpColFlags->OrValue(rBreakPos, CRFlags::ManualBreak);
1066
1067 // Hidden flags.
1068 lcl_syncFlags(&rDocument, *mpHiddenCols, *mpHiddenRows, mpColFlags.get(), pRowFlags.get(),
1069 CRFlags::Hidden);
1070 lcl_syncFlags(&rDocument, *mpFilteredCols, *mpFilteredRows, mpColFlags.get(), pRowFlags.get(),
1071 CRFlags::Filtered);
1072 }
1073
SetPageSize(const Size & rSize)1074 void ScTable::SetPageSize(const Size& rSize)
1075 {
1076 if (!rSize.IsEmpty())
1077 {
1078 if (aPageSizeTwips != rSize)
1079 InvalidatePageBreaks();
1080
1081 bPageSizeValid = true;
1082 aPageSizeTwips = rSize;
1083 }
1084 else
1085 bPageSizeValid = false;
1086 }
1087
IsProtected() const1088 bool ScTable::IsProtected() const { return pTabProtection && pTabProtection->isProtected(); }
1089
SetProtection(const ScTableProtection * pProtect)1090 void ScTable::SetProtection(const ScTableProtection* pProtect)
1091 {
1092 if (pProtect)
1093 pTabProtection.reset(new ScTableProtection(*pProtect));
1094 else
1095 pTabProtection.reset();
1096
1097 SetStreamValid(false);
1098 }
1099
GetProtection() const1100 const ScTableProtection* ScTable::GetProtection() const { return pTabProtection.get(); }
1101
GetPageSize() const1102 Size ScTable::GetPageSize() const
1103 {
1104 if (bPageSizeValid)
1105 return aPageSizeTwips;
1106 else
1107 return Size(); // blank
1108 }
1109
SetRepeatArea(SCCOL nStartCol,SCCOL nEndCol,SCROW nStartRow,SCROW nEndRow)1110 void ScTable::SetRepeatArea(SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow)
1111 {
1112 // #i117952# page break calculation uses these values (set from ScPrintFunc), not pRepeatColRange/pRepeatRowRange
1113 if (nStartCol != nRepeatStartX || nEndCol != nRepeatEndX || nStartRow != nRepeatStartY
1114 || nEndRow != nRepeatEndY)
1115 InvalidatePageBreaks();
1116
1117 nRepeatStartX = nStartCol;
1118 nRepeatEndX = nEndCol;
1119 nRepeatStartY = nStartRow;
1120 nRepeatEndY = nEndRow;
1121 }
1122
StartListening(const ScAddress & rAddress,SvtListener * pListener)1123 void ScTable::StartListening(const ScAddress& rAddress, SvtListener* pListener)
1124 {
1125 if (!ValidCol(rAddress.Col()))
1126 return;
1127
1128 CreateColumnIfNotExists(rAddress.Col()).StartListening(*pListener, rAddress.Row());
1129 }
1130
EndListening(const ScAddress & rAddress,SvtListener * pListener)1131 void ScTable::EndListening(const ScAddress& rAddress, SvtListener* pListener)
1132 {
1133 if (!ValidCol(rAddress.Col()))
1134 return;
1135
1136 if (rAddress.Col() < aCol.size())
1137 aCol[rAddress.Col()].EndListening(*pListener, rAddress.Row());
1138 }
1139
StartListening(sc::StartListeningContext & rCxt,const ScAddress & rAddress,SvtListener & rListener)1140 void ScTable::StartListening(sc::StartListeningContext& rCxt, const ScAddress& rAddress,
1141 SvtListener& rListener)
1142 {
1143 if (!ValidCol(rAddress.Col()))
1144 return;
1145
1146 CreateColumnIfNotExists(rAddress.Col()).StartListening(rCxt, rAddress, rListener);
1147 }
1148
EndListening(sc::EndListeningContext & rCxt,const ScAddress & rAddress,SvtListener & rListener)1149 void ScTable::EndListening(sc::EndListeningContext& rCxt, const ScAddress& rAddress,
1150 SvtListener& rListener)
1151 {
1152 if (!ValidCol(rAddress.Col()))
1153 return;
1154
1155 if (rAddress.Col() < aCol.size())
1156 aCol[rAddress.Col()].EndListening(rCxt, rAddress, rListener);
1157 }
1158
SetPageStyle(const OUString & rName)1159 void ScTable::SetPageStyle(const OUString& rName)
1160 {
1161 if (aPageStyle == rName)
1162 return;
1163
1164 OUString aStrNew = rName;
1165 SfxStyleSheetBasePool* pStylePool = rDocument.GetStyleSheetPool();
1166 SfxStyleSheetBase* pNewStyle = pStylePool->Find(aStrNew, SfxStyleFamily::Page);
1167
1168 if (!pNewStyle)
1169 {
1170 aStrNew = ScResId(STR_STYLENAME_STANDARD);
1171 pNewStyle = pStylePool->Find(aStrNew, SfxStyleFamily::Page);
1172 }
1173
1174 if (aPageStyle == aStrNew)
1175 return;
1176
1177 SfxStyleSheetBase* pOldStyle = pStylePool->Find(aPageStyle, SfxStyleFamily::Page);
1178 if (pOldStyle && pNewStyle)
1179 {
1180 SfxItemSet& rOldSet = pOldStyle->GetItemSet();
1181 SfxItemSet& rNewSet = pNewStyle->GetItemSet();
1182 auto getScaleValue = [](const SfxItemSet& rSet, sal_uInt16 nId) {
1183 return static_cast<const SfxUInt16Item&>(rSet.Get(nId)).GetValue();
1184 };
1185
1186 const sal_uInt16 nOldScale = getScaleValue(rOldSet, ATTR_PAGE_SCALE);
1187 const sal_uInt16 nOldScaleToPages = getScaleValue(rOldSet, ATTR_PAGE_SCALETOPAGES);
1188 const sal_uInt16 nNewScale = getScaleValue(rNewSet, ATTR_PAGE_SCALE);
1189 const sal_uInt16 nNewScaleToPages = getScaleValue(rNewSet, ATTR_PAGE_SCALETOPAGES);
1190
1191 if ((nOldScale != nNewScale) || (nOldScaleToPages != nNewScaleToPages))
1192 InvalidateTextWidth(nullptr, nullptr, false, false);
1193 }
1194
1195 if (pNewStyle) // also without the old one (for UpdateStdNames)
1196 aPageStyle = aStrNew;
1197
1198 SetStreamValid(false);
1199 }
1200
PageStyleModified(const OUString & rNewName)1201 void ScTable::PageStyleModified(const OUString& rNewName)
1202 {
1203 aPageStyle = rNewName;
1204 InvalidateTextWidth(nullptr, nullptr, false, false); // don't know what was in the style before
1205 }
1206
InvalidateTextWidth(const ScAddress * pAdrFrom,const ScAddress * pAdrTo,bool bNumFormatChanged,bool bBroadcast)1207 void ScTable::InvalidateTextWidth(const ScAddress* pAdrFrom, const ScAddress* pAdrTo,
1208 bool bNumFormatChanged, bool bBroadcast)
1209 {
1210 if (pAdrFrom && !pAdrTo)
1211 {
1212 // Special case: only process the "from" cell.
1213 SCCOL nCol = pAdrFrom->Col();
1214 SCROW nRow = pAdrFrom->Row();
1215 if (nCol >= aCol.size())
1216 return;
1217 ScColumn& rCol = aCol[nCol];
1218 ScRefCellValue aCell = rCol.GetCellValue(nRow);
1219 if (aCell.isEmpty())
1220 return;
1221
1222 rCol.SetTextWidth(nRow, TEXTWIDTH_DIRTY);
1223
1224 if (bNumFormatChanged)
1225 rCol.SetScriptType(nRow, SvtScriptType::UNKNOWN);
1226
1227 if (bBroadcast)
1228 { // Only with CalcAsShown
1229 switch (aCell.meType)
1230 {
1231 case CELLTYPE_VALUE:
1232 rCol.Broadcast(nRow);
1233 break;
1234 case CELLTYPE_FORMULA:
1235 aCell.mpFormula->SetDirty();
1236 break;
1237 default:
1238 {
1239 // added to avoid warnings
1240 }
1241 }
1242 }
1243
1244 return;
1245 }
1246
1247 const SCCOL nCol1 = pAdrFrom ? pAdrFrom->Col() : 0;
1248 const SCROW nRow1 = pAdrFrom ? pAdrFrom->Row() : 0;
1249 const SCCOL nCol2 = pAdrTo ? pAdrTo->Col() : aCol.size() - 1;
1250 const SCROW nRow2 = pAdrTo ? pAdrTo->Row() : rDocument.MaxRow();
1251
1252 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
1253 {
1254 ScColumnTextWidthIterator aIter(GetDoc(), aCol[nCol], nRow1, nRow2);
1255 sc::ColumnBlockPosition blockPos; // cache mdds position
1256 InitColumnBlockPosition(blockPos, nCol);
1257
1258 for (; aIter.hasCell(); aIter.next())
1259 {
1260 SCROW nRow = aIter.getPos();
1261 aIter.setValue(TEXTWIDTH_DIRTY);
1262 ScRefCellValue aCell = aCol[nCol].GetCellValue(blockPos, nRow);
1263 if (aCell.isEmpty())
1264 continue;
1265
1266 if (bNumFormatChanged)
1267 aCol[nCol].SetScriptType(nRow, SvtScriptType::UNKNOWN);
1268
1269 if (bBroadcast)
1270 { // Only with CalcAsShown
1271 switch (aCell.meType)
1272 {
1273 case CELLTYPE_VALUE:
1274 aCol[nCol].Broadcast(nRow);
1275 break;
1276 case CELLTYPE_FORMULA:
1277 aCell.mpFormula->SetDirty();
1278 break;
1279 default:
1280 {
1281 // added to avoid warnings
1282 }
1283 }
1284 }
1285 }
1286 }
1287 }
1288
1289 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1290