diff options
Diffstat (limited to 'sc/inc/dociter.hxx')
-rw-r--r-- | sc/inc/dociter.hxx | 625 |
1 files changed, 625 insertions, 0 deletions
diff --git a/sc/inc/dociter.hxx b/sc/inc/dociter.hxx new file mode 100644 index 000000000..f1092b1c1 --- /dev/null +++ b/sc/inc/dociter.hxx @@ -0,0 +1,625 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_SC_INC_DOCITER_HXX +#define INCLUDED_SC_INC_DOCITER_HXX + +#include "address.hxx" +#include "formulagroup.hxx" +#include "global.hxx" +#include "scdllapi.h" +#include "cellvalue.hxx" +#include "mtvelements.hxx" +#include "queryparam.hxx" +#include <vcl/outdev.hxx> +#include <vcl/vclptr.hxx> + +#include <memory> +#include <set> +#include <vector> + +class ScDocument; +class ScPatternAttr; +class ScAttrArray; +class ScAttrIterator; +class ScFlatBoolRowSegments; +class ScMatrix; +struct ScDBQueryParamBase; +struct ScQueryParam; +struct ScDBQueryParamInternal; +struct ScDBQueryParamMatrix; +class ScFormulaCell; +class OutputDevice; +struct ScInterpreterContext; +enum class SvNumFormatType : sal_Int16; + +class ScValueIterator // walk through all values in an area +{ + typedef sc::CellStoreType::const_position_type PositionType; + + ScDocument* pDoc; + ScInterpreterContext* pContext; + const ScAttrArray* pAttrArray; + sal_uInt32 nNumFormat; // for CalcAsShown + sal_uInt32 nNumFmtIndex; + ScAddress maStartPos; + ScAddress maEndPos; + SCCOL mnCol; + SCTAB mnTab; + SCROW nAttrEndRow; + SubtotalFlags mnSubTotalFlags; + SvNumFormatType nNumFmtType; + bool bNumValid; + bool bCalcAsShown; + bool bTextAsZero; + + const sc::CellStoreType* mpCells; + PositionType maCurPos; + + SCROW GetRow() const; + void IncBlock(); + void IncPos(); + + /** + * See if the cell at the current position is a non-empty cell. If not, + * move to the next non-empty cell position. + */ + bool GetThis( double& rValue, FormulaError& rErr ); + +public: + + ScValueIterator( + ScDocument* pDocument, const ScRange& rRange, SubtotalFlags nSubTotalFlags = SubtotalFlags::NONE, + bool bTextAsZero = false ); + + void GetCurNumFmtInfo( const ScInterpreterContext& rContext, SvNumFormatType& nType, sal_uInt32& nIndex ); + + /// Does NOT reset rValue if no value found! + bool GetFirst( double& rValue, FormulaError& rErr ); + + /// Does NOT reset rValue if no value found! + bool GetNext( double& rValue, FormulaError& rErr ); + + void SetInterpreterContext( ScInterpreterContext* context ) { pContext = context; } +}; + +class ScDBQueryDataIterator +{ +public: + struct Value + { + OUString maString; + double mfValue; + FormulaError mnError; + bool mbIsNumber; + + Value(); + }; + +private: + static const sc::CellStoreType* GetColumnCellStore(ScDocument& rDoc, SCTAB nTab, SCCOL nCol); + static const ScAttrArray* GetAttrArrayByCol(ScDocument& rDoc, SCTAB nTab, SCCOL nCol); + static bool IsQueryValid(ScDocument& rDoc, const ScQueryParam& rParam, SCTAB nTab, SCROW nRow, const ScRefCellValue* pCell); + + class DataAccess + { + public: + DataAccess(); + virtual ~DataAccess() = 0; + virtual bool getCurrent(Value& rValue) = 0; + virtual bool getFirst(Value& rValue) = 0; + virtual bool getNext(Value& rValue) = 0; + }; + + class DataAccessInternal final : public DataAccess + { + typedef std::pair<sc::CellStoreType::const_iterator,size_t> PositionType; + public: + DataAccessInternal(ScDBQueryParamInternal* pParam, ScDocument* pDoc, const ScInterpreterContext& rContext); + virtual ~DataAccessInternal() override; + virtual bool getCurrent(Value& rValue) override; + virtual bool getFirst(Value& rValue) override; + virtual bool getNext(Value& rValue) override; + + private: + void incBlock(); + void incPos(); + + const sc::CellStoreType* mpCells; + PositionType maCurPos; + ScDBQueryParamInternal* mpParam; + ScDocument* mpDoc; + const ScInterpreterContext& mrContext; + const ScAttrArray* pAttrArray; + sal_uInt32 nNumFormat; // for CalcAsShown + sal_uInt32 nNumFmtIndex; + SCCOL nCol; + SCROW nRow; + SCROW nAttrEndRow; + SCTAB nTab; + SvNumFormatType nNumFmtType; + bool bCalcAsShown; + }; + + class DataAccessMatrix final : public DataAccess + { + public: + DataAccessMatrix(ScDBQueryParamMatrix* pParam); + virtual ~DataAccessMatrix() override; + virtual bool getCurrent(Value& rValue) override; + virtual bool getFirst(Value& rValue) override; + virtual bool getNext(Value& rValue) override; + + private: + bool isValidQuery(SCROW mnRow, const ScMatrix& rMat) const; + + ScDBQueryParamMatrix* mpParam; + SCROW mnCurRow; + SCROW mnRows; + }; + + ::std::unique_ptr<ScDBQueryParamBase> mpParam; + ::std::unique_ptr<DataAccess> mpData; + +public: + ScDBQueryDataIterator(ScDocument* pDocument, const ScInterpreterContext& rContext, std::unique_ptr<ScDBQueryParamBase> pParam); + /// Does NOT reset rValue if no value found! + bool GetFirst(Value& rValue); + /// Does NOT reset rValue if no value found! + bool GetNext(Value& rValue); +}; + +class ScFormulaGroupIterator +{ +private: + ScDocument* mpDoc; + SCTAB mnTab; + SCCOL mnCol; + bool mbNullCol; + size_t mnIndex; + std::vector<sc::FormulaGroupEntry> maEntries; + +public: + ScFormulaGroupIterator( ScDocument* pDoc ); + + sc::FormulaGroupEntry* first(); + sc::FormulaGroupEntry* next(); +}; + +/** + * Walk through all cells in an area. For SubTotal and Aggregate depending on mnSubTotalFlags. + **/ +class ScCellIterator +{ + typedef std::pair<sc::CellStoreType::const_iterator, size_t> PositionType; + + ScDocument* mpDoc; + ScAddress maStartPos; + ScAddress maEndPos; + ScAddress maCurPos; + + PositionType maCurColPos; + SubtotalFlags mnSubTotalFlags; + + ScRefCellValue maCurCell; + + void incBlock(); + void incPos(); + void setPos(size_t nPos); + + const ScColumn* getColumn() const; + + void init(); + bool getCurrent(); + +public: + ScCellIterator( ScDocument* pDoc, const ScRange& rRange, SubtotalFlags nSubTotalFlags = SubtotalFlags::NONE ); + + const ScAddress& GetPos() const { return maCurPos; } + + CellType getType() const { return maCurCell.meType;} + OUString getString() const; + const EditTextObject* getEditText() const { return maCurCell.mpEditText;} + ScFormulaCell* getFormulaCell() { return maCurCell.mpFormula;} + const ScFormulaCell* getFormulaCell() const { return maCurCell.mpFormula;} + ScCellValue getCellValue() const; + const ScRefCellValue& getRefCellValue() const { return maCurCell;} + + bool hasString() const; + bool isEmpty() const; + bool equalsWithoutFormat( const ScAddress& rPos ) const; + + bool first(); + bool next(); +}; + +class ScQueryCellIterator // walk through all non-empty cells in an area +{ + enum StopOnMismatchBits + { + nStopOnMismatchDisabled = 0x00, + nStopOnMismatchEnabled = 0x01, + nStopOnMismatchOccurred = 0x02, + nStopOnMismatchExecuted = nStopOnMismatchEnabled | nStopOnMismatchOccurred + }; + + enum TestEqualConditionBits + { + nTestEqualConditionDisabled = 0x00, + nTestEqualConditionEnabled = 0x01, + nTestEqualConditionMatched = 0x02, + nTestEqualConditionFulfilled = nTestEqualConditionEnabled | nTestEqualConditionMatched + }; + + typedef sc::CellStoreType::const_position_type PositionType; + PositionType maCurPos; + + ScQueryParam maParam; + ScDocument* pDoc; + const ScInterpreterContext& mrContext; + SCTAB nTab; + SCCOL nCol; + SCROW nRow; + sal_uInt8 nStopOnMismatch; + sal_uInt8 nTestEqualCondition; + bool bAdvanceQuery; + bool bIgnoreMismatchOnLeadingStrings; + + /** Initialize position for new column. */ + void InitPos(); + void IncPos(); + void IncBlock(); + bool GetThis(); + + /* Only works if no regular expression is involved, only + searches for rows in one column, and only the first + query entry is considered with simple conditions + SC_LESS_EQUAL (sorted ascending) or SC_GREATER_EQUAL + (sorted descending). Check these things before + invocation! Delivers a starting point, continue with + GetThis() and GetNext() afterwards. Introduced for + FindEqualOrSortedLastInRange() + */ + bool BinarySearch(); + +public: + ScQueryCellIterator(ScDocument* pDocument, const ScInterpreterContext& rContext, SCTAB nTable, + const ScQueryParam& aParam, bool bMod); + // when !bMod, the QueryParam has to be filled + // (bIsString) + bool GetFirst(); + bool GetNext(); + SCCOL GetCol() const { return nCol; } + SCROW GetRow() const { return nRow; } + + // increments all Entry.nField, if column + // changes, for ScInterpreter ScHLookup() + void SetAdvanceQueryParamEntryField( bool bVal ) + { bAdvanceQuery = bVal; } + void AdvanceQueryParamEntryField(); + + /** If set, iterator stops on first non-matching cell + content. May be used in SC_LESS_EQUAL queries where a + cell range is assumed to be sorted; stops on first + value being greater than the queried value and + GetFirst()/GetNext() return NULL. StoppedOnMismatch() + returns true then. + However, the iterator's conditions are not set to end + all queries, GetCol() and GetRow() return values for + the non-matching cell, further GetNext() calls may be + executed. */ + void SetStopOnMismatch( bool bVal ) + { + nStopOnMismatch = sal::static_int_cast<sal_uInt8>(bVal ? nStopOnMismatchEnabled : + nStopOnMismatchDisabled); + } + bool StoppedOnMismatch() const + { return nStopOnMismatch == nStopOnMismatchExecuted; } + + /** If set, an additional test for SC_EQUAL condition is + executed in ScTable::ValidQuery() if SC_LESS_EQUAL or + SC_GREATER_EQUAL conditions are to be tested. May be + used where a cell range is assumed to be sorted to stop + if an equal match is found. */ + void SetTestEqualCondition( bool bVal ) + { + nTestEqualCondition = sal::static_int_cast<sal_uInt8>(bVal ? + nTestEqualConditionEnabled : + nTestEqualConditionDisabled); + } + bool IsEqualConditionFulfilled() const + { return nTestEqualCondition == nTestEqualConditionFulfilled; } + + /** In a range assumed to be sorted find either the last of + a sequence of equal entries or the last being less than + (or greater than) the queried value. Used by the + interpreter for [HV]?LOOKUP() and MATCH(). Column and + row position of the found entry are returned, otherwise + invalid. + + The search does not stop when encountering a string and does not + assume that no values follow anymore. + If querying for a string a mismatch on the first + entry, e.g. column header, is ignored. + + @ATTENTION! StopOnMismatch, TestEqualCondition and + the internal IgnoreMismatchOnLeadingStrings and query + params are in an undefined state upon return! The + iterator is not usable anymore except for obtaining the + number format! + */ + bool FindEqualOrSortedLastInRange( SCCOL& nFoundCol, SCROW& nFoundRow ); +}; + +// Used by ScInterpreter::ScCountIf. +// Walk through all non-empty cells in an area. +class ScCountIfCellIterator +{ + typedef sc::CellStoreType::const_position_type PositionType; + PositionType maCurPos; + ScQueryParam maParam; + ScDocument* pDoc; + const ScInterpreterContext& mrContext; + SCTAB nTab; + SCCOL nCol; + SCROW nRow; + + /** Initialize position for new column. */ + void InitPos(); + void IncPos(); + void IncBlock(); + void AdvanceQueryParamEntryField(); + +public: + ScCountIfCellIterator(ScDocument* pDocument, const ScInterpreterContext& rContext, SCTAB nTable, + const ScQueryParam& aParam); + int GetCount(); +}; + +class ScDocAttrIterator // all attribute areas +{ +private: + ScDocument* pDoc; + SCTAB nTab; + SCCOL nEndCol; + SCROW nStartRow; + SCROW nEndRow; + SCCOL nCol; + std::unique_ptr<ScAttrIterator> + pColIter; + +public: + ScDocAttrIterator(ScDocument* pDocument, SCTAB nTable, + SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2); + ~ScDocAttrIterator(); + + const ScPatternAttr* GetNext( SCCOL& rCol, SCROW& rRow1, SCROW& rRow2 ); +}; + +class ScAttrRectIterator // all attribute areas, including areas stretching + // across more than one column +{ +private: + ScDocument* pDoc; + SCTAB nTab; + SCCOL nEndCol; + SCROW nStartRow; + SCROW nEndRow; + SCCOL nIterStartCol; + SCCOL nIterEndCol; + std::unique_ptr<ScAttrIterator> + pColIter; + +public: + ScAttrRectIterator(ScDocument* pDocument, SCTAB nTable, + SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2); + ~ScAttrRectIterator(); + + void DataChanged(); + const ScPatternAttr* GetNext( SCCOL& rCol1, SCCOL& rCol2, SCROW& rRow1, SCROW& rRow2 ); +}; + +class ScHorizontalCellIterator // walk through all non empty cells in an area +{ // row by row + struct ColParam + { + sc::CellStoreType::const_iterator maPos; + sc::CellStoreType::const_iterator maEnd; + SCCOL mnCol; + }; + + std::vector<ColParam>::iterator maColPos; + std::vector<ColParam> maColPositions; + + ScDocument* pDoc; + SCTAB mnTab; + SCCOL nStartCol; + SCCOL nEndCol; + SCROW nStartRow; + SCROW nEndRow; + SCCOL mnCol; + SCROW mnRow; + ScRefCellValue maCurCell; + bool mbMore; + +public: + ScHorizontalCellIterator(ScDocument* pDocument, SCTAB nTable, + SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2); + ~ScHorizontalCellIterator(); + + ScRefCellValue* GetNext( SCCOL& rCol, SCROW& rRow ); + bool GetPos( SCCOL& rCol, SCROW& rRow ); + /// Set a(nother) sheet and (re)init. + void SetTab( SCTAB nTab ); + +private: + void Advance(); + void SkipInvalid(); + bool SkipInvalidInRow(); + SCROW FindNextNonEmptyRow(); +}; + +/** Row-wise value iterator. */ +class ScHorizontalValueIterator +{ +private: + ScDocument *pDoc; + const ScAttrArray *pAttrArray; + std::unique_ptr<ScHorizontalCellIterator> + pCellIter; + sal_uInt32 nNumFormat; // for CalcAsShown + SCTAB nEndTab; + SCCOL nCurCol; + SCROW nCurRow; + SCTAB nCurTab; + SCROW nAttrEndRow; + bool bCalcAsShown; + +public: + + ScHorizontalValueIterator( ScDocument* pDocument, + const ScRange& rRange ); + ~ScHorizontalValueIterator(); + /// Does NOT reset rValue if no value found! + bool GetNext( double& rValue, FormulaError& rErr ); +}; + +// returns all areas with non-default formatting (horizontal) + +class ScHorizontalAttrIterator +{ +private: + ScDocument* pDoc; + SCTAB nTab; + SCCOL nStartCol; + SCROW nStartRow; + SCCOL nEndCol; + SCROW nEndRow; + + std::unique_ptr<SCROW[]> pNextEnd; + std::unique_ptr<SCCOL[]> pHorizEnd; + std::unique_ptr<SCSIZE[]> pIndices; + std::unique_ptr<const ScPatternAttr*[]> + ppPatterns; + SCCOL nCol; + SCROW nRow; + bool bRowEmpty; + SCROW nMinNextEnd; + + void InitForNextRow(bool bInitialization); + bool InitForNextAttr(); + +public: + ScHorizontalAttrIterator( ScDocument* pDocument, SCTAB nTable, + SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ); + ~ScHorizontalAttrIterator(); + + const ScPatternAttr* GetNext( SCCOL& rCol1, SCCOL& rCol2, SCROW& rRow ); +}; + +// returns non-empty cells and areas with formatting (horizontal) + +class SC_DLLPUBLIC ScUsedAreaIterator +{ +private: + ScHorizontalCellIterator aCellIter; + ScHorizontalAttrIterator aAttrIter; + + SCCOL nNextCol; + SCROW nNextRow; + + SCCOL nCellCol; + SCROW nCellRow; + ScRefCellValue* pCell; + SCCOL nAttrCol1; + SCCOL nAttrCol2; + SCROW nAttrRow; + const ScPatternAttr* pPattern; + + SCCOL nFoundStartCol; // results after GetNext + SCCOL nFoundEndCol; + SCROW nFoundRow; + const ScPatternAttr* pFoundPattern; + + ScRefCellValue maFoundCell; + +public: + ScUsedAreaIterator( ScDocument* pDocument, SCTAB nTable, + SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ); + ~ScUsedAreaIterator(); + + bool GetNext(); + + SCCOL GetStartCol() const { return nFoundStartCol; } + SCCOL GetEndCol() const { return nFoundEndCol; } + SCROW GetRow() const { return nFoundRow; } + const ScPatternAttr* GetPattern() const { return pFoundPattern; } + const ScRefCellValue& GetCell() const { return maFoundCell;} +}; + +class ScRowBreakIterator +{ +public: + static constexpr SCROW NOT_FOUND = -1; + + explicit ScRowBreakIterator(::std::set<SCROW>& rBreaks); + SCROW first(); + SCROW next(); + +private: + ::std::set<SCROW>& mrBreaks; + ::std::set<SCROW>::const_iterator maItr; + ::std::set<SCROW>::const_iterator maEnd; +}; + +class ScDocRowHeightUpdater +{ +public: + struct TabRanges + { + SCTAB mnTab; + ScFlatBoolRowSegments maRanges; + + TabRanges(SCTAB nTab, SCROW nMaxRow); + }; + + /** + * Passing a NULL pointer to pTabRangesArray forces the heights of all + * rows in all tables to be updated. + */ + explicit ScDocRowHeightUpdater( + ScDocument& rDoc, OutputDevice* pOutDev, double fPPTX, double fPPTY, + const ::std::vector<TabRanges>* pTabRangesArray); + + void update(); + +private: + void updateAll(); + +private: + ScDocument& mrDoc; + VclPtr<OutputDevice> mpOutDev; + double mfPPTX; + double mfPPTY; + const ::std::vector<TabRanges>* mpTabRangesArray; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |