Anonymous avatar Anonymous committed 89feb2f

calcishmakkica: #i117283# support new functions AVERAGEIF, AVERAGEIFS, COUNTIFS, SUMIFS, XOR in Excel filters

Comments (0)

Files changed (8)

oox/source/xls/formulabase.cxx

     { 0,                        "CUBESET",              478,    NOID,   2,  5,  V, { VR, RX, VR }, 0 },
     { 0,                        "CUBESETCOUNT",         479,    NOID,   1,  1,  V, { VR }, 0 },
     { 0,                        "IFERROR",              480,    NOID,   2,  2,  V, { VO, RO }, 0 },
-    { 0,                        "COUNTIFS",             481,    NOID,   2,  MX, V, { RO, VR }, FUNCFLAG_PARAMPAIRS },
-    { 0,                        "SUMIFS",               482,    NOID,   3,  MX, V, { RO, RO, VR }, FUNCFLAG_PARAMPAIRS },
-    { 0,                        "AVERAGEIF",            483,    NOID,   2,  3,  V, { RO, VR, RO }, 0 },
-    { 0,                        "AVERAGEIFS",           484,    NOID,   3,  MX, V, { RO, RO, VR }, 0 }
+    { "COUNTIFS",               "COUNTIFS",             481,    NOID,   2,  MX, V, { RO, VR }, FUNCFLAG_MACROCALL | FUNCFLAG_PARAMPAIRS },
+    { "SUMIFS",                 "SUMIFS",               482,    NOID,   3,  MX, V, { RO, RO, VR }, FUNCFLAG_MACROCALL | FUNCFLAG_PARAMPAIRS },
+    { "AVERAGEIF",              "AVERAGEIF",            483,    NOID,   2,  3,  V, { RO, VR, RO }, FUNCFLAG_MACROCALL },
+    { "AVERAGEIFS",             "AVERAGEIFS",           484,    NOID,   3,  MX, V, { RO, RO, VR }, FUNCFLAG_MACROCALL | FUNCFLAG_PARAMPAIRS }
 };
 
 /** Functions defined by OpenFormula, but not supported by Calc or by Excel. */
     mpParamInfoEnd( rFuncInfo.mpParamInfos + FUNCINFO_PARAMINFOCOUNT ),
     mbParamPairs( rFuncInfo.mbParamPairs )
 {
-    OSL_ENSURE( !mbParamPairs || (mpParamInfo + 1 < mpParamInfoEnd),
-        "FunctionParamInfoIterator::FunctionParamInfoIterator - expecting at least 2 infos for paired parameters" );
 }
 
 const FunctionParamInfo& FunctionParamInfoIterator::getParamInfo() const
         // move pointer to next entry, if something explicit follows
         if( (mpParamInfo + 1 < mpParamInfoEnd) && (mpParamInfo[ 1 ].meValid != FUNC_PARAM_NONE) )
             ++mpParamInfo;
+        // if last parameter type is 'Excel-only' or 'Calc-only', do not repeat it
+        else if( isExcelOnlyParam() || isCalcOnlyParam() )
+            mpParamInfo = 0;
         // points to last info, but parameter pairs expected, move to previous info
         else if( mbParamPairs )
             --mpParamInfo;
-        // if last parameter type is 'Excel-only' or 'Calc-only', do not repeat it
-        else if( isExcelOnlyParam() || isCalcOnlyParam() )
-            mpParamInfo = 0;
         // otherwise: repeat last parameter class
     }
     return *this;
         initFuncs( saFuncTableBiff5, STATIC_ARRAY_END( saFuncTableBiff5 ), nMaxParam, bImportFilter );
     if( eBiff >= BIFF8 )
         initFuncs( saFuncTableBiff8, STATIC_ARRAY_END( saFuncTableBiff8 ), nMaxParam, bImportFilter );
-    if( eFilter == FILTER_OOXML )
-        initFuncs( saFuncTableOox, STATIC_ARRAY_END( saFuncTableOox ), nMaxParam, bImportFilter );
+    initFuncs( saFuncTableOox, STATIC_ARRAY_END( saFuncTableOox ), nMaxParam, bImportFilter );
     initFuncs( saFuncTableOdf, STATIC_ARRAY_END( saFuncTableOdf ), nMaxParam, bImportFilter );
 }
 

sc/source/filter/excel/excform.cxx

 	TokenId			nMerk0;
 	const sal_Bool		bRangeName = eFT == FT_RangeName;
 	const sal_Bool		bSharedFormula = eFT == FT_SharedFormula;
-	const sal_Bool		bRNorSF = bRangeName || bSharedFormula;
+	const sal_Bool		bConditional = eFT == FT_Conditional;
+	const sal_Bool		bRNorSF = bRangeName || bSharedFormula || bConditional;
 
 	ScSingleRefData		aSRD;
 	ScComplexRefData		aCRD;

sc/source/filter/excel/excform8.cxx

 	TokenId					nMerk0;
 	const sal_Bool				bRangeName = eFT == FT_RangeName;
 	const sal_Bool				bSharedFormula = eFT == FT_SharedFormula;
-	const sal_Bool				bRNorSF = bRangeName || bSharedFormula;
+	const sal_Bool		        bConditional = eFT == FT_Conditional;
+	const sal_Bool				bRNorSF = bRangeName || bSharedFormula || bConditional;
 
 	ScSingleRefData			aSRD;
 	ScComplexRefData			aCRD;

sc/source/filter/excel/xeformula.cxx

     if( mpParamInfo )
     {
         // move pointer to next entry, if something explicit follows
-        if( (static_cast<size_t>(mpParamInfo - mrFuncInfo.mpParamInfos + 1) < EXC_FUNCINFO_PARAMINFO_COUNT) && (mpParamInfo[ 1 ].meValid != EXC_PARAM_NONE) )
+        if( (static_cast< size_t >( mpParamInfo - mrFuncInfo.mpParamInfos + 1 ) < EXC_FUNCINFO_PARAMINFO_COUNT) && (mpParamInfo[ 1 ].meValid != EXC_PARAM_NONE) )
             ++mpParamInfo;
         // if last parameter type is 'Excel-only' or 'Calc-only', do not repeat it
         else if( IsExcelOnlyParam() || IsCalcOnlyParam() )
             mpParamInfo = 0;
+        // points to last info, but parameter pairs expected, move to previous info
+        else if( mrFuncInfo.IsParamPairs() )
+            --mpParamInfo;
         // otherwise: repeat last parameter class
     }
 }

sc/source/filter/excel/xicontent.cxx

     {
         const ScTokenArray* pTokArr = 0;
         rFmlaConv.Reset( rPos );
-        rFmlaConv.Convert( pTokArr, rStrm, nFmlaSize1, false, FT_RangeName );
+        rFmlaConv.Convert( pTokArr, rStrm, nFmlaSize1, false, FT_Conditional );
         // formula converter owns pTokArr -> create a copy of the token array
         if( pTokArr )
             xTokArr1.reset( pTokArr->Clone() );
     {
         const ScTokenArray* pTokArr = 0;
         rFmlaConv.Reset( rPos );
-        rFmlaConv.Convert( pTokArr, rStrm, nFmlaSize2, false, FT_RangeName );
+        rFmlaConv.Convert( pTokArr, rStrm, nFmlaSize2, false, FT_Conditional );
         // formula converter owns pTokArr -> create a copy of the token array
         if( pTokArr )
             pTokArr2.reset( pTokArr->Clone() );
         {
             const ScTokenArray* pTokArr = 0;
             rFmlaConv.Reset();
-            rFmlaConv.Convert( pTokArr, rStrm, nLen, false, FT_RangeName );
+            rFmlaConv.Convert( pTokArr, rStrm, nLen, false, FT_Conditional );
             // formula converter owns pTokArr -> create a copy of the token array
             if( pTokArr )
                 xTokArr1.reset( pTokArr->Clone() );
         {
             const ScTokenArray* pTokArr = 0;
             rFmlaConv.Reset();
-            rFmlaConv.Convert( pTokArr, rStrm, nLen, false, FT_RangeName );
+            rFmlaConv.Convert( pTokArr, rStrm, nLen, false, FT_Conditional );
             // formula converter owns pTokArr -> create a copy of the token array
             if( pTokArr )
                 xTokArr2.reset( pTokArr->Clone() );

sc/source/filter/excel/xlformula.cxx

     { ocEuroConvert,        255,    4,  6,  V, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, "EUROCONVERT" }
 };
 
+/** Functions new in OOXML. */
+static 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" ) }
+};
+
 #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 ) }
     EXC_FUNCENTRY_ODF( ocNoName,        1,  MX, 0,  "SKEWP" ),
     EXC_FUNCENTRY_ODF( ocUnichar,       1,  1,  0,  "UNICHAR" ),
     EXC_FUNCENTRY_ODF( ocUnicode,       1,  1,  0,  "UNICODE" ),
-    EXC_FUNCENTRY_ODF( ocNoName,        1,  MX, 0,  "XOR" )
+    EXC_FUNCENTRY_ODF( ocXor,           1,  MX, 0,  "XOR" )
 };
 
 #undef EXC_FUNCENTRY_ODF
         (this->*pFillFunc)( saFuncTable_5, STATIC_TABLE_END( saFuncTable_5 ) );
     if( eBiff >= EXC_BIFF8 )
         (this->*pFillFunc)( saFuncTable_8, STATIC_TABLE_END( saFuncTable_8 ) );
+    (this->*pFillFunc)( saFuncTable_Oox, STATIC_TABLE_END( saFuncTable_Oox ) );
     (this->*pFillFunc)( saFuncTable_Odf, STATIC_TABLE_END( saFuncTable_Odf ) );
 }
 
     {
         if( !::get_flag( pIt->mnFlags, EXC_FUNCFLAG_EXPORTONLY ) )
         {
-            maXclFuncMap[ pIt->mnXclFunc ] = pIt;
+            if( pIt->mnXclFunc != NOID )
+                maXclFuncMap[ pIt->mnXclFunc ] = pIt;
             if( pIt->IsMacroFunc() )
                 maXclMacroNameMap[ pIt->GetMacroFuncName() ] = pIt;
         }

sc/source/filter/inc/formel.hxx

 {
 	FT_CellFormula,
 	FT_RangeName,
-	FT_SharedFormula
+	FT_SharedFormula,
+	FT_Conditional
 };
 
 

sc/source/filter/inc/xlformula.hxx

 const sal_uInt8 EXC_FUNCFLAG_VOLATILE       = 0x01;     /// Result is volatile (e.g. NOW() function).
 const sal_uInt8 EXC_FUNCFLAG_IMPORTONLY     = 0x02;     /// Only used in import filter.
 const sal_uInt8 EXC_FUNCFLAG_EXPORTONLY     = 0x04;     /// Only used in export filter.
+const sal_uInt8 EXC_FUNCFLAG_PARAMPAIRS     = 0x08;     /// Optional parameters are expected to appear in pairs.
 
 // selected function IDs
 const sal_uInt16 EXC_FUNCID_IF              = 1;
 
     /** Returns true, if the function is volatile. */
     inline bool         IsVolatile() const { return ::get_flag( mnFlags, EXC_FUNCFLAG_VOLATILE ); }
+    /** Returns true, if optional parameters are expected to appear in pairs. */
+    inline bool         IsParamPairs() const { return ::get_flag( mnFlags, EXC_FUNCFLAG_PARAMPAIRS ); }
     /** Returns true, if the function parameter count is fixed. */
     inline bool         IsFixedParamCount() const { return (mnXclFunc != EXC_FUNCID_EXTERNCALL) && (mnMinParamCount == mnMaxParamCount); }
     /** Returns true, if the function is simulated by a macro call. */
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.