LibreOffice Module sc (master)  1
dociter.cxx
Go to the documentation of this file.
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 <svl/numformat.hxx>
21 #include <svl/zforlist.hxx>
22 
23 #include <global.hxx>
24 #include <dociter.hxx>
25 #include <document.hxx>
26 #include <table.hxx>
27 #include <column.hxx>
28 #include <formulacell.hxx>
29 #include <attarray.hxx>
30 #include <patattr.hxx>
31 #include <docoptio.hxx>
32 #include <cellform.hxx>
33 #include <segmenttree.hxx>
34 #include <progress.hxx>
35 #include <queryparam.hxx>
36 #include <queryentry.hxx>
37 #include <globstr.hrc>
38 #include <scresid.hxx>
39 #include <cellvalue.hxx>
40 #include <scmatrix.hxx>
41 #include <rowheightcontext.hxx>
42 #include <queryevaluator.hxx>
43 
44 #include <o3tl/safeint.hxx>
45 #include <tools/fract.hxx>
46 #include <editeng/editobj.hxx>
47 #include <svl/sharedstring.hxx>
49 #include <osl/diagnose.h>
50 #include <sal/log.hxx>
51 
52 #include <algorithm>
53 #include <limits>
54 #include <vector>
55 
56 using ::rtl::math::approxEqual;
57 using ::std::vector;
58 using ::std::set;
59 
60 // iterators have very high frequency use -> custom debug.
61 // #define debugiter(...) fprintf(stderr, __VA_ARGS__)
62 #define debugiter(...)
63 
64 static void ScAttrArray_IterGetNumberFormat( sal_uInt32& nFormat, const ScAttrArray*& rpArr,
65  SCROW& nAttrEndRow, const ScAttrArray* pNewArr, SCROW nRow,
66  const ScDocument& rDoc, const ScInterpreterContext* pContext = nullptr )
67 {
68  if ( rpArr == pNewArr && nAttrEndRow >= nRow )
69  return;
70 
71  SCROW nRowStart = 0;
72  SCROW nRowEnd = rDoc.MaxRow();
73  const ScPatternAttr* pPattern = pNewArr->GetPatternRange( nRowStart, nRowEnd, nRow );
74  if( !pPattern )
75  {
76  pPattern = rDoc.GetDefPattern();
77  nRowEnd = rDoc.MaxRow();
78  }
79 
80  nFormat = pPattern->GetNumberFormat( pContext ? pContext->GetFormatTable() : rDoc.GetFormatTable() );
81  rpArr = pNewArr;
82  nAttrEndRow = nRowEnd;
83 }
84 
86  SubtotalFlags nSubTotalFlags, bool bTextZero )
87  : mrDoc(rDocument)
88  , pContext(nullptr)
89  , pAttrArray(nullptr)
90  , nNumFormat(0) // Initialized in GetNumberFormat
91  , nNumFmtIndex(0)
92  , maStartPos(rRange.aStart)
93  , maEndPos(rRange.aEnd)
94  , mnCol(0)
95  , mnTab(0)
96  , nAttrEndRow(0)
97  , mnSubTotalFlags(nSubTotalFlags)
98  , nNumFmtType(SvNumFormatType::UNDEFINED)
99  , bNumValid(false)
100  , bCalcAsShown(rDocument.GetDocOptions().IsCalcAsShown())
101  , bTextAsZero(bTextZero)
102  , mpCells(nullptr)
103 {
104  SCTAB nDocMaxTab = rDocument.GetTableCount() - 1;
105 
106  if (!rDocument.ValidCol(maStartPos.Col())) maStartPos.SetCol(mrDoc.MaxCol());
107  if (!rDocument.ValidCol(maEndPos.Col())) maEndPos.SetCol(mrDoc.MaxCol());
108  if (!rDocument.ValidRow(maStartPos.Row())) maStartPos.SetRow(mrDoc.MaxRow());
109  if (!rDocument.ValidRow(maEndPos.Row())) maEndPos.SetRow(mrDoc.MaxRow());
110  if (!ValidTab(maStartPos.Tab()) || maStartPos.Tab() > nDocMaxTab) maStartPos.SetTab(nDocMaxTab);
111  if (!ValidTab(maEndPos.Tab()) || maEndPos.Tab() > nDocMaxTab) maEndPos.SetTab(nDocMaxTab);
112 }
113 
115 {
116  // Position of the head of the current block + offset within the block
117  // equals the logical element position.
118  return maCurPos.first->position + maCurPos.second;
119 }
120 
122 {
123  ++maCurPos.first;
124  maCurPos.second = 0;
125 }
126 
128 {
129  if (maCurPos.second + 1 < maCurPos.first->size)
130  // Move within the same block.
131  ++maCurPos.second;
132  else
133  // Move to the next block.
134  IncBlock();
135 }
136 
137 bool ScValueIterator::GetThis(double& rValue, FormulaError& rErr)
138 {
139  while (true)
140  {
141  bool bNextColumn = !mpCells || maCurPos.first == mpCells->end();
142  if (!bNextColumn)
143  {
144  if (GetRow() > maEndPos.Row())
145  bNextColumn = true;
146  }
147 
148  ScColumn* pCol;
149  if (!bNextColumn)
150  pCol = &(mrDoc.maTabs[mnTab])->aCol[mnCol];
151  else
152  {
153  // Find the next available column.
154  do
155  {
156  ++mnCol;
157  if (mnCol > maEndPos.Col() || mnCol >= mrDoc.maTabs[mnTab]->GetAllocatedColumnsCount())
158  {
159  mnCol = maStartPos.Col();
160  ++mnTab;
161  if (mnTab > maEndPos.Tab())
162  {
163  rErr = FormulaError::NONE;
164  return false;
165  }
166  }
167  pCol = &(mrDoc.maTabs[mnTab])->aCol[mnCol];
168  }
169  while (pCol->IsEmptyData());
170 
171  mpCells = &pCol->maCells;
172  maCurPos = mpCells->position(maStartPos.Row());
173  }
174 
175  SCROW nCurRow = GetRow();
176  SCROW nLastRow;
177  // Skip all filtered or hidden rows, depending on mnSubTotalFlags
179  mrDoc.RowFiltered( nCurRow, mnTab, nullptr, &nLastRow ) ) ||
181  mrDoc.RowHidden( nCurRow, mnTab, nullptr, &nLastRow ) ) )
182  {
183  maCurPos = mpCells->position(maCurPos.first, nLastRow+1);
184  continue;
185  }
186 
187  switch (maCurPos.first->type)
188  {
190  {
191  bNumValid = false;
192  rValue = sc::numeric_block::at(*maCurPos.first->data, maCurPos.second);
193  rErr = FormulaError::NONE;
194  if (bCalcAsShown)
195  {
197  nAttrEndRow, pCol->pAttrArray.get(), nCurRow, mrDoc, pContext);
198  rValue = mrDoc.RoundValueAsShown(rValue, nNumFormat, pContext);
199  }
200  return true; // Found it!
201  }
202  break;
204  {
205  ScFormulaCell& rCell = *sc::formula_block::at(*maCurPos.first->data, maCurPos.second);
207  {
208  // Skip subtotal formula cells.
209  IncPos();
210  break;
211  }
212 
213  if (rCell.GetErrorOrValue(rErr, rValue))
214  {
215  if ( rErr != FormulaError::NONE && ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) )
216  {
217  IncPos();
218  break;
219  }
220  bNumValid = false;
221  return true; // Found it!
222  }
223  else if (bTextAsZero)
224  {
225  rValue = 0.0;
226  bNumValid = false;
227  return true;
228  }
229  IncPos();
230  }
231  break;
234  {
235  if (bTextAsZero)
236  {
237  rErr = FormulaError::NONE;
238  rValue = 0.0;
239  nNumFmtType = SvNumFormatType::NUMBER;
240  nNumFmtIndex = 0;
241  bNumValid = true;
242  return true;
243  }
244  IncBlock();
245  }
246  break;
248  default:
249  // Skip the whole block.
250  IncBlock();
251  }
252  }
253 }
254 
256 {
257  if (!bNumValid && mnTab < mrDoc.GetTableCount())
258  {
259  SCROW nCurRow = GetRow();
260  const ScColumn* pCol = &(mrDoc.maTabs[mnTab])->aCol[mnCol];
261  nNumFmtIndex = pCol->GetNumberFormat(rContext, nCurRow);
263  bNumValid = true;
264  }
265 
266  nType = nNumFmtType;
267  nIndex = nNumFmtIndex;
268 }
269 
270 bool ScValueIterator::GetFirst(double& rValue, FormulaError& rErr)
271 {
272  mnCol = maStartPos.Col();
273  mnTab = maStartPos.Tab();
274 
275  ScTable* pTab = mrDoc.FetchTable(mnTab);
276  if (!pTab)
277  return false;
278 
279  nNumFormat = 0; // Initialized in GetNumberFormat
280  pAttrArray = nullptr;
281  nAttrEndRow = 0;
282 
283  auto nCol = maStartPos.Col();
284  if (nCol < pTab->GetAllocatedColumnsCount())
285  {
286  mpCells = &pTab->aCol[nCol].maCells;
287  maCurPos = mpCells->position(maStartPos.Row());
288  }
289  else
290  mpCells = nullptr;
291  return GetThis(rValue, rErr);
292 }
293 
294 bool ScValueIterator::GetNext(double& rValue, FormulaError& rErr)
295 {
296  IncPos();
297  return GetThis(rValue, rErr);
298 }
299 
301 {
302 }
303 
305 {
306 }
307 
309 {
310  ScTable* pTab = rDoc.FetchTable(nTab);
311  if (!pTab)
312  return nullptr;
313  if (nCol >= pTab->GetAllocatedColumnsCount())
314  return nullptr;
315  return &pTab->aCol[nCol].maCells;
316 }
317 
319 {
320  assert(nTab < rDoc.GetTableCount() && "index out of bounds, FIX IT");
321  ScColumn* pCol = &rDoc.maTabs[nTab]->aCol[nCol];
322  return pCol->pAttrArray.get();
323 }
324 
326  ScDocument& rDoc, const ScQueryParam& rParam, SCTAB nTab, SCROW nRow, const ScRefCellValue* pCell)
327 {
328  assert(nTab < rDoc.GetTableCount() && "index out of bounds, FIX IT");
329  ScQueryEvaluator queryEvaluator(rDoc, *rDoc.maTabs[nTab], rParam);
330  return queryEvaluator.ValidQuery(nRow, pCell);
331 }
332 
334  : mpCells(nullptr)
335  , mpParam(pParam)
336  , mrDoc(rDoc)
337  , mrContext(rContext)
338  , pAttrArray(nullptr)
339  , nNumFormat(0) // Initialized in GetNumberFormat
340  , nNumFmtIndex(0)
341  , nCol(mpParam->mnField)
342  , nRow(mpParam->nRow1)
343  , nAttrEndRow(0)
344  , nTab(mpParam->nTab)
345  , nNumFmtType(SvNumFormatType::ALL)
346  , bCalcAsShown(rDoc.GetDocOptions().IsCalcAsShown())
347 {
348  SCSIZE i;
350  for (i=0; (i<nCount) && (mpParam->GetEntry(i).bDoQuery); i++)
351  {
352  ScQueryEntry& rEntry = mpParam->GetEntry(i);
353  ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
354  rItems.resize(1);
355  ScQueryEntry::Item& rItem = rItems.front();
356  sal_uInt32 nIndex = 0;
357  bool bNumber = mrDoc.GetFormatTable()->IsNumberFormat(
358  rItem.maString.getString(), nIndex, rItem.mfVal);
360  }
361 }
362 
364 {
365 }
366 
368 {
369  // Start with the current row position, and find the first row position
370  // that satisfies the query.
371 
372  // If the query starts in the same column as the result vector we can
373  // prefetch the cell which saves us one fetch in the success case.
374  SCCOLROW nFirstQueryField = mpParam->GetEntry(0).nField;
375  ScRefCellValue aCell;
376 
377  while (true)
378  {
379  if (maCurPos.first == mpCells->end() || nRow > mpParam->nRow2)
380  {
381  // Bottom of the range reached. Bail out.
382  rValue.mnError = FormulaError::NONE;
383  return false;
384  }
385 
386  if (maCurPos.first->type == sc::element_type_empty)
387  {
388  // Skip the whole empty block.
389  incBlock();
390  continue;
391  }
392 
393  ScRefCellValue* pCell = nullptr;
394  if (nCol == static_cast<SCCOL>(nFirstQueryField))
395  {
396  aCell = sc::toRefCell(maCurPos.first, maCurPos.second);
397  pCell = &aCell;
398  }
399 
400  if (ScDBQueryDataIterator::IsQueryValid(mrDoc, *mpParam, nTab, nRow, pCell))
401  {
402  if (!pCell)
403  aCell = sc::toRefCell(maCurPos.first, maCurPos.second);
404  switch (aCell.meType)
405  {
406  case CELLTYPE_VALUE:
407  {
408  rValue.mfValue = aCell.mfValue;
409  rValue.mbIsNumber = true;
410  if ( bCalcAsShown )
411  {
412  const ScAttrArray* pNewAttrArray =
413  ScDBQueryDataIterator::GetAttrArrayByCol(mrDoc, nTab, nCol);
414  ScAttrArray_IterGetNumberFormat( nNumFormat, pAttrArray,
415  nAttrEndRow, pNewAttrArray, nRow, mrDoc );
416  rValue.mfValue = mrDoc.RoundValueAsShown( rValue.mfValue, nNumFormat );
417  }
418  nNumFmtType = SvNumFormatType::NUMBER;
419  nNumFmtIndex = 0;
420  rValue.mnError = FormulaError::NONE;
421  return true; // Found it!
422  }
423 
424  case CELLTYPE_FORMULA:
425  {
426  if (aCell.mpFormula->IsValue())
427  {
428  rValue.mfValue = aCell.mpFormula->GetValue();
429  rValue.mbIsNumber = true;
430  mrDoc.GetNumberFormatInfo(
431  mrContext, nNumFmtType, nNumFmtIndex, ScAddress(nCol, nRow, nTab));
432  rValue.mnError = aCell.mpFormula->GetErrCode();
433  return true; // Found it!
434  }
435  else if(mpParam->mbSkipString)
436  incPos();
437  else
438  {
439  rValue.maString = aCell.mpFormula->GetString().getString();
440  rValue.mfValue = 0.0;
441  rValue.mnError = aCell.mpFormula->GetErrCode();
442  rValue.mbIsNumber = false;
443  return true;
444  }
445  }
446  break;
447  case CELLTYPE_STRING:
448  case CELLTYPE_EDIT:
449  if (mpParam->mbSkipString)
450  incPos();
451  else
452  {
453  rValue.maString = aCell.getString(&mrDoc);
454  rValue.mfValue = 0.0;
455  rValue.mnError = FormulaError::NONE;
456  rValue.mbIsNumber = false;
457  return true;
458  }
459  break;
460  default:
461  incPos();
462  }
463  }
464  else
465  incPos();
466  }
467 // statement unreachable
468 }
469 
471 {
472  if (mpParam->bHasHeader)
473  ++nRow;
474 
475  mpCells = ScDBQueryDataIterator::GetColumnCellStore(mrDoc, nTab, nCol);
476  if (!mpCells)
477  return false;
478 
479  maCurPos = mpCells->position(nRow);
480  return getCurrent(rValue);
481 }
482 
484 {
485  if (!mpCells || maCurPos.first == mpCells->end())
486  return false;
487 
488  incPos();
489  return getCurrent(rValue);
490 }
491 
493 {
494  ++maCurPos.first;
495  maCurPos.second = 0;
496 
497  nRow = maCurPos.first->position;
498 }
499 
501 {
502  if (maCurPos.second + 1 < maCurPos.first->size)
503  {
504  // Move within the same block.
505  ++maCurPos.second;
506  ++nRow;
507  }
508  else
509  // Move to the next block.
510  incBlock();
511 }
512 
514  : mpParam(pParam)
515  , mnCurRow(0)
516 {
517  SCSIZE nC, nR;
518  mpParam->mpMatrix->GetDimensions(nC, nR);
519  mnRows = static_cast<SCROW>(nR);
520 }
521 
523 {
524 }
525 
527 {
528  // Starting from row == mnCurRow, get the first row that satisfies all the
529  // query parameters.
530  for ( ;mnCurRow < mnRows; ++mnCurRow)
531  {
532  const ScMatrix& rMat = *mpParam->mpMatrix;
533  if (rMat.IsEmpty(mpParam->mnField, mnCurRow))
534  // Don't take empty values into account.
535  continue;
536 
537  bool bIsStrVal = rMat.IsStringOrEmpty(mpParam->mnField, mnCurRow);
538  if (bIsStrVal && mpParam->mbSkipString)
539  continue;
540 
541  if (isValidQuery(mnCurRow, rMat))
542  {
543  rValue.maString = rMat.GetString(mpParam->mnField, mnCurRow).getString();
544  rValue.mfValue = rMat.GetDouble(mpParam->mnField, mnCurRow);
545  rValue.mbIsNumber = !bIsStrVal;
546  rValue.mnError = FormulaError::NONE;
547  return true;
548  }
549  }
550  return false;
551 }
552 
554 {
555  mnCurRow = mpParam->bHasHeader ? 1 : 0;
556  return getCurrent(rValue);
557 }
558 
560 {
561  ++mnCurRow;
562  return getCurrent(rValue);
563 }
564 
565 namespace {
566 
567 bool isQueryByValue(const ScQueryEntry::Item& rItem, const ScMatrix& rMat, SCSIZE nCol, SCSIZE nRow)
568 {
569  if (rItem.meType == ScQueryEntry::ByString)
570  return false;
571 
572  if (!rMat.IsValueOrEmpty(nCol, nRow))
573  return false;
574 
575  return true;
576 }
577 
578 bool isQueryByString(const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem, const ScMatrix& rMat, SCSIZE nCol, SCSIZE nRow)
579 {
580  switch (rEntry.eOp)
581  {
582  case SC_EQUAL:
583  case SC_NOT_EQUAL:
584  case SC_CONTAINS:
585  case SC_DOES_NOT_CONTAIN:
586  case SC_BEGINS_WITH:
587  case SC_ENDS_WITH:
590  return true;
591  default:
592  ;
593  }
594 
595  return rItem.meType == ScQueryEntry::ByString && rMat.IsStringOrEmpty(nCol, nRow);
596 }
597 
598 }
599 
601 {
602  SCSIZE nEntryCount = mpParam->GetEntryCount();
603  vector<bool> aResults;
604  aResults.reserve(nEntryCount);
605 
606  const CollatorWrapper& rCollator = ScGlobal::GetCollator(mpParam->bCaseSens);
607 
608  for (SCSIZE i = 0; i < nEntryCount; ++i)
609  {
610  const ScQueryEntry& rEntry = mpParam->GetEntry(i);
611  const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
612  if (!rEntry.bDoQuery)
613  continue;
614 
615  switch (rEntry.eOp)
616  {
617  case SC_EQUAL:
618  case SC_LESS:
619  case SC_GREATER:
620  case SC_LESS_EQUAL:
621  case SC_GREATER_EQUAL:
622  case SC_NOT_EQUAL:
623  break;
624  default:
625  // Only the above operators are supported.
626  SAL_WARN("sc.core", "Unsupported operator " << rEntry.eOp
627  << " in ScDBQueryDataIterator::DataAccessMatrix::isValidQuery()");
628  continue;
629  }
630 
631  bool bValid = false;
632 
633  SCSIZE nField = static_cast<SCSIZE>(rEntry.nField);
634  if (isQueryByValue(rItem, rMat, nField, nRow))
635  {
636  // By value
637  double fMatVal = rMat.GetDouble(nField, nRow);
638  bool bEqual = approxEqual(fMatVal, rItem.mfVal);
639  switch (rEntry.eOp)
640  {
641  case SC_EQUAL:
642  bValid = bEqual;
643  break;
644  case SC_LESS:
645  bValid = (fMatVal < rItem.mfVal) && !bEqual;
646  break;
647  case SC_GREATER:
648  bValid = (fMatVal > rItem.mfVal) && !bEqual;
649  break;
650  case SC_LESS_EQUAL:
651  bValid = (fMatVal < rItem.mfVal) || bEqual;
652  break;
653  case SC_GREATER_EQUAL:
654  bValid = (fMatVal > rItem.mfVal) || bEqual;
655  break;
656  case SC_NOT_EQUAL:
657  bValid = !bEqual;
658  break;
659  default:
660  ;
661  }
662  }
663  else if (isQueryByString(rEntry, rItem, rMat, nField, nRow))
664  {
665  // By string
666  do
667  {
668  // Equality check first.
669  svl::SharedString aMatStr = rMat.GetString(nField, nRow);
670  svl::SharedString aQueryStr = rEntry.GetQueryItem().maString;
671  bool bDone = false;
672  rtl_uString* p1 = mpParam->bCaseSens ? aMatStr.getData() : aMatStr.getDataIgnoreCase();
673  rtl_uString* p2 = mpParam->bCaseSens ? aQueryStr.getData() : aQueryStr.getDataIgnoreCase();
674  switch (rEntry.eOp)
675  {
676  case SC_EQUAL:
677  bValid = (p1 == p2);
678  bDone = true;
679  break;
680  case SC_NOT_EQUAL:
681  bValid = (p1 != p2);
682  bDone = true;
683  break;
684  default:
685  ;
686  }
687 
688  if (bDone)
689  break;
690 
691  // Unequality check using collator.
692  sal_Int32 nCompare = rCollator.compareString(aMatStr.getString(), aQueryStr.getString());
693  switch (rEntry.eOp)
694  {
695  case SC_LESS :
696  bValid = (nCompare < 0);
697  break;
698  case SC_GREATER :
699  bValid = (nCompare > 0);
700  break;
701  case SC_LESS_EQUAL :
702  bValid = (nCompare <= 0);
703  break;
704  case SC_GREATER_EQUAL :
705  bValid = (nCompare >= 0);
706  break;
707  default:
708  ;
709  }
710  }
711  while (false);
712  }
713 
714  if (aResults.empty())
715  // First query entry.
716  aResults.push_back(bValid);
717  else if (rEntry.eConnect == SC_AND)
718  {
719  // For AND op, tuck the result into the last result value.
720  size_t n = aResults.size();
721  aResults[n-1] = aResults[n-1] && bValid;
722  }
723  else
724  // For OR op, store its own result.
725  aResults.push_back(bValid);
726  }
727 
728  // Row is valid as long as there is at least one result being true.
729  return std::find(aResults.begin(), aResults.end(), true) != aResults.end();
730 }
731 
733  : mfValue(std::numeric_limits<double>::quiet_NaN())
734  , mnError(FormulaError::NONE), mbIsNumber(true)
735 {
736 }
737 
738 ScDBQueryDataIterator::ScDBQueryDataIterator(ScDocument& rDocument, const ScInterpreterContext& rContext, std::unique_ptr<ScDBQueryParamBase> pParam) :
739  mpParam (std::move(pParam))
740 {
741  switch (mpParam->GetType())
742  {
744  {
745  ScDBQueryParamInternal* p = static_cast<ScDBQueryParamInternal*>(mpParam.get());
746  mpData.reset(new DataAccessInternal(p, rDocument, rContext));
747  }
748  break;
750  {
751  ScDBQueryParamMatrix* p = static_cast<ScDBQueryParamMatrix*>(mpParam.get());
752  mpData.reset(new DataAccessMatrix(p));
753  }
754  }
755 }
756 
758 {
759  return mpData->getFirst(rValue);
760 }
761 
763 {
764  return mpData->getNext(rValue);
765 }
766 
768  mrDoc(rDoc),
769  mnTab(0),
770  mnCol(0),
771  mnIndex(0)
772 {
773  ScTable *pTab = mrDoc.FetchTable(mnTab);
774  ScColumn *pCol = pTab ? pTab->FetchColumn(mnCol) : nullptr;
775  if (pCol)
776  {
777  mbNullCol = false;
779  }
780  else
781  mbNullCol = true;
782 }
783 
785 {
786  return next();
787 }
788 
790 {
791  if (mnIndex >= maEntries.size() || mbNullCol)
792  {
793  while (mnIndex >= maEntries.size() || mbNullCol)
794  {
795  mnIndex = 0;
796  mnCol++;
797  if (mnCol > mrDoc.MaxCol())
798  {
799  mnCol = 0;
800  mnTab++;
801  if (mnTab >= mrDoc.GetTableCount())
802  return nullptr;
803  }
804  ScTable *pTab = mrDoc.FetchTable(mnTab);
805  ScColumn *pCol = pTab ? pTab->FetchColumn(mnCol) : nullptr;
806  if (pCol)
807  {
808  mbNullCol = false;
810  }
811  else
812  mbNullCol = true;
813  }
814  }
815 
816  return &maEntries[mnIndex++];
817 }
818 
819 ScCellIterator::ScCellIterator( ScDocument& rDoc, const ScRange& rRange, SubtotalFlags nSubTotalFlags ) :
820  mrDoc(rDoc),
821  maStartPos(rRange.aStart),
822  maEndPos(rRange.aEnd),
823  mnSubTotalFlags(nSubTotalFlags)
824 {
825  init();
826 }
827 
829 {
830  ++maCurColPos.first;
831  maCurColPos.second = 0;
832 
833  maCurPos.SetRow(maCurColPos.first->position);
834 }
835 
837 {
838  if (maCurColPos.second + 1 < maCurColPos.first->size)
839  {
840  // Move within the same block.
841  ++maCurColPos.second;
842  maCurPos.IncRow();
843  }
844  else
845  // Move to the next block.
846  incBlock();
847 }
848 
849 void ScCellIterator::setPos(size_t nPos)
850 {
851  maCurColPos = getColumn()->maCells.position(maCurColPos.first, nPos);
852  maCurPos.SetRow(nPos);
853 }
854 
856 {
857  return &mrDoc.maTabs[maCurPos.Tab()]->aCol[maCurPos.Col()];
858 }
859 
861 {
862  SCTAB nDocMaxTab = mrDoc.GetTableCount() - 1;
863 
865 
870  if (!ValidTab(maStartPos.Tab(), nDocMaxTab)) maStartPos.SetTab(nDocMaxTab);
871  if (!ValidTab(maEndPos.Tab(), nDocMaxTab)) maEndPos.SetTab(nDocMaxTab);
872 
873  while (maEndPos.Tab() > 0 && !mrDoc.maTabs[maEndPos.Tab()])
874  maEndPos.IncTab(-1); // Only the tables in use
875 
876  if (maStartPos.Tab() > maEndPos.Tab())
878 
879  if (!mrDoc.maTabs[maStartPos.Tab()])
880  {
881  assert(!"Table not found");
882  maStartPos = ScAddress(mrDoc.MaxCol()+1, mrDoc.MaxRow()+1, MAXTAB+1); // -> Abort on GetFirst.
883  }
884  else
885  {
886  maStartPos.SetCol(mrDoc.maTabs[maStartPos.Tab()]->ClampToAllocatedColumns(maStartPos.Col()));
887  }
888 
890 }
891 
893 {
894  const ScColumn* pCol = getColumn();
895 
896  while (true)
897  {
898  bool bNextColumn = maCurColPos.first == pCol->maCells.end();
899  if (!bNextColumn)
900  {
901  if (maCurPos.Row() > maEndPos.Row())
902  bNextColumn = true;
903  }
904 
905  if (bNextColumn)
906  {
907  // Move to the next column.
909  do
910  {
911  maCurPos.IncCol();
913  || maCurPos.Col() > maEndPos.Col())
914  {
916  maCurPos.IncTab();
917  if (maCurPos.Tab() > maEndPos.Tab())
918  {
919  maCurCell.clear();
920  return false;
921  }
922  }
923  pCol = getColumn();
924  }
925  while (pCol->IsEmptyData());
926 
927  maCurColPos = pCol->maCells.position(maCurPos.Row());
928  }
929 
930  if (maCurColPos.first->type == sc::element_type_empty)
931  {
932  incBlock();
933  continue;
934  }
935 
936  SCROW nLastRow;
937  // Skip all filtered or hidden rows, depending on mSubTotalFlags
939  pCol->GetDoc().RowFiltered(maCurPos.Row(), maCurPos.Tab(), nullptr, &nLastRow) ) ||
941  pCol->GetDoc().RowHidden(maCurPos.Row(), maCurPos.Tab(), nullptr, &nLastRow) ) )
942  {
943  setPos(nLastRow+1);
944  continue;
945  }
946 
947  if (maCurColPos.first->type == sc::element_type_formula)
948  {
950  {
951  ScFormulaCell* pCell = sc::formula_block::at(*maCurColPos.first->data, maCurColPos.second);
952  // Skip formula cells with Subtotal formulae or errors, depending on mnSubTotalFlags
953  if ( ( ( mnSubTotalFlags & SubtotalFlags::IgnoreNestedStAg ) && pCell->IsSubTotal() ) ||
954  ( ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) && pCell->GetErrCode() != FormulaError::NONE ) )
955  {
956  incPos();
957  continue;
958  }
959  }
960  }
961 
963  return true;
964  }
965  return false;
966 }
967 
969 {
970  return maCurCell.getString(&mrDoc);
971 }
972 
974 {
975  ScCellValue aRet;
976  aRet.meType = maCurCell.meType;
977 
978  switch (maCurCell.meType)
979  {
980  case CELLTYPE_STRING:
982  break;
983  case CELLTYPE_EDIT:
984  aRet.mpEditText = maCurCell.mpEditText->Clone().release();
985  break;
986  case CELLTYPE_VALUE:
987  aRet.mfValue = maCurCell.mfValue;
988  break;
989  case CELLTYPE_FORMULA:
991  break;
992  default:
993  ;
994  }
995 
996  return aRet;
997 }
998 
1000 {
1001  return maCurCell.hasString();
1002 }
1003 
1005 {
1006  return maCurCell.isEmpty();
1007 }
1008 
1010 {
1011  ScRefCellValue aOther(mrDoc, rPos);
1012  return maCurCell.equalsWithoutFormat(aOther);
1013 }
1014 
1016 {
1017  if (!ValidTab(maCurPos.Tab()))
1018  return false;
1019 
1020  maCurPos = maStartPos;
1021  const ScColumn* pCol = getColumn();
1022 
1023  maCurColPos = pCol->maCells.position(maCurPos.Row());
1024  return getCurrent();
1025 }
1026 
1028 {
1029  incPos();
1030  return getCurrent();
1031 }
1032 
1034  SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) :
1035  rDoc( rDocument ),
1036  mnTab( nTable ),
1037  nStartCol( nCol1 ),
1038  nEndCol( nCol2 ),
1039  nStartRow( nRow1 ),
1040  nEndRow( nRow2 ),
1041  mnCol( nCol1 ),
1042  mnRow( nRow1 ),
1043  mbMore( false )
1044 {
1045  assert(mnTab < rDoc.GetTableCount() && "index out of bounds, FIX IT");
1046 
1047  nEndCol = rDoc.maTabs[mnTab]->ClampToAllocatedColumns(nEndCol);
1048  if (nEndCol < nStartCol) // E.g., somewhere completely outside allocated area
1049  nEndCol = nStartCol - 1; // Empty
1050 
1051  maColPositions.reserve( nEndCol-nStartCol+1 );
1052 
1053  SetTab( mnTab );
1054 }
1055 
1057 {
1058 }
1059 
1061 {
1062  mbMore = false;
1063  mnTab = nTabP;
1064  mnRow = nStartRow;
1065  mnCol = nStartCol;
1066  maColPositions.resize(0);
1067 
1068  // Set the start position in each column.
1069  for (SCCOL i = nStartCol; i <= nEndCol; ++i)
1070  {
1071  ScColumn* pCol = &rDoc.maTabs[mnTab]->aCol[i];
1072  ColParam aParam;
1073  aParam.maPos = pCol->maCells.position(nStartRow).first;
1074  aParam.maEnd = pCol->maCells.end();
1075  aParam.mnCol = i;
1076 
1077  // find first non-empty element.
1078  while (aParam.maPos != aParam.maEnd) {
1079  if (aParam.maPos->type == sc::element_type_empty)
1080  ++aParam.maPos;
1081  else
1082  {
1083  maColPositions.push_back( aParam );
1084  break;
1085  }
1086  }
1087  }
1088 
1089  if (maColPositions.empty())
1090  return;
1091 
1092  maColPos = maColPositions.begin();
1093  mbMore = true;
1094  SkipInvalid();
1095 }
1096 
1098 {
1099  if (!mbMore)
1100  {
1101  debugiter("no more !\n");
1102  return nullptr;
1103  }
1104 
1105  // Return the current non-empty cell, and move the cursor to the next one.
1106  ColParam& r = *maColPos;
1107 
1108  rCol = mnCol = r.mnCol;
1109  rRow = mnRow;
1110  debugiter("return col %d row %d\n", (int)rCol, (int)rRow);
1111 
1112  size_t nOffset = static_cast<size_t>(mnRow) - r.maPos->position;
1113  maCurCell = sc::toRefCell(r.maPos, nOffset);
1114  Advance();
1115  debugiter("advance to: col %d row %d\n", (int)maColPos->mnCol, (int)mnRow);
1116 
1117  return &maCurCell;
1118 }
1119 
1121 {
1122  rCol = mnCol;
1123  rRow = mnRow;
1124  return mbMore;
1125 }
1126 
1127 // Skip any invalid / empty cells across the current row,
1128 // we only advance the cursor if the current entry is invalid.
1129 // if we return true we have a valid cursor (or hit the end)
1131 {
1132  assert (mbMore);
1133  assert (maColPos != maColPositions.end());
1134 
1135  // Find the next non-empty cell in the current row.
1136  while( maColPos != maColPositions.end() )
1137  {
1138  ColParam& r = *maColPos;
1139  assert (r.maPos != r.maEnd);
1140 
1141  size_t nRow = static_cast<size_t>(mnRow);
1142 
1143  if (nRow >= r.maPos->position)
1144  {
1145  if (nRow < r.maPos->position + r.maPos->size)
1146  {
1147  mnCol = maColPos->mnCol;
1148  debugiter("found valid cell at column %d, row %d\n",
1149  (int)mnCol, (int)mnRow);
1150  assert(r.maPos->type != sc::element_type_empty);
1151  return true;
1152  }
1153  else
1154  {
1155  bool bMoreBlocksInColumn = false;
1156  // This block is behind the current row position. Advance the block.
1157  for (++r.maPos; r.maPos != r.maEnd; ++r.maPos)
1158  {
1159  if (nRow < r.maPos->position + r.maPos->size &&
1160  r.maPos->type != sc::element_type_empty)
1161  {
1162  bMoreBlocksInColumn = true;
1163  break;
1164  }
1165  }
1166  if (!bMoreBlocksInColumn)
1167  {
1168  debugiter("remove column %d at row %d\n",
1169  (int)maColPos->mnCol, (int)nRow);
1170  maColPos = maColPositions.erase(maColPos);
1171  if (maColPositions.empty())
1172  {
1173  debugiter("no more columns\n");
1174  mbMore = false;
1175  }
1176  }
1177  else
1178  {
1179  debugiter("advanced column %d to block starting row %d, retrying\n",
1180  (int)maColPos->mnCol, r.maPos->position);
1181  }
1182  }
1183  }
1184  else
1185  {
1186  debugiter("skip empty cells at column %d, row %d\n",
1187  (int)maColPos->mnCol, (int)nRow);
1188  ++maColPos;
1189  }
1190  }
1191 
1192  // No more columns with anything interesting in them ?
1193  if (maColPositions.empty())
1194  {
1195  debugiter("no more live columns left - done\n");
1196  mbMore = false;
1197  return true;
1198  }
1199 
1200  return false;
1201 }
1202 
1205 {
1206  size_t nNextRow = rDoc.MaxRow()+1;
1207 
1208  for (const ColParam& r : maColPositions)
1209  {
1210  assert(o3tl::make_unsigned(mnRow) <= r.maPos->position);
1211  nNextRow = std::min (nNextRow, static_cast<size_t>(r.maPos->position));
1212  }
1213 
1214  SCROW nRow = std::max(static_cast<SCROW>(nNextRow), mnRow);
1215  debugiter("Next non empty row is %d\n", (int) nRow);
1216  return nRow;
1217 }
1218 
1220 {
1221  assert (mbMore);
1222  assert (maColPos != maColPositions.end());
1223 
1224  ++maColPos;
1225 
1226  SkipInvalid();
1227 }
1228 
1230 {
1231  if (maColPos == maColPositions.end() ||
1232  !SkipInvalidInRow())
1233  {
1234  mnRow++;
1235 
1236  if (mnRow > nEndRow)
1237  {
1238  mbMore = false;
1239  return;
1240  }
1241 
1242  maColPos = maColPositions.begin();
1243  debugiter("moving to next row\n");
1244  if (SkipInvalidInRow())
1245  {
1246  debugiter("moved to valid cell in next row (or end)\n");
1247  return;
1248  }
1249 
1251  maColPos = maColPositions.begin();
1252  bool bCorrect = SkipInvalidInRow();
1253  assert (bCorrect); (void) bCorrect;
1254  }
1255 
1256  if (mnRow > nEndRow)
1257  mbMore = false;
1258 }
1259 
1261  const ScRange& rRange ) :
1262  rDoc( rDocument ),
1263  nEndTab( rRange.aEnd.Tab() ),
1264  bCalcAsShown( rDocument.GetDocOptions().IsCalcAsShown() )
1265 {
1266  SCCOL nStartCol = rRange.aStart.Col();
1267  SCROW nStartRow = rRange.aStart.Row();
1268  SCTAB nStartTab = rRange.aStart.Tab();
1269  SCCOL nEndCol = rRange.aEnd.Col();
1270  SCROW nEndRow = rRange.aEnd.Row();
1271  PutInOrder( nStartCol, nEndCol);
1272  PutInOrder( nStartRow, nEndRow);
1273  PutInOrder( nStartTab, nEndTab );
1274 
1275  if (!rDoc.ValidCol(nStartCol)) nStartCol = rDoc.MaxCol();
1276  if (!rDoc.ValidCol(nEndCol)) nEndCol = rDoc.MaxCol();
1277  if (!rDoc.ValidRow(nStartRow)) nStartRow = rDoc.MaxRow();
1278  if (!rDoc.ValidRow(nEndRow)) nEndRow = rDoc.MaxRow();
1279  if (!ValidTab(nStartTab)) nStartTab = MAXTAB;
1280  if (!ValidTab(nEndTab)) nEndTab = MAXTAB;
1281 
1282  nCurCol = nStartCol;
1283  nCurRow = nStartRow;
1284  nCurTab = nStartTab;
1285 
1286  nNumFormat = 0; // Will be initialized in GetNumberFormat()
1287  pAttrArray = nullptr;
1288  nAttrEndRow = 0;
1289 
1290  pCellIter.reset( new ScHorizontalCellIterator( rDoc, nStartTab, nStartCol,
1291  nStartRow, nEndCol, nEndRow ) );
1292 }
1293 
1295 {
1296 }
1297 
1299 {
1300  bool bFound = false;
1301  while ( !bFound )
1302  {
1303  ScRefCellValue* pCell = pCellIter->GetNext( nCurCol, nCurRow );
1304  while ( !pCell )
1305  {
1306  if ( nCurTab < nEndTab )
1307  {
1308  pCellIter->SetTab( ++nCurTab);
1309  pCell = pCellIter->GetNext( nCurCol, nCurRow );
1310  }
1311  else
1312  return false;
1313  }
1314  switch (pCell->meType)
1315  {
1316  case CELLTYPE_VALUE:
1317  {
1318  rValue = pCell->mfValue;
1319  rErr = FormulaError::NONE;
1320  if ( bCalcAsShown )
1321  {
1322  ScColumn* pCol = &rDoc.maTabs[nCurTab]->aCol[nCurCol];
1324  nAttrEndRow, pCol->pAttrArray.get(), nCurRow, rDoc );
1325  rValue = rDoc.RoundValueAsShown( rValue, nNumFormat );
1326  }
1327  bFound = true;
1328  }
1329  break;
1330  case CELLTYPE_FORMULA:
1331  {
1332  rErr = pCell->mpFormula->GetErrCode();
1333  if (rErr != FormulaError::NONE || pCell->mpFormula->IsValue())
1334  {
1335  rValue = pCell->mpFormula->GetValue();
1336  bFound = true;
1337  }
1338  }
1339  break;
1340  case CELLTYPE_STRING :
1341  case CELLTYPE_EDIT :
1342  break;
1343  default: ; // nothing
1344  }
1345  }
1346  return bFound;
1347 }
1348 
1350  SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) :
1351  rDoc( rDocument ),
1352  nTab( nTable ),
1353  nStartCol( nCol1 ),
1354  nStartRow( nRow1 ),
1355  nEndCol( nCol2 ),
1356  nEndRow( nRow2 )
1357 {
1358  assert(nTab < rDoc.GetTableCount() && "index out of bounds, FIX IT");
1359  assert(rDoc.maTabs[nTab]);
1360 
1361  nRow = nStartRow;
1362  nCol = nStartCol;
1363 
1364  pIndices.reset( new SCSIZE[nEndCol-nStartCol+1] );
1365  pNextEnd.reset( new SCROW[nEndCol-nStartCol+1] );
1366  pHorizEnd.reset( new SCCOL[nEndCol-nStartCol+1] );
1367  ppPatterns.reset( new const ScPatternAttr*[nEndCol-nStartCol+1] );
1368 
1369  InitForNextRow(true);
1370 }
1371 
1373 {
1374 }
1375 
1377 {
1378  nMinNextEnd = rDoc.MaxRow();
1379  SCCOL nThisHead = 0;
1380 
1381  for (SCCOL i=nStartCol; i<=nEndCol; i++)
1382  {
1383  SCCOL nPos = i - nStartCol;
1384  if ( bInitialization || pNextEnd[nPos] < nRow )
1385  {
1386  const ScAttrArray& pArray = rDoc.maTabs[nTab]->ColumnData(i).AttrArray();
1387 
1388  SCSIZE nIndex;
1389  if (bInitialization)
1390  {
1391  if ( pArray.Count() )
1392  pArray.Search( nStartRow, nIndex );
1393  else
1394  nIndex = 0;
1395  pIndices[nPos] = nIndex;
1396  pHorizEnd[nPos] = rDoc.MaxCol()+1; // only for assert()
1397  }
1398  else
1399  nIndex = ++pIndices[nPos];
1400 
1401  if ( !nIndex && !pArray.Count() )
1402  {
1403  pNextEnd[nPos] = rDoc.MaxRow();
1404  assert( pNextEnd[nPos] >= nRow && "Sequence out of order" );
1405  ppPatterns[nPos] = rDoc.GetDefPattern();
1406  }
1407  else if ( nIndex < pArray.Count() )
1408  {
1409  const ScPatternAttr* pPattern = pArray.mvData[nIndex].pPattern;
1410  SCROW nThisEnd = pArray.mvData[nIndex].nEndRow;
1411  pNextEnd[nPos] = nThisEnd;
1412  assert( pNextEnd[nPos] >= nRow && "Sequence out of order" );
1413  ppPatterns[nPos] = pPattern;
1414  }
1415  else
1416  {
1417  assert(!"AttrArray does not range to MAXROW");
1418  pNextEnd[nPos] = rDoc.MaxRow();
1419  ppPatterns[nPos] = nullptr;
1420  }
1421  }
1422 
1423  if ( nMinNextEnd > pNextEnd[nPos] )
1424  nMinNextEnd = pNextEnd[nPos];
1425 
1426  // store positions of ScHorizontalAttrIterator elements (minimizing expensive ScPatternAttr comparisons)
1427  if (i > nStartCol && ppPatterns[nThisHead] != ppPatterns[nPos])
1428  {
1429  pHorizEnd[nThisHead] = i - 1;
1430  nThisHead = nPos; // start position of the next horizontal group
1431  }
1432  }
1433 
1434  pHorizEnd[nThisHead] = nEndCol; // set the end position of the last horizontal group, too
1435 }
1436 
1438 {
1439  assert(nTab < rDoc.GetTableCount() && "index out of bounds, FIX IT");
1440  for (;;)
1441  {
1442  if ( nCol <= nEndCol )
1443  {
1444  const ScPatternAttr* pPat = ppPatterns[nCol-nStartCol];
1445  rRow = nRow;
1446  rCol1 = nCol;
1447  assert( pHorizEnd[nCol-nStartCol] < rDoc.MaxCol()+1 && "missing stored data" );
1448  nCol = pHorizEnd[nCol-nStartCol];
1449  rCol2 = nCol;
1450  ++nCol; // Count up for next call
1451  return pPat; // Found it!
1452  }
1453 
1454  // Next row
1455  ++nRow;
1456  if ( nRow > nEndRow ) // Already at the end?
1457  return nullptr; // Found nothing
1458  nCol = nStartCol; // Start at the left again
1459 
1460  if ( nRow > nMinNextEnd )
1461  InitForNextRow(false);
1462  }
1463 }
1464 
1465 static bool IsGreater( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
1466 {
1467  return ( nRow1 > nRow2 ) || ( nRow1 == nRow2 && nCol1 > nCol2 );
1468 }
1469 
1471  SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
1472  : aCellIter( rDocument, nTable, nCol1, nRow1, nCol2, nRow2 )
1473  , aAttrIter( rDocument, nTable, nCol1, nRow1, nCol2, nRow2 )
1474  , nNextCol( nCol1 )
1475  , nNextRow( nRow1 )
1476  , nCellCol( 0 )
1477  , nCellRow( 0 )
1478  , nAttrCol1( 0 )
1479  , nAttrCol2( 0 )
1480  , nAttrRow( 0 )
1481  , nFoundStartCol( 0 )
1482  , nFoundEndCol( 0 )
1483  , nFoundRow( 0 )
1484  , pFoundPattern( nullptr )
1485 {
1488 }
1489 
1491 {
1492 }
1493 
1495 {
1496  // Forward iterators
1499 
1500  while (pCell && pCell->isEmpty())
1502 
1505 
1506  if ( pPattern && nAttrRow == nNextRow && nAttrCol1 < nNextCol )
1507  nAttrCol1 = nNextCol;
1508 
1509  // Find next area
1510  bool bFound = true;
1511  bool bUseCell = false;
1512 
1513  if ( pCell && pPattern )
1514  {
1515  if ( IsGreater( nCellCol, nCellRow, nAttrCol1, nAttrRow ) ) // Only attributes at the beginning?
1516  {
1517  maFoundCell.clear();
1519  nFoundRow = nAttrRow;
1521  if ( nCellRow == nAttrRow && nCellCol <= nAttrCol2 ) // Area also contains cell?
1522  nFoundEndCol = nCellCol - 1; // Only until right before the cell
1523  else
1524  nFoundEndCol = nAttrCol2; // Everything
1525  }
1526  else
1527  {
1528  bUseCell = true;
1529  if ( nAttrRow == nCellRow && nAttrCol1 == nCellCol ) // Attributes on the cell?
1531  else
1532  pFoundPattern = nullptr;
1533  }
1534  }
1535  else if ( pCell ) // Just a cell -> take over right away
1536  {
1537  pFoundPattern = nullptr;
1538  bUseCell = true; // Cell position
1539  }
1540  else if ( pPattern ) // Just attributes -> take over right away
1541  {
1542  maFoundCell.clear();
1544  nFoundRow = nAttrRow;
1547  }
1548  else // Nothing
1549  bFound = false;
1550 
1551  if ( bUseCell ) // Cell position
1552  {
1553  if (pCell)
1554  maFoundCell = *pCell;
1555  else
1556  maFoundCell.clear();
1557 
1558  nFoundRow = nCellRow;
1560  }
1561 
1562  if (bFound)
1563  {
1564  nNextRow = nFoundRow;
1565  nNextCol = nFoundEndCol + 1;
1566  }
1567 
1568  return bFound;
1569 }
1570 
1572  SCCOL nCol1, SCROW nRow1,
1573  SCCOL nCol2, SCROW nRow2) :
1574  rDoc( rDocument ),
1575  nTab( nTable ),
1576  nEndCol( nCol2 ),
1577  nStartRow( nRow1 ),
1578  nEndRow( nRow2 ),
1579  nCol( nCol1 )
1580 {
1581  if ( ValidTab(nTab) && nTab < rDoc.GetTableCount() && rDoc.maTabs[nTab] )
1582  pColIter = rDoc.maTabs[nTab]->ColumnData(nCol).CreateAttrIterator( nStartRow, nEndRow );
1583 }
1584 
1586 {
1587 }
1588 
1590 {
1591  while ( pColIter )
1592  {
1593  const ScPatternAttr* pPattern = pColIter->Next( rRow1, rRow2 );
1594  if ( pPattern )
1595  {
1596  rCol = nCol;
1597  return pPattern;
1598  }
1599 
1600  ++nCol;
1601  if ( nCol <= nEndCol )
1602  pColIter = rDoc.maTabs[nTab]->ColumnData(nCol).CreateAttrIterator( nStartRow, nEndRow );
1603  else
1604  pColIter.reset();
1605  }
1606  return nullptr; // Nothing anymore
1607 }
1608 
1610  mnTab(nTab), maRanges(nMaxRow)
1611 {
1612 }
1613 
1614 ScDocRowHeightUpdater::ScDocRowHeightUpdater(ScDocument& rDoc, OutputDevice* pOutDev, double fPPTX, double fPPTY, const vector<TabRanges>* pTabRangesArray) :
1615  mrDoc(rDoc), mpOutDev(pOutDev), mfPPTX(fPPTX), mfPPTY(fPPTY), mpTabRangesArray(pTabRangesArray)
1616 {
1617 }
1618 
1620 {
1621  if (!mpTabRangesArray || mpTabRangesArray->empty())
1622  {
1623  // No ranges defined. Update all rows in all tables.
1624  updateAll();
1625  return;
1626  }
1627 
1628  sal_uInt64 nCellCount = 0;
1629  for (const auto& rTabRanges : *mpTabRangesArray)
1630  {
1631  const SCTAB nTab = rTabRanges.mnTab;
1632  if (!ValidTab(nTab) || nTab >= mrDoc.GetTableCount() || !mrDoc.maTabs[nTab])
1633  continue;
1634 
1636  ScFlatBoolRowSegments::RangeIterator aRangeItr(rTabRanges.maRanges);
1637  for (bool bFound = aRangeItr.getFirst(aData); bFound; bFound = aRangeItr.getNext(aData))
1638  {
1639  if (!aData.mbValue)
1640  continue;
1641 
1642  nCellCount += mrDoc.maTabs[nTab]->GetWeightedCount(aData.mnRow1, aData.mnRow2);
1643  }
1644  }
1645 
1646  ScProgress aProgress(mrDoc.GetDocumentShell(), ScResId(STR_PROGRESS_HEIGHTING), nCellCount, true);
1647 
1648  Fraction aZoom(1, 1);
1649  sal_uInt64 nProgressStart = 0;
1650  for (const auto& rTabRanges : *mpTabRangesArray)
1651  {
1652  const SCTAB nTab = rTabRanges.mnTab;
1653  if (!ValidTab(nTab) || nTab >= mrDoc.GetTableCount() || !mrDoc.maTabs[nTab])
1654  continue;
1655 
1656  sc::RowHeightContext aCxt(mrDoc.MaxRow(), mfPPTX, mfPPTY, aZoom, aZoom, mpOutDev);
1658  ScFlatBoolRowSegments::RangeIterator aRangeItr(rTabRanges.maRanges);
1659  for (bool bFound = aRangeItr.getFirst(aData); bFound; bFound = aRangeItr.getNext(aData))
1660  {
1661  if (!aData.mbValue)
1662  continue;
1663 
1664  mrDoc.maTabs[nTab]->SetOptimalHeight(
1665  aCxt, aData.mnRow1, aData.mnRow2, true, &aProgress, nProgressStart);
1666 
1667  nProgressStart += mrDoc.maTabs[nTab]->GetWeightedCount(aData.mnRow1, aData.mnRow2);
1668  }
1669  }
1670 }
1671 
1673 {
1674  sal_uInt64 nCellCount = 0;
1675  for (SCTAB nTab = 0; nTab < mrDoc.GetTableCount(); ++nTab)
1676  {
1677  if (!ValidTab(nTab) || !mrDoc.maTabs[nTab])
1678  continue;
1679 
1680  nCellCount += mrDoc.maTabs[nTab]->GetWeightedCount();
1681  }
1682 
1683  ScProgress aProgress(mrDoc.GetDocumentShell(), ScResId(STR_PROGRESS_HEIGHTING), nCellCount, true);
1684 
1685  Fraction aZoom(1, 1);
1686  sc::RowHeightContext aCxt(mrDoc.MaxRow(), mfPPTX, mfPPTY, aZoom, aZoom, mpOutDev);
1687  sal_uInt64 nProgressStart = 0;
1688  for (SCTAB nTab = 0; nTab < mrDoc.GetTableCount(); ++nTab)
1689  {
1690  if (!ValidTab(nTab) || !mrDoc.maTabs[nTab])
1691  continue;
1692 
1693  mrDoc.maTabs[nTab]->SetOptimalHeight(aCxt, 0, mrDoc.MaxRow(), true, &aProgress, nProgressStart);
1694  nProgressStart += mrDoc.maTabs[nTab]->GetWeightedCount();
1695  }
1696 }
1697 
1699  SCCOL nCol1, SCROW nRow1,
1700  SCCOL nCol2, SCROW nRow2) :
1701  rDoc( rDocument ),
1702  nTab( nTable ),
1703  nEndCol( nCol2 ),
1704  nStartRow( nRow1 ),
1705  nEndRow( nRow2 ),
1706  nIterStartCol( nCol1 ),
1707  nIterEndCol( nCol1 )
1708 {
1709  if ( ValidTab(nTab) && nTab < rDoc.GetTableCount() && rDoc.maTabs[nTab] )
1710  {
1711  pColIter = rDoc.maTabs[nTab]->ColumnData(nIterStartCol).CreateAttrIterator( nStartRow, nEndRow );
1712  while ( nIterEndCol < nEndCol &&
1713  rDoc.maTabs[nTab]->ColumnData(nIterEndCol).IsAllAttrEqual(
1714  rDoc.maTabs[nTab]->ColumnData(nIterEndCol+1), nStartRow, nEndRow ) )
1715  ++nIterEndCol;
1716  }
1717 }
1718 
1720 {
1721 }
1722 
1724 {
1725  if (pColIter)
1726  {
1727  SCROW nNextRow = pColIter->GetNextRow();
1728  pColIter = rDoc.maTabs[nTab]->ColumnData(nIterStartCol).CreateAttrIterator( nNextRow, nEndRow );
1729  }
1730 }
1731 
1733  SCROW& rRow1, SCROW& rRow2 )
1734 {
1735  while ( pColIter )
1736  {
1737  const ScPatternAttr* pPattern = pColIter->Next( rRow1, rRow2 );
1738  if ( pPattern )
1739  {
1740  rCol1 = nIterStartCol;
1741  rCol2 = nIterEndCol;
1742  return pPattern;
1743  }
1744 
1746  if ( nIterStartCol <= nEndCol )
1747  {
1749  pColIter = rDoc.maTabs[nTab]->ColumnData(nIterStartCol).CreateAttrIterator( nStartRow, nEndRow );
1750  while ( nIterEndCol < nEndCol &&
1751  rDoc.maTabs[nTab]->ColumnData(nIterEndCol).IsAllAttrEqual(
1752  rDoc.maTabs[nTab]->ColumnData(nIterEndCol+1), nStartRow, nEndRow ) )
1753  ++nIterEndCol;
1754  }
1755  else
1756  pColIter.reset();
1757  }
1758  return nullptr; // Nothing anymore
1759 }
1760 
1762  mrBreaks(rBreaks),
1763  maItr(rBreaks.begin()), maEnd(rBreaks.end())
1764 {
1765 }
1766 
1768 {
1769  maItr = mrBreaks.begin();
1770  return maItr == maEnd ? NOT_FOUND : *maItr;
1771 }
1772 
1774 {
1775  ++maItr;
1776  return maItr == maEnd ? NOT_FOUND : *maItr;
1777 }
1778 
1779 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:112
ScValueIterator(ScDocument &rDocument, const ScRange &rRange, SubtotalFlags nSubTotalFlags=SubtotalFlags::NONE, bool bTextAsZero=false)
Definition: dociter.cxx:85
bool getFirst(RangeData &rRange)
ScUsedAreaIterator(ScDocument &rDocument, SCTAB nTable, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: dociter.cxx:1470
UNDEFINED
ScAddress maCurPos
Definition: dociter.hxx:214
static void ScAttrArray_IterGetNumberFormat(sal_uInt32 &nFormat, const ScAttrArray *&rpArr, SCROW &nAttrEndRow, const ScAttrArray *pNewArr, SCROW nRow, const ScDocument &rDoc, const ScInterpreterContext *pContext=nullptr)
Definition: dociter.cxx:64
sal_Int32 nIndex
CellType meType
Definition: cellvalue.hxx:37
OUString getString() const
OUString getString() const
Definition: dociter.cxx:968
bool isValidQuery(SCROW mnRow, const ScMatrix &rMat) const
Definition: dociter.cxx:600
ScAddress aStart
Definition: address.hxx:497
ScRefCellValue * GetNext(SCCOL &rCol, SCROW &rRow)
Definition: dociter.cxx:1097
sal_Int32 compareString(const OUString &s1, const OUString &s2) const
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
ScDocRowHeightUpdater(ScDocument &rDoc, OutputDevice *pOutDev, double fPPTX, double fPPTY, const ::std::vector< TabRanges > *pTabRangesArray)
Passing a NULL pointer to pTabRangesArray forces the heights of all rows in all tables to be updated...
Definition: dociter.cxx:1614
void IncTab(SCTAB nDelta=1)
Definition: address.hxx:320
std::unique_ptr< const ScPatternAttr *[]> ppPatterns
Definition: dociter.hxx:373
SCROW Row() const
Definition: address.hxx:274
OUString getString(const ScDocument *pDoc) const
Retrieve string value.
Definition: cellvalue.cxx:660
const Item & GetQueryItem() const
Definition: queryentry.hxx:85
DataAccessMatrix(ScDBQueryParamMatrix *pParam)
Definition: dociter.cxx:513
ScTable * FetchTable(SCTAB nTab)
Definition: document.cxx:2536
ScDocument & rDoc
Definition: dociter.hxx:254
rtl_uString * getDataIgnoreCase()
bool isEmpty() const
Definition: cellvalue.cxx:670
ScColumn * FetchColumn(SCCOL nCol)
Definition: table2.cxx:1226
ScFormulaCell * Clone() const
virtual bool getFirst(Value &rValue) override
Definition: dociter.cxx:470
bool GetPos(SCCOL &rCol, SCROW &rRow)
Definition: dociter.cxx:1120
bool equalsWithoutFormat(const ScAddress &rPos) const
Definition: dociter.cxx:1009
ScRefCellValue maCurCell
Definition: dociter.hxx:314
::std::set< SCROW >::const_iterator maEnd
Definition: dociter.hxx:440
sal_Int64 n
QueryItemsType & GetQueryItems()
Definition: queryentry.hxx:75
bool bTextAsZero
Definition: dociter.hxx:69
bool getCurrent()
Definition: dociter.cxx:892
std::unique_ptr< ScAttrIterator > pColIter
Definition: dociter.hxx:261
sal_Int32 mnCol
const ScAttrArray * pAttrArray
Definition: dociter.hxx:339
bool GetNext(Value &rValue)
Does NOT reset rValue if no value found!
Definition: dociter.cxx:762
std::vector< sc::FormulaGroupEntry > maEntries
Definition: dociter.hxx:195
bool IsEmptyData() const
Definition: column2.cxx:1251
double mfValue
Definition: cellvalue.hxx:39
SCCOLROW nField
Definition: queryentry.hxx:61
ScAddress aEnd
Definition: address.hxx:498
bool hasString() const
Definition: dociter.cxx:999
ScAddress maStartPos
Definition: dociter.hxx:212
This is very similar to ScCellValue, except that it references the original value instead of copying ...
Definition: cellvalue.hxx:103
static bool IsQueryValid(ScDocument &rDoc, const ScQueryParam &rParam, SCTAB nTab, SCROW nRow, const ScRefCellValue *pCell)
Definition: dociter.cxx:325
SubtotalFlags mnSubTotalFlags
Definition: dociter.hxx:217
static const sc::CellStoreType * GetColumnCellStore(ScDocument &rDoc, SCTAB nTab, SCCOL nCol)
Definition: dociter.cxx:308
bool getNext(RangeData &rRange)
ScAddress maEndPos
Definition: dociter.hxx:213
DataAccessInternal(ScDBQueryParamInternal *pParam, ScDocument &rDoc, const ScInterpreterContext &rContext)
Definition: dociter.cxx:333
std::unique_ptr< SCSIZE[]> pIndices
Definition: dociter.hxx:371
NONE
double GetDouble(SCSIZE nC, SCSIZE nR) const
Definition: scmatrix.cxx:3010
ScFormulaGroupIterator(ScDocument &rDoc)
Definition: dociter.cxx:767
::std::set< SCROW >::const_iterator maItr
Definition: dociter.hxx:439
const ScPatternAttr * pPattern
Definition: dociter.hxx:405
def position
bool equalsWithoutFormat(const ScRefCellValue &r) const
Definition: cellvalue.cxx:686
Store arbitrary cell value of any kind.
Definition: cellvalue.hxx:35
SubtotalFlags
Definition: global.hxx:238
const ScColumn * getColumn() const
Definition: dociter.cxx:855
const sc::CellStoreType * mpCells
Definition: dociter.hxx:71
const mdds::mtv::element_t element_type_formula
Definition: mtvelements.hxx:50
void SetTab(SCTAB nTab)
Set a(nother) sheet and (re)init.
Definition: dociter.cxx:1060
const EditTextObject * mpEditText
Definition: cellvalue.hxx:109
enumrange< T >::Iterator begin(enumrange< T >)
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
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
Definition: types.hxx:23
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:315
ScMatrixRef mpMatrix
Definition: queryparam.hxx:197
double GetValue()
bool hasString() const
Definition: cellvalue.cxx:617
FormulaError GetErrCode()
TableContainer maTabs
Definition: document.hxx:377
int nCount
PositionType maCurColPos
Definition: dociter.hxx:216
SC_DLLPUBLIC SCSIZE GetEntryCount() const
Definition: queryparam.cxx:110
SCROW GetRow() const
Definition: dociter.cxx:114
sc::CellStoreType maCells
Definition: column.hxx:193
SC_DLLPUBLIC const ScQueryEntry & GetEntry(SCSIZE n) const
Definition: queryparam.cxx:115
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:110
SCTAB Tab() const
Definition: address.hxx:283
void SetRow(SCROW nRowP)
Definition: address.hxx:287
bool IsStringOrEmpty(SCSIZE nIndex) const
Definition: scmatrix.cxx:3045
const ::std::vector< TabRanges > * mpTabRangesArray
Definition: dociter.hxx:472
bool Search(SCROW nRow, SCSIZE &nIndex) const
Definition: attarray.cxx:194
ScAttrRectIterator(ScDocument &rDocument, SCTAB nTable, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: dociter.cxx:1698
void SetCol(SCCOL nColP)
Definition: address.hxx:291
SC_DLLPUBLIC SCCOL GetAllocatedColumnsCount(SCTAB nTab) const
Definition: documen3.cxx:2150
bool GetNext(double &rValue, FormulaError &rErr)
Does NOT reset rValue if no value found!
Definition: dociter.cxx:1298
void PutInOrder(T &nStart, T &nEnd)
Definition: address.hxx:150
ScDBQueryParamMatrix * mpParam
Definition: dociter.hxx:171
constexpr OUStringLiteral aData
std::vector< ScAttrEntry > mvData
Definition: attarray.hxx:98
std::vector< ColParam >::iterator maColPos
Definition: dociter.hxx:303
SvNumFormatType nNumFmtType
Definition: dociter.hxx:66
sc::CellStoreType::const_iterator maEnd
Definition: dociter.hxx:299
void SetTab(SCTAB nTabP)
Definition: address.hxx:295
ScDocument & mrDoc
Definition: dociter.hxx:190
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:890
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:459
std::unique_ptr< SCCOL[]> pHorizEnd
Definition: dociter.hxx:370
ScRefCellValue maCurCell
Definition: dociter.hxx:219
int i
PositionType maCurPos
Definition: dociter.hxx:72
svl::SharedString GetString(SCSIZE nC, SCSIZE nR) const
Definition: scmatrix.cxx:3025
SC_DLLPUBLIC bool RowFiltered(SCROW nRow, SCTAB nTab, SCROW *pFirstRow=nullptr, SCROW *pLastRow=nullptr) const
Definition: document.cxx:4549
void IncCol(SCCOL nDelta=1)
Definition: address.hxx:316
ScAddress maEndPos
Definition: dociter.hxx:61
const svl::SharedString * mpString
Definition: cellvalue.hxx:108
sal_Int16 SCCOL
Definition: types.hxx:21
bool ValidCol(SCCOL nCol) const
Definition: document.hxx:897
void setPos(size_t nPos)
Definition: dociter.cxx:849
sc::FormulaGroupEntry * next()
Definition: dociter.cxx:789
virtual bool getFirst(Value &rValue) override
Definition: dociter.cxx:553
svl::SharedString * mpString
Definition: cellvalue.hxx:40
bool GetThis(double &rValue, FormulaError &rErr)
See if the cell at the current position is a non-empty cell.
Definition: dociter.cxx:137
std::vector< ColParam > maColPositions
Definition: dociter.hxx:304
SCROW nAttrEndRow
Definition: dociter.hxx:64
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
const mdds::mtv::element_t element_type_empty
Definition: mtvelements.hxx:57
void IncRow(SCROW nDelta=1)
Definition: address.hxx:312
ScDocument & GetDoc() const
Definition: column.hxx:127
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber, SvNumInputOptions eInputOptions=SvNumInputOptions::NONE)
bool GetErrorOrValue(FormulaError &rErr, double &rVal)
VclPtr< OutputDevice > mpOutDev
Definition: dociter.hxx:469
SvNumFormatType
const mdds::mtv::element_t element_type_numeric
Mapped standard element types (for convenience).
Definition: mtvelements.hxx:56
ScColContainer aCol
Definition: table.hxx:160
sal_uInt32 GetNumberFormat(SvNumberFormatter *) const
Definition: patattr.cxx:1301
SCROW FindNextNonEmptyRow()
Find the next row that has some real content in one of its columns.
Definition: dociter.cxx:1204
sal_uInt32 nNumFmtIndex
Definition: dociter.hxx:59
bool GetFirst(Value &rValue)
Does NOT reset rValue if no value found!
Definition: dociter.cxx:757
TabRanges(SCTAB nTab, SCROW nMaxRow)
Definition: dociter.cxx:1609
ScHorizontalAttrIterator(ScDocument &rDocument, SCTAB nTable, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: dociter.cxx:1349
std::unique_ptr< ScAttrIterator > pColIter
Definition: dociter.hxx:283
const Point maEnd
ScCellIterator(ScDocument &rDoc, const ScRange &rRange, SubtotalFlags nSubTotalFlags=SubtotalFlags::NONE)
Definition: dociter.cxx:819
const SCTAB MAXTAB
Definition: address.hxx:70
::std::set< SCROW > & mrBreaks
Definition: dociter.hxx:438
SCSIZE Count() const
Definition: attarray.hxx:226
sal_uInt32 GetNumberFormat(const ScInterpreterContext &rContext, SCROW nRow) const
Definition: column.hxx:966
rtl_uString * getData()
svl::SharedString maString
Definition: queryentry.hxx:49
enumrange< T >::Iterator end(enumrange< T >)
const NodeContext & mrContext
const svl::SharedString & GetString()
FormulaError
SCCOL Col() const
Definition: address.hxx:279
bool isEmpty() const
Definition: dociter.cxx:1004
ScHorizontalCellIterator(ScDocument &rDocument, SCTAB nTable, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: dociter.cxx:1033
SC_DLLPUBLIC double RoundValueAsShown(double fVal, sal_uInt32 nFormat, const ScInterpreterContext *pContext=nullptr) const
Definition: documen4.cxx:641
sal_uInt32 nNumFormat
Definition: dociter.hxx:58
std::unique_ptr< ScHorizontalCellIterator > pCellIter
Definition: dociter.hxx:341
CellType meType
Definition: cellvalue.hxx:105
sal_Int32 SCROW
Definition: types.hxx:17
mdds::mtv::soa::multi_type_vector< CellFunc, CellStoreTrait > CellStoreType
static constexpr SCROW NOT_FOUND
Definition: dociter.hxx:431
::std::unique_ptr< ScDBQueryParamBase > mpParam
Definition: dociter.hxx:176
bool ValidRow(SCROW nRow) const
Definition: document.hxx:898
bool IsSubTotal() const
sc::CellStoreType::const_iterator maPos
Definition: dociter.hxx:298
static SC_DLLPUBLIC CollatorWrapper & GetCollator()
case-insensitive collator
Definition: global.cxx:1055
ScDocument & mrDoc
Definition: dociter.hxx:211
static const ScAttrArray * GetAttrArrayByCol(ScDocument &rDoc, SCTAB nTab, SCCOL nCol)
Definition: dociter.cxx:318
bool IsEmpty(SCSIZE nC, SCSIZE nR) const
Definition: scmatrix.cxx:3055
ScAddress maStartPos
Definition: dociter.hxx:60
bool GetFirst(double &rValue, FormulaError &rErr)
Does NOT reset rValue if no value found!
Definition: dociter.cxx:270
void InitForNextRow(bool bInitialization)
Definition: dociter.cxx:1376
sc::FormulaGroupEntry * first()
Definition: dociter.cxx:784
const mdds::mtv::element_t element_type_edittext
Definition: mtvelements.hxx:49
#define debugiter(...)
Definition: dociter.cxx:62
ScHorizontalValueIterator(ScDocument &rDocument, const ScRange &rRange)
Definition: dociter.cxx:1260
virtual bool getNext(Value &rValue) override
Definition: dociter.cxx:559
virtual std::unique_ptr< EditTextObject > Clone() const =0
bool bCalcAsShown
Definition: dociter.hxx:68
const ScPatternAttr * GetNext(SCCOL &rCol1, SCCOL &rCol2, SCROW &rRow1, SCROW &rRow2)
Definition: dociter.cxx:1732
SvNumFormatType GetNumberFormatType(sal_uInt32 nFIndex) const
void * p
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:398
const ScPatternAttr * GetNext(SCCOL &rCol, SCROW &rRow1, SCROW &rRow2)
Definition: dociter.cxx:1589
std::vector< sc::FormulaGroupEntry > GetFormulaGroupEntries()
Get all non-grouped formula cells and formula cell groups in the whole column.
Definition: column.cxx:2455
SC_DLLPUBLIC ScPatternAttr * GetDefPattern() const
Definition: document.cxx:6151
ScHorizontalAttrIterator aAttrIter
Definition: dociter.hxx:394
EditTextObject * mpEditText
Definition: cellvalue.hxx:41
ScQueryConnect eConnect
Definition: queryentry.hxx:63
void GetCurNumFmtInfo(const ScInterpreterContext &rContext, SvNumFormatType &nType, sal_uInt32 &nIndex)
Definition: dociter.cxx:255
bool GetNext(double &rValue, FormulaError &rErr)
Does NOT reset rValue if no value found!
Definition: dociter.cxx:294
ScCellValue getCellValue() const
Definition: dociter.cxx:973
SC_DLLPUBLIC bool RowHidden(SCROW nRow, SCTAB nTab, SCROW *pFirstRow=nullptr, SCROW *pLastRow=nullptr) const
Definition: document.cxx:4479
ScRefCellValue * pCell
Definition: dociter.hxx:401
ScRefCellValue toRefCell(const sc::CellStoreType::const_iterator &itPos, size_t nOffset)
std::vector< Item > QueryItemsType
Definition: queryentry.hxx:58
virtual bool getCurrent(Value &rValue) override
Definition: dociter.cxx:526
const ScPatternAttr * GetNext(SCCOL &rCol1, SCCOL &rCol2, SCROW &rRow)
Definition: dociter.cxx:1437
const ScPatternAttr * GetPatternRange(SCROW &rStartRow, SCROW &rEndRow, SCROW nRow) const
Returns if you search for attributes at nRow the range from rStartRow to rEndRow where that attribute...
Definition: attarray.cxx:254
ScDocument & rDoc
Definition: dociter.hxx:275
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1080
#define SAL_WARN(area, stream)
ScDocAttrIterator(ScDocument &rDocument, SCTAB nTable, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: dociter.cxx:1571
virtual bool getCurrent(Value &rValue) override
Definition: dociter.cxx:367
void incPos()
Definition: dociter.cxx:836
sal_Int32 mnRow
SubtotalFlags mnSubTotalFlags
Definition: dociter.hxx:65
const ScPatternAttr * pFoundPattern
Definition: dociter.hxx:410
ScInterpreterContext * pContext
Definition: dociter.hxx:56
int mnIndex
ScRowBreakIterator(::std::set< SCROW > &rBreaks)
Definition: dociter.cxx:1761
ScDocument & mrDoc
Definition: dociter.hxx:468
ScQueryOp eOp
Definition: queryentry.hxx:62
ScHorizontalCellIterator aCellIter
Definition: dociter.hxx:393
std::unique_ptr< ScAttrArray > pAttrArray
Definition: column.hxx:118
SCCOL GetAllocatedColumnsCount() const
Definition: table.hxx:1127
const mdds::mtv::element_t element_type_string
Definition: mtvelements.hxx:48
void incBlock()
Definition: dociter.cxx:828
::std::unique_ptr< DataAccess > mpData
Definition: dociter.hxx:177
virtual bool getNext(Value &rValue) override
Definition: dociter.cxx:483
void IncBlock()
Definition: dociter.cxx:121
ScDBQueryDataIterator(ScDocument &rDocument, const ScInterpreterContext &rContext, std::unique_ptr< ScDBQueryParamBase > pParam)
Definition: dociter.cxx:738
bool ValidTab(SCTAB nTab)
Definition: address.hxx:111
std::unique_ptr< SCROW[]> pNextEnd
Definition: dociter.hxx:369
Each instance of this struct represents a single filtering criteria.
Definition: queryentry.hxx:33
ScDBQueryParamInternal * mpParam
Definition: dociter.hxx:145
const ScAttrArray * pAttrArray
Definition: dociter.hxx:57
bool IsValueOrEmpty(SCSIZE nC, SCSIZE nR) const
Definition: scmatrix.cxx:3085
sal_uInt16 nPos
sal_Int16 SCTAB
Definition: types.hxx:22
ScRefCellValue maFoundCell
Definition: dociter.hxx:412
static bool IsGreater(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: dociter.cxx:1465
bool m_bDetectedRangeSegmentation false
ScDocument & mrDoc
Definition: dociter.hxx:55
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo