1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
22 #include "address.hxx"
23 #include "formulagroup.hxx"
26 #include "cellvalue.hxx"
27 #include "mtvelements.hxx"
28 #include "queryparam.hxx"
29 #include <vcl/outdev.hxx>
30 #include <vcl/vclptr.hxx>
40 class ScFlatBoolRowSegments
;
42 struct ScDBQueryParamBase
;
44 struct ScDBQueryParamInternal
;
45 struct ScDBQueryParamMatrix
;
48 struct ScInterpreterContext
;
49 enum class SvNumFormatType
: sal_Int16
;
51 class ScValueIterator
// walk through all values in an area
53 typedef sc::CellStoreType::const_position_type PositionType
;
56 ScInterpreterContext
* pContext
;
57 const ScAttrArray
* pAttrArray
;
58 sal_uInt32 nNumFormat
; // for CalcAsShown
59 sal_uInt32 nNumFmtIndex
;
65 SubtotalFlags mnSubTotalFlags
;
66 SvNumFormatType nNumFmtType
;
71 const sc::CellStoreType
* mpCells
;
72 PositionType maCurPos
;
79 * See if the cell at the current position is a non-empty cell. If not,
80 * move to the next non-empty cell position.
82 bool GetThis( double& rValue
, FormulaError
& rErr
);
87 ScDocument
& rDocument
, const ScRange
& rRange
, SubtotalFlags nSubTotalFlags
= SubtotalFlags::NONE
,
88 bool bTextAsZero
= false );
90 void GetCurNumFmtInfo( const ScInterpreterContext
& rContext
, SvNumFormatType
& nType
, sal_uInt32
& nIndex
);
92 /// Does NOT reset rValue if no value found!
93 bool GetFirst( double& rValue
, FormulaError
& rErr
);
95 /// Does NOT reset rValue if no value found!
96 bool GetNext( double& rValue
, FormulaError
& rErr
);
98 void SetInterpreterContext( ScInterpreterContext
* context
) { pContext
= context
; }
101 class ScDBQueryDataIterator
108 FormulaError mnError
;
115 static const sc::CellStoreType
* GetColumnCellStore(ScDocument
& rDoc
, SCTAB nTab
, SCCOL nCol
);
116 static const ScAttrArray
* GetAttrArrayByCol(ScDocument
& rDoc
, SCTAB nTab
, SCCOL nCol
);
117 static bool IsQueryValid(ScDocument
& rDoc
, const ScQueryParam
& rParam
, SCTAB nTab
, SCROW nRow
, const ScRefCellValue
* pCell
);
123 virtual ~DataAccess() = 0;
124 virtual bool getCurrent(Value
& rValue
) = 0;
125 virtual bool getFirst(Value
& rValue
) = 0;
126 virtual bool getNext(Value
& rValue
) = 0;
129 class DataAccessInternal final
: public DataAccess
131 typedef std::pair
<sc::CellStoreType::const_iterator
,size_t> PositionType
;
133 DataAccessInternal(ScDBQueryParamInternal
* pParam
, ScDocument
& rDoc
, const ScInterpreterContext
& rContext
);
134 virtual ~DataAccessInternal() override
;
135 virtual bool getCurrent(Value
& rValue
) override
;
136 virtual bool getFirst(Value
& rValue
) override
;
137 virtual bool getNext(Value
& rValue
) override
;
143 const sc::CellStoreType
* mpCells
;
144 PositionType maCurPos
;
145 ScDBQueryParamInternal
* mpParam
;
147 const ScInterpreterContext
& mrContext
;
148 const ScAttrArray
* pAttrArray
;
149 sal_uInt32 nNumFormat
; // for CalcAsShown
150 sal_uInt32 nNumFmtIndex
;
155 SvNumFormatType nNumFmtType
;
159 class DataAccessMatrix final
: public DataAccess
162 DataAccessMatrix(ScDBQueryParamMatrix
* pParam
);
163 virtual ~DataAccessMatrix() override
;
164 virtual bool getCurrent(Value
& rValue
) override
;
165 virtual bool getFirst(Value
& rValue
) override
;
166 virtual bool getNext(Value
& rValue
) override
;
169 bool isValidQuery(SCROW mnRow
, const ScMatrix
& rMat
) const;
171 ScDBQueryParamMatrix
* mpParam
;
176 ::std::unique_ptr
<ScDBQueryParamBase
> mpParam
;
177 ::std::unique_ptr
<DataAccess
> mpData
;
180 ScDBQueryDataIterator(ScDocument
& rDocument
, const ScInterpreterContext
& rContext
, std::unique_ptr
<ScDBQueryParamBase
> pParam
);
181 /// Does NOT reset rValue if no value found!
182 bool GetFirst(Value
& rValue
);
183 /// Does NOT reset rValue if no value found!
184 bool GetNext(Value
& rValue
);
187 class ScFormulaGroupIterator
195 std::vector
<sc::FormulaGroupEntry
> maEntries
;
198 ScFormulaGroupIterator( ScDocument
& rDoc
);
200 sc::FormulaGroupEntry
* first();
201 sc::FormulaGroupEntry
* next();
205 * Walk through all cells in an area. For SubTotal and Aggregate depending on mnSubTotalFlags.
209 typedef std::pair
<sc::CellStoreType::const_iterator
, size_t> PositionType
;
212 ScAddress maStartPos
;
216 PositionType maCurColPos
;
217 SubtotalFlags mnSubTotalFlags
;
219 ScRefCellValue maCurCell
;
223 void setPos(size_t nPos
);
225 const ScColumn
* getColumn() const;
231 ScCellIterator( ScDocument
& rDoc
, const ScRange
& rRange
, SubtotalFlags nSubTotalFlags
= SubtotalFlags::NONE
);
233 const ScAddress
& GetPos() const { return maCurPos
; }
235 CellType
getType() const { return maCurCell
.meType
;}
236 OUString
getString() const;
237 const EditTextObject
* getEditText() const { return maCurCell
.mpEditText
;}
238 ScFormulaCell
* getFormulaCell() { return maCurCell
.mpFormula
;}
239 const ScFormulaCell
* getFormulaCell() const { return maCurCell
.mpFormula
;}
240 ScCellValue
getCellValue() const;
241 const ScRefCellValue
& getRefCellValue() const { return maCurCell
;}
243 bool hasString() const;
244 bool isEmpty() const;
245 bool equalsWithoutFormat( const ScAddress
& rPos
) const;
251 class ScQueryCellIterator
// walk through all non-empty cells in an area
253 enum StopOnMismatchBits
255 nStopOnMismatchDisabled
= 0x00,
256 nStopOnMismatchEnabled
= 0x01,
257 nStopOnMismatchOccurred
= 0x02,
258 nStopOnMismatchExecuted
= nStopOnMismatchEnabled
| nStopOnMismatchOccurred
261 enum TestEqualConditionBits
263 nTestEqualConditionDisabled
= 0x00,
264 nTestEqualConditionEnabled
= 0x01,
265 nTestEqualConditionMatched
= 0x02,
266 nTestEqualConditionFulfilled
= nTestEqualConditionEnabled
| nTestEqualConditionMatched
269 typedef sc::CellStoreType::const_position_type PositionType
;
270 PositionType maCurPos
;
272 ScQueryParam maParam
;
274 const ScInterpreterContext
& mrContext
;
278 sal_uInt8 nStopOnMismatch
;
279 sal_uInt8 nTestEqualCondition
;
281 bool bIgnoreMismatchOnLeadingStrings
;
283 /** Initialize position for new column. */
289 /* Only works if no regular expression is involved, only
290 searches for rows in one column, and only the first
291 query entry is considered with simple conditions
292 SC_LESS_EQUAL (sorted ascending) or SC_GREATER_EQUAL
293 (sorted descending). Check these things before
294 invocation! Delivers a starting point, continue with
295 GetThis() and GetNext() afterwards. Introduced for
296 FindEqualOrSortedLastInRange()
301 ScQueryCellIterator(ScDocument
& rDocument
, const ScInterpreterContext
& rContext
, SCTAB nTable
,
302 const ScQueryParam
& aParam
, bool bMod
);
303 // when !bMod, the QueryParam has to be filled
307 SCCOL
GetCol() const { return nCol
; }
308 SCROW
GetRow() const { return nRow
; }
310 // increments all Entry.nField, if column
311 // changes, for ScInterpreter ScHLookup()
312 void SetAdvanceQueryParamEntryField( bool bVal
)
313 { bAdvanceQuery
= bVal
; }
314 void AdvanceQueryParamEntryField();
316 /** If set, iterator stops on first non-matching cell
317 content. May be used in SC_LESS_EQUAL queries where a
318 cell range is assumed to be sorted; stops on first
319 value being greater than the queried value and
320 GetFirst()/GetNext() return NULL. StoppedOnMismatch()
322 However, the iterator's conditions are not set to end
323 all queries, GetCol() and GetRow() return values for
324 the non-matching cell, further GetNext() calls may be
326 void SetStopOnMismatch( bool bVal
)
328 nStopOnMismatch
= sal::static_int_cast
<sal_uInt8
>(bVal
? nStopOnMismatchEnabled
:
329 nStopOnMismatchDisabled
);
331 bool StoppedOnMismatch() const
332 { return nStopOnMismatch
== nStopOnMismatchExecuted
; }
334 /** If set, an additional test for SC_EQUAL condition is
335 executed in ScTable::ValidQuery() if SC_LESS_EQUAL or
336 SC_GREATER_EQUAL conditions are to be tested. May be
337 used where a cell range is assumed to be sorted to stop
338 if an equal match is found. */
339 void SetTestEqualCondition( bool bVal
)
341 nTestEqualCondition
= sal::static_int_cast
<sal_uInt8
>(bVal
?
342 nTestEqualConditionEnabled
:
343 nTestEqualConditionDisabled
);
345 bool IsEqualConditionFulfilled() const
346 { return nTestEqualCondition
== nTestEqualConditionFulfilled
; }
348 /** In a range assumed to be sorted find either the last of
349 a sequence of equal entries or the last being less than
350 (or greater than) the queried value. Used by the
351 interpreter for [HV]?LOOKUP() and MATCH(). Column and
352 row position of the found entry are returned, otherwise
355 The search does not stop when encountering a string and does not
356 assume that no values follow anymore.
357 If querying for a string a mismatch on the first
358 entry, e.g. column header, is ignored.
360 @ATTENTION! StopOnMismatch, TestEqualCondition and
361 the internal IgnoreMismatchOnLeadingStrings and query
362 params are in an undefined state upon return! The
363 iterator is not usable anymore except for obtaining the
366 bool FindEqualOrSortedLastInRange( SCCOL
& nFoundCol
, SCROW
& nFoundRow
);
369 // Used by ScInterpreter::ScCountIf.
370 // Walk through all non-empty cells in an area.
371 class ScCountIfCellIterator
373 typedef sc::CellStoreType::const_position_type PositionType
;
374 PositionType maCurPos
;
375 ScQueryParam maParam
;
377 const ScInterpreterContext
& mrContext
;
382 /** Initialize position for new column. */
386 void AdvanceQueryParamEntryField();
389 ScCountIfCellIterator(ScDocument
& rDocument
, const ScInterpreterContext
& rContext
, SCTAB nTable
,
390 const ScQueryParam
& aParam
);
394 class ScDocAttrIterator
// all attribute areas
403 std::unique_ptr
<ScAttrIterator
>
407 ScDocAttrIterator(ScDocument
& rDocument
, SCTAB nTable
,
408 SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
);
409 ~ScDocAttrIterator();
411 const ScPatternAttr
* GetNext( SCCOL
& rCol
, SCROW
& rRow1
, SCROW
& rRow2
);
414 class ScAttrRectIterator
// all attribute areas, including areas stretching
415 // across more than one column
425 std::unique_ptr
<ScAttrIterator
>
429 ScAttrRectIterator(ScDocument
& rDocument
, SCTAB nTable
,
430 SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
);
431 ~ScAttrRectIterator();
434 const ScPatternAttr
* GetNext( SCCOL
& rCol1
, SCCOL
& rCol2
, SCROW
& rRow1
, SCROW
& rRow2
);
437 class ScHorizontalCellIterator
// walk through all non empty cells in an area
441 sc::CellStoreType::const_iterator maPos
;
442 sc::CellStoreType::const_iterator maEnd
;
446 std::vector
<ColParam
>::iterator maColPos
;
447 std::vector
<ColParam
> maColPositions
;
457 ScRefCellValue maCurCell
;
461 ScHorizontalCellIterator(ScDocument
& rDocument
, SCTAB nTable
,
462 SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
);
463 ~ScHorizontalCellIterator();
465 ScRefCellValue
* GetNext( SCCOL
& rCol
, SCROW
& rRow
);
466 bool GetPos( SCCOL
& rCol
, SCROW
& rRow
);
467 /// Set a(nother) sheet and (re)init.
468 void SetTab( SCTAB nTab
);
473 bool SkipInvalidInRow();
474 SCROW
FindNextNonEmptyRow();
477 /** Row-wise value iterator. */
478 class ScHorizontalValueIterator
482 const ScAttrArray
* pAttrArray
;
483 std::unique_ptr
<ScHorizontalCellIterator
>
485 sal_uInt32 nNumFormat
; // for CalcAsShown
495 ScHorizontalValueIterator( ScDocument
& rDocument
,
496 const ScRange
& rRange
);
497 ~ScHorizontalValueIterator();
498 /// Does NOT reset rValue if no value found!
499 bool GetNext( double& rValue
, FormulaError
& rErr
);
502 class ScHorizontalAttrIterator
512 std::unique_ptr
<SCROW
[]> pNextEnd
;
513 std::unique_ptr
<SCCOL
[]> pHorizEnd
;
514 std::unique_ptr
<SCSIZE
[]> pIndices
;
515 std::unique_ptr
<const ScPatternAttr
*[]>
521 void InitForNextRow(bool bInitialization
);
524 ScHorizontalAttrIterator( ScDocument
& rDocument
, SCTAB nTable
,
525 SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
);
526 ~ScHorizontalAttrIterator();
528 const ScPatternAttr
* GetNext( SCCOL
& rCol1
, SCCOL
& rCol2
, SCROW
& rRow
);
531 // returns non-empty cells and areas with formatting (horizontal)
533 class SC_DLLPUBLIC ScUsedAreaIterator
536 ScHorizontalCellIterator aCellIter
;
537 ScHorizontalAttrIterator aAttrIter
;
544 ScRefCellValue
* pCell
;
548 const ScPatternAttr
* pPattern
;
550 SCCOL nFoundStartCol
; // results after GetNext
553 const ScPatternAttr
* pFoundPattern
;
555 ScRefCellValue maFoundCell
;
558 ScUsedAreaIterator( ScDocument
& rDocument
, SCTAB nTable
,
559 SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
);
560 ~ScUsedAreaIterator();
564 SCCOL
GetStartCol() const { return nFoundStartCol
; }
565 SCCOL
GetEndCol() const { return nFoundEndCol
; }
566 SCROW
GetRow() const { return nFoundRow
; }
567 const ScPatternAttr
* GetPattern() const { return pFoundPattern
; }
568 const ScRefCellValue
& GetCell() const { return maFoundCell
;}
571 class ScRowBreakIterator
574 static constexpr SCROW NOT_FOUND
= -1;
576 explicit ScRowBreakIterator(::std::set
<SCROW
>& rBreaks
);
581 ::std::set
<SCROW
>& mrBreaks
;
582 ::std::set
<SCROW
>::const_iterator maItr
;
583 ::std::set
<SCROW
>::const_iterator maEnd
;
586 class ScDocRowHeightUpdater
592 ScFlatBoolRowSegments maRanges
;
594 TabRanges(SCTAB nTab
, SCROW nMaxRow
);
598 * Passing a NULL pointer to pTabRangesArray forces the heights of all
599 * rows in all tables to be updated.
601 explicit ScDocRowHeightUpdater(
602 ScDocument
& rDoc
, OutputDevice
* pOutDev
, double fPPTX
, double fPPTY
,
603 const ::std::vector
<TabRanges
>* pTabRangesArray
);
612 VclPtr
<OutputDevice
> mpOutDev
;
615 const ::std::vector
<TabRanges
>* mpTabRangesArray
;
618 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */