summaryrefslogtreecommitdiffstats
path: root/sc/inc/dociter.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/inc/dociter.hxx')
-rw-r--r--sc/inc/dociter.hxx625
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: */