enum MatchMode{ exactorNA=0, exactorS=-1, exactorG=1, wildcard=2, regex=3 }; // mode for the TOCOL and TOROW formula functions enumclass IgnoreValues{ DEFAULT=0, BLANKS=1, ERRORS=2, ALL=3 };
struct VectorSearchArguments
{ // struct contains the contents of the function arguments // OpCode of struct owner
sal_uInt16 nSearchOpCode = SC_OPCODE_NONE;
// match mode (common, enum values are from XLOOKUP) // optional 5th argument to set match mode // 0 - Exact match. If none found, return #N/A. (MATCH value 0) // -1 - Exact match. If none found, return the next smaller item. (MATCH value 1) // 1 - Exact match. If none found, return the next larger item. (MATCH value -1) // 2 - A wildcard match where *, ?, and ~ have special meaning. (XLOOKUP only) // TODO : is this enum needed, or do we solely use rEntry.eOp ?
MatchMode eMatchMode = exactorG;
// search mode (only XLOOKUP has all 4 options, MATCH only uses Forward) // optional 6th argument to set search mode // 1 - Perform a search starting at the first item. This is the default. // -1 - Perform a reverse search starting at the last item. // 2 - Perform a binary search that relies on lookup_array being sorted in ascending order. // If not sorted, invalid results will be returned. // -2 - Perform a binary search that relies on lookup_array being sorted in descending order. // If not sorted, invalid results will be returned. //
LookupSearchMode eSearchMode = LookupSearchMode::Forward;
struct FormulaTokenRef_hash
{ booloperator () ( const formula::FormulaConstTokenRef& r1 ) const
{ return std::hash<constvoid*>()(static_cast<constvoid*>(r1.get())); } // So we don't have to create a FormulaConstTokenRef to search by formula::FormulaToken* using is_transparent = void; booloperator () ( const formula::FormulaToken* p1 ) const
{ return std::hash<constvoid *>()(static_cast<constvoid*>(p1)); }
}; typedef ::std::unordered_map< const formula::FormulaConstTokenRef, formula::FormulaConstTokenRef, FormulaTokenRef_hash> ScTokenMatrixMap; typedef ::std::unordered_map< OUString, const formula::FormulaConstTokenRef> ScResultTokenMap;
class ScInterpreter
{ // distribution function objects need the GetxxxDist methods friendclass ScGammaDistFunction; friendclass ScBetaDistFunction; friendclass ScTDistFunction; friendclass ScFDistFunction; friendclass ScChiDistFunction; friendclass ScChiSqDistFunction;
staticvoid GlobalExit(); // called by ScGlobal::Clear()
/** Detect if string should be used as regular expression or wildcard expressionorliteralstring.
*/ static utl::SearchParam::SearchType DetectSearchType(std::u16string_view rStr, constScDocument& rDoc );
/// Fail safe division, returning a FormulaError::DivisionByZero coded into a double /// if denominator is 0.0 staticinlinedouble div( constdouble& fNumerator, constdouble& fDenominator );
ScCalcConfig maCalcConfig;
formula::FormulaTokenIterator aCode;
ScAddress aPos;
ScTokenArray* pArr;
ScInterpreterContext& mrContext;
ScDocument& mrDoc;
sfx2::LinkManager* mpLinkManager;
svl::SharedStringPool& mrStrPool;
formula::FormulaConstTokenRef xResult;
ScJumpMatrix* pJumpMatrix; // currently active array condition, if any
ScTokenMatrixMap maTokenMatrixMap; // map FormulaToken* to formula::FormulaTokenRef if in array condition
ScResultTokenMap maResultTokenMap; // Result FormulaToken* to formula::FormulaTokenRef
ScFormulaCell* pMyFormulaCell; // the cell of this formula expression
const formula::FormulaToken* pCur; // current token
ScTokenStack* pStackObj; // contains the stacks const formula::FormulaToken ** pStack; // the current stack
FormulaError nGlobalError; // global (local to this formula expression) error
sal_uInt16 sp; // stack pointer
sal_uInt16 maxsp; // the maximal used stack pointer
sal_uInt32 nFuncFmtIndex; // NumberFormatIndex of a function
sal_uInt32 nCurFmtIndex; // current NumberFormatIndex
sal_uInt32 nRetFmtIndex; // NumberFormatIndex of an expression, if any
SvNumFormatType nFuncFmtType; // NumberFormatType of a function
SvNumFormatType nCurFmtType; // current NumberFormatType
SvNumFormatType nRetFmtType; // NumberFormatType of an expression
FormulaError mnStringNoValueError; // the error set in ConvertStringToValue() if no value
SubtotalFlags mnSubTotalFlags; // flags for subtotal and aggregate functions
sal_uInt8 cPar; // current count of parameters bool bCalcAsShown; // precision as shown bool bMatrixFormula; // formula cell is a matrix formula
/// Merge global and document specific settings. void MergeCalcConfig();
// nMust <= nAct <= nMax ? ok : PushError inlinebool MustHaveParamCount( short nAct, short nMust ); inlinebool MustHaveParamCount( short nAct, short nMust, short nMax ); inlinebool MustHaveParamCountMin( short nAct, short nMin ); inlinebool MustHaveParamCountMinWithStackCheck( short nAct, short nMin ); void PushParameterExpected(); void PushIllegalParameter(); void PushIllegalArgument(); void PushNoValue(); void PushNA();
/** Does substitute with formula::FormulaErrorToken in case nGlobalError is set and the token passedisnotformula::FormulaErrorToken.
Increments RefCount of the original token if not substituted. */ void Push( const formula::FormulaToken& r );
/** Does not substitute with formula::FormulaErrorToken in case nGlobalError is set. UsedtopushRPNtokensorfromwithinPush()ortokensthatarealready
explicit formula::FormulaErrorToken. Increments RefCount. */ void PushWithoutError( const formula::FormulaToken& r );
/** Does substitute with formula::FormulaErrorToken in case nGlobalError is set and the token passedisnotformula::FormulaErrorToken. IncrementsRefCountoftheoriginaltokenifnotsubstituted. ATTENTION!Thetokenhadtobeallocatedwith`new'andmustnotbeused afterthiscallifnoRefCountwassetbecausepossiblyitgetsimmediately
deleted in case of a FormulaError::StackOverflow or if substituted with formula::FormulaErrorToken! */ void PushTempToken( formula::FormulaToken* );
/** Pushes the token or substitutes with formula::FormulaErrorToken in case nGlobalErrorissetandthetokenpassedisnotformula::FormulaErrorToken.
Increments RefCount of the original token if not substituted. */ void PushTokenRef( const formula::FormulaConstTokenRef& );
/** Does not substitute with formula::FormulaErrorToken in case nGlobalError is set. UsedtopushtokensfromwithinPushTempToken()ortokensthatarealready explicitformula::FormulaErrorToken.IncrementsRefCount. ATTENTION!Thetokenhadtobeallocatedwith`new'andmustnotbeused afterthiscallifnoRefCountwassetbecausepossiblyitgetsimmediately
decremented again and thus deleted in case of a FormulaError::StackOverflow! */ void PushTempTokenWithoutError( const formula::FormulaToken* );
/** If nGlobalError is set push formula::FormulaErrorToken. IfnGlobalErrorisnotsetdonothing. UsedinPushTempToken()andaliketosimplifyhandling.
@return: <TRUE/> if nGlobalError. */ bool IfErrorPushError()
{ if (nGlobalError != FormulaError::NONE)
{
PushTempTokenWithoutError( new formula::FormulaErrorToken( nGlobalError)); returntrue;
} returnfalse;
}
/** Obtain cell result / content from address and push as temp token.
/** Guarantees that nGlobalError is set if rToken could not be obtained. */ void PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt = nullptr);
/** Guarantees that nGlobalError is set if rToken could not be obtained. */ void PopExternalSingleRef(sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef,
ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt = nullptr);
void PopExternalDoubleRef(sal_uInt16& rFileId, OUString& rTabName, ScComplexRefData& rRef); void PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray); void PopExternalDoubleRef(ScMatrixRef& rMat); void GetExternalDoubleRef(sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& aData, ScExternalRefCache::TokenArrayRef& rArray); bool PopDoubleRefOrSingleRef( ScAddress& rAdr ); void PopDoubleRefPushMatrix(); void PopRefListPushMatrixOrRef(); // If MatrixFormula: convert svDoubleRef to svMatrix, create JumpMatrix. // Else convert area reference parameters marked as ForceArray to array. // Returns true if JumpMatrix created. bool ConvertMatrixParameters(); // If MatrixFormula: ConvertMatrixJumpConditionToMatrix() inlinevoid MatrixJumpConditionToMatrix(); // For MatrixFormula (preconditions already checked by // MatrixJumpConditionToMatrix()): convert svDoubleRef to svMatrix, or if // JumpMatrix currently in effect convert also other types to svMatrix so // another JumpMatrix will be created by jump commands. void ConvertMatrixJumpConditionToMatrix(); // If MatrixFormula or ForceArray: ConvertMatrixParameters() inlinebool MatrixParameterConversion(); // If MatrixFormula or ForceArray. Can be used within spreadsheet functions // that do not depend on the formula cell's matrix size, for which only // bMatrixFormula can be used. inlinebool IsInArrayContext() const;
ScMatrixRef PopMatrix();
sc::RangeMatrix PopRangeMatrix(); void QueryMatrixType(const ScMatrixRef& xMat, SvNumFormatType& rRetTypeExpr, sal_uInt32& rRetIndexExpr);
void PushDouble(double nVal); void PushInt( int nVal ); void PushStringBuffer( const sal_Unicode* pString ); void PushString( const OUString& rStr ); void PushString( const svl::SharedString& rString ); void PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab); void PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
SCCOL nCol2, SCROW nRow2, SCTAB nTab2); void PushExternalSingleRef(sal_uInt16 nFileId, const OUString& rTabName,
SCCOL nCol, SCROW nRow, SCTAB nTab); void PushExternalDoubleRef(sal_uInt16 nFileId, const OUString& rTabName,
SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
SCCOL nCol2, SCROW nRow2, SCTAB nTab2); void PushSingleRef( const ScRefAddress& rRef ); void PushDoubleRef( const ScRefAddress& rRef1, const ScRefAddress& rRef2 ); void PushMatrix( const sc::RangeMatrix& rMat ); void PushMatrix(const ScMatrixRef& pMat); void PushError( FormulaError nError ); /// Raw stack type without default replacements.
formula::StackVar GetRawStackType(); /// Stack type with replacement of defaults, e.g. svMissing and formula::svEmptyCell will result in formula::svDouble.
formula::StackVar GetStackType(); // peek StackType of Parameter, Parameter 1 == TOS, 2 == TOS-1, ...
formula::StackVar GetStackType( sal_uInt8 nParam );
sal_uInt8 GetByte() const { return cPar; } // reverse order of stack void ReverseStack( sal_uInt8 nParamCount ); // generates a position-dependent SingleRef out of a DoubleRef bool DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& rAdr ); double GetDoubleFromMatrix(const ScMatrixRef& pMat); double GetDouble(); double GetDoubleWithDefault(double nDefault); bool IsMissing() const; template <typenameInt> requires std::is_integral_v<Int> Int double_to(double fVal);
sal_Int32 double_to_int32(double fVal); /** if GetDouble() not within int32 limits sets nGlobalError and returns SAL_MAX_INT32 */
sal_Int32 GetInt32(); /** if GetDoubleWithDefault() not within int32 limits sets nGlobalError and returns SAL_MAX_INT32 */
sal_Int32 GetInt32WithDefault( sal_Int32 nDefault ); /** if GetDouble() not within int32 limits sets nGlobalError and returns SAL_MAX_INT32 */
sal_Int32 GetFloor32(); /** if GetDouble() not within int16 limits sets nGlobalError and returns SAL_MAX_INT16 */
sal_Int16 GetInt16();
sal_Int16 GetInt16WithDefault(sal_Int16 nDefault); /** if GetDouble() not within uint32 limits sets nGlobalError and returns SAL_MAX_UINT32 */
sal_uInt32 GetUInt32(); bool GetBool() { return GetDouble() != 0.0; } bool GetBoolWithDefault(bool bDefault); /// returns TRUE if double (or error, check nGlobalError), else FALSE bool GetDoubleOrString( double& rValue, svl::SharedString& rString );
svl::SharedString GetString();
svl::SharedString GetStringFromMatrix(const ScMatrixRef& pMat);
svl::SharedString GetStringFromDouble( constdouble fVal); // pop matrix and obtain one element, upper left or according to jump matrix
ScMatValType GetDoubleOrStringFromMatrix( double& rDouble, svl::SharedString& rString );
ScMatrixRef CreateMatrixFromDoubleRef( const formula::FormulaToken* pToken,
SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
SCCOL nCol2, SCROW nRow2, SCTAB nTab2 ); inline ScTokenMatrixMap& GetTokenMatrixMap();
ScMatrixRef GetMatrix();
ScMatrixRef GetMatrix( short & rParam, size_t & rInRefList );
sc::RangeMatrix GetRangeMatrix();
// Get tokens at specific parameters for LET (lambda) function staticvoid replaceNamesToResult( const std::unordered_map<OUString, formula::FormulaToken*>& rResultIndexes,
ScTokenArray& rTokens, short nStartPos, short nEndPos );
ScTokenArray checkPushTokens( const ScTokenArray& rTokens, short nStartPos, short nEndPos );
/** Obtain a sal_Int32 suitable as string position or length argument. Returns-1ifthenumberisInforNaNorlessthan0orgreaterthansome implementationdefinedmaxstringlength.Inthesecasesalsosets
nGlobalError to FormulaError::IllegalArgument, if not already set. */ inline sal_Int32 GetStringPositionArgument();
// Check for String overflow of rResult+rAdd and set error and erase rResult // if so. Return true if ok, false if overflow inlinebool CheckStringResultLen( OUString& rResult, sal_Int32 nIncrease );
// Check for String overflow of rResult+rAdd and set error and erase rResult // if so. Return true if ok, false if overflow inlinebool CheckStringResultLen( OUStringBuffer& rResult, sal_Int32 nIncrease );
// Set error according to rVal, and set rVal to 0.0 if there was an error. inlinevoid TreatDoubleError( double& rVal ); // Lookup using ScLookupCache, @returns true if found and result address bool LookupQueryWithCache( ScAddress & o_rResultPos, const ScQueryParam & rParam, const ScComplexRefData* refData, LookupSearchMode nSearchMode, sal_uInt16 nOpCode ) const;
// Be sure to only call this if pStack[sp-nStackLevel] really contains a // ScJumpMatrixToken, no further checks are applied! // Returns true if last jump was executed and result matrix pushed. bool JumpMatrix( short nStackLevel );
public: // If upon call rMissingField==true then the database field parameter may be // missing (Xcl DCOUNT() syntax), or may be faked as missing by having the // value 0.0 or being exactly the entire database range reference (old SO // compatibility). If this was the case then rMissingField is set to true upon // return. If rMissingField==false upon call all "missing cases" are considered // to be an error.
std::unique_ptr<ScDBQueryParamBase> GetDBParams( bool& rMissingField );
/** Obtain the date serial number for a given date. @parambStrict Iffalse,nYear<100takesthetwo-digityearsettingintoaccount, androlloverofinvalidcalendardatestakesplace,e.g.1999-02-31=> 1999-03-03. Iftrue,thedatepassedmustbeavalidGregoriancalendardate.No two-digitexpandingorrolloverisdone.
// Used only for threaded formula-groups. // Resets the interpreter object, allowing reuse of interpreter object for each cell // in the group. void Init( ScFormulaCell* pCell, const ScAddress& rPos, ScTokenArray& rTokArray ); // Used only for threaded formula-groups. // Drops any caches that contain Tokens void DropTokenCaches();
inlinebool ScInterpreter::MustHaveParamCount( short nAct, short nMust )
{ if ( nAct == nMust ) returntrue; if ( nAct < nMust )
PushParameterExpected(); else
PushIllegalParameter(); returnfalse;
}
inlinebool ScInterpreter::MustHaveParamCount( short nAct, short nMust, short nMax )
{ if (nAct <= nMax) return MustHaveParamCountMin(nAct, nMust);
PushIllegalParameter(); returnfalse;
}
inlinebool ScInterpreter::MustHaveParamCountMin( short nAct, short nMin )
{ if ( nAct >= nMin ) returntrue;
PushParameterExpected(); returnfalse;
}
inlinebool ScInterpreter::MustHaveParamCountMinWithStackCheck( short nAct, short nMin )
{
assert(sp >= nAct); if (sp < nAct)
{
PushError(FormulaError::UnknownStackVariable); returnfalse;
} return MustHaveParamCountMin( nAct, nMin);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.