diff options
Diffstat (limited to 'sc/source/filter/excel/xlformula.cxx')
-rw-r--r-- | sc/source/filter/excel/xlformula.cxx | 1022 |
1 files changed, 1022 insertions, 0 deletions
diff --git a/sc/source/filter/excel/xlformula.cxx b/sc/source/filter/excel/xlformula.cxx new file mode 100644 index 000000000..e2e082ac2 --- /dev/null +++ b/sc/source/filter/excel/xlformula.cxx @@ -0,0 +1,1022 @@ +/* -*- 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 . + */ + +#include <xlformula.hxx> + +#include <refdata.hxx> +#include <tokenarray.hxx> +#include <xestream.hxx> +#include <xistream.hxx> +#include <xlroot.hxx> + +#include <comphelper/string.hxx> +#include <svl/sharedstringpool.hxx> + +using namespace ::formula; + +// Function data ============================================================== + +OUString XclFunctionInfo::GetMacroFuncName() const +{ + if( IsMacroFunc() ) + return OUString( mpcMacroName, strlen(mpcMacroName), RTL_TEXTENCODING_UTF8 ); + return OUString(); +} + +OUString XclFunctionInfo::GetAddInEquivalentFuncName() const +{ + if( IsAddInEquivalent() ) + return OUString( mpcMacroName, strlen(mpcMacroName), RTL_TEXTENCODING_UTF8 ); + return OUString(); +} + +// abbreviations for function return token class +const sal_uInt8 R = EXC_TOKCLASS_REF; +const sal_uInt8 V = EXC_TOKCLASS_VAL; +const sal_uInt8 A = EXC_TOKCLASS_ARR; + +// abbreviations for parameter infos +#define RO { EXC_PARAM_REGULAR, EXC_PARAMCONV_ORG, false } +#define RA { EXC_PARAM_REGULAR, EXC_PARAMCONV_ARR, false } +#define RR { EXC_PARAM_REGULAR, EXC_PARAMCONV_RPT, false } +#define RX { EXC_PARAM_REGULAR, EXC_PARAMCONV_RPX, false } +#define VO { EXC_PARAM_REGULAR, EXC_PARAMCONV_ORG, true } +#define VV { EXC_PARAM_REGULAR, EXC_PARAMCONV_VAL, true } +#define VA { EXC_PARAM_REGULAR, EXC_PARAMCONV_ARR, true } +#define VR { EXC_PARAM_REGULAR, EXC_PARAMCONV_RPT, true } +#define VX { EXC_PARAM_REGULAR, EXC_PARAMCONV_RPX, true } +#define RO_E { EXC_PARAM_EXCELONLY, EXC_PARAMCONV_ORG, false } +#define VR_E { EXC_PARAM_EXCELONLY, EXC_PARAMCONV_RPT, true } +#define C { EXC_PARAM_CALCONLY, EXC_PARAMCONV_ORG, false } + +const sal_uInt16 NOID = SAL_MAX_UINT16; /// No BIFF/OOBIN function identifier available. +const sal_uInt8 MX = 30; /// Maximum parameter count. + +#define EXC_FUNCNAME( ascii ) "_xlfn." ascii +#define EXC_FUNCNAME_ODF( ascii ) "_xlfnodf." ascii +#define EXC_FUNCNAME_ADDIN( ascii ) "com.sun.star.sheet.addin." ascii + +/** Functions new in BIFF2. */ +const XclFunctionInfo saFuncTable_2[] = +{ + { ocCount, 0, 0, MX, V, { RX }, 0, nullptr }, + { ocIf, 1, 2, 3, R, { VO, RO }, 0, nullptr }, + { ocIsNA, 2, 1, 1, V, { VR }, 0, nullptr }, + { ocIsError, 3, 1, 1, V, { VR }, 0, nullptr }, + { ocSum, 4, 0, MX, V, { RX }, 0, nullptr }, + { ocAverage, 5, 1, MX, V, { RX }, 0, nullptr }, + { ocMin, 6, 1, MX, V, { RX }, 0, nullptr }, + { ocMax, 7, 1, MX, V, { RX }, 0, nullptr }, + { ocRow, 8, 0, 1, V, { RO }, 0, nullptr }, + { ocColumn, 9, 0, 1, V, { RO }, 0, nullptr }, + { ocNotAvail, 10, 0, 0, V, {}, 0, nullptr }, + { ocNPV, 11, 2, MX, V, { VR, RX }, 0, nullptr }, + { ocStDev, 12, 1, MX, V, { RX }, 0, nullptr }, + { ocCurrency, 13, 1, 2, V, { VR }, 0, nullptr }, + { ocFixed, 14, 1, 2, V, { VR, VR, C }, 0, nullptr }, + { ocSin, 15, 1, 1, V, { VR }, 0, nullptr }, + { ocCosecant, 15, 1, 1, V, { VR }, EXC_FUNCFLAG_EXPORTONLY, nullptr }, + { ocCos, 16, 1, 1, V, { VR }, 0, nullptr }, + { ocSecant, 16, 1, 1, V, { VR }, EXC_FUNCFLAG_EXPORTONLY, nullptr }, + { ocTan, 17, 1, 1, V, { VR }, 0, nullptr }, + { ocCot, 17, 1, 1, V, { VR }, EXC_FUNCFLAG_EXPORTONLY, nullptr }, + { ocArcTan, 18, 1, 1, V, { VR }, 0, nullptr }, + { ocArcCot, 18, 1, 1, V, { VR }, EXC_FUNCFLAG_EXPORTONLY, nullptr }, + { ocPi, 19, 0, 0, V, {}, 0, nullptr }, + { ocSqrt, 20, 1, 1, V, { VR }, 0, nullptr }, + { ocExp, 21, 1, 1, V, { VR }, 0, nullptr }, + { ocLn, 22, 1, 1, V, { VR }, 0, nullptr }, + { ocLog10, 23, 1, 1, V, { VR }, 0, nullptr }, + { ocAbs, 24, 1, 1, V, { VR }, 0, nullptr }, + { ocInt, 25, 1, 1, V, { VR }, 0, nullptr }, + { ocPlusMinus, 26, 1, 1, V, { VR }, 0, nullptr }, + { ocRound, 27, 2, 2, V, { VR }, 0, nullptr }, + { ocLookup, 28, 2, 3, V, { VR, RA }, 0, nullptr }, + { ocIndex, 29, 2, 4, R, { RA, VV }, 0, nullptr }, + { ocRept, 30, 2, 2, V, { VR }, 0, nullptr }, + { ocMid, 31, 3, 3, V, { VR }, 0, nullptr }, + { ocLen, 32, 1, 1, V, { VR }, 0, nullptr }, + { ocValue, 33, 1, 1, V, { VR }, 0, nullptr }, + { ocTrue, 34, 0, 0, V, {}, 0, nullptr }, + { ocFalse, 35, 0, 0, V, {}, 0, nullptr }, + { ocAnd, 36, 1, MX, V, { RX }, 0, nullptr }, + { ocOr, 37, 1, MX, V, { RX }, 0, nullptr }, + { ocNot, 38, 1, 1, V, { VR }, 0, nullptr }, + { ocMod, 39, 2, 2, V, { VR }, 0, nullptr }, + { ocDBCount, 40, 3, 3, V, { RO, RR }, 0, nullptr }, + { ocDBSum, 41, 3, 3, V, { RO, RR }, 0, nullptr }, + { ocDBAverage, 42, 3, 3, V, { RO, RR }, 0, nullptr }, + { ocDBMin, 43, 3, 3, V, { RO, RR }, 0, nullptr }, + { ocDBMax, 44, 3, 3, V, { RO, RR }, 0, nullptr }, + { ocDBStdDev, 45, 3, 3, V, { RO, RR }, 0, nullptr }, + { ocVar, 46, 1, MX, V, { RX }, 0, nullptr }, + { ocDBVar, 47, 3, 3, V, { RO, RR }, 0, nullptr }, + { ocText, 48, 2, 2, V, { VR }, 0, nullptr }, + { ocLinest, 49, 1, 2, A, { RA, RA, C, C }, 0, nullptr }, + { ocTrend, 50, 1, 3, A, { RA, RA, RA, C }, 0, nullptr }, + { ocLogest, 51, 1, 2, A, { RA, RA, C, C }, 0, nullptr }, + { ocGrowth, 52, 1, 3, A, { RA, RA, RA, C }, 0, nullptr }, + { ocPV, 56, 3, 5, V, { VR }, 0, nullptr }, + { ocFV, 57, 3, 5, V, { VR }, 0, nullptr }, + { ocNper, 58, 3, 5, V, { VR }, 0, nullptr }, + { ocPMT, 59, 3, 5, V, { VR }, 0, nullptr }, + { ocRate, 60, 3, 6, V, { VR }, 0, nullptr }, + { ocMIRR, 61, 3, 3, V, { RA, VR }, 0, nullptr }, + { ocIRR, 62, 1, 2, V, { RA, VR }, 0, nullptr }, + { ocRandom, 63, 0, 0, V, {}, EXC_FUNCFLAG_VOLATILE, nullptr }, + { ocMatch, 64, 2, 3, V, { VR, RX, RR }, 0, nullptr }, + { ocGetDate, 65, 3, 3, V, { VR }, 0, nullptr }, + { ocGetTime, 66, 3, 3, V, { VR }, 0, nullptr }, + { ocGetDay, 67, 1, 1, V, { VR }, 0, nullptr }, + { ocGetMonth, 68, 1, 1, V, { VR }, 0, nullptr }, + { ocGetYear, 69, 1, 1, V, { VR }, 0, nullptr }, + { ocGetDayOfWeek, 70, 1, 1, V, { VR, C }, 0, nullptr }, + { ocGetHour, 71, 1, 1, V, { VR }, 0, nullptr }, + { ocGetMin, 72, 1, 1, V, { VR }, 0, nullptr }, + { ocGetSec, 73, 1, 1, V, { VR }, 0, nullptr }, + { ocGetActTime, 74, 0, 0, V, {}, EXC_FUNCFLAG_VOLATILE, nullptr }, + { ocAreas, 75, 1, 1, V, { RO }, 0, nullptr }, + { ocRows, 76, 1, 1, V, { RO }, 0, nullptr }, + { ocColumns, 77, 1, 1, V, { RO }, 0, nullptr }, + { ocOffset, 78, 3, 5, R, { RO, VR }, EXC_FUNCFLAG_VOLATILE, nullptr }, + { ocSearch, 82, 2, 3, V, { VR }, 0, nullptr }, + { ocMatTrans, 83, 1, 1, A, { VO }, 0, nullptr }, + { ocType, 86, 1, 1, V, { VX }, 0, nullptr }, + { ocArcTan2, 97, 2, 2, V, { VR }, 0, nullptr }, + { ocArcSin, 98, 1, 1, V, { VR }, 0, nullptr }, + { ocArcCos, 99, 1, 1, V, { VR }, 0, nullptr }, + { ocChoose, 100, 2, MX, R, { VO, RO }, 0, nullptr }, + { ocHLookup, 101, 3, 3, V, { VV, RO, RO, C }, 0, nullptr }, + { ocVLookup, 102, 3, 3, V, { VV, RO, RO, C }, 0, nullptr }, + { ocIsRef, 105, 1, 1, V, { RX }, 0, nullptr }, + { ocLog, 109, 1, 2, V, { VR }, 0, nullptr }, + { ocChar, 111, 1, 1, V, { VR }, 0, nullptr }, + { ocLower, 112, 1, 1, V, { VR }, 0, nullptr }, + { ocUpper, 113, 1, 1, V, { VR }, 0, nullptr }, + { ocProper, 114, 1, 1, V, { VR }, 0, nullptr }, + { ocLeft, 115, 1, 2, V, { VR }, 0, nullptr }, + { ocRight, 116, 1, 2, V, { VR }, 0, nullptr }, + { ocExact, 117, 2, 2, V, { VR }, 0, nullptr }, + { ocTrim, 118, 1, 1, V, { VR }, 0, nullptr }, + { ocReplace, 119, 4, 4, V, { VR }, 0, nullptr }, + { ocSubstitute, 120, 3, 4, V, { VR }, 0, nullptr }, + { ocCode, 121, 1, 1, V, { VR }, 0, nullptr }, + { ocFind, 124, 2, 3, V, { VR }, 0, nullptr }, + { ocCell, 125, 1, 2, V, { VV, RO }, EXC_FUNCFLAG_VOLATILE, nullptr }, + { ocIsErr, 126, 1, 1, V, { VR }, 0, nullptr }, + { ocIsString, 127, 1, 1, V, { VR }, 0, nullptr }, + { ocIsValue, 128, 1, 1, V, { VR }, 0, nullptr }, + { ocIsEmpty, 129, 1, 1, V, { VR }, 0, nullptr }, + { ocT, 130, 1, 1, V, { RO }, 0, nullptr }, + { ocN, 131, 1, 1, V, { RO }, 0, nullptr }, + { ocGetDateValue, 140, 1, 1, V, { VR }, 0, nullptr }, + { ocGetTimeValue, 141, 1, 1, V, { VR }, 0, nullptr }, + { ocSLN, 142, 3, 3, V, { VR }, 0, nullptr }, + { ocSYD, 143, 4, 4, V, { VR }, 0, nullptr }, + { ocDDB, 144, 4, 5, V, { VR }, 0, nullptr }, + { ocIndirect, 148, 1, 2, R, { VR }, EXC_FUNCFLAG_VOLATILE, nullptr }, + { ocClean, 162, 1, 1, V, { VR }, 0, nullptr }, + { ocMatDet, 163, 1, 1, V, { VA }, 0, nullptr }, + { ocMatInv, 164, 1, 1, A, { VA }, 0, nullptr }, + { ocMatMult, 165, 2, 2, A, { VA }, 0, nullptr }, + { ocIpmt, 167, 4, 6, V, { VR }, 0, nullptr }, + { ocPpmt, 168, 4, 6, V, { VR }, 0, nullptr }, + { ocCount2, 169, 0, MX, V, { RX }, 0, nullptr }, + { ocProduct, 183, 0, MX, V, { RX }, 0, nullptr }, + { ocFact, 184, 1, 1, V, { VR }, 0, nullptr }, + { ocDBProduct, 189, 3, 3, V, { RO, RR }, 0, nullptr }, + { ocIsNonString, 190, 1, 1, V, { VR }, 0, nullptr }, + { ocStDevP, 193, 1, MX, V, { RX }, 0, nullptr }, + { ocVarP, 194, 1, MX, V, { RX }, 0, nullptr }, + { ocDBStdDevP, 195, 3, 3, V, { RO, RR }, 0, nullptr }, + { ocDBVarP, 196, 3, 3, V, { RO, RR }, 0, nullptr }, + { ocTrunc, 197, 1, 1, V, { VR, C }, 0, nullptr }, + { ocIsLogical, 198, 1, 1, V, { VR }, 0, nullptr }, + { ocDBCount2, 199, 3, 3, V, { RO, RR }, 0, nullptr }, + { ocCurrency, 204, 1, 2, V, { VR }, EXC_FUNCFLAG_IMPORTONLY, nullptr }, + { ocFindB, 205, 2, 3, V, { VR }, 0, nullptr }, + { ocSearchB, 206, 2, 3, V, { VR }, 0, nullptr }, + { ocReplaceB, 207, 4, 4, V, { VR }, 0, nullptr }, + { ocLeftB, 208, 1, 2, V, { VR }, 0, nullptr }, + { ocRightB, 209, 1, 2, V, { VR }, 0, nullptr }, + { ocMidB, 210, 3, 3, V, { VR }, 0, nullptr }, + { ocLenB, 211, 1, 1, V, { VR }, 0, nullptr }, + { ocRoundUp, 212, 2, 2, V, { VR }, 0, nullptr }, + { ocRoundDown, 213, 2, 2, V, { VR }, 0, nullptr }, + { ocExternal, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_IMPORTONLY, nullptr } +}; + +/** Functions new in BIFF3. */ +const XclFunctionInfo saFuncTable_3[] = +{ + { ocLinest, 49, 1, 4, A, { RA, RA, VV }, 0, nullptr }, // BIFF2: 1-2, BIFF3: 1-4 + { ocTrend, 50, 1, 4, A, { RA, RA, RA, VV }, 0, nullptr }, // BIFF2: 1-3, BIFF3: 1-4 + { ocLogest, 51, 1, 4, A, { RA, RA, VV }, 0, nullptr }, // BIFF2: 1-2, BIFF3: 1-4 + { ocGrowth, 52, 1, 4, A, { RA, RA, RA, VV }, 0, nullptr }, // BIFF2: 1-3, BIFF3: 1-4 + { ocTrunc, 197, 1, 2, V, { VR }, 0, nullptr }, // BIFF2: 1, BIFF3: 1-2 + { ocAddress, 219, 2, 5, V, { VR }, 0, nullptr }, + { ocGetDiffDate360, 220, 2, 2, V, { VR, VR, C }, 0, nullptr }, + { ocGetActDate, 221, 0, 0, V, {}, EXC_FUNCFLAG_VOLATILE, nullptr }, + { ocVBD, 222, 5, 7, V, { VR }, 0, nullptr }, + { ocMedian, 227, 1, MX, V, { RX }, 0, nullptr }, + { ocSumProduct, 228, 1, MX, V, { VA }, 0, nullptr }, + { ocSinHyp, 229, 1, 1, V, { VR }, 0, nullptr }, + { ocCosecantHyp, 229, 1, 1, V, { VR }, EXC_FUNCFLAG_EXPORTONLY, nullptr }, + { ocCosHyp, 230, 1, 1, V, { VR }, 0, nullptr }, + { ocSecantHyp, 230, 1, 1, V, { VR }, EXC_FUNCFLAG_EXPORTONLY, nullptr }, + { ocTanHyp, 231, 1, 1, V, { VR }, 0, nullptr }, + { ocCotHyp, 231, 1, 1, V, { VR }, EXC_FUNCFLAG_EXPORTONLY, nullptr }, + { ocArcSinHyp, 232, 1, 1, V, { VR }, 0, nullptr }, + { ocArcCosHyp, 233, 1, 1, V, { VR }, 0, nullptr }, + { ocArcTanHyp, 234, 1, 1, V, { VR }, 0, nullptr }, + { ocArcCotHyp, 234, 1, 1, V, { VR }, EXC_FUNCFLAG_EXPORTONLY, nullptr }, + { ocDBGet, 235, 3, 3, V, { RO, RR }, 0, nullptr }, + { ocInfo, 244, 1, 1, V, { VR }, EXC_FUNCFLAG_VOLATILE, nullptr } +}; + +/** Functions new in BIFF4. */ +const XclFunctionInfo saFuncTable_4[] = +{ + { ocFixed, 14, 1, 3, V, { VR }, 0, nullptr }, // BIFF2-3: 1-2, BIFF4: 1-3 + { ocAsc, 214, 1, 1, V, { VR }, 0, nullptr }, + { ocJis, 215, 1, 1, V, { VR }, 0, nullptr }, + { ocRank, 216, 2, 3, V, { VR, RO, VR }, 0, nullptr }, + { ocDB, 247, 4, 5, V, { VR }, 0, nullptr }, + { ocFrequency, 252, 2, 2, A, { RA }, 0, nullptr }, + { ocErrorType_ODF, 261, 1, 1, V, { VR }, 0, nullptr }, + { ocAveDev, 269, 1, MX, V, { RX }, 0, nullptr }, + { ocBetaDist, 270, 3, 5, V, { VR }, 0, nullptr }, + { ocGammaLn, 271, 1, 1, V, { VR }, 0, nullptr }, + { ocBetaInv, 272, 3, 5, V, { VR }, 0, nullptr }, + { ocBinomDist, 273, 4, 4, V, { VR }, 0, nullptr }, + { ocChiDist, 274, 2, 2, V, { VR }, 0, nullptr }, + { ocChiInv, 275, 2, 2, V, { VR }, 0, nullptr }, + { ocCombin, 276, 2, 2, V, { VR }, 0, nullptr }, + { ocConfidence, 277, 3, 3, V, { VR }, 0, nullptr }, + { ocCritBinom, 278, 3, 3, V, { VR }, 0, nullptr }, + { ocEven, 279, 1, 1, V, { VR }, 0, nullptr }, + { ocExpDist, 280, 3, 3, V, { VR }, 0, nullptr }, + { ocFDist, 281, 3, 3, V, { VR }, 0, nullptr }, + { ocFInv, 282, 3, 3, V, { VR }, 0, nullptr }, + { ocFisher, 283, 1, 1, V, { VR }, 0, nullptr }, + { ocFisherInv, 284, 1, 1, V, { VR }, 0, nullptr }, + { ocFloor_MS, 285, 2, 2, V, { VR }, 0, nullptr }, + { ocGammaDist, 286, 4, 4, V, { VR }, 0, nullptr }, + { ocGammaInv, 287, 3, 3, V, { VR }, 0, nullptr }, + { ocCeil_MS, 288, 2, 2, V, { VR }, 0, nullptr }, + { ocHypGeomDist, 289, 4, 4, V, { VR }, 0, nullptr }, + { ocLogNormDist, 290, 3, 3, V, { VR }, 0, nullptr }, + { ocLogInv, 291, 3, 3, V, { VR }, 0, nullptr }, + { ocNegBinomVert, 292, 3, 3, V, { VR }, 0, nullptr }, + { ocNormDist, 293, 4, 4, V, { VR }, 0, nullptr }, + { ocStdNormDist, 294, 1, 1, V, { VR }, 0, nullptr }, + { ocNormInv, 295, 3, 3, V, { VR }, 0, nullptr }, + { ocSNormInv, 296, 1, 1, V, { VR }, 0, nullptr }, + { ocStandard, 297, 3, 3, V, { VR }, 0, nullptr }, + { ocOdd, 298, 1, 1, V, { VR }, 0, nullptr }, + { ocPermut, 299, 2, 2, V, { VR }, 0, nullptr }, + { ocPoissonDist, 300, 3, 3, V, { VR }, 0, nullptr }, + { ocTDist, 301, 3, 3, V, { VR }, 0, nullptr }, + { ocWeibull, 302, 4, 4, V, { VR }, 0, nullptr }, + { ocSumXMY2, 303, 2, 2, V, { VA }, 0, nullptr }, + { ocSumX2MY2, 304, 2, 2, V, { VA }, 0, nullptr }, + { ocSumX2DY2, 305, 2, 2, V, { VA }, 0, nullptr }, + { ocChiTest, 306, 2, 2, V, { VA }, 0, nullptr }, + { ocCorrel, 307, 2, 2, V, { VA }, 0, nullptr }, + { ocCovar, 308, 2, 2, V, { VA }, 0, nullptr }, + { ocForecast, 309, 3, 3, V, { VR, VA }, 0, nullptr }, + { ocFTest, 310, 2, 2, V, { VA }, 0, nullptr }, + { ocIntercept, 311, 2, 2, V, { VA }, 0, nullptr }, + { ocPearson, 312, 2, 2, V, { VA }, 0, nullptr }, + { ocRSQ, 313, 2, 2, V, { VA }, 0, nullptr }, + { ocSTEYX, 314, 2, 2, V, { VA }, 0, nullptr }, + { ocSlope, 315, 2, 2, V, { VA }, 0, nullptr }, + { ocTTest, 316, 4, 4, V, { VA, VA, VR }, 0, nullptr }, + { ocProb, 317, 3, 4, V, { VA, VA, VR }, 0, nullptr }, + { ocDevSq, 318, 1, MX, V, { RX }, 0, nullptr }, + { ocGeoMean, 319, 1, MX, V, { RX }, 0, nullptr }, + { ocHarMean, 320, 1, MX, V, { RX }, 0, nullptr }, + { ocSumSQ, 321, 0, MX, V, { RX }, 0, nullptr }, + { ocKurt, 322, 1, MX, V, { RX }, 0, nullptr }, + { ocSkew, 323, 1, MX, V, { RX }, 0, nullptr }, + { ocZTest, 324, 2, 3, V, { RX, VR }, 0, nullptr }, + { ocLarge, 325, 2, 2, V, { RX, VR }, 0, nullptr }, + { ocSmall, 326, 2, 2, V, { RX, VR }, 0, nullptr }, + { ocQuartile, 327, 2, 2, V, { RX, VR }, 0, nullptr }, + { ocPercentile, 328, 2, 2, V, { RX, VR }, 0, nullptr }, + { ocPercentrank, 329, 2, 3, V, { RX, VR, VR_E }, 0, nullptr }, + { ocModalValue, 330, 1, MX, V, { VA }, 0, nullptr }, + { ocTrimMean, 331, 2, 2, V, { RX, VR }, 0, nullptr }, + { ocTInv, 332, 2, 2, V, { VR }, 0, nullptr }, + // Functions equivalent to add-in functions, use same parameters as + // ocExternal but add programmatical function name (here without + // "com.sun.star.sheet.addin.") so it can be looked up and stored as + // add-in, as older Excel versions only know them as add-in. + { ocIsEven, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY | EXC_FUNCFLAG_ADDINEQUIV, EXC_FUNCNAME_ADDIN( "Analysis.getIseven" ) }, + { ocIsOdd, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY | EXC_FUNCFLAG_ADDINEQUIV, EXC_FUNCNAME_ADDIN( "Analysis.getIsodd" ) }, + { ocGCD, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY | EXC_FUNCFLAG_ADDINEQUIV, EXC_FUNCNAME_ADDIN( "Analysis.getGcd" ) }, + { ocLCM, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY | EXC_FUNCFLAG_ADDINEQUIV, EXC_FUNCNAME_ADDIN( "Analysis.getLcm" ) }, + { ocEffect, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY | EXC_FUNCFLAG_ADDINEQUIV, EXC_FUNCNAME_ADDIN( "Analysis.getEffect" ) }, + { ocCumPrinc, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY | EXC_FUNCFLAG_ADDINEQUIV, EXC_FUNCNAME_ADDIN( "Analysis.getCumprinc" ) }, + { ocCumIpmt, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY | EXC_FUNCFLAG_ADDINEQUIV, EXC_FUNCNAME_ADDIN( "Analysis.getCumipmt" ) }, + { ocNominal, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY | EXC_FUNCFLAG_ADDINEQUIV, EXC_FUNCNAME_ADDIN( "Analysis.getNominal" ) }, + { ocNetWorkdays, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY | EXC_FUNCFLAG_ADDINEQUIV, EXC_FUNCNAME_ADDIN( "Analysis.getNetworkdays" ) } +}; + +/** Functions new in BIFF5/BIFF7. Unsupported functions: DATESTRING, NUMBERSTRING. */ +const XclFunctionInfo saFuncTable_5[] = +{ + { ocGetDayOfWeek, 70, 1, 2, V, { VR }, 0, nullptr }, // BIFF2-4: 1, BIFF5: 1-2 + { ocHLookup, 101, 3, 4, V, { VV, RO, RO, VV }, 0, nullptr }, // BIFF2-4: 3, BIFF5: 3-4 + { ocVLookup, 102, 3, 4, V, { VV, RO, RO, VV }, 0, nullptr }, // BIFF2-4: 3, BIFF5: 3-4 + { ocGetDiffDate360, 220, 2, 3, V, { VR }, 0, nullptr }, // BIFF3-4: 2, BIFF5: 2-3 + { ocMacro, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, nullptr }, + { ocExternal, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, nullptr }, + { ocConcat, 336, 0, MX, V, { VR }, 0, nullptr }, + { ocPower, 337, 2, 2, V, { VR }, 0, nullptr }, + { ocRad, 342, 1, 1, V, { VR }, 0, nullptr }, + { ocDeg, 343, 1, 1, V, { VR }, 0, nullptr }, + { ocSubTotal, 344, 2, MX, V, { VR, RO }, 0, nullptr }, + { ocSumIf, 345, 2, 3, V, { RO, VR, RO }, 0, nullptr }, + { ocCountIf, 346, 2, 2, V, { RO, VR }, 0, nullptr }, + { ocCountEmptyCells, 347, 1, 1, V, { RO }, 0, nullptr }, + { ocISPMT, 350, 4, 4, V, { VR }, 0, nullptr }, + { ocGetDateDif, 351, 3, 3, V, { VR }, 0, nullptr }, + { ocNoName, 352, 1, 1, V, { VR }, EXC_FUNCFLAG_IMPORTONLY, nullptr }, // DATESTRING + { ocNoName, 353, 2, 2, V, { VR }, EXC_FUNCFLAG_IMPORTONLY, nullptr }, // NUMBERSTRING + { ocRoman, 354, 1, 2, V, { VR }, 0, nullptr } +}; + +/** Functions new in BIFF8. Unsupported functions: PHONETIC. */ +const XclFunctionInfo saFuncTable_8[] = +{ + { ocGetPivotData, 358, 2, MX, V, { RR, RR, VR }, 0, nullptr }, + { ocHyperLink, 359, 1, 2, V, { VV, VO }, 0, nullptr }, + { ocNoName, 360, 1, 1, V, { RO }, EXC_FUNCFLAG_IMPORTONLY, nullptr }, // PHONETIC + { ocAverageA, 361, 1, MX, V, { RX }, 0, nullptr }, + { ocMaxA, 362, 1, MX, V, { RX }, 0, nullptr }, + { ocMinA, 363, 1, MX, V, { RX }, 0, nullptr }, + { ocStDevPA, 364, 1, MX, V, { RX }, 0, nullptr }, + { ocVarPA, 365, 1, MX, V, { RX }, 0, nullptr }, + { ocStDevA, 366, 1, MX, V, { RX }, 0, nullptr }, + { ocVarA, 367, 1, MX, V, { RX }, 0, nullptr }, + { ocBahtText, 368, 1, 1, V, { VR }, EXC_FUNCFLAG_IMPORTONLY, EXC_FUNCNAME( "BAHTTEXT" ) }, + { ocBahtText, 255, 2, 2, V, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, EXC_FUNCNAME( "BAHTTEXT" ) }, + { ocEuroConvert, 255, 4, 6, V, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, "EUROCONVERT" } +}; + +#define EXC_FUNCENTRY_V_VR( opcode, minparam, maxparam, flags, asciiname ) \ + { opcode, NOID, minparam, maxparam, V, { VR }, EXC_FUNCFLAG_IMPORTONLY|(flags), EXC_FUNCNAME( asciiname ) }, \ + { opcode, 255, (minparam)+1, (maxparam)+1, V, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY|(flags), EXC_FUNCNAME( asciiname ) } + +/** Functions new in OOXML. */ +const XclFunctionInfo saFuncTable_Oox[] = +{ + { ocCountIfs, NOID, 2, MX, V, { RO, VR }, EXC_FUNCFLAG_IMPORTONLY|EXC_FUNCFLAG_PARAMPAIRS, EXC_FUNCNAME( "COUNTIFS" ) }, + { ocCountIfs, 255, 3, MX, V, { RO_E, RO, VR }, EXC_FUNCFLAG_EXPORTONLY|EXC_FUNCFLAG_PARAMPAIRS, EXC_FUNCNAME( "COUNTIFS" ) }, + { ocSumIfs, NOID, 3, MX, V, { RO, RO, VR }, EXC_FUNCFLAG_IMPORTONLY|EXC_FUNCFLAG_PARAMPAIRS, EXC_FUNCNAME( "SUMIFS" ) }, + { ocSumIfs, 255, 4, MX, V, { RO_E, RO, RO, VR }, EXC_FUNCFLAG_EXPORTONLY|EXC_FUNCFLAG_PARAMPAIRS, EXC_FUNCNAME( "SUMIFS" ) }, + { ocAverageIf, NOID, 2, 3, V, { RO, VR, RO }, EXC_FUNCFLAG_IMPORTONLY, EXC_FUNCNAME( "AVERAGEIF" ) }, + { ocAverageIf, 255, 3, 4, V, { RO_E, RO, VR, RO }, EXC_FUNCFLAG_EXPORTONLY, EXC_FUNCNAME( "AVERAGEIF" ) }, + { ocAverageIfs, NOID, 3, MX, V, { RO, RO, VR }, EXC_FUNCFLAG_IMPORTONLY|EXC_FUNCFLAG_PARAMPAIRS, EXC_FUNCNAME( "AVERAGEIFS" ) }, + { ocAverageIfs, 255, 4, MX, V, { RO_E, RO, RO, VR }, EXC_FUNCFLAG_EXPORTONLY|EXC_FUNCFLAG_PARAMPAIRS, EXC_FUNCNAME( "AVERAGEIFS" ) }, + { ocIfError, NOID, 2, 2, V, { VO, RO }, EXC_FUNCFLAG_IMPORTONLY, EXC_FUNCNAME( "IFERROR" ) }, + { ocIfError, 255, 3, 3, V, { RO_E, VO, RO }, EXC_FUNCFLAG_EXPORTONLY, EXC_FUNCNAME( "IFERROR" ) }, + { ocNetWorkdays_MS, NOID, 2, 4, V, { VR, VR, RO, RO }, EXC_FUNCFLAG_IMPORTONLY, EXC_FUNCNAME( "NETWORKDAYS.INTL" ) }, + { ocNetWorkdays_MS, 255, 3, 5, V, { RO_E, VR, VR, RO, RO }, EXC_FUNCFLAG_EXPORTONLY, EXC_FUNCNAME( "NETWORKDAYS.INTL" ) }, + { ocWorkday_MS, NOID, 2, 4, V, { VR, VR, VR, RO }, EXC_FUNCFLAG_IMPORTONLY, EXC_FUNCNAME( "WORKDAY.INTL" ) }, + { ocWorkday_MS, 255, 3, 5, V, { RO_E, VR, VR, VR, RO }, EXC_FUNCFLAG_EXPORTONLY, EXC_FUNCNAME( "WORKDAY.INTL" ) }, + EXC_FUNCENTRY_V_VR( ocCeil_ISO, 1, 2, 0, "ISO.CEILING" ) +}; + +#define EXC_FUNCENTRY_V_VR_IMPORT( opcode, minparam, maxparam, flags, asciiname ) \ + { opcode, NOID, minparam, maxparam, V, { VR }, EXC_FUNCFLAG_IMPORTONLY|(flags), EXC_FUNCNAME( asciiname ) } + +#define EXC_FUNCENTRY_V_RO_EXPORT( opcode, minparam, maxparam, flags, asciiname ) \ + { opcode, 255, (minparam)+1, (maxparam)+1, V, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY|(flags), EXC_FUNCNAME( asciiname ) } + +#define EXC_FUNCENTRY_A_VR( opcode, minparam, maxparam, flags, asciiname ) \ + { opcode, NOID, minparam, maxparam, A, { VR }, EXC_FUNCFLAG_IMPORTONLY|(flags), EXC_FUNCNAME( asciiname ) }, \ + { opcode, 255, (minparam)+1, (maxparam)+1, A, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY|(flags), EXC_FUNCNAME( asciiname ) } + +#define EXC_FUNCENTRY_V_RO( opcode, minparam, maxparam, flags, asciiname ) \ + { opcode, NOID, minparam, maxparam, V, { RO }, EXC_FUNCFLAG_IMPORTONLY|(flags), EXC_FUNCNAME( asciiname ) }, \ + { opcode, 255, (minparam)+1, (maxparam)+1, V, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY|(flags), EXC_FUNCNAME( asciiname ) } + +// implicit maxparam=MX +#define EXC_FUNCENTRY_V_RX( opcode, minparam, maxparam, flags, asciiname ) \ + { opcode, NOID, minparam, MX, V, { RX }, EXC_FUNCFLAG_IMPORTONLY|(flags), EXC_FUNCNAME( asciiname ) }, \ + { opcode, 255, (minparam)+1, MX, V, { RO_E, RX }, EXC_FUNCFLAG_EXPORTONLY|(flags), EXC_FUNCNAME( asciiname ) } + +#define EXC_FUNCENTRY_V_VA( opcode, minparam, maxparam, flags, asciiname ) \ + { opcode, NOID, minparam, maxparam, V, { VA }, EXC_FUNCFLAG_IMPORTONLY|(flags), EXC_FUNCNAME( asciiname ) }, \ + { opcode, 255, (minparam)+1, (maxparam)+1, V, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY|(flags), EXC_FUNCNAME( asciiname ) } + +/** Functions new in Excel 2010. + + See http://office.microsoft.com/en-us/excel-help/what-s-new-changes-made-to-excel-functions-HA010355760.aspx + A lot of statistical functions have been renamed (the 'old' function names still exist). + + @See sc/source/filter/oox/formulabase.cxx saFuncTable2010 for V,VR,RO,... + */ +const XclFunctionInfo saFuncTable_2010[] = +{ + EXC_FUNCENTRY_V_VA( ocCovarianceP, 2, 2, 0, "COVARIANCE.P" ), + EXC_FUNCENTRY_V_VA( ocCovarianceS, 2, 2, 0, "COVARIANCE.S" ), + EXC_FUNCENTRY_V_RX( ocStDevP_MS, 1, MX, 0, "STDEV.P" ), + EXC_FUNCENTRY_V_RX( ocStDevS, 1, MX, 0, "STDEV.S" ), + EXC_FUNCENTRY_V_RX( ocVarP_MS, 1, MX, 0, "VAR.P" ), + EXC_FUNCENTRY_V_RX( ocVarS, 1, MX, 0, "VAR.S" ), + EXC_FUNCENTRY_V_VR( ocBetaDist_MS, 4, 6, 0, "BETA.DIST" ), + EXC_FUNCENTRY_V_VR( ocBetaInv_MS, 3, 5, 0, "BETA.INV" ), + EXC_FUNCENTRY_V_VR( ocBinomDist_MS, 4, 4, 0, "BINOM.DIST" ), + EXC_FUNCENTRY_V_VR( ocBinomInv, 3, 3, 0, "BINOM.INV" ), + EXC_FUNCENTRY_V_VR( ocChiSqDist_MS, 3, 3, 0, "CHISQ.DIST" ), + EXC_FUNCENTRY_V_VR( ocChiSqInv_MS, 2, 2, 0, "CHISQ.INV" ), + EXC_FUNCENTRY_V_VR( ocChiDist_MS, 2, 2, 0, "CHISQ.DIST.RT" ), + EXC_FUNCENTRY_V_VR( ocChiInv_MS, 2, 2, 0, "CHISQ.INV.RT" ), + EXC_FUNCENTRY_V_VR( ocChiTest_MS, 2, 2, 0, "CHISQ.TEST" ), + EXC_FUNCENTRY_V_VR( ocConfidence_N, 3, 3, 0, "CONFIDENCE.NORM" ), + EXC_FUNCENTRY_V_VR( ocConfidence_T, 3, 3, 0, "CONFIDENCE.T" ), + EXC_FUNCENTRY_V_VR( ocFDist_LT, 4, 4, 0, "F.DIST" ), + EXC_FUNCENTRY_V_VR( ocFDist_RT, 3, 3, 0, "F.DIST.RT" ), + EXC_FUNCENTRY_V_VR( ocFInv_LT, 3, 3, 0, "F.INV" ), + EXC_FUNCENTRY_V_VR( ocFInv_RT, 3, 3, 0, "F.INV.RT" ), + EXC_FUNCENTRY_V_VR( ocFTest_MS, 2, 2, 0, "F.TEST" ), + EXC_FUNCENTRY_V_VR( ocExpDist_MS, 3, 3, 0, "EXPON.DIST" ), + EXC_FUNCENTRY_V_VR( ocHypGeomDist_MS, 5, 5, 0, "HYPGEOM.DIST" ), + EXC_FUNCENTRY_V_VR( ocPoissonDist_MS, 3, 3, 0, "POISSON.DIST" ), + EXC_FUNCENTRY_V_VR( ocWeibull_MS, 4, 4, 0, "WEIBULL.DIST" ), + EXC_FUNCENTRY_V_VR( ocGammaDist_MS, 4, 4, 0, "GAMMA.DIST" ), + EXC_FUNCENTRY_V_VR( ocGammaInv_MS, 3, 3, 0, "GAMMA.INV" ), + EXC_FUNCENTRY_V_VR( ocGammaLn_MS, 1, 1, 0, "GAMMALN.PRECISE" ), + EXC_FUNCENTRY_V_VR( ocLogNormDist_MS, 4, 4, 0, "LOGNORM.DIST" ), + EXC_FUNCENTRY_V_VR( ocLogInv_MS, 3, 3, 0, "LOGNORM.INV" ), + EXC_FUNCENTRY_V_VR( ocNormDist_MS, 4, 4, 0, "NORM.DIST" ), + EXC_FUNCENTRY_V_VR( ocNormInv_MS, 3, 3, 0, "NORM.INV" ), + EXC_FUNCENTRY_V_VR( ocStdNormDist_MS, 2, 2, 0, "NORM.S.DIST" ), + EXC_FUNCENTRY_V_VR( ocSNormInv_MS, 1, 1, 0, "NORM.S.INV" ), + EXC_FUNCENTRY_V_VR( ocTDist_2T, 2, 2, 0, "T.DIST.2T" ), + EXC_FUNCENTRY_V_VR( ocTDist_MS, 3, 3, 0, "T.DIST" ), + EXC_FUNCENTRY_V_VR( ocTDist_RT, 2, 2, 0, "T.DIST.RT" ), + EXC_FUNCENTRY_V_VR( ocTInv_2T, 2, 2, 0, "T.INV.2T" ), + EXC_FUNCENTRY_V_VR( ocTInv_MS, 2, 2, 0, "T.INV" ), + EXC_FUNCENTRY_V_VR( ocTTest_MS, 4, 4, 0, "T.TEST" ), + EXC_FUNCENTRY_V_VR( ocPercentile_Inc, 2, 2, 0, "PERCENTILE.INC" ), + EXC_FUNCENTRY_V_VR( ocPercentrank_Inc, 2, 3, 0, "PERCENTRANK.INC" ), + EXC_FUNCENTRY_V_VR( ocQuartile_Inc, 2, 2, 0, "QUARTILE.INC" ), + EXC_FUNCENTRY_V_VR( ocRank_Eq, 2, 3, 0, "RANK.EQ" ), + EXC_FUNCENTRY_V_VR( ocPercentile_Exc, 2, 2, 0, "PERCENTILE.EXC" ), + EXC_FUNCENTRY_V_VR( ocPercentrank_Exc, 2, 3, 0, "PERCENTRANK.EXC" ), + EXC_FUNCENTRY_V_VR( ocQuartile_Exc, 2, 2, 0, "QUARTILE.EXC" ), + EXC_FUNCENTRY_V_VR( ocRank_Avg, 2, 3, 0, "RANK.AVG" ), + EXC_FUNCENTRY_V_RX( ocModalValue_MS, 1, MX, 0, "MODE.SNGL" ), + EXC_FUNCENTRY_V_RX( ocModalValue_Multi, 1, MX, 0, "MODE.MULT" ), + EXC_FUNCENTRY_V_VR( ocNegBinomDist_MS, 4, 4, 0, "NEGBINOM.DIST" ), + EXC_FUNCENTRY_V_VR( ocZTest_MS, 2, 3, 0, "Z.TEST" ), + EXC_FUNCENTRY_V_VR( ocCeil_Precise, 1, 2, 0, "CEILING.PRECISE" ), + EXC_FUNCENTRY_V_VR( ocFloor_Precise, 1, 2, 0, "FLOOR.PRECISE" ), + EXC_FUNCENTRY_V_VR( ocErf_MS, 1, 1, 0, "ERF.PRECISE" ), + EXC_FUNCENTRY_V_VR( ocErfc_MS, 1, 1, 0, "ERFC.PRECISE" ), + EXC_FUNCENTRY_V_RX( ocAggregate, 3, MX, 0, "AGGREGATE" ), +}; + +/** Functions new in Excel 2013. + + See http://office.microsoft.com/en-us/excel-help/new-functions-in-excel-2013-HA103980604.aspx + Most functions apparently were added for ODF1.2 ODFF / OpenFormula + compatibility. + + Functions with EXC_FUNCENTRY_V_VR_IMPORT are rewritten in + sc/source/filter/excel/xeformula.cxx during export for BIFF, OOXML export + uses a different mapping but still uses this mapping here to determine the + feature set. + + FIXME: either have the exporter determine the feature set from the active + mapping, preferred, or enhance this mapping here such that for OOXML the + rewrite can be overridden. + + @See sc/source/filter/oox/formulabase.cxx saFuncTable2013 for V,VR,RO,... + */ +const XclFunctionInfo saFuncTable_2013[] = +{ + EXC_FUNCENTRY_V_VR_IMPORT( ocArcCot, 1, 1, 0, "ACOT" ), + EXC_FUNCENTRY_V_VR_IMPORT( ocArcCotHyp, 1, 1, 0, "ACOTH" ), + EXC_FUNCENTRY_V_VR( ocArabic, 1, 1, 0, "ARABIC" ), + EXC_FUNCENTRY_V_VR( ocBase, 2, 3, 0, "BASE" ), + EXC_FUNCENTRY_V_VR( ocB, 3, 4, 0, "BINOM.DIST.RANGE" ), + EXC_FUNCENTRY_V_VR( ocBitAnd, 2, 2, 0, "BITAND" ), + EXC_FUNCENTRY_V_VR( ocBitLshift, 2, 2, 0, "BITLSHIFT" ), + EXC_FUNCENTRY_V_VR( ocBitOr, 2, 2, 0, "BITOR" ), + EXC_FUNCENTRY_V_VR( ocBitRshift, 2, 2, 0, "BITRSHIFT" ), + EXC_FUNCENTRY_V_VR( ocBitXor, 2, 2, 0, "BITXOR" ), + EXC_FUNCENTRY_V_VR( ocCeil_Math, 1, 3, 0, "CEILING.MATH" ), + EXC_FUNCENTRY_V_RO_EXPORT( ocCeil, 1, 3, 0, "CEILING.MATH" ), + EXC_FUNCENTRY_V_VR( ocCombinA, 2, 2, 0, "COMBINA" ), + EXC_FUNCENTRY_V_VR_IMPORT( ocCot, 1, 1, 0, "COT" ), + EXC_FUNCENTRY_V_VR_IMPORT( ocCotHyp, 1, 1, 0, "COTH" ), + EXC_FUNCENTRY_V_VR_IMPORT( ocCosecant, 1, 1, 0, "CSC" ), + EXC_FUNCENTRY_V_VR_IMPORT( ocCosecantHyp, 1, 1, 0, "CSCH" ), + EXC_FUNCENTRY_V_VR( ocGetDiffDate, 2, 2, 0, "DAYS" ), + EXC_FUNCENTRY_V_VR( ocDecimal, 2, 2, 0, "DECIMAL" ), + EXC_FUNCENTRY_V_VR( ocEncodeURL, 1, 1, 0, "ENCODEURL" ), + // NOTE: this FDIST is not our LEGACY.FDIST + EXC_FUNCENTRY_V_VR( ocNoName, 3, 4, 0, "FDIST" ), + // NOTE: this FINV is not our LEGACY.FINV + EXC_FUNCENTRY_V_VR( ocNoName, 3, 3, 0, "FINV" ), + EXC_FUNCENTRY_V_VR( ocFilterXML, 2, 2, 0, "FILTERXML" ), + EXC_FUNCENTRY_V_VR( ocFloor_Math, 1, 3, 0, "FLOOR.MATH" ), + EXC_FUNCENTRY_V_RO_EXPORT( ocFloor, 1, 3, 0, "FLOOR.MATH" ), + EXC_FUNCENTRY_V_RO( ocFormula, 1, 1, 0, "FORMULATEXT" ), + EXC_FUNCENTRY_V_VR( ocGamma, 1, 1, 0, "GAMMA" ), + EXC_FUNCENTRY_V_VR( ocGauss, 1, 1, 0, "GAUSS" ), + { ocIfNA, NOID, 2, 2, V, { VO, RO }, EXC_FUNCFLAG_IMPORTONLY, EXC_FUNCNAME( "IFNA" ) }, + { ocIfNA, 255, 3, 3, V, { RO_E, VO, RO }, EXC_FUNCFLAG_EXPORTONLY, EXC_FUNCNAME( "IFNA" ) }, + // IMCOSH, IMCOT, IMCSC, IMCSCH, IMSEC, IMSECH, IMSINH and IMTAN are + // implemented in the Analysis Add-In. + EXC_FUNCENTRY_V_RO( ocIsFormula, 1, 1, 0, "ISFORMULA" ), + EXC_FUNCENTRY_V_VR( ocWeek, 1, 2, 0, "WEEKNUM" ), + EXC_FUNCENTRY_V_VR( ocIsoWeeknum, 1, 1, 0, "ISOWEEKNUM" ), + EXC_FUNCENTRY_A_VR( ocMatrixUnit, 1, 1, 0, "MUNIT" ), + EXC_FUNCENTRY_V_VR( ocNumberValue, 1, 3, 0, "NUMBERVALUE" ), + EXC_FUNCENTRY_V_VR( ocPDuration, 3, 3, 0, "PDURATION" ), + EXC_FUNCENTRY_V_VR( ocPermutationA, 2, 2, 0, "PERMUTATIONA" ), + EXC_FUNCENTRY_V_VR( ocPhi, 1, 1, 0, "PHI" ), + EXC_FUNCENTRY_V_VR( ocRRI, 3, 3, 0, "RRI" ), + EXC_FUNCENTRY_V_VR_IMPORT( ocSecant, 1, 1, 0, "SEC" ), + EXC_FUNCENTRY_V_VR_IMPORT( ocSecantHyp, 1, 1, 0, "SECH" ), + EXC_FUNCENTRY_V_RO( ocSheet, 0, 1, 0, "SHEET" ), + EXC_FUNCENTRY_V_RO( ocSheets, 0, 1, 0, "SHEETS" ), + EXC_FUNCENTRY_V_RX( ocSkewp, 1, MX, 0, "SKEW.P" ), + EXC_FUNCENTRY_V_VR( ocUnichar, 1, 1, 0, "UNICHAR" ), + EXC_FUNCENTRY_V_VR( ocUnicode, 1, 1, 0, "UNICODE" ), + EXC_FUNCENTRY_V_VR( ocWebservice, 1, 1, 0, "WEBSERVICE" ), + EXC_FUNCENTRY_V_RX( ocXor, 1, MX, 0, "XOR" ), + EXC_FUNCENTRY_V_VR( ocErrorType_ODF, 1, 1, 0, "ERROR.TYPE" ) +}; + +/** Functions new in Excel 2016. + + See https://support.office.com/en-us/article/Forecasting-functions-897a2fe9-6595-4680-a0b0-93e0308d5f6e?ui=en-US&rs=en-US&ad=US#_forecast.ets + and https://support.office.com/en-us/article/What-s-New-and-Improved-in-Office-2016-for-Office-365-95c8d81d-08ba-42c1-914f-bca4603e1426?ui=en-US&rs=en-US&ad=US + + @See sc/source/filter/oox/formulabase.cxx saFuncTable2016 for V,VR,RO,... + */ +const XclFunctionInfo saFuncTable_2016[] = +{ + EXC_FUNCENTRY_V_VR( ocForecast_ETS_ADD, 3, 6, 0, "FORECAST.ETS" ), + EXC_FUNCENTRY_V_VR( ocForecast_ETS_PIA, 3, 7, 0, "FORECAST.ETS.CONFINT" ), + EXC_FUNCENTRY_V_VR( ocForecast_ETS_SEA, 2, 4, 0, "FORECAST.ETS.SEASONALITY" ), + EXC_FUNCENTRY_V_VR( ocForecast_ETS_STA, 3, 6, 0, "FORECAST.ETS.STAT" ), + EXC_FUNCENTRY_V_VR( ocForecast_LIN, 3, 3, 0, "FORECAST.LINEAR" ), + EXC_FUNCENTRY_V_VR( ocConcat_MS, 1, MX, 0, "CONCAT" ), + EXC_FUNCENTRY_V_VR( ocTextJoin_MS, 3, MX, 0, "TEXTJOIN" ), + EXC_FUNCENTRY_V_VR( ocIfs_MS, 2, MX, 0, "IFS" ), + EXC_FUNCENTRY_V_VR( ocSwitch_MS, 3, MX, 0, "SWITCH" ), + EXC_FUNCENTRY_V_VR( ocMinIfs_MS, 3, MX, 0, "MINIFS" ), + EXC_FUNCENTRY_V_VR( ocMaxIfs_MS, 3, MX, 0, "MAXIFS" ) +}; + +#define EXC_FUNCENTRY_ODF( opcode, minparam, maxparam, flags, asciiname ) \ + { opcode, NOID, minparam, maxparam, V, { VR }, EXC_FUNCFLAG_IMPORTONLY|(flags), EXC_FUNCNAME_ODF( asciiname ) }, \ + { opcode, 255, (minparam)+1, (maxparam)+1, V, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY|(flags), EXC_FUNCNAME_ODF( asciiname ) } + +/** Functions defined by OpenFormula, but not supported by Calc (ocNoName) or by Excel (defined op-code). */ +const XclFunctionInfo saFuncTable_Odf[] = +{ + EXC_FUNCENTRY_ODF( ocChiSqDist, 2, 3, 0, "CHISQDIST" ), + EXC_FUNCENTRY_ODF( ocChiSqInv, 2, 2, 0, "CHISQINV" ) +}; + +#undef EXC_FUNCENTRY_ODF + +#define EXC_FUNCENTRY_OOO( opcode, minparam, maxparam, flags, asciiname ) \ + { opcode, NOID, minparam, maxparam, V, { VR }, EXC_FUNCFLAG_IMPORTONLY|(flags), EXC_FUNCNAME( asciiname ) }, \ + { opcode, 255, (minparam)+1, (maxparam)+1, V, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY|(flags), EXC_FUNCNAME( asciiname ) } + +// Import Broken Raw ... even without leading _xlfn. +#define EXC_FUNCENTRY_OOO_IBR( opcode, minparam, maxparam, flags, asciiname ) \ + { opcode, NOID, minparam, maxparam, V, { VR }, EXC_FUNCFLAG_IMPORTONLY|(flags), asciiname } + +/** Functions defined by Calc, but not in OpenFormula nor supported by Excel. */ +const XclFunctionInfo saFuncTable_OOoLO[] = +{ + EXC_FUNCENTRY_OOO( ocErrorType, 1, 1, 0, "ORG.OPENOFFICE.ERRORTYPE" ), + EXC_FUNCENTRY_OOO_IBR( ocErrorType, 1, 1, 0, "ERRORTYPE" ), // was written wrongly, read it + EXC_FUNCENTRY_OOO( ocMultiArea, 1, MX, 0, "ORG.OPENOFFICE.MULTIRANGE" ), + EXC_FUNCENTRY_OOO_IBR( ocMultiArea, 1, MX, 0, "MULTIRANGE" ), // was written wrongly, read it + EXC_FUNCENTRY_OOO( ocBackSolver, 3, 3, 0, "ORG.OPENOFFICE.GOALSEEK" ), + EXC_FUNCENTRY_OOO_IBR( ocBackSolver,3, 3, 0, "GOALSEEK" ), // was written wrongly, read it + EXC_FUNCENTRY_OOO( ocEasterSunday, 1, 1, 0, "ORG.OPENOFFICE.EASTERSUNDAY" ), + EXC_FUNCENTRY_OOO_IBR( ocEasterSunday,1,1, 0, "EASTERSUNDAY" ), // was written wrongly, read it + EXC_FUNCENTRY_OOO( ocCurrent, 0, 0, 0, "ORG.OPENOFFICE.CURRENT" ), + EXC_FUNCENTRY_OOO_IBR( ocCurrent, 0, 0, 0, "CURRENT" ), // was written wrongly, read it + EXC_FUNCENTRY_OOO( ocStyle, 1, 3, 0, "ORG.OPENOFFICE.STYLE" ), + EXC_FUNCENTRY_OOO_IBR( ocStyle, 1, 3, 0, "STYLE" ), // was written wrongly, read it + EXC_FUNCENTRY_OOO( ocConvertOOo, 3, 3, 0, "ORG.OPENOFFICE.CONVERT" ), + EXC_FUNCENTRY_OOO( ocColor, 3, 4, 0, "ORG.LIBREOFFICE.COLOR" ), + EXC_FUNCENTRY_OOO( ocRawSubtract, 2, MX, 0, "ORG.LIBREOFFICE.RAWSUBTRACT" ), + EXC_FUNCENTRY_OOO( ocWeeknumOOo, 2, 2, 0, "ORG.LIBREOFFICE.WEEKNUM_OOO" ), + EXC_FUNCENTRY_OOO( ocForecast_ETS_MUL, 3, 6, 0, "ORG.LIBREOFFICE.FORECAST.ETS.MULT" ), + EXC_FUNCENTRY_OOO( ocForecast_ETS_PIM, 3, 7, 0, "ORG.LIBREOFFICE.FORECAST.ETS.PI.MULT" ), + EXC_FUNCENTRY_OOO( ocForecast_ETS_STM, 3, 6, 0, "ORG.LIBREOFFICE.FORECAST.ETS.STAT.MULT" ), + EXC_FUNCENTRY_OOO( ocRoundSig, 2, 2, 0, "ORG.LIBREOFFICE.ROUNDSIG" ), + EXC_FUNCENTRY_OOO( ocRegex, 2, 4, 0, "ORG.LIBREOFFICE.REGEX" ), + EXC_FUNCENTRY_OOO( ocFourier, 2, 5, 0, "ORG.LIBREOFFICE.FOURIER" ), + EXC_FUNCENTRY_OOO( ocRandomNV, 0, 0, 0, "ORG.LIBREOFFICE.RAND.NV" ), + EXC_FUNCENTRY_OOO( ocRandbetweenNV, 2, 2, 0, "ORG.LIBREOFFICE.RANDBETWEEN.NV" ) +}; + +#undef EXC_FUNCENTRY_OOO_IBR +#undef EXC_FUNCENTRY_OOO + +XclFunctionProvider::XclFunctionProvider( const XclRoot& rRoot ) +{ + void (XclFunctionProvider::*pFillFunc)( const XclFunctionInfo*, const XclFunctionInfo* ) = + rRoot.IsImport() ? &XclFunctionProvider::FillXclFuncMap : &XclFunctionProvider::FillScFuncMap; + + /* Only read/write functions supported in the current BIFF version. + Function tables from later BIFF versions may overwrite single functions + from earlier tables. */ + XclBiff eBiff = rRoot.GetBiff(); + if( eBiff >= EXC_BIFF2 ) + (this->*pFillFunc)(saFuncTable_2, saFuncTable_2 + SAL_N_ELEMENTS(saFuncTable_2)); + if( eBiff >= EXC_BIFF3 ) + (this->*pFillFunc)(saFuncTable_3, saFuncTable_3 + SAL_N_ELEMENTS(saFuncTable_3)); + if( eBiff >= EXC_BIFF4 ) + (this->*pFillFunc)(saFuncTable_4, saFuncTable_4 + SAL_N_ELEMENTS(saFuncTable_4)); + if( eBiff >= EXC_BIFF5 ) + (this->*pFillFunc)(saFuncTable_5, saFuncTable_5 + SAL_N_ELEMENTS(saFuncTable_5)); + if( eBiff >= EXC_BIFF8 ) + (this->*pFillFunc)(saFuncTable_8, saFuncTable_8 + SAL_N_ELEMENTS(saFuncTable_8)); + (this->*pFillFunc)(saFuncTable_Oox, saFuncTable_Oox + SAL_N_ELEMENTS(saFuncTable_Oox)); + (this->*pFillFunc)(saFuncTable_2010, saFuncTable_2010 + SAL_N_ELEMENTS(saFuncTable_2010)); + (this->*pFillFunc)(saFuncTable_2013, saFuncTable_2013 + SAL_N_ELEMENTS(saFuncTable_2013)); + (this->*pFillFunc)(saFuncTable_2016, saFuncTable_2016 + SAL_N_ELEMENTS(saFuncTable_2016)); + (this->*pFillFunc)(saFuncTable_Odf, saFuncTable_Odf + SAL_N_ELEMENTS(saFuncTable_Odf)); + (this->*pFillFunc)(saFuncTable_OOoLO, saFuncTable_OOoLO + SAL_N_ELEMENTS(saFuncTable_OOoLO)); +} + +const XclFunctionInfo* XclFunctionProvider::GetFuncInfoFromXclFunc( sal_uInt16 nXclFunc ) const +{ + // only in import filter allowed + OSL_ENSURE( !maXclFuncMap.empty(), "XclFunctionProvider::GetFuncInfoFromXclFunc - wrong filter" ); + XclFuncMap::const_iterator aIt = maXclFuncMap.find( nXclFunc ); + return (aIt == maXclFuncMap.end()) ? nullptr : aIt->second; +} + +const XclFunctionInfo* XclFunctionProvider::GetFuncInfoFromXclMacroName( const OUString& rXclMacroName ) const +{ + // only in import filter allowed, but do not test maXclMacroNameMap, it may be empty for old BIFF versions + OSL_ENSURE( !maXclFuncMap.empty(), "XclFunctionProvider::GetFuncInfoFromXclMacroName - wrong filter" ); + XclMacroNameMap::const_iterator aIt = maXclMacroNameMap.find( rXclMacroName ); + return (aIt == maXclMacroNameMap.end()) ? nullptr : aIt->second; +} + +const XclFunctionInfo* XclFunctionProvider::GetFuncInfoFromOpCode( OpCode eOpCode ) const +{ + // only in export filter allowed + OSL_ENSURE( !maScFuncMap.empty(), "XclFunctionProvider::GetFuncInfoFromOpCode - wrong filter" ); + ScFuncMap::const_iterator aIt = maScFuncMap.find( eOpCode ); + return (aIt == maScFuncMap.end()) ? nullptr : aIt->second; +} + +void XclFunctionProvider::FillXclFuncMap( const XclFunctionInfo* pBeg, const XclFunctionInfo* pEnd ) +{ + for( const XclFunctionInfo* pIt = pBeg; pIt != pEnd; ++pIt ) + { + if( !::get_flag( pIt->mnFlags, EXC_FUNCFLAG_EXPORTONLY ) ) + { + if( pIt->mnXclFunc != NOID ) + maXclFuncMap[ pIt->mnXclFunc ] = pIt; + if( pIt->IsMacroFunc() ) + maXclMacroNameMap[ pIt->GetMacroFuncName() ] = pIt; + } + } +} + +void XclFunctionProvider::FillScFuncMap( const XclFunctionInfo* pBeg, const XclFunctionInfo* pEnd ) +{ + for( const XclFunctionInfo* pIt = pBeg; pIt != pEnd; ++pIt ) + if( !::get_flag( pIt->mnFlags, EXC_FUNCFLAG_IMPORTONLY ) ) + maScFuncMap[ pIt->meOpCode ] = pIt; +} + +// Token array ================================================================ + +XclTokenArray::XclTokenArray( bool bVolatile ) : + mbVolatile( bVolatile ) +{ +} + +XclTokenArray::XclTokenArray( ScfUInt8Vec& rTokVec, ScfUInt8Vec& rExtDataVec, bool bVolatile ) : + mbVolatile( bVolatile ) +{ + maTokVec.swap( rTokVec ); + maExtDataVec.swap( rExtDataVec ); +} + +sal_uInt16 XclTokenArray::GetSize() const +{ + OSL_ENSURE( maTokVec.size() <= 0xFFFF, "XclTokenArray::GetSize - array too long" ); + return limit_cast< sal_uInt16 >( maTokVec.size() ); +} + +sal_uInt16 XclTokenArray::ReadSize(XclImpStream& rStrm) +{ + return rStrm.ReaduInt16(); +} + +void XclTokenArray::ReadArray(sal_uInt16 nSize, XclImpStream& rStrm) +{ + maTokVec.resize(0); + + const std::size_t nMaxBuffer = 4096; + std::size_t nBytesLeft = nSize; + std::size_t nTotalRead = 0; + + while (true) + { + if (!nBytesLeft) + break; + std::size_t nReadRequest = o3tl::sanitizing_min(nBytesLeft, nMaxBuffer); + maTokVec.resize(maTokVec.size() + nReadRequest); + auto nRead = rStrm.Read(maTokVec.data() + nTotalRead, nReadRequest); + nTotalRead += nRead; + if (nRead != nReadRequest) + { + maTokVec.resize(nTotalRead); + break; + } + nBytesLeft -= nRead; + } +} + +void XclTokenArray::Read( XclImpStream& rStrm ) +{ + ReadArray(ReadSize(rStrm), rStrm); +} + +void XclTokenArray::WriteSize( XclExpStream& rStrm ) const +{ + rStrm << GetSize(); +} + +void XclTokenArray::WriteArray( XclExpStream& rStrm ) const +{ + if( !maTokVec.empty() ) + rStrm.Write(maTokVec.data(), GetSize()); + if( !maExtDataVec.empty() ) + rStrm.Write(maExtDataVec.data(), maExtDataVec.size()); +} + +void XclTokenArray::Write( XclExpStream& rStrm ) const +{ + WriteSize( rStrm ); + WriteArray( rStrm ); +} + +bool XclTokenArray::operator==( const XclTokenArray& rTokArr ) const +{ + return (mbVolatile == rTokArr.mbVolatile) && (maTokVec == rTokArr.maTokVec) && (maExtDataVec == rTokArr.maExtDataVec); +} + +XclImpStream& operator>>( XclImpStream& rStrm, XclTokenArray& rTokArr ) +{ + rTokArr.Read( rStrm ); + return rStrm; +} + +XclExpStream& operator<<( XclExpStream& rStrm, const XclTokenArray& rTokArr ) +{ + rTokArr.Write( rStrm ); + return rStrm; +} + +XclExpStream& operator<<( XclExpStream& rStrm, const XclTokenArrayRef& rxTokArr ) +{ + if( rxTokArr ) + rxTokArr->Write( rStrm ); + else + rStrm << sal_uInt16( 0 ); + return rStrm; +} + +XclTokenArrayIterator::XclTokenArrayIterator() : + mppScTokenBeg( nullptr ), + mppScTokenEnd( nullptr ), + mppScToken( nullptr ), + mbSkipSpaces( false ) +{ +} + +XclTokenArrayIterator::XclTokenArrayIterator( const ScTokenArray& rScTokArr, bool bSkipSpaces ) +{ + Init( rScTokArr, bSkipSpaces ); +} + +XclTokenArrayIterator::XclTokenArrayIterator( const XclTokenArrayIterator& rTokArrIt, bool bSkipSpaces ) : + mppScTokenBeg( rTokArrIt.mppScTokenBeg ), + mppScTokenEnd( rTokArrIt.mppScTokenEnd ), + mppScToken( rTokArrIt.mppScToken ), + mbSkipSpaces( bSkipSpaces ) +{ + SkipSpaces(); +} + +void XclTokenArrayIterator::Init( const ScTokenArray& rScTokArr, bool bSkipSpaces ) +{ + sal_uInt16 nTokArrLen = rScTokArr.GetLen(); + mppScTokenBeg = static_cast< const FormulaToken* const* >( nTokArrLen ? rScTokArr.GetArray() : nullptr ); + mppScTokenEnd = mppScTokenBeg ? (mppScTokenBeg + nTokArrLen) : nullptr; + mppScToken = (mppScTokenBeg != mppScTokenEnd) ? mppScTokenBeg : nullptr; + mbSkipSpaces = bSkipSpaces; + SkipSpaces(); +} + +XclTokenArrayIterator& XclTokenArrayIterator::operator++() +{ + NextRawToken(); + SkipSpaces(); + return *this; +} + +void XclTokenArrayIterator::NextRawToken() +{ + if( mppScToken ) + if( (++mppScToken == mppScTokenEnd) || !*mppScToken ) + mppScToken = nullptr; +} + +void XclTokenArrayIterator::SkipSpaces() +{ + if( mbSkipSpaces ) + { + OpCode eOp; + while( Is() && (((eOp = (*this)->GetOpCode()) == ocSpaces) || eOp == ocWhitespace) ) + NextRawToken(); + } +} + +// strings and string lists --------------------------------------------------- + +bool XclTokenArrayHelper::GetTokenString( OUString& rString, const FormulaToken& rScToken ) +{ + bool bIsStr = (rScToken.GetType() == svString) && (rScToken.GetOpCode() == ocPush); + if( bIsStr ) rString = rScToken.GetString().getString(); + return bIsStr; +} + +bool XclTokenArrayHelper::GetString( OUString& rString, const ScTokenArray& rScTokArr ) +{ + XclTokenArrayIterator aIt( rScTokArr, true ); + // something is following the string token -> error + return aIt.Is() && GetTokenString( rString, *aIt ) && !++aIt; +} + +bool XclTokenArrayHelper::GetStringList( OUString& rStringList, const ScTokenArray& rScTokArr, sal_Unicode cSep ) +{ + bool bRet = true; + XclTokenArrayIterator aIt( rScTokArr, true ); + enum { STATE_START, STATE_STR, STATE_SEP, STATE_END } eState = STATE_START; + while( eState != STATE_END ) switch( eState ) + { + case STATE_START: + eState = aIt.Is() ? STATE_STR : STATE_END; + break; + case STATE_STR: + { + OUString aString; + bRet = GetTokenString( aString, *aIt ); + if( bRet ) rStringList += aString ; + eState = (bRet && (++aIt).Is()) ? STATE_SEP : STATE_END; + break; + } + case STATE_SEP: + bRet = aIt->GetOpCode() == ocSep; + if( bRet ) rStringList += OUStringChar(cSep); + eState = (bRet && (++aIt).Is()) ? STATE_STR : STATE_END; + break; + default:; + } + return bRet; +} + +void XclTokenArrayHelper::ConvertStringToList( + ScTokenArray& rScTokArr, svl::SharedStringPool& rSPool, sal_Unicode cStringSep ) +{ + OUString aString; + if( !GetString( aString, rScTokArr ) ) + return; + + rScTokArr.Clear(); + if (aString.isEmpty()) + return; + sal_Int32 nStringIx = 0; + for (;;) + { + OUString aToken( aString.getToken( 0, cStringSep, nStringIx ) ); + rScTokArr.AddString(rSPool.intern(comphelper::string::stripStart(aToken, ' '))); + if (nStringIx<0) + break; + rScTokArr.AddOpCode( ocSep ); + } +} + +// multiple operations -------------------------------------------------------- + +namespace { + +bool lclGetAddress( const ScDocument& rDoc, ScAddress& rAddress, const FormulaToken& rToken, const ScAddress& rPos ) +{ + OpCode eOpCode = rToken.GetOpCode(); + bool bIsSingleRef = (eOpCode == ocPush) && (rToken.GetType() == svSingleRef); + if( bIsSingleRef ) + { + const ScSingleRefData& rRef = *rToken.GetSingleRef(); + rAddress = rRef.toAbs(rDoc, rPos); + bIsSingleRef = !rRef.IsDeleted(); + } + return bIsSingleRef; +} + +} // namespace + +bool XclTokenArrayHelper::GetMultipleOpRefs( + const ScDocument& rDoc, + XclMultipleOpRefs& rRefs, const ScTokenArray& rScTokArr, const ScAddress& rScPos ) +{ + rRefs.mbDblRefMode = false; + enum + { + stBegin, stTableOp, stOpen, stFormula, stFormulaSep, + stColFirst, stColFirstSep, stColRel, stColRelSep, + stRowFirst, stRowFirstSep, stRowRel, stClose, stError + } eState = stBegin; // last read token + for( XclTokenArrayIterator aIt( rScTokArr, true ); aIt.Is() && (eState != stError); ++aIt ) + { + OpCode eOpCode = aIt->GetOpCode(); + bool bIsSep = eOpCode == ocSep; + switch( eState ) + { + case stBegin: + eState = (eOpCode == ocTableOp) ? stTableOp : stError; + break; + case stTableOp: + eState = (eOpCode == ocOpen) ? stOpen : stError; + break; + case stOpen: + eState = lclGetAddress(rDoc, rRefs.maFmlaScPos, *aIt, rScPos) ? stFormula : stError; + break; + case stFormula: + eState = bIsSep ? stFormulaSep : stError; + break; + case stFormulaSep: + eState = lclGetAddress(rDoc, rRefs.maColFirstScPos, *aIt, rScPos) ? stColFirst : stError; + break; + case stColFirst: + eState = bIsSep ? stColFirstSep : stError; + break; + case stColFirstSep: + eState = lclGetAddress(rDoc, rRefs.maColRelScPos, *aIt, rScPos) ? stColRel : stError; + break; + case stColRel: + eState = bIsSep ? stColRelSep : ((eOpCode == ocClose) ? stClose : stError); + break; + case stColRelSep: + eState = lclGetAddress(rDoc, rRefs.maRowFirstScPos, *aIt, rScPos) ? stRowFirst : stError; + rRefs.mbDblRefMode = true; + break; + case stRowFirst: + eState = bIsSep ? stRowFirstSep : stError; + break; + case stRowFirstSep: + eState = lclGetAddress(rDoc, rRefs.maRowRelScPos, *aIt, rScPos) ? stRowRel : stError; + break; + case stRowRel: + eState = (eOpCode == ocClose) ? stClose : stError; + break; + default: + eState = stError; + } + } + return eState == stClose; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |