/* -*- 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 . */ #pragma once #include "address.hxx" #include "formulagroup.hxx" #include "global.hxx" #include "scdllapi.h" #include "cellvalue.hxx" #include "mtvelements.hxx" #include "queryparam.hxx" #include "attarray.hxx" #include #include #include #include #include #include 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; const ScDocument& mrDoc; ScInterpreterContext& mrContext; 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(ScInterpreterContext& rContext, const ScRange& rRange, SubtotalFlags nSubTotalFlags = SubtotalFlags::NONE, bool bTextAsZero = false ); void GetCurNumFmtInfo( 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 ); }; 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 PositionType; public: DataAccessInternal(ScDBQueryParamInternal* pParam, ScDocument& rDoc, 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& mrDoc; 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 mpParam; ::std::unique_ptr mpData; public: ScDBQueryDataIterator(ScDocument& rDocument, const ScInterpreterContext& rContext, std::unique_ptr 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& mrDoc; SCTAB mnTab; SCCOL mnCol; bool mbNullCol; size_t mnIndex; std::vector maEntries; public: ScFormulaGroupIterator( ScDocument& rDoc ); 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 PositionType; ScDocument& mrDoc; 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& rDoc, const ScRange& rRange, SubtotalFlags nSubTotalFlags = SubtotalFlags::NONE ); const ScAddress& GetPos() const { return maCurPos; } CellType getType() const { return maCurCell.getType();} OUString getString() const; const EditTextObject* getEditText() const { return maCurCell.getEditText();} ScFormulaCell* getFormulaCell() { return maCurCell.getFormula();} const ScFormulaCell* getFormulaCell() const { return maCurCell.getFormula();} 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 ScDocAttrIterator // all attribute areas { private: ScDocument& rDoc; SCTAB nTab; SCCOL nEndCol; SCROW nStartRow; SCROW nEndRow; SCCOL nCol; std::optional moColIter; public: ScDocAttrIterator(ScDocument& rDocument, SCTAB nTable, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2); const ScPatternAttr* GetNext( SCCOL& rCol, SCROW& rRow1, SCROW& rRow2 ); }; class ScAttrRectIterator // all attribute areas, including areas stretching // across more than one column { private: ScDocument& rDoc; SCTAB nTab; SCCOL nEndCol; SCROW nStartRow; SCROW nEndRow; SCCOL nIterStartCol; SCCOL nIterEndCol; std::optional moColIter; public: ScAttrRectIterator(ScDocument& rDocument, SCTAB nTable, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2); 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::iterator maColPos; std::vector maColPositions; ScDocument& rDoc; SCTAB mnTab; SCCOL nStartCol; SCCOL nEndCol; SCROW nStartRow; SCROW nEndRow; SCCOL mnCol; SCROW mnRow; ScRefCellValue maCurCell; bool mbMore; public: ScHorizontalCellIterator(ScDocument& rDocument, 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& rDoc; const ScAttrArray* pAttrArray; std::unique_ptr pCellIter; sal_uInt32 nNumFormat; // for CalcAsShown SCTAB nEndTab; SCCOL nCurCol; SCROW nCurRow; SCTAB nCurTab; SCROW nAttrEndRow; bool bCalcAsShown; public: ScHorizontalValueIterator( ScDocument& rDocument, const ScRange& rRange ); ~ScHorizontalValueIterator(); /// Does NOT reset rValue if no value found! bool GetNext( double& rValue, FormulaError& rErr ); }; class ScHorizontalAttrIterator { private: ScDocument& rDoc; SCTAB nTab; SCCOL nStartCol; SCROW nStartRow; SCCOL nEndCol; SCROW nEndRow; std::unique_ptr pNextEnd; std::unique_ptr pHorizEnd; std::unique_ptr pIndices; std::unique_ptr ppPatterns; SCCOL nCol; SCROW nRow; SCROW nMinNextEnd; void InitForNextRow(bool bInitialization); public: ScHorizontalAttrIterator( ScDocument& rDocument, 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& rDocument, 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& rBreaks); SCROW first(); SCROW next(); private: ::std::set& mrBreaks; ::std::set::const_iterator maItr; ::std::set::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* pTabRangesArray); void update(const bool bOnlyUsedRows = false); private: void updateAll(const bool bOnlyUsedRows); private: ScDocument& mrDoc; VclPtr mpOutDev; double mfPPTX; double mfPPTY; const ::std::vector* mpTabRangesArray; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */