1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include "oox/xls/formulabase.hxx" 25 26 #include <map> 27 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 28 #include <com/sun/star/table/XCellRange.hpp> 29 #include <com/sun/star/sheet/AddressConvention.hpp> 30 #include <com/sun/star/sheet/ReferenceFlags.hpp> 31 #include <com/sun/star/sheet/SingleReference.hpp> 32 #include <com/sun/star/sheet/ComplexReference.hpp> 33 #include <com/sun/star/sheet/FormulaLanguage.hpp> 34 #include <com/sun/star/sheet/FormulaMapGroup.hpp> 35 #include <com/sun/star/sheet/FormulaMapGroupSpecialOffset.hpp> 36 #include <com/sun/star/sheet/XFormulaOpCodeMapper.hpp> 37 #include <com/sun/star/sheet/XFormulaParser.hpp> 38 #include <rtl/strbuf.hxx> 39 #include <rtl/ustrbuf.hxx> 40 #include "oox/core/filterbase.hxx" 41 #include "oox/helper/containerhelper.hxx" 42 #include "oox/xls/biffinputstream.hxx" 43 44 namespace oox { 45 namespace xls { 46 47 // ============================================================================ 48 49 using namespace ::com::sun::star::lang; 50 using namespace ::com::sun::star::sheet; 51 using namespace ::com::sun::star::table; 52 using namespace ::com::sun::star::uno; 53 54 using ::rtl::OString; 55 using ::rtl::OStringBuffer; 56 using ::rtl::OStringToOUString; 57 using ::rtl::OUString; 58 using ::rtl::OUStringBuffer; 59 using ::rtl::OUStringToOString; 60 61 // reference helpers ========================================================== 62 63 BinSingleRef2d::BinSingleRef2d() : 64 mnCol( 0 ), 65 mnRow( 0 ), 66 mbColRel( false ), 67 mbRowRel( false ) 68 { 69 } 70 71 void BinSingleRef2d::setBiff12Data( sal_uInt16 nCol, sal_Int32 nRow, bool bRelativeAsOffset ) 72 { 73 mnCol = nCol & BIFF12_TOK_REF_COLMASK; 74 mnRow = nRow & BIFF12_TOK_REF_ROWMASK; 75 mbColRel = getFlag( nCol, BIFF12_TOK_REF_COLREL ); 76 mbRowRel = getFlag( nCol, BIFF12_TOK_REF_ROWREL ); 77 if( bRelativeAsOffset && mbColRel && (mnCol > (BIFF12_TOK_REF_COLMASK >> 1)) ) 78 mnCol -= (BIFF12_TOK_REF_COLMASK + 1); 79 if( bRelativeAsOffset && mbRowRel && (mnRow > (BIFF12_TOK_REF_ROWMASK >> 1)) ) 80 mnRow -= (BIFF12_TOK_REF_ROWMASK + 1); 81 } 82 83 void BinSingleRef2d::setBiff2Data( sal_uInt8 nCol, sal_uInt16 nRow, bool bRelativeAsOffset ) 84 { 85 mnCol = nCol; 86 mnRow = nRow & BIFF_TOK_REF_ROWMASK; 87 mbColRel = getFlag( nRow, BIFF_TOK_REF_COLREL ); 88 mbRowRel = getFlag( nRow, BIFF_TOK_REF_ROWREL ); 89 if( bRelativeAsOffset && mbColRel && (mnCol >= 0x80) ) 90 mnCol -= 0x100; 91 if( bRelativeAsOffset && mbRowRel && (mnRow > (BIFF_TOK_REF_ROWMASK >> 1)) ) 92 mnRow -= (BIFF_TOK_REF_ROWMASK + 1); 93 } 94 95 void BinSingleRef2d::setBiff8Data( sal_uInt16 nCol, sal_uInt16 nRow, bool bRelativeAsOffset ) 96 { 97 mnCol = nCol & BIFF_TOK_REF_COLMASK; 98 mnRow = nRow; 99 mbColRel = getFlag( nCol, BIFF_TOK_REF_COLREL ); 100 mbRowRel = getFlag( nCol, BIFF_TOK_REF_ROWREL ); 101 if( bRelativeAsOffset && mbColRel && (mnCol > (BIFF_TOK_REF_COLMASK >> 1)) ) 102 mnCol -= (BIFF_TOK_REF_COLMASK + 1); 103 if( bRelativeAsOffset && mbRowRel && (mnRow >= 0x8000) ) 104 mnRow -= 0x10000; 105 } 106 107 void BinSingleRef2d::readBiff12Data( SequenceInputStream& rStrm, bool bRelativeAsOffset ) 108 { 109 sal_Int32 nRow; 110 sal_uInt16 nCol; 111 rStrm >> nRow >> nCol; 112 setBiff12Data( nCol, nRow, bRelativeAsOffset ); 113 } 114 115 void BinSingleRef2d::readBiff2Data( BiffInputStream& rStrm, bool bRelativeAsOffset ) 116 { 117 sal_uInt16 nRow; 118 sal_uInt8 nCol; 119 rStrm >> nRow >> nCol; 120 setBiff2Data( nCol, nRow, bRelativeAsOffset ); 121 } 122 123 void BinSingleRef2d::readBiff8Data( BiffInputStream& rStrm, bool bRelativeAsOffset ) 124 { 125 sal_uInt16 nRow, nCol; 126 rStrm >> nRow >> nCol; 127 setBiff8Data( nCol, nRow, bRelativeAsOffset ); 128 } 129 130 // ---------------------------------------------------------------------------- 131 132 void BinComplexRef2d::readBiff12Data( SequenceInputStream& rStrm, bool bRelativeAsOffset ) 133 { 134 sal_Int32 nRow1, nRow2; 135 sal_uInt16 nCol1, nCol2; 136 rStrm >> nRow1 >> nRow2 >> nCol1 >> nCol2; 137 maRef1.setBiff12Data( nCol1, nRow1, bRelativeAsOffset ); 138 maRef2.setBiff12Data( nCol2, nRow2, bRelativeAsOffset ); 139 } 140 141 void BinComplexRef2d::readBiff2Data( BiffInputStream& rStrm, bool bRelativeAsOffset ) 142 { 143 sal_uInt16 nRow1, nRow2; 144 sal_uInt8 nCol1, nCol2; 145 rStrm >> nRow1 >> nRow2 >> nCol1 >> nCol2; 146 maRef1.setBiff2Data( nCol1, nRow1, bRelativeAsOffset ); 147 maRef2.setBiff2Data( nCol2, nRow2, bRelativeAsOffset ); 148 } 149 150 void BinComplexRef2d::readBiff8Data( BiffInputStream& rStrm, bool bRelativeAsOffset ) 151 { 152 sal_uInt16 nRow1, nRow2, nCol1, nCol2; 153 rStrm >> nRow1 >> nRow2 >> nCol1 >> nCol2; 154 maRef1.setBiff8Data( nCol1, nRow1, bRelativeAsOffset ); 155 maRef2.setBiff8Data( nCol2, nRow2, bRelativeAsOffset ); 156 } 157 158 // token vector, sequence ===================================================== 159 160 ApiTokenVector::ApiTokenVector() 161 { 162 } 163 164 Any& ApiTokenVector::append( sal_Int32 nOpCode ) 165 { 166 resize( size() + 1 ); 167 back().OpCode = nOpCode; 168 return back().Data; 169 } 170 171 // token sequence iterator ==================================================== 172 173 ApiTokenIterator::ApiTokenIterator( const ApiTokenSequence& rTokens, sal_Int32 nSpacesOpCode, bool bSkipSpaces ) : 174 mpToken( rTokens.getConstArray() ), 175 mpTokenEnd( rTokens.getConstArray() + rTokens.getLength() ), 176 mnSpacesOpCode( nSpacesOpCode ), 177 mbSkipSpaces( bSkipSpaces ) 178 { 179 skipSpaces(); 180 } 181 182 ApiTokenIterator::ApiTokenIterator( const ApiTokenIterator& rIter, bool bSkipSpaces ) : 183 mpToken( rIter.mpToken ), 184 mpTokenEnd( rIter.mpTokenEnd ), 185 mnSpacesOpCode( rIter.mnSpacesOpCode ), 186 mbSkipSpaces( bSkipSpaces ) 187 { 188 skipSpaces(); 189 } 190 191 ApiTokenIterator& ApiTokenIterator::operator++() 192 { 193 if( is() ) 194 { 195 ++mpToken; 196 skipSpaces(); 197 } 198 return *this; 199 } 200 201 void ApiTokenIterator::skipSpaces() 202 { 203 if( mbSkipSpaces ) 204 while( is() && (mpToken->OpCode == mnSpacesOpCode) ) 205 ++mpToken; 206 } 207 208 // function data ============================================================== 209 210 namespace { 211 212 const size_t FUNCINFO_PARAMINFOCOUNT = 5; /// Number of parameter type entries. 213 214 const sal_uInt16 FUNCFLAG_VOLATILE = 0x0001; /// Result is volatile (e.g. NOW() function). 215 const sal_uInt16 FUNCFLAG_IMPORTONLY = 0x0002; /// Only used in import filter. 216 const sal_uInt16 FUNCFLAG_EXPORTONLY = 0x0004; /// Only used in export filter. 217 const sal_uInt16 FUNCFLAG_MACROCALL = 0x0008; /// Function is stored as macro call in Excel (_xlfn. prefix). OOXML name MUST exist. 218 const sal_uInt16 FUNCFLAG_MACROCALLODF = 0x0010; /// ODF-only function stored as macro call in Excel (_xlfnodf. prefix). ODF name MUST exist. 219 const sal_uInt16 FUNCFLAG_EXTERNAL = 0x0020; /// Function is external in Calc. 220 const sal_uInt16 FUNCFLAG_MACROFUNC = 0x0040; /// Function is a macro-sheet function. 221 const sal_uInt16 FUNCFLAG_MACROCMD = 0x0080; /// Function is a macro-sheet command. 222 const sal_uInt16 FUNCFLAG_ALWAYSVAR = 0x0100; /// Function is always represented by a tFuncVar token. 223 const sal_uInt16 FUNCFLAG_PARAMPAIRS = 0x0200; /// Optional parameters are expected to appear in pairs. 224 225 /// Converts a function library index (value of enum FunctionLibraryType) to function flags. 226 #define FUNCLIB_TO_FUNCFLAGS( funclib_index ) static_cast< sal_uInt16 >( static_cast< sal_uInt8 >( funclib_index ) << 12 ) 227 /// Extracts a function library index (value of enum FunctionLibraryType) from function flags. 228 #define FUNCFLAGS_TO_FUNCLIB( func_flags ) extractValue< FunctionLibraryType >( func_flags, 12, 4 ) 229 230 typedef ::boost::shared_ptr< FunctionInfo > FunctionInfoRef; 231 232 struct FunctionData 233 { 234 const sal_Char* mpcOdfFuncName; /// ODF function name. 235 const sal_Char* mpcOoxFuncName; /// OOXML function name. 236 sal_uInt16 mnBiff12FuncId; /// BIFF12 function identifier. 237 sal_uInt16 mnBiffFuncId; /// BIFF2-BIFF8 function identifier. 238 sal_uInt8 mnMinParamCount; /// Minimum number of parameters. 239 sal_uInt8 mnMaxParamCount; /// Maximum number of parameters. 240 sal_uInt8 mnRetClass; /// BIFF token class of the return value. 241 FunctionParamInfo mpParamInfos[ FUNCINFO_PARAMINFOCOUNT ]; /// Information about all parameters. 242 sal_uInt16 mnFlags; /// Additional flags. 243 244 inline bool isSupported( bool bImportFilter ) const; 245 }; 246 247 inline bool FunctionData::isSupported( bool bImportFilter ) const 248 { 249 /* For import filters: the FUNCFLAG_EXPORTONLY flag must not be set, 250 for export filters: the FUNCFLAG_IMPORTONLY flag must not be set. */ 251 return !getFlag( mnFlags, bImportFilter ? FUNCFLAG_EXPORTONLY : FUNCFLAG_IMPORTONLY ); 252 } 253 254 const sal_uInt16 NOID = SAL_MAX_UINT16; /// No BIFF function identifier available. 255 const sal_uInt8 MX = SAL_MAX_UINT8; /// Maximum parameter count. 256 257 // abbreviations for function return token class 258 const sal_uInt8 R = BIFF_TOKCLASS_REF; 259 const sal_uInt8 V = BIFF_TOKCLASS_VAL; 260 const sal_uInt8 A = BIFF_TOKCLASS_ARR; 261 262 // abbreviations for parameter infos 263 #define RO { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_ORG, false } 264 #define RV { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_VAL, false } 265 #define RA { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_ARR, false } 266 #define RR { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_RPT, false } 267 #define RX { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_RPX, false } 268 #define VO { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_ORG, true } 269 #define VV { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_VAL, true } 270 #define VA { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_ARR, true } 271 #define VR { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_RPT, true } 272 #define VX { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_RPX, true } 273 #define RO_E { FUNC_PARAM_EXCELONLY, FUNC_PARAMCONV_ORG, false } 274 #define VR_E { FUNC_PARAM_EXCELONLY, FUNC_PARAMCONV_RPT, true } 275 #define C { FUNC_PARAM_CALCONLY, FUNC_PARAMCONV_ORG, false } 276 277 // Note: parameter types of all macro sheet functions (FUNCFLAG_MACROFUNC/FUNCFLAG_MACROCMD) untested! 278 279 /** Functions new in BIFF2. */ 280 static const FunctionData saFuncTableBiff2[] = 281 { 282 { "COUNT", "COUNT", 0, 0, 0, MX, V, { RX }, 0 }, 283 { "IF", "IF", 1, 1, 2, 3, R, { VO, RO }, 0 }, 284 { "ISNA", "ISNA", 2, 2, 1, 1, V, { VR }, 0 }, 285 { "ISERROR", "ISERROR", 3, 3, 1, 1, V, { VR }, 0 }, 286 { "SUM", "SUM", 4, 4, 0, MX, V, { RX }, 0 }, 287 { "AVERAGE", "AVERAGE", 5, 5, 1, MX, V, { RX }, 0 }, 288 { "MIN", "MIN", 6, 6, 1, MX, V, { RX }, 0 }, 289 { "MAX", "MAX", 7, 7, 1, MX, V, { RX }, 0 }, 290 { "ROW", "ROW", 8, 8, 0, 1, V, { RO }, 0 }, 291 { "COLUMN", "COLUMN", 9, 9, 0, 1, V, { RO }, 0 }, 292 { "NA", "NA", 10, 10, 0, 0, V, {}, 0 }, 293 { "NPV", "NPV", 11, 11, 2, MX, V, { VR, RX }, 0 }, 294 { "STDEV", "STDEV", 12, 12, 1, MX, V, { RX }, 0 }, 295 { "DOLLAR", "DOLLAR", 13, 13, 1, 2, V, { VR }, 0 }, 296 { "FIXED", "FIXED", 14, 14, 1, 2, V, { VR, VR, C }, 0 }, 297 { "SIN", "SIN", 15, 15, 1, 1, V, { VR }, 0 }, 298 { "CSC", "SIN", 15, 15, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY }, 299 { "COS", "COS", 16, 16, 1, 1, V, { VR }, 0 }, 300 { "SEC", "COS", 16, 16, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY }, 301 { "TAN", "TAN", 17, 17, 1, 1, V, { VR }, 0 }, 302 { "COT", "TAN", 17, 17, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY }, 303 { "ATAN", "ATAN", 18, 18, 1, 1, V, { VR }, 0 }, 304 { "ACOT", "ATAN", 18, 18, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY }, 305 { "PI", "PI", 19, 19, 0, 0, V, {}, 0 }, 306 { "SQRT", "SQRT", 20, 20, 1, 1, V, { VR }, 0 }, 307 { "EXP", "EXP", 21, 21, 1, 1, V, { VR }, 0 }, 308 { "LN", "LN", 22, 22, 1, 1, V, { VR }, 0 }, 309 { "LOG10", "LOG10", 23, 23, 1, 1, V, { VR }, 0 }, 310 { "ABS", "ABS", 24, 24, 1, 1, V, { VR }, 0 }, 311 { "INT", "INT", 25, 25, 1, 1, V, { VR }, 0 }, 312 { "SIGN", "SIGN", 26, 26, 1, 1, V, { VR }, 0 }, 313 { "ROUND", "ROUND", 27, 27, 2, 2, V, { VR }, 0 }, 314 { "LOOKUP", "LOOKUP", 28, 28, 2, 3, V, { VR, RA }, 0 }, 315 { "INDEX", "INDEX", 29, 29, 2, 4, R, { RA, VV }, 0 }, 316 { "REPT", "REPT", 30, 30, 2, 2, V, { VR }, 0 }, 317 { "MID", "MID", 31, 31, 3, 3, V, { VR }, 0 }, 318 { "LEN", "LEN", 32, 32, 1, 1, V, { VR }, 0 }, 319 { "VALUE", "VALUE", 33, 33, 1, 1, V, { VR }, 0 }, 320 { "TRUE", "TRUE", 34, 34, 0, 0, V, {}, 0 }, 321 { "FALSE", "FALSE", 35, 35, 0, 0, V, {}, 0 }, 322 { "AND", "AND", 36, 36, 1, MX, V, { RX }, 0 }, 323 { "OR", "OR", 37, 37, 1, MX, V, { RX }, 0 }, 324 { "NOT", "NOT", 38, 38, 1, 1, V, { VR }, 0 }, 325 { "MOD", "MOD", 39, 39, 2, 2, V, { VR }, 0 }, 326 { "DCOUNT", "DCOUNT", 40, 40, 3, 3, V, { RO, RR }, 0 }, 327 { "DSUM", "DSUM", 41, 41, 3, 3, V, { RO, RR }, 0 }, 328 { "DAVERAGE", "DAVERAGE", 42, 42, 3, 3, V, { RO, RR }, 0 }, 329 { "DMIN", "DMIN", 43, 43, 3, 3, V, { RO, RR }, 0 }, 330 { "DMAX", "DMAX", 44, 44, 3, 3, V, { RO, RR }, 0 }, 331 { "DSTDEV", "DSTDEV", 45, 45, 3, 3, V, { RO, RR }, 0 }, 332 { "VAR", "VAR", 46, 46, 1, MX, V, { RX }, 0 }, 333 { "DVAR", "DVAR", 47, 47, 3, 3, V, { RO, RR }, 0 }, 334 { "TEXT", "TEXT", 48, 48, 2, 2, V, { VR }, 0 }, 335 { "LINEST", "LINEST", 49, 49, 1, 2, A, { RA, RA, C, C }, 0 }, 336 { "TREND", "TREND", 50, 50, 1, 3, A, { RA, RA, RA, C }, 0 }, 337 { "LOGEST", "LOGEST", 51, 51, 1, 2, A, { RA, RA, C, C }, 0 }, 338 { "GROWTH", "GROWTH", 52, 52, 1, 3, A, { RA, RA, RA, C }, 0 }, 339 { "PV", "PV", 56, 56, 3, 5, V, { VR }, 0 }, 340 { "FV", "FV", 57, 57, 3, 5, V, { VR }, 0 }, 341 { "NPER", "NPER", 58, 58, 3, 5, V, { VR }, 0 }, 342 { "PMT", "PMT", 59, 59, 3, 5, V, { VR }, 0 }, 343 { "RATE", "RATE", 60, 60, 3, 6, V, { VR }, 0 }, 344 { "MIRR", "MIRR", 61, 61, 3, 3, V, { RA, VR }, 0 }, 345 { "IRR", "IRR", 62, 62, 1, 2, V, { RA, VR }, 0 }, 346 { "RAND", "RAND", 63, 63, 0, 0, V, {}, FUNCFLAG_VOLATILE }, 347 { "MATCH", "MATCH", 64, 64, 2, 3, V, { VR, RX, RR }, 0 }, 348 { "DATE", "DATE", 65, 65, 3, 3, V, { VR }, 0 }, 349 { "TIME", "TIME", 66, 66, 3, 3, V, { VR }, 0 }, 350 { "DAY", "DAY", 67, 67, 1, 1, V, { VR }, 0 }, 351 { "MONTH", "MONTH", 68, 68, 1, 1, V, { VR }, 0 }, 352 { "YEAR", "YEAR", 69, 69, 1, 1, V, { VR }, 0 }, 353 { "WEEKDAY", "WEEKDAY", 70, 70, 1, 1, V, { VR, C }, 0 }, 354 { "HOUR", "HOUR", 71, 71, 1, 1, V, { VR }, 0 }, 355 { "MINUTE", "MINUTE", 72, 72, 1, 1, V, { VR }, 0 }, 356 { "SECOND", "SECOND", 73, 73, 1, 1, V, { VR }, 0 }, 357 { "NOW", "NOW", 74, 74, 0, 0, V, {}, FUNCFLAG_VOLATILE }, 358 { "AREAS", "AREAS", 75, 75, 1, 1, V, { RO }, 0 }, 359 { "ROWS", "ROWS", 76, 76, 1, 1, V, { RO }, 0 }, 360 { "COLUMNS", "COLUMNS", 77, 77, 1, 1, V, { RO }, 0 }, 361 { "OFFSET", "OFFSET", 78, 78, 3, 5, R, { RO, VR }, FUNCFLAG_VOLATILE }, 362 { "SEARCH", "SEARCH", 82, 82, 2, 3, V, { VR }, 0 }, 363 { "TRANSPOSE", "TRANSPOSE", 83, 83, 1, 1, A, { VO }, 0 }, 364 { "TYPE", "TYPE", 86, 86, 1, 1, V, { VX }, 0 }, 365 { "ATAN2", "ATAN2", 97, 97, 2, 2, V, { VR }, 0 }, 366 { "ASIN", "ASIN", 98, 98, 1, 1, V, { VR }, 0 }, 367 { "ACOS", "ACOS", 99, 99, 1, 1, V, { VR }, 0 }, 368 { "CHOOSE", "CHOOSE", 100, 100, 2, MX, R, { VO, RO }, 0 }, 369 { "HLOOKUP", "HLOOKUP", 101, 101, 3, 3, V, { VV, RO, RO, C }, 0 }, 370 { "VLOOKUP", "VLOOKUP", 102, 102, 3, 3, V, { VV, RO, RO, C }, 0 }, 371 { "ISREF", "ISREF", 105, 105, 1, 1, V, { RX }, 0 }, 372 { "LOG", "LOG", 109, 109, 1, 2, V, { VR }, 0 }, 373 { "CHAR", "CHAR", 111, 111, 1, 1, V, { VR }, 0 }, 374 { "LOWER", "LOWER", 112, 112, 1, 1, V, { VR }, 0 }, 375 { "UPPER", "UPPER", 113, 113, 1, 1, V, { VR }, 0 }, 376 { "PROPER", "PROPER", 114, 114, 1, 1, V, { VR }, 0 }, 377 { "LEFT", "LEFT", 115, 115, 1, 2, V, { VR }, 0 }, 378 { "RIGHT", "RIGHT", 116, 116, 1, 2, V, { VR }, 0 }, 379 { "EXACT", "EXACT", 117, 117, 2, 2, V, { VR }, 0 }, 380 { "TRIM", "TRIM", 118, 118, 1, 1, V, { VR }, 0 }, 381 { "REPLACE", "REPLACE", 119, 119, 4, 4, V, { VR }, 0 }, 382 { "SUBSTITUTE", "SUBSTITUTE", 120, 120, 3, 4, V, { VR }, 0 }, 383 { "CODE", "CODE", 121, 121, 1, 1, V, { VR }, 0 }, 384 { "FIND", "FIND", 124, 124, 2, 3, V, { VR }, 0 }, 385 { "CELL", "CELL", 125, 125, 1, 2, V, { VV, RO }, FUNCFLAG_VOLATILE }, 386 { "ISERR", "ISERR", 126, 126, 1, 1, V, { VR }, 0 }, 387 { "ISTEXT", "ISTEXT", 127, 127, 1, 1, V, { VR }, 0 }, 388 { "ISNUMBER", "ISNUMBER", 128, 128, 1, 1, V, { VR }, 0 }, 389 { "ISBLANK", "ISBLANK", 129, 129, 1, 1, V, { VR }, 0 }, 390 { "T", "T", 130, 130, 1, 1, V, { RO }, 0 }, 391 { "N", "N", 131, 131, 1, 1, V, { RO }, 0 }, 392 { "DATEVALUE", "DATEVALUE", 140, 140, 1, 1, V, { VR }, 0 }, 393 { "TIMEVALUE", "TIMEVALUE", 141, 141, 1, 1, V, { VR }, 0 }, 394 { "SLN", "SLN", 142, 142, 3, 3, V, { VR }, 0 }, 395 { "SYD", "SYD", 143, 143, 4, 4, V, { VR }, 0 }, 396 { "DDB", "DDB", 144, 144, 4, 5, V, { VR }, 0 }, 397 { "INDIRECT", "INDIRECT", 148, 148, 1, 2, R, { VR }, FUNCFLAG_VOLATILE }, 398 { "CLEAN", "CLEAN", 162, 162, 1, 1, V, { VR }, 0 }, 399 { "MDETERM", "MDETERM", 163, 163, 1, 1, V, { VA }, 0 }, 400 { "MINVERSE", "MINVERSE", 164, 164, 1, 1, A, { VA }, 0 }, 401 { "MMULT", "MMULT", 165, 165, 2, 2, A, { VA }, 0 }, 402 { "IPMT", "IPMT", 167, 167, 4, 6, V, { VR }, 0 }, 403 { "PPMT", "PPMT", 168, 168, 4, 6, V, { VR }, 0 }, 404 { "COUNTA", "COUNTA", 169, 169, 0, MX, V, { RX }, 0 }, 405 { "PRODUCT", "PRODUCT", 183, 183, 0, MX, V, { RX }, 0 }, 406 { "FACT", "FACT", 184, 184, 1, 1, V, { VR }, 0 }, 407 { "DPRODUCT", "DPRODUCT", 189, 189, 3, 3, V, { RO, RR }, 0 }, 408 { "ISNONTEXT", "ISNONTEXT", 190, 190, 1, 1, V, { VR }, 0 }, 409 { "STDEVP", "STDEVP", 193, 193, 1, MX, V, { RX }, 0 }, 410 { "VARP", "VARP", 194, 194, 1, MX, V, { RX }, 0 }, 411 { "DSTDEVP", "DSTDEVP", 195, 195, 3, 3, V, { RO, RR }, 0 }, 412 { "DVARP", "DVARP", 196, 196, 3, 3, V, { RO, RR }, 0 }, 413 { "TRUNC", "TRUNC", 197, 197, 1, 1, V, { VR, C }, 0 }, 414 { "ISLOGICAL", "ISLOGICAL", 198, 198, 1, 1, V, { VR }, 0 }, 415 { "DCOUNTA", "DCOUNTA", 199, 199, 3, 3, V, { RO, RR }, 0 }, 416 { 0, "EXTERN.CALL", 255, 255, 1, MX, R, { RO_E, RO }, FUNCFLAG_IMPORTONLY }, 417 418 // *** macro sheet commands *** 419 420 { 0, "A1.R1C1", 30, 30, 0, 1, V, { VR }, FUNCFLAG_MACROCMD }, 421 { 0, "RETURN", 55, 55, 0, 1, R, { RO }, FUNCFLAG_MACROFUNC }, 422 { 0, "ABSREF", 79, 79, 2, 2, R, { VR, RO }, FUNCFLAG_MACROFUNC }, 423 { 0, "ADD.ARROW", 81, 81, 0, 0, V, {}, FUNCFLAG_MACROCMD }, 424 { 0, "ACTIVE.CELL", 94, 94, 0, 0, R, {}, FUNCFLAG_MACROFUNC }, 425 { 0, "ACTIVATE", 103, 103, 0, 2, V, { VR }, FUNCFLAG_MACROCMD }, 426 { 0, "ACTIVATE.NEXT", 104, 104, 0, 0, V, {}, FUNCFLAG_MACROCMD }, 427 { 0, "ACTIVATE.PREV", 105, 105, 0, 0, V, {}, FUNCFLAG_MACROCMD }, 428 { 0, "ADD.BAR", 151, 151, 0, 0, V, {}, FUNCFLAG_MACROFUNC | FUNCFLAG_ALWAYSVAR }, 429 { 0, "ADD.MENU", 152, 152, 2, 2, V, { VR, RO }, FUNCFLAG_MACROFUNC | FUNCFLAG_ALWAYSVAR }, 430 { 0, "ADD.COMMAND", 153, 153, 3, 3, V, { VR, RO }, FUNCFLAG_MACROFUNC | FUNCFLAG_ALWAYSVAR } 431 }; 432 433 /** Functions new in BIFF3. */ 434 static const FunctionData saFuncTableBiff3[] = 435 { 436 { "LINEST", "LINEST", 49, 49, 1, 4, A, { RA, RA, VV }, 0 }, // BIFF2: 1-2, BIFF3: 1-4 437 { "TREND", "TREND", 50, 50, 1, 4, A, { RA, RA, RA, VV }, 0 }, // BIFF2: 1-3, BIFF3: 1-4 438 { "LOGEST", "LOGEST", 51, 51, 1, 4, A, { RA, RA, VV }, 0 }, // BIFF2: 1-2, BIFF3: 1-4 439 { "GROWTH", "GROWTH", 52, 52, 1, 4, A, { RA, RA, RA, VV }, 0 }, // BIFF2: 1-3, BIFF3: 1-4 440 { "TRUNC", "TRUNC", 197, 197, 1, 2, V, { VR }, 0 }, // BIFF2: 1, BIFF3: 1-2 441 { "DOLLAR", "USDOLLAR", 204, 204, 1, 2, V, { VR }, FUNCFLAG_IMPORTONLY }, 442 { 0/*"FIND"*/, "FINDB", 205, 205, 2, 3, V, { VR }, 0 }, 443 { 0/*"SEARCH"*/, "SEARCHB", 206, 206, 2, 3, V, { VR }, 0 }, 444 { 0/*"REPLACE"*/, "REPLACEB", 207, 207, 4, 4, V, { VR }, 0 }, 445 { 0/*"LEFT"*/, "LEFTB", 208, 208, 1, 2, V, { VR }, 0 }, 446 { 0/*"RIGHT"*/, "RIGHTB", 209, 209, 1, 2, V, { VR }, 0 }, 447 { 0/*"MID"*/, "MIDB", 210, 210, 3, 3, V, { VR }, 0 }, 448 { 0/*"LEN"*/, "LENB", 211, 211, 1, 1, V, { VR }, 0 }, 449 { "ROUNDUP", "ROUNDUP", 212, 212, 2, 2, V, { VR }, 0 }, 450 { "ROUNDDOWN", "ROUNDDOWN", 213, 213, 2, 2, V, { VR }, 0 }, 451 { "ASC", "ASC", 214, 214, 1, 1, V, { VR }, 0 }, 452 { "JIS", "DBCS", 215, 215, 1, 1, V, { VR }, 0 }, 453 { "ADDRESS", "ADDRESS", 219, 219, 2, 5, V, { VR }, 0 }, 454 { "DAYS360", "DAYS360", 220, 220, 2, 2, V, { VR, VR, C }, 0 }, 455 { "TODAY", "TODAY", 221, 221, 0, 0, V, {}, FUNCFLAG_VOLATILE }, 456 { "VDB", "VDB", 222, 222, 5, 7, V, { VR }, 0 }, 457 { "MEDIAN", "MEDIAN", 227, 227, 1, MX, V, { RX }, 0 }, 458 { "SUMPRODUCT", "SUMPRODUCT", 228, 228, 1, MX, V, { VA }, 0 }, 459 { "SINH", "SINH", 229, 229, 1, 1, V, { VR }, 0 }, 460 { "CSCH", "SINH", 229, 229, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY }, 461 { "COSH", "COSH", 230, 230, 1, 1, V, { VR }, 0 }, 462 { "SECH", "COSH", 230, 230, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY }, 463 { "TANH", "TANH", 231, 231, 1, 1, V, { VR }, 0 }, 464 { "COTH", "TANH", 231, 231, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY }, 465 { "ASINH", "ASINH", 232, 232, 1, 1, V, { VR }, 0 }, 466 { "ACOSH", "ACOSH", 233, 233, 1, 1, V, { VR }, 0 }, 467 { "ATANH", "ATANH", 234, 234, 1, 1, V, { VR }, 0 }, 468 { "ACOTH", "ATANH", 234, 234, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY }, 469 { "DGET", "DGET", 235, 235, 3, 3, V, { RO, RR }, 0 }, 470 { "INFO", "INFO", 244, 244, 1, 1, V, { VR }, FUNCFLAG_VOLATILE }, 471 472 // *** macro sheet commands *** 473 474 { 0, "ADD.BAR", 151, 151, 0, 1, V, { VR }, FUNCFLAG_MACROFUNC }, // BIFF2: 0, BIFF3: 0-1 475 { 0, "ADD.MENU", 152, 152, 2, 3, V, { VR, RO }, FUNCFLAG_MACROFUNC }, // BIFF2: 2, BIFF3: 2-3 476 { 0, "ADD.COMMAND", 153, 153, 3, 4, V, { VR, RO }, FUNCFLAG_MACROFUNC } // BIFF2: 3, BIFF3: 3-4 477 }; 478 479 /** Functions new in BIFF4. */ 480 static const FunctionData saFuncTableBiff4[] = 481 { 482 { "FIXED", "FIXED", 14, 14, 1, 3, V, { VR }, 0 }, // BIFF2-3: 1-2, BIFF4: 1-3 483 { "RANK", "RANK", 216, 216, 2, 3, V, { VR, RO, VR }, 0 }, 484 { "DB", "DB", 247, 247, 4, 5, V, { VR }, 0 }, 485 { "FREQUENCY", "FREQUENCY", 252, 252, 2, 2, A, { RA }, 0 }, 486 { "ORG.OPENOFFICE.ERRORTYPE","ERROR.TYPE", 261, 261, 1, 1, V, { VR }, 0 }, 487 { "AVEDEV", "AVEDEV", 269, 269, 1, MX, V, { RX }, 0 }, 488 { "BETADIST", "BETADIST", 270, 270, 3, 5, V, { VR }, 0 }, 489 { "GAMMALN", "GAMMALN", 271, 271, 1, 1, V, { VR }, 0 }, 490 { "BETAINV", "BETAINV", 272, 272, 3, 5, V, { VR }, 0 }, 491 { "BINOMDIST", "BINOMDIST", 273, 273, 4, 4, V, { VR }, 0 }, 492 { "LEGACY.CHIDIST", "CHIDIST", 274, 274, 2, 2, V, { VR }, 0 }, 493 { "LEGACY.CHIINV", "CHIINV", 275, 275, 2, 2, V, { VR }, 0 }, 494 { "COMBIN", "COMBIN", 276, 276, 2, 2, V, { VR }, 0 }, 495 { "CONFIDENCE", "CONFIDENCE", 277, 277, 3, 3, V, { VR }, 0 }, 496 { "CRITBINOM", "CRITBINOM", 278, 278, 3, 3, V, { VR }, 0 }, 497 { "EVEN", "EVEN", 279, 279, 1, 1, V, { VR }, 0 }, 498 { "EXPONDIST", "EXPONDIST", 280, 280, 3, 3, V, { VR }, 0 }, 499 { "LEGACY.FDIST", "FDIST", 281, 281, 3, 3, V, { VR }, 0 }, 500 { "LEGACY.FINV", "FINV", 282, 282, 3, 3, V, { VR }, 0 }, 501 { "FISHER", "FISHER", 283, 283, 1, 1, V, { VR }, 0 }, 502 { "FISHERINV", "FISHERINV", 284, 284, 1, 1, V, { VR }, 0 }, 503 { "FLOOR", "FLOOR", 285, 285, 2, 2, V, { VR, VR, C }, 0 }, 504 { "GAMMADIST", "GAMMADIST", 286, 286, 4, 4, V, { VR }, 0 }, 505 { "GAMMAINV", "GAMMAINV", 287, 287, 3, 3, V, { VR }, 0 }, 506 { "CEILING", "CEILING", 288, 288, 2, 2, V, { VR, VR, C }, 0 }, 507 { "HYPGEOMDIST", "HYPGEOMDIST", 289, 289, 4, 4, V, { VR }, 0 }, 508 { "LOGNORMDIST", "LOGNORMDIST", 290, 290, 3, 3, V, { VR }, 0 }, 509 { "LOGINV", "LOGINV", 291, 291, 3, 3, V, { VR }, 0 }, 510 { "NEGBINOMDIST", "NEGBINOMDIST", 292, 292, 3, 3, V, { VR }, 0 }, 511 { "NORMDIST", "NORMDIST", 293, 293, 4, 4, V, { VR }, 0 }, 512 { "LEGACY.NORMSDIST", "NORMSDIST", 294, 294, 1, 1, V, { VR }, 0 }, 513 { "NORMINV", "NORMINV", 295, 295, 3, 3, V, { VR }, 0 }, 514 { "LEGACY.NORMSINV", "NORMSINV", 296, 296, 1, 1, V, { VR }, 0 }, 515 { "STANDARDIZE", "STANDARDIZE", 297, 297, 3, 3, V, { VR }, 0 }, 516 { "ODD", "ODD", 298, 298, 1, 1, V, { VR }, 0 }, 517 { "PERMUT", "PERMUT", 299, 299, 2, 2, V, { VR }, 0 }, 518 { "POISSON", "POISSON", 300, 300, 3, 3, V, { VR }, 0 }, 519 { "TDIST", "TDIST", 301, 301, 3, 3, V, { VR }, 0 }, 520 { "WEIBULL", "WEIBULL", 302, 302, 4, 4, V, { VR }, 0 }, 521 { "SUMXMY2", "SUMXMY2", 303, 303, 2, 2, V, { VA }, 0 }, 522 { "SUMX2MY2", "SUMX2MY2", 304, 304, 2, 2, V, { VA }, 0 }, 523 { "SUMX2PY2", "SUMX2PY2", 305, 305, 2, 2, V, { VA }, 0 }, 524 { "LEGACY.CHITEST", "CHITEST", 306, 306, 2, 2, V, { VA }, 0 }, 525 { "CORREL", "CORREL", 307, 307, 2, 2, V, { VA }, 0 }, 526 { "COVAR", "COVAR", 308, 308, 2, 2, V, { VA }, 0 }, 527 { "FORECAST", "FORECAST", 309, 309, 3, 3, V, { VR, VA }, 0 }, 528 { "FTEST", "FTEST", 310, 310, 2, 2, V, { VA }, 0 }, 529 { "INTERCEPT", "INTERCEPT", 311, 311, 2, 2, V, { VA }, 0 }, 530 { "PEARSON", "PEARSON", 312, 312, 2, 2, V, { VA }, 0 }, 531 { "RSQ", "RSQ", 313, 313, 2, 2, V, { VA }, 0 }, 532 { "STEYX", "STEYX", 314, 314, 2, 2, V, { VA }, 0 }, 533 { "SLOPE", "SLOPE", 315, 315, 2, 2, V, { VA }, 0 }, 534 { "TTEST", "TTEST", 316, 316, 4, 4, V, { VA, VA, VR }, 0 }, 535 { "PROB", "PROB", 317, 317, 3, 4, V, { VA, VA, VR }, 0 }, 536 { "DEVSQ", "DEVSQ", 318, 318, 1, MX, V, { RX }, 0 }, 537 { "GEOMEAN", "GEOMEAN", 319, 319, 1, MX, V, { RX }, 0 }, 538 { "HARMEAN", "HARMEAN", 320, 320, 1, MX, V, { RX }, 0 }, 539 { "SUMSQ", "SUMSQ", 321, 321, 0, MX, V, { RX }, 0 }, 540 { "KURT", "KURT", 322, 322, 1, MX, V, { RX }, 0 }, 541 { "SKEW", "SKEW", 323, 323, 1, MX, V, { RX }, 0 }, 542 { "ZTEST", "ZTEST", 324, 324, 2, 3, V, { RX, VR }, 0 }, 543 { "LARGE", "LARGE", 325, 325, 2, 2, V, { RX, VR }, 0 }, 544 { "SMALL", "SMALL", 326, 326, 2, 2, V, { RX, VR }, 0 }, 545 { "QUARTILE", "QUARTILE", 327, 327, 2, 2, V, { RX, VR }, 0 }, 546 { "PERCENTILE", "PERCENTILE", 328, 328, 2, 2, V, { RX, VR }, 0 }, 547 { "PERCENTRANK", "PERCENTRANK", 329, 329, 2, 3, V, { RX, VR, VR_E }, 0 }, 548 { "MODE", "MODE", 330, 330, 1, MX, V, { VA }, 0 }, 549 { "TRIMMEAN", "TRIMMEAN", 331, 331, 2, 2, V, { RX, VR }, 0 }, 550 { "TINV", "TINV", 332, 332, 2, 2, V, { VR }, 0 }, 551 552 // *** Analysis add-in *** 553 554 { "HEX2BIN", "HEX2BIN", 384, NOID, 1, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 555 { "HEX2DEC", "HEX2DEC", 385, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 556 { "HEX2OCT", "HEX2OCT", 386, NOID, 1, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 557 { "DEC2BIN", "DEC2BIN", 387, NOID, 1, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 558 { "DEC2HEX", "DEC2HEX", 388, NOID, 1, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 559 { "DEC2OCT", "DEC2OCT", 389, NOID, 1, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 560 { "OCT2BIN", "OCT2BIN", 390, NOID, 1, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 561 { "OCT2HEX", "OCT2HEX", 391, NOID, 1, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 562 { "OCT2DEC", "OCT2DEC", 392, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 563 { "BIN2DEC", "BIN2DEC", 393, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 564 { "BIN2OCT", "BIN2OCT", 394, NOID, 1, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 565 { "BIN2HEX", "BIN2HEX", 395, NOID, 1, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 566 { "IMSUB", "IMSUB", 396, NOID, 2, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 567 { "IMDIV", "IMDIV", 397, NOID, 2, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 568 { "IMPOWER", "IMPOWER", 398, NOID, 2, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 569 { "IMABS", "IMABS", 399, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 570 { "IMSQRT", "IMSQRT", 400, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 571 { "IMLN", "IMLN", 401, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 572 { "IMLOG2", "IMLOG2", 402, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 573 { "IMLOG10", "IMLOG10", 403, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 574 { "IMSIN", "IMSIN", 404, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 575 { "IMCOS", "IMCOS", 405, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 576 { "IMEXP", "IMEXP", 406, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 577 { "IMARGUMENT", "IMARGUMENT", 407, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 578 { "IMCONJUGATE", "IMCONJUGATE", 408, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 579 { "IMAGINARY", "IMAGINARY", 409, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 580 { "IMREAL", "IMREAL", 410, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 581 { "COMPLEX", "COMPLEX", 411, NOID, 2, 3, V, { RR }, FUNCFLAG_EXTERNAL }, 582 { "IMSUM", "IMSUM", 412, NOID, 1, MX, V, { RX }, FUNCFLAG_EXTERNAL }, 583 { "IMPRODUCT", "IMPRODUCT", 413, NOID, 1, MX, V, { RX }, FUNCFLAG_EXTERNAL }, 584 { "SERIESSUM", "SERIESSUM", 414, NOID, 4, 4, V, { RR, RR, RR, RX }, FUNCFLAG_EXTERNAL }, 585 { "FACTDOUBLE", "FACTDOUBLE", 415, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 586 { "SQRTPI", "SQRTPI", 416, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 587 { "QUOTIENT", "QUOTIENT", 417, NOID, 2, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 588 { "DELTA", "DELTA", 418, NOID, 1, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 589 { "GESTEP", "GESTEP", 419, NOID, 1, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 590 { "ISEVEN", "ISEVEN", 420, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in 591 { "ISODD", "ISODD", 421, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in 592 { "MROUND", "MROUND", 422, NOID, 2, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 593 { "ERF", "ERF", 423, NOID, 1, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 594 { "ERFC", "ERFC", 424, NOID, 1, 1, V, { RR }, FUNCFLAG_EXTERNAL }, 595 { "BESSELJ", "BESSELJ", 425, NOID, 2, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 596 { "BESSELK", "BESSELK", 426, NOID, 2, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 597 { "BESSELY", "BESSELY", 427, NOID, 2, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 598 { "BESSELI", "BESSELI", 428, NOID, 2, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 599 { "XIRR", "XIRR", 429, NOID, 2, 3, V, { RX, RX, RR }, FUNCFLAG_EXTERNAL }, 600 { "XNPV", "XNPV", 430, NOID, 3, 3, V, { RR, RX, RX }, FUNCFLAG_EXTERNAL }, 601 { "PRICEMAT", "PRICEMAT", 431, NOID, 5, 6, V, { RR }, FUNCFLAG_EXTERNAL }, 602 { "YIELDMAT", "YIELDMAT", 432, NOID, 5, 6, V, { RR }, FUNCFLAG_EXTERNAL }, 603 { "INTRATE", "INTRATE", 433, NOID, 4, 5, V, { RR }, FUNCFLAG_EXTERNAL }, 604 { "RECEIVED", "RECEIVED", 434, NOID, 4, 5, V, { RR }, FUNCFLAG_EXTERNAL }, 605 { "DISC", "DISC", 435, NOID, 4, 5, V, { RR }, FUNCFLAG_EXTERNAL }, 606 { "PRICEDISC", "PRICEDISC", 436, NOID, 4, 5, V, { RR }, FUNCFLAG_EXTERNAL }, 607 { "YIELDDISC", "YIELDDISC", 437, NOID, 4, 5, V, { RR }, FUNCFLAG_EXTERNAL }, 608 { "TBILLEQ", "TBILLEQ", 438, NOID, 3, 3, V, { RR }, FUNCFLAG_EXTERNAL }, 609 { "TBILLPRICE", "TBILLPRICE", 439, NOID, 3, 3, V, { RR }, FUNCFLAG_EXTERNAL }, 610 { "TBILLYIELD", "TBILLYIELD", 440, NOID, 3, 3, V, { RR }, FUNCFLAG_EXTERNAL }, 611 { "PRICE", "PRICE", 441, NOID, 6, 7, V, { RR }, FUNCFLAG_EXTERNAL }, 612 { "YIELD", "YIELD", 442, NOID, 6, 7, V, { RR }, FUNCFLAG_EXTERNAL }, 613 { "DOLLARDE", "DOLLARDE", 443, NOID, 2, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 614 { "DOLLARFR", "DOLLARFR", 444, NOID, 2, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 615 { "NOMINAL", "NOMINAL", 445, NOID, 2, 2, V, { RR }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in 616 { "EFFECT", "EFFECT", 446, NOID, 2, 2, V, { RR }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in 617 { "CUMPRINC", "CUMPRINC", 447, NOID, 6, 6, V, { RR }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in 618 { "CUMIPMT", "CUMIPMT", 448, NOID, 6, 6, V, { RR }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in 619 { "EDATE", "EDATE", 449, NOID, 2, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 620 { "EOMONTH", "EOMONTH", 450, NOID, 2, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 621 { "YEARFRAC", "YEARFRAC", 451, NOID, 2, 3, V, { RR }, FUNCFLAG_EXTERNAL }, 622 { "COUPDAYBS", "COUPDAYBS", 452, NOID, 3, 4, V, { RR }, FUNCFLAG_EXTERNAL }, 623 { "COUPDAYS", "COUPDAYS", 453, NOID, 3, 4, V, { RR }, FUNCFLAG_EXTERNAL }, 624 { "COUPDAYSNC", "COUPDAYSNC", 454, NOID, 3, 4, V, { RR }, FUNCFLAG_EXTERNAL }, 625 { "COUPNCD", "COUPNCD", 455, NOID, 3, 4, V, { RR }, FUNCFLAG_EXTERNAL }, 626 { "COUPNUM", "COUPNUM", 456, NOID, 3, 4, V, { RR }, FUNCFLAG_EXTERNAL }, 627 { "COUPPCD", "COUPPCD", 457, NOID, 3, 4, V, { RR }, FUNCFLAG_EXTERNAL }, 628 { "DURATION", "DURATION", 458, NOID, 5, 6, V, { RR }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in 629 { "MDURATION", "MDURATION", 459, NOID, 5, 6, V, { RR }, FUNCFLAG_EXTERNAL }, 630 { "ODDLPRICE", "ODDLPRICE", 460, NOID, 7, 8, V, { RR }, FUNCFLAG_EXTERNAL }, 631 { "ODDLYIELD", "ODDLYIELD", 461, NOID, 8, 9, V, { RR }, FUNCFLAG_EXTERNAL }, 632 { "ODDFPRICE", "ODDFPRICE", 462, NOID, 8, 9, V, { RR }, FUNCFLAG_EXTERNAL }, 633 { "ODDFYIELD", "ODDFYIELD", 463, NOID, 8, 9, V, { RR }, FUNCFLAG_EXTERNAL }, 634 { "RANDBETWEEN", "RANDBETWEEN", 464, NOID, 2, 2, V, { RR }, FUNCFLAG_VOLATILE | FUNCFLAG_EXTERNAL }, 635 { "WEEKNUM", "WEEKNUM", 465, NOID, 1, 2, V, { RR }, FUNCFLAG_EXTERNAL }, 636 { "AMORDEGRC", "AMORDEGRC", 466, NOID, 6, 7, V, { RR }, FUNCFLAG_EXTERNAL }, 637 { "AMORLINC", "AMORLINC", 467, NOID, 6, 7, V, { RR }, FUNCFLAG_EXTERNAL }, 638 { "CONVERT", "CONVERT", 468, NOID, 3, 3, V, { RR }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in 639 { "ACCRINT", "ACCRINT", 469, NOID, 6, 7, V, { RR }, FUNCFLAG_EXTERNAL }, 640 { "ACCRINTM", "ACCRINTM", 470, NOID, 4, 5, V, { RR }, FUNCFLAG_EXTERNAL }, 641 { "WORKDAY", "WORKDAY", 471, NOID, 2, 3, V, { RR, RR, RX, C }, FUNCFLAG_EXTERNAL }, 642 { "NETWORKDAYS", "NETWORKDAYS", 472, NOID, 2, 3, V, { RR, RR, RX, C }, FUNCFLAG_EXTERNAL }, 643 { "GCD", "GCD", 473, NOID, 1, MX, V, { RX }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in 644 { "MULTINOMIAL", "MULTINOMIAL", 474, NOID, 1, MX, V, { RX }, FUNCFLAG_EXTERNAL }, 645 { "LCM", "LCM", 475, NOID, 1, MX, V, { RX }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in 646 { "FVSCHEDULE", "FVSCHEDULE", 476, NOID, 2, 2, V, { RR, RX }, FUNCFLAG_EXTERNAL }, 647 648 // *** macro sheet commands *** 649 650 { 0, "ACTIVATE.NEXT", 104, 104, 0, 1, V, { VR }, FUNCFLAG_MACROCMD }, // BIFF2-3: 0, BIFF4: 0-1 651 { 0, "ACTIVATE.PREV", 105, 105, 0, 1, V, { VR }, FUNCFLAG_MACROCMD } // BIFF2-3: 0, BIFF4: 0-1 652 }; 653 654 /** Functions new in BIFF5/BIFF7. */ 655 static const FunctionData saFuncTableBiff5[] = 656 { 657 { "WEEKDAY", "WEEKDAY", 70, 70, 1, 2, V, { VR }, 0 }, // BIFF2-4: 1, BIFF5: 1-2 658 { "HLOOKUP", "HLOOKUP", 101, 101, 3, 4, V, { VV, RO, RO, VV }, 0 }, // BIFF2-4: 3, BIFF5: 3-4 659 { "VLOOKUP", "VLOOKUP", 102, 102, 3, 4, V, { VV, RO, RO, VV }, 0 }, // BIFF2-4: 3, BIFF5: 3-4 660 { "DAYS360", "DAYS360", 220, 220, 2, 3, V, { VR }, 0 }, // BIFF3-4: 2, BIFF5: 2-3 661 { 0, "EXTERN.CALL", 255, 255, 1, MX, R, { RO_E, RO }, FUNCFLAG_EXPORTONLY }, // MACRO or EXTERNAL 662 { "CONCATENATE", "CONCATENATE", 336, 336, 0, MX, V, { VR }, 0 }, 663 { "POWER", "POWER", 337, 337, 2, 2, V, { VR }, 0 }, 664 { "RADIANS", "RADIANS", 342, 342, 1, 1, V, { VR }, 0 }, 665 { "DEGREES", "DEGREES", 343, 343, 1, 1, V, { VR }, 0 }, 666 { "SUBTOTAL", "SUBTOTAL", 344, 344, 2, MX, V, { VR, RO }, 0 }, 667 { "SUMIF", "SUMIF", 345, 345, 2, 3, V, { RO, VR, RO }, 0 }, 668 { "COUNTIF", "COUNTIF", 346, 346, 2, 2, V, { RO, VR }, 0 }, 669 { "COUNTBLANK", "COUNTBLANK", 347, 347, 1, 1, V, { RO }, 0 }, 670 { "ISPMT", "ISPMT", 350, 350, 4, 4, V, { VR }, 0 }, 671 { 0, "DATEDIF", 351, 351, 3, 3, V, { VR }, FUNCFLAG_IMPORTONLY }, // not supported in Calc 672 { 0, "DATESTRING", 352, 352, 1, 1, V, { VR }, FUNCFLAG_IMPORTONLY }, // not supported in Calc, missing in OOXML spec 673 { 0, "NUMBERSTRING", 353, 353, 2, 2, V, { VR }, FUNCFLAG_IMPORTONLY }, // not supported in Calc, missing in OOXML spec 674 { "ROMAN", "ROMAN", 354, 354, 1, 2, V, { VR }, 0 }, 675 676 // *** EuroTool add-in *** 677 678 { "EUROCONVERT", "EUROCONVERT", NOID, NOID, 3, 5, V, { VR }, FUNCLIB_TO_FUNCFLAGS( FUNCLIB_EUROTOOL ) }, 679 680 // *** macro sheet commands *** 681 682 { 0, "ADD.MENU", 152, 152, 2, 4, V, { VR, RO, RO, VR }, FUNCFLAG_MACROFUNC }, // BIFF3-4: 2-3, BIFF5: 2-4 683 { 0, "ADD.COMMAND", 153, 153, 3, 5, V, { VR, RO, RO, RO, VR }, FUNCFLAG_MACROFUNC }, // BIFF3-4: 3-4, BIFF5: 3-5 684 { 0, "ADD.CHART.AUTOFORMAT", 390, 390, 0, 2, V, { VR }, FUNCFLAG_MACROCMD }, 685 { 0, "ADD.LIST.ITEM", 451, 451, 0, 2, V, { VR }, FUNCFLAG_MACROCMD }, 686 { 0, "ACTIVE.CELL.FONT", 476, 476, 0, 14, V, { VR }, FUNCFLAG_MACROCMD } 687 }; 688 689 /** Functions new in BIFF8. */ 690 static const FunctionData saFuncTableBiff8[] = 691 { 692 { "GETPIVOTDATA", "GETPIVOTDATA", 358, 358, 2, MX, V, { RR, RR, VR, VR }, FUNCFLAG_IMPORTONLY | FUNCFLAG_PARAMPAIRS }, 693 { "HYPERLINK", "HYPERLINK", 359, 359, 1, 2, V, { VV, VO }, 0 }, 694 { 0, "PHONETIC", 360, 360, 1, 1, V, { RO }, FUNCFLAG_IMPORTONLY }, 695 { "AVERAGEA", "AVERAGEA", 361, 361, 1, MX, V, { RX }, 0 }, 696 { "MAXA", "MAXA", 362, 362, 1, MX, V, { RX }, 0 }, 697 { "MINA", "MINA", 363, 363, 1, MX, V, { RX }, 0 }, 698 { "STDEVPA", "STDEVPA", 364, 364, 1, MX, V, { RX }, 0 }, 699 { "VARPA", "VARPA", 365, 365, 1, MX, V, { RX }, 0 }, 700 { "STDEVA", "STDEVA", 366, 366, 1, MX, V, { RX }, 0 }, 701 { "VARA", "VARA", 367, 367, 1, MX, V, { RX }, 0 }, 702 { "COM.MICROSOFT.BAHTTEXT", "BAHTTEXT", 368, 368, 1, 1, V, { VR }, FUNCFLAG_MACROCALL }, 703 { 0, "THAIDAYOFWEEK", 369, 369, 1, 1, V, { VR }, FUNCFLAG_MACROCALL }, 704 { 0, "THAIDIGIT", 370, 370, 1, 1, V, { VR }, FUNCFLAG_MACROCALL }, 705 { 0, "THAIMONTHOFYEAR", 371, 371, 1, 1, V, { VR }, FUNCFLAG_MACROCALL }, 706 { 0, "THAINUMSOUND", 372, 372, 1, 1, V, { VR }, FUNCFLAG_MACROCALL }, 707 { 0, "THAINUMSTRING", 373, 373, 1, 1, V, { VR }, FUNCFLAG_MACROCALL }, 708 { 0, "THAISTRINGLENGTH", 374, 374, 1, 1, V, { VR }, FUNCFLAG_MACROCALL }, 709 { 0, "ISTHAIDIGIT", 375, 375, 1, 1, V, { VR }, FUNCFLAG_MACROCALL }, 710 { 0, "ROUNDBAHTDOWN", 376, 376, 1, 1, V, { VR }, FUNCFLAG_MACROCALL }, 711 { 0, "ROUNDBAHTUP", 377, 377, 1, 1, V, { VR }, FUNCFLAG_MACROCALL }, 712 { 0, "THAIYEAR", 378, 378, 1, 1, V, { VR }, FUNCFLAG_MACROCALL }, 713 { 0, "RTD", 379, 379, 3, 3, A, { VR, VR, RO }, 0 } 714 }; 715 716 /** Functions new in OOXML. */ 717 static const FunctionData saFuncTableOox[] = 718 { 719 { 0, "CUBEVALUE", 380, NOID, 1, MX, V, { VR, RX }, 0 }, 720 { 0, "CUBEMEMBER", 381, NOID, 2, 3, V, { VR, RX, VR }, 0 }, 721 { 0, "CUBEMEMBERPROPERTY", 382, NOID, 3, 3, V, { VR }, 0 }, 722 { 0, "CUBERANKEDMEMBER", 383, NOID, 3, 4, V, { VR }, 0 }, 723 { 0, "CUBEKPIMEMBER", 477, NOID, 3, 4, V, { VR }, 0 }, 724 { 0, "CUBESET", 478, NOID, 2, 5, V, { VR, RX, VR }, 0 }, 725 { 0, "CUBESETCOUNT", 479, NOID, 1, 1, V, { VR }, 0 }, 726 { 0, "IFERROR", 480, NOID, 2, 2, V, { VO, RO }, 0 }, 727 { "COUNTIFS", "COUNTIFS", 481, NOID, 2, MX, V, { RO, VR }, FUNCFLAG_MACROCALL | FUNCFLAG_PARAMPAIRS }, 728 { "SUMIFS", "SUMIFS", 482, NOID, 3, MX, V, { RO, RO, VR }, FUNCFLAG_MACROCALL | FUNCFLAG_PARAMPAIRS }, 729 { "AVERAGEIF", "AVERAGEIF", 483, NOID, 2, 3, V, { RO, VR, RO }, FUNCFLAG_MACROCALL }, 730 { "AVERAGEIFS", "AVERAGEIFS", 484, NOID, 3, MX, V, { RO, RO, VR }, FUNCFLAG_MACROCALL | FUNCFLAG_PARAMPAIRS } 731 }; 732 733 /** Functions defined by OpenFormula, but not supported by Calc or by Excel. */ 734 static const FunctionData saFuncTableOdf[] = 735 { 736 { "ARABIC", 0, NOID, NOID, 1, 1, V, { VR }, FUNCFLAG_MACROCALLODF }, 737 { "B", 0, NOID, NOID, 3, 4, V, { VR }, FUNCFLAG_MACROCALLODF }, 738 { "BASE", 0, NOID, NOID, 2, 3, V, { VR }, FUNCFLAG_MACROCALLODF }, 739 { "BITAND", 0, NOID, NOID, 2, 2, V, { VR }, FUNCFLAG_MACROCALLODF }, 740 { "BITLSHIFT", 0, NOID, NOID, 2, 2, V, { VR }, FUNCFLAG_MACROCALLODF }, 741 { "BITOR", 0, NOID, NOID, 2, 2, V, { VR }, FUNCFLAG_MACROCALLODF }, 742 { "BITRSHIFT", 0, NOID, NOID, 2, 2, V, { VR }, FUNCFLAG_MACROCALLODF }, 743 { "BITXOR", 0, NOID, NOID, 2, 2, V, { VR }, FUNCFLAG_MACROCALLODF }, 744 { "CHISQDIST", 0, NOID, NOID, 2, 3, V, { VR }, FUNCFLAG_MACROCALLODF }, 745 { "CHISQINV", 0, NOID, NOID, 2, 2, V, { VR }, FUNCFLAG_MACROCALLODF }, 746 { "COMBINA", 0, NOID, NOID, 2, 2, V, { VR }, FUNCFLAG_MACROCALLODF }, 747 { "DAYS", 0, NOID, NOID, 2, 2, V, { VR }, FUNCFLAG_MACROCALLODF }, 748 { "DECIMAL", 0, NOID, NOID, 2, 2, V, { VR }, FUNCFLAG_MACROCALLODF }, 749 { "FDIST", 0, NOID, NOID, 3, 4, V, { VR }, FUNCFLAG_MACROCALLODF }, 750 { "FINV", 0, NOID, NOID, 3, 3, V, { VR }, FUNCFLAG_MACROCALLODF }, 751 { "FORMULA", 0, NOID, NOID, 1, 1, V, { RO }, FUNCFLAG_MACROCALLODF }, 752 { "GAMMA", 0, NOID, NOID, 1, 1, V, { VR }, FUNCFLAG_MACROCALLODF }, 753 { "GAUSS", 0, NOID, NOID, 1, 1, V, { VR }, FUNCFLAG_MACROCALLODF }, 754 { "IFNA", 0, NOID, NOID, 2, 2, V, { VR, RO }, FUNCFLAG_MACROCALLODF }, 755 { "ISFORMULA", 0, NOID, NOID, 1, 1, V, { RO }, FUNCFLAG_MACROCALLODF }, 756 { "ISOWEEKNUM", 0, NOID, NOID, 1, 2, V, { VR }, FUNCFLAG_MACROCALLODF }, 757 { "MUNIT", 0, NOID, NOID, 1, 1, A, { VR }, FUNCFLAG_MACROCALLODF }, 758 { "NUMBERVALUE", 0, NOID, NOID, 2, 2, V, { VR }, FUNCFLAG_MACROCALLODF }, 759 { "PDURATION", 0, NOID, NOID, 3, 3, V, { VR }, FUNCFLAG_MACROCALLODF }, 760 { "PERMUTATIONA", 0, NOID, NOID, 2, 2, V, { VR }, FUNCFLAG_MACROCALLODF }, 761 { "PHI", 0, NOID, NOID, 1, 1, V, { VR }, FUNCFLAG_MACROCALLODF }, 762 { "RRI", 0, NOID, NOID, 3, 3, V, { VR }, FUNCFLAG_MACROCALLODF }, 763 { "SHEET", 0, NOID, NOID, 0, 1, V, { RO }, FUNCFLAG_MACROCALLODF }, 764 { "SHEETS", 0, NOID, NOID, 0, 1, V, { RO }, FUNCFLAG_MACROCALLODF }, 765 { "SKEWP", 0, NOID, NOID, 1, MX, V, { RX }, FUNCFLAG_MACROCALLODF }, 766 { "UNICHAR", 0, NOID, NOID, 1, 1, V, { VR }, FUNCFLAG_MACROCALLODF }, 767 { "UNICODE", 0, NOID, NOID, 1, 1, V, { VR }, FUNCFLAG_MACROCALLODF }, 768 { "XOR", 0, NOID, NOID, 1, MX, V, { RX }, FUNCFLAG_MACROCALLODF } 769 }; 770 771 // ---------------------------------------------------------------------------- 772 773 const sal_Unicode API_TOKEN_OPEN = '('; 774 const sal_Unicode API_TOKEN_CLOSE = ')'; 775 const sal_Unicode API_TOKEN_SEP = ';'; 776 777 const sal_Unicode API_TOKEN_ARRAY_OPEN = '{'; 778 const sal_Unicode API_TOKEN_ARRAY_CLOSE = '}'; 779 const sal_Unicode API_TOKEN_ARRAY_ROWSEP = '|'; 780 const sal_Unicode API_TOKEN_ARRAY_COLSEP = ';'; 781 782 } // namespace 783 784 // function info parameter class iterator ===================================== 785 786 FunctionParamInfoIterator::FunctionParamInfoIterator( const FunctionInfo& rFuncInfo ) : 787 mpParamInfo( rFuncInfo.mpParamInfos ), 788 mpParamInfoEnd( rFuncInfo.mpParamInfos + FUNCINFO_PARAMINFOCOUNT ), 789 mbParamPairs( rFuncInfo.mbParamPairs ) 790 { 791 } 792 793 const FunctionParamInfo& FunctionParamInfoIterator::getParamInfo() const 794 { 795 static const FunctionParamInfo saInvalidInfo = { FUNC_PARAM_NONE, FUNC_PARAMCONV_ORG, false }; 796 return mpParamInfo ? *mpParamInfo : saInvalidInfo; 797 } 798 799 bool FunctionParamInfoIterator::isCalcOnlyParam() const 800 { 801 return mpParamInfo && (mpParamInfo->meValid == FUNC_PARAM_CALCONLY); 802 } 803 804 bool FunctionParamInfoIterator::isExcelOnlyParam() const 805 { 806 return mpParamInfo && (mpParamInfo->meValid == FUNC_PARAM_EXCELONLY); 807 } 808 809 FunctionParamInfoIterator& FunctionParamInfoIterator::operator++() 810 { 811 if( mpParamInfo ) 812 { 813 // move pointer to next entry, if something explicit follows 814 if( (mpParamInfo + 1 < mpParamInfoEnd) && (mpParamInfo[ 1 ].meValid != FUNC_PARAM_NONE) ) 815 ++mpParamInfo; 816 // if last parameter type is 'Excel-only' or 'Calc-only', do not repeat it 817 else if( isExcelOnlyParam() || isCalcOnlyParam() ) 818 mpParamInfo = 0; 819 // points to last info, but parameter pairs expected, move to previous info 820 else if( mbParamPairs ) 821 --mpParamInfo; 822 // otherwise: repeat last parameter class 823 } 824 return *this; 825 } 826 827 // function provider ========================================================== 828 829 struct FunctionProviderImpl 830 { 831 typedef RefMap< OUString, FunctionInfo > FuncNameMap; 832 typedef RefMap< sal_uInt16, FunctionInfo > FuncIdMap; 833 834 FunctionInfoVector maFuncs; /// All function infos in one list. 835 FuncNameMap maOdfFuncs; /// Maps ODF function names to function data. 836 FuncNameMap maOoxFuncs; /// Maps OOXML function names to function data. 837 FuncIdMap maBiff12Funcs; /// Maps BIFF12 function indexes to function data. 838 FuncIdMap maBiffFuncs; /// Maps BIFF2-BIFF8 function indexes to function data. 839 FuncNameMap maMacroFuncs; /// Maps macro function names to function data. 840 841 explicit FunctionProviderImpl( FilterType eFilter, BiffType eBiff, bool bImportFilter ); 842 843 private: 844 /** Creates and inserts a function info struct from the passed function data. */ 845 void initFunc( const FunctionData& rFuncData, sal_uInt8 nMaxParam ); 846 847 /** Initializes the members from the passed function data list. */ 848 void initFuncs( 849 const FunctionData* pBeg, const FunctionData* pEnd, 850 sal_uInt8 nMaxParam, bool bImportFilter ); 851 }; 852 853 // ---------------------------------------------------------------------------- 854 855 FunctionProviderImpl::FunctionProviderImpl( FilterType eFilter, BiffType eBiff, bool bImportFilter ) 856 { 857 OSL_ENSURE( bImportFilter, "FunctionProviderImpl::FunctionProviderImpl - need special handling for macro call functions" ); 858 sal_uInt8 nMaxParam = 0; 859 switch( eFilter ) 860 { 861 case FILTER_OOXML: 862 nMaxParam = OOX_MAX_PARAMCOUNT; 863 eBiff = BIFF8; // insert all BIFF function tables, then the OOXML table 864 break; 865 case FILTER_BIFF: 866 nMaxParam = BIFF_MAX_PARAMCOUNT; 867 break; 868 case FILTER_UNKNOWN: 869 OSL_ENSURE( false, "FunctionProviderImpl::FunctionProviderImpl - invalid filter type" ); 870 break; 871 } 872 OSL_ENSURE( eBiff != BIFF_UNKNOWN, "FunctionProviderImpl::FunctionProviderImpl - invalid BIFF type" ); 873 874 /* Add functions supported in the current BIFF version only. Function 875 tables from later BIFF versions may overwrite single functions from 876 earlier tables. */ 877 if( eBiff >= BIFF2 ) 878 initFuncs( saFuncTableBiff2, STATIC_ARRAY_END( saFuncTableBiff2 ), nMaxParam, bImportFilter ); 879 if( eBiff >= BIFF3 ) 880 initFuncs( saFuncTableBiff3, STATIC_ARRAY_END( saFuncTableBiff3 ), nMaxParam, bImportFilter ); 881 if( eBiff >= BIFF4 ) 882 initFuncs( saFuncTableBiff4, STATIC_ARRAY_END( saFuncTableBiff4 ), nMaxParam, bImportFilter ); 883 if( eBiff >= BIFF5 ) 884 initFuncs( saFuncTableBiff5, STATIC_ARRAY_END( saFuncTableBiff5 ), nMaxParam, bImportFilter ); 885 if( eBiff >= BIFF8 ) 886 initFuncs( saFuncTableBiff8, STATIC_ARRAY_END( saFuncTableBiff8 ), nMaxParam, bImportFilter ); 887 initFuncs( saFuncTableOox, STATIC_ARRAY_END( saFuncTableOox ), nMaxParam, bImportFilter ); 888 initFuncs( saFuncTableOdf, STATIC_ARRAY_END( saFuncTableOdf ), nMaxParam, bImportFilter ); 889 } 890 891 void FunctionProviderImpl::initFunc( const FunctionData& rFuncData, sal_uInt8 nMaxParam ) 892 { 893 // create a function info object 894 FunctionInfoRef xFuncInfo( new FunctionInfo ); 895 if( rFuncData.mpcOdfFuncName ) 896 xFuncInfo->maOdfFuncName = OUString::createFromAscii( rFuncData.mpcOdfFuncName ); 897 if( rFuncData.mpcOoxFuncName ) 898 xFuncInfo->maOoxFuncName = OUString::createFromAscii( rFuncData.mpcOoxFuncName ); 899 900 if( getFlag( rFuncData.mnFlags, FUNCFLAG_MACROCALL ) ) 901 { 902 OSL_ENSURE( xFuncInfo->maOoxFuncName.getLength() > 0, "FunctionProviderImpl::initFunc - missing OOXML function name" ); 903 OSL_ENSURE( !getFlag( rFuncData.mnFlags, FUNCFLAG_MACROCALLODF ), "FunctionProviderImpl::initFunc - unexpected flag FUNCFLAG_MACROCALLODF" ); 904 xFuncInfo->maBiffMacroName = CREATE_OUSTRING( "_xlfn." ) + xFuncInfo->maOoxFuncName; 905 } 906 else if( getFlag( rFuncData.mnFlags, FUNCFLAG_MACROCALLODF ) ) 907 { 908 OSL_ENSURE( xFuncInfo->maOdfFuncName.getLength() > 0, "FunctionProviderImpl::initFunc - missing ODF function name" ); 909 xFuncInfo->maBiffMacroName = CREATE_OUSTRING( "_xlfnodf." ) + xFuncInfo->maOdfFuncName; 910 } 911 912 xFuncInfo->meFuncLibType = FUNCFLAGS_TO_FUNCLIB( rFuncData.mnFlags ); 913 xFuncInfo->mnApiOpCode = -1; 914 xFuncInfo->mnBiff12FuncId = rFuncData.mnBiff12FuncId; 915 xFuncInfo->mnBiffFuncId = rFuncData.mnBiffFuncId; 916 xFuncInfo->mnMinParamCount = rFuncData.mnMinParamCount; 917 xFuncInfo->mnMaxParamCount = (rFuncData.mnMaxParamCount == MX) ? nMaxParam : rFuncData.mnMaxParamCount; 918 xFuncInfo->mnRetClass = rFuncData.mnRetClass; 919 xFuncInfo->mpParamInfos = rFuncData.mpParamInfos; 920 xFuncInfo->mbParamPairs = getFlag( rFuncData.mnFlags, FUNCFLAG_PARAMPAIRS ); 921 xFuncInfo->mbVolatile = getFlag( rFuncData.mnFlags, FUNCFLAG_VOLATILE ); 922 xFuncInfo->mbExternal = getFlag( rFuncData.mnFlags, FUNCFLAG_EXTERNAL ); 923 bool bMacroCmd = getFlag( rFuncData.mnFlags, FUNCFLAG_MACROCMD ); 924 xFuncInfo->mbMacroFunc = bMacroCmd || getFlag( rFuncData.mnFlags, FUNCFLAG_MACROFUNC ); 925 xFuncInfo->mbVarParam = bMacroCmd || (rFuncData.mnMinParamCount != rFuncData.mnMaxParamCount) || getFlag( rFuncData.mnFlags, FUNCFLAG_ALWAYSVAR ); 926 927 setFlag( xFuncInfo->mnBiff12FuncId, BIFF_TOK_FUNCVAR_CMD, bMacroCmd ); 928 setFlag( xFuncInfo->mnBiffFuncId, BIFF_TOK_FUNCVAR_CMD, bMacroCmd ); 929 930 // insert the function info into the member maps 931 maFuncs.push_back( xFuncInfo ); 932 if( xFuncInfo->maOdfFuncName.getLength() > 0 ) 933 maOdfFuncs[ xFuncInfo->maOdfFuncName ] = xFuncInfo; 934 if( xFuncInfo->maOoxFuncName.getLength() > 0 ) 935 maOoxFuncs[ xFuncInfo->maOoxFuncName ] = xFuncInfo; 936 if( xFuncInfo->mnBiff12FuncId != NOID ) 937 maBiff12Funcs[ xFuncInfo->mnBiff12FuncId ] = xFuncInfo; 938 if( xFuncInfo->mnBiffFuncId != NOID ) 939 maBiffFuncs[ xFuncInfo->mnBiffFuncId ] = xFuncInfo; 940 if( xFuncInfo->maBiffMacroName.getLength() > 0 ) 941 maMacroFuncs[ xFuncInfo->maBiffMacroName ] = xFuncInfo; 942 } 943 944 void FunctionProviderImpl::initFuncs( const FunctionData* pBeg, const FunctionData* pEnd, sal_uInt8 nMaxParam, bool bImportFilter ) 945 { 946 for( const FunctionData* pIt = pBeg; pIt != pEnd; ++pIt ) 947 if( pIt->isSupported( bImportFilter ) ) 948 initFunc( *pIt, nMaxParam ); 949 } 950 951 // ---------------------------------------------------------------------------- 952 953 FunctionProvider::FunctionProvider( FilterType eFilter, BiffType eBiff, bool bImportFilter ) : 954 mxFuncImpl( new FunctionProviderImpl( eFilter, eBiff, bImportFilter ) ) 955 { 956 } 957 958 FunctionProvider::~FunctionProvider() 959 { 960 } 961 962 const FunctionInfo* FunctionProvider::getFuncInfoFromOdfFuncName( const OUString& rFuncName ) const 963 { 964 return mxFuncImpl->maOdfFuncs.get( rFuncName ).get(); 965 } 966 967 const FunctionInfo* FunctionProvider::getFuncInfoFromOoxFuncName( const OUString& rFuncName ) const 968 { 969 return mxFuncImpl->maOoxFuncs.get( rFuncName ).get(); 970 } 971 972 const FunctionInfo* FunctionProvider::getFuncInfoFromBiff12FuncId( sal_uInt16 nFuncId ) const 973 { 974 return mxFuncImpl->maBiff12Funcs.get( nFuncId ).get(); 975 } 976 977 const FunctionInfo* FunctionProvider::getFuncInfoFromBiffFuncId( sal_uInt16 nFuncId ) const 978 { 979 return mxFuncImpl->maBiffFuncs.get( nFuncId ).get(); 980 } 981 982 const FunctionInfo* FunctionProvider::getFuncInfoFromMacroName( const OUString& rFuncName ) const 983 { 984 return mxFuncImpl->maMacroFuncs.get( rFuncName ).get(); 985 } 986 987 FunctionLibraryType FunctionProvider::getFuncLibTypeFromLibraryName( const OUString& rLibraryName ) const 988 { 989 #define OOX_XLS_IS_LIBNAME( libname, basename ) (libname.equalsIgnoreAsciiCaseAscii( basename ".XLA" ) || libname.equalsIgnoreAsciiCaseAscii( basename ".XLAM" )) 990 991 // the EUROTOOL add-in containing the EUROCONVERT function 992 if( OOX_XLS_IS_LIBNAME( rLibraryName, "EUROTOOL" ) ) 993 return FUNCLIB_EUROTOOL; 994 995 #undef OOX_XLS_IS_LIBNAME 996 997 // default: unknown library 998 return FUNCLIB_UNKNOWN; 999 } 1000 1001 const FunctionInfoVector& FunctionProvider::getFuncs() const 1002 { 1003 return mxFuncImpl->maFuncs; 1004 } 1005 1006 // op-code and function provider ============================================== 1007 1008 struct OpCodeProviderImpl : public ApiOpCodes 1009 { 1010 typedef RefMap< sal_Int32, FunctionInfo > OpCodeFuncMap; 1011 typedef RefMap< OUString, FunctionInfo > FuncNameMap; 1012 typedef ::std::vector< FormulaOpCodeMapEntry > OpCodeEntryVector; 1013 1014 OpCodeFuncMap maOpCodeFuncs; /// Maps API function op-codes to function data. 1015 FuncNameMap maExtProgFuncs; /// Maps programmatical API function names to function data. 1016 OpCodeEntryVector maParserMap; /// OOXML token mapping for formula parser service. 1017 1018 explicit OpCodeProviderImpl( 1019 const FunctionInfoVector& rFuncInfos, 1020 const Reference< XMultiServiceFactory >& rxModelFactory ); 1021 1022 private: 1023 typedef ::std::map< OUString, ApiToken > ApiTokenMap; 1024 typedef Sequence< FormulaOpCodeMapEntry > OpCodeEntrySequence; 1025 1026 static bool fillEntrySeq( OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup ); 1027 static bool fillTokenMap( ApiTokenMap& orTokenMap, OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup ); 1028 bool fillFuncTokenMaps( ApiTokenMap& orIntFuncTokenMap, ApiTokenMap& orExtFuncTokenMap, OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper ) const; 1029 1030 static bool initOpCode( sal_Int32& ornOpCode, const OpCodeEntrySequence& rEntrySeq, sal_Int32 nSpecialId ); 1031 bool initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, const OUString& rOdfName, const OUString& rOoxName ); 1032 bool initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, const sal_Char* pcOdfName, const sal_Char* pcOoxName ); 1033 bool initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, sal_Unicode cOdfName, sal_Unicode cOoxName ); 1034 1035 bool initFuncOpCode( FunctionInfo& orFuncInfo, const ApiTokenMap& rFuncTokenMap ); 1036 bool initFuncOpCodes( const ApiTokenMap& rIntFuncTokenMap, const ApiTokenMap& rExtFuncTokenMap, const FunctionInfoVector& rFuncInfos ); 1037 }; 1038 1039 // ---------------------------------------------------------------------------- 1040 1041 OpCodeProviderImpl::OpCodeProviderImpl( const FunctionInfoVector& rFuncInfos, 1042 const Reference< XMultiServiceFactory >& rxModelFactory ) 1043 { 1044 if( rxModelFactory.is() ) try 1045 { 1046 Reference< XFormulaOpCodeMapper > xMapper( rxModelFactory->createInstance( 1047 CREATE_OUSTRING( "com.sun.star.sheet.FormulaOpCodeMapper" ) ), UNO_QUERY_THROW ); 1048 1049 // op-codes provided as attributes 1050 OPCODE_UNKNOWN = xMapper->getOpCodeUnknown(); 1051 OPCODE_EXTERNAL = xMapper->getOpCodeExternal(); 1052 1053 using namespace ::com::sun::star::sheet::FormulaMapGroup; 1054 using namespace ::com::sun::star::sheet::FormulaMapGroupSpecialOffset; 1055 1056 OpCodeEntrySequence aEntrySeq; 1057 ApiTokenMap aTokenMap, aExtFuncTokenMap; 1058 bool bIsValid = 1059 // special 1060 fillEntrySeq( aEntrySeq, xMapper, SPECIAL ) && 1061 initOpCode( OPCODE_PUSH, aEntrySeq, PUSH ) && 1062 initOpCode( OPCODE_MISSING, aEntrySeq, MISSING ) && 1063 initOpCode( OPCODE_SPACES, aEntrySeq, SPACES ) && 1064 initOpCode( OPCODE_NAME, aEntrySeq, NAME ) && 1065 initOpCode( OPCODE_DBAREA, aEntrySeq, DB_AREA ) && 1066 initOpCode( OPCODE_NLR, aEntrySeq, COL_ROW_NAME ) && 1067 initOpCode( OPCODE_MACRO, aEntrySeq, MACRO ) && 1068 initOpCode( OPCODE_BAD, aEntrySeq, BAD ) && 1069 initOpCode( OPCODE_NONAME, aEntrySeq, NO_NAME ) && 1070 // separators 1071 fillTokenMap( aTokenMap, aEntrySeq, xMapper, SEPARATORS ) && 1072 initOpCode( OPCODE_OPEN, aTokenMap, API_TOKEN_OPEN, '(' ) && 1073 initOpCode( OPCODE_CLOSE, aTokenMap, API_TOKEN_CLOSE, ')' ) && 1074 initOpCode( OPCODE_SEP, aTokenMap, API_TOKEN_SEP, ',' ) && 1075 // array separators 1076 fillTokenMap( aTokenMap, aEntrySeq, xMapper, ARRAY_SEPARATORS ) && 1077 initOpCode( OPCODE_ARRAY_OPEN, aTokenMap, API_TOKEN_ARRAY_OPEN, '{' ) && 1078 initOpCode( OPCODE_ARRAY_CLOSE, aTokenMap, API_TOKEN_ARRAY_CLOSE, '}' ) && 1079 initOpCode( OPCODE_ARRAY_ROWSEP, aTokenMap, API_TOKEN_ARRAY_ROWSEP, ';' ) && 1080 initOpCode( OPCODE_ARRAY_COLSEP, aTokenMap, API_TOKEN_ARRAY_COLSEP, ',' ) && 1081 // unary operators 1082 fillTokenMap( aTokenMap, aEntrySeq, xMapper, UNARY_OPERATORS ) && 1083 initOpCode( OPCODE_PLUS_SIGN, aTokenMap, '+', '\0' ) && // same op-code as OPCODE_ADD 1084 initOpCode( OPCODE_MINUS_SIGN, aTokenMap, '-', '-' ) && 1085 initOpCode( OPCODE_PERCENT, aTokenMap, '%', '%' ) && 1086 // binary operators 1087 fillTokenMap( aTokenMap, aEntrySeq, xMapper, BINARY_OPERATORS ) && 1088 initOpCode( OPCODE_ADD, aTokenMap, '+', '+' ) && 1089 initOpCode( OPCODE_SUB, aTokenMap, '-', '-' ) && 1090 initOpCode( OPCODE_MULT, aTokenMap, '*', '*' ) && 1091 initOpCode( OPCODE_DIV, aTokenMap, '/', '/' ) && 1092 initOpCode( OPCODE_POWER, aTokenMap, '^', '^' ) && 1093 initOpCode( OPCODE_CONCAT, aTokenMap, '&', '&' ) && 1094 initOpCode( OPCODE_EQUAL, aTokenMap, '=', '=' ) && 1095 initOpCode( OPCODE_NOT_EQUAL, aTokenMap, "<>", "<>" ) && 1096 initOpCode( OPCODE_LESS, aTokenMap, '<', '<' ) && 1097 initOpCode( OPCODE_LESS_EQUAL, aTokenMap, "<=", "<=" ) && 1098 initOpCode( OPCODE_GREATER, aTokenMap, '>', '>' ) && 1099 initOpCode( OPCODE_GREATER_EQUAL, aTokenMap, ">=", ">=" ) && 1100 initOpCode( OPCODE_INTERSECT, aTokenMap, '!', ' ' ) && 1101 initOpCode( OPCODE_LIST, aTokenMap, '~', ',' ) && 1102 initOpCode( OPCODE_RANGE, aTokenMap, ':', ':' ) && 1103 // functions 1104 fillFuncTokenMaps( aTokenMap, aExtFuncTokenMap, aEntrySeq, xMapper ) && 1105 initFuncOpCodes( aTokenMap, aExtFuncTokenMap, rFuncInfos ) && 1106 initOpCode( OPCODE_DDE, aTokenMap, "DDE", 0 ); 1107 1108 OSL_ENSURE( bIsValid, "OpCodeProviderImpl::OpCodeProviderImpl - opcodes not initialized" ); 1109 (void)bIsValid; 1110 1111 // OPCODE_PLUS_SIGN and OPCODE_ADD should be equal, otherwise "+" has to be passed above 1112 OSL_ENSURE( OPCODE_PLUS_SIGN == OPCODE_ADD, "OpCodeProviderImpl::OpCodeProviderImpl - need opcode mapping for OPCODE_PLUS_SIGN" ); 1113 } 1114 catch( Exception& ) 1115 { 1116 OSL_ENSURE( false, "OpCodeProviderImpl::OpCodeProviderImpl - cannot receive formula opcode mapper" ); 1117 } 1118 } 1119 1120 bool OpCodeProviderImpl::fillEntrySeq( OpCodeEntrySequence& orEntrySeq, 1121 const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup ) 1122 { 1123 try 1124 { 1125 orEntrySeq = rxMapper->getAvailableMappings( ::com::sun::star::sheet::FormulaLanguage::ODFF, nMapGroup ); 1126 return orEntrySeq.hasElements(); 1127 } 1128 catch( Exception& ) 1129 { 1130 } 1131 return false; 1132 } 1133 1134 bool OpCodeProviderImpl::fillTokenMap( ApiTokenMap& orTokenMap, OpCodeEntrySequence& orEntrySeq, 1135 const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup ) 1136 { 1137 orTokenMap.clear(); 1138 if( fillEntrySeq( orEntrySeq, rxMapper, nMapGroup ) ) 1139 { 1140 const FormulaOpCodeMapEntry* pEntry = orEntrySeq.getConstArray(); 1141 const FormulaOpCodeMapEntry* pEntryEnd = pEntry + orEntrySeq.getLength(); 1142 for( ; pEntry != pEntryEnd; ++pEntry ) 1143 orTokenMap[ pEntry->Name ] = pEntry->Token; 1144 } 1145 return orEntrySeq.hasElements(); 1146 } 1147 1148 bool OpCodeProviderImpl::fillFuncTokenMaps( ApiTokenMap& orIntFuncTokenMap, ApiTokenMap& orExtFuncTokenMap, OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper ) const 1149 { 1150 orIntFuncTokenMap.clear(); 1151 orExtFuncTokenMap.clear(); 1152 if( fillEntrySeq( orEntrySeq, rxMapper, ::com::sun::star::sheet::FormulaMapGroup::FUNCTIONS ) ) 1153 { 1154 const FormulaOpCodeMapEntry* pEntry = orEntrySeq.getConstArray(); 1155 const FormulaOpCodeMapEntry* pEntryEnd = pEntry + orEntrySeq.getLength(); 1156 for( ; pEntry != pEntryEnd; ++pEntry ) 1157 ((pEntry->Token.OpCode == OPCODE_EXTERNAL) ? orExtFuncTokenMap : orIntFuncTokenMap)[ pEntry->Name ] = pEntry->Token; 1158 } 1159 return orEntrySeq.hasElements(); 1160 } 1161 1162 bool OpCodeProviderImpl::initOpCode( sal_Int32& ornOpCode, const OpCodeEntrySequence& rEntrySeq, sal_Int32 nSpecialId ) 1163 { 1164 if( (0 <= nSpecialId) && (nSpecialId < rEntrySeq.getLength()) ) 1165 { 1166 ornOpCode = rEntrySeq[ nSpecialId ].Token.OpCode; 1167 return true; 1168 } 1169 OSL_ENSURE( false, 1170 OStringBuffer( "OpCodeProviderImpl::initOpCode - opcode for special offset " ). 1171 append( nSpecialId ).append( " not found" ).getStr() ); 1172 return false; 1173 } 1174 1175 bool OpCodeProviderImpl::initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, const OUString& rOdfName, const OUString& rOoxName ) 1176 { 1177 ApiTokenMap::const_iterator aIt = rTokenMap.find( rOdfName ); 1178 if( aIt != rTokenMap.end() ) 1179 { 1180 ornOpCode = aIt->second.OpCode; 1181 if( rOoxName.getLength() > 0 ) 1182 { 1183 FormulaOpCodeMapEntry aEntry; 1184 aEntry.Name = rOoxName; 1185 aEntry.Token.OpCode = ornOpCode; 1186 maParserMap.push_back( aEntry ); 1187 } 1188 return true; 1189 } 1190 OSL_ENSURE( false, 1191 OStringBuffer( "OpCodeProviderImpl::initOpCode - opcode for \"" ). 1192 append( OUStringToOString( rOdfName, RTL_TEXTENCODING_ASCII_US ) ). 1193 append( "\" not found" ).getStr() ); 1194 return false; 1195 } 1196 1197 bool OpCodeProviderImpl::initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, const sal_Char* pcOdfName, const sal_Char* pcOoxName ) 1198 { 1199 OUString aOoxName; 1200 if( pcOoxName ) aOoxName = OUString::createFromAscii( pcOoxName ); 1201 return initOpCode( ornOpCode, rTokenMap, OUString::createFromAscii( pcOdfName ), aOoxName ); 1202 } 1203 1204 bool OpCodeProviderImpl::initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, sal_Unicode cOdfName, sal_Unicode cOoxName ) 1205 { 1206 OUString aOoxName; 1207 if( cOoxName ) aOoxName = OUString( cOoxName ); 1208 return initOpCode( ornOpCode, rTokenMap, OUString( cOdfName ), aOoxName ); 1209 } 1210 1211 bool OpCodeProviderImpl::initFuncOpCode( FunctionInfo& orFuncInfo, const ApiTokenMap& rFuncTokenMap ) 1212 { 1213 bool bIsValid = false; 1214 if( orFuncInfo.maOdfFuncName.getLength() > 0 ) 1215 { 1216 ApiTokenMap::const_iterator aIt = rFuncTokenMap.find( orFuncInfo.maOdfFuncName ); 1217 if( aIt != rFuncTokenMap.end() ) 1218 { 1219 orFuncInfo.mnApiOpCode = aIt->second.OpCode; 1220 bIsValid = 1221 (orFuncInfo.mnApiOpCode >= 0) && 1222 (orFuncInfo.mnApiOpCode != OPCODE_UNKNOWN) && 1223 (orFuncInfo.mnApiOpCode != OPCODE_NONAME); 1224 OSL_ENSURE( bIsValid, 1225 OStringBuffer( "OpCodeProviderImpl::initFuncOpCode - no valid opcode for ODF function \"" ). 1226 append( OUStringToOString( orFuncInfo.maOdfFuncName, RTL_TEXTENCODING_ASCII_US ) ). 1227 append( '"' ).getStr() ); 1228 1229 if( bIsValid && (orFuncInfo.mnApiOpCode == OPCODE_EXTERNAL) ) 1230 { 1231 bIsValid = (aIt->second.Data >>= orFuncInfo.maExtProgName) && (orFuncInfo.maExtProgName.getLength() > 0); 1232 OSL_ENSURE( bIsValid, 1233 OStringBuffer( "OpCodeProviderImpl::initFuncOpCode - no programmatical name for external function \"" ). 1234 append( OUStringToOString( orFuncInfo.maOdfFuncName, RTL_TEXTENCODING_ASCII_US ) ). 1235 append( '"' ).getStr() ); 1236 } 1237 1238 // add to parser map, if OOXML function name exists 1239 if( bIsValid && (orFuncInfo.maOoxFuncName.getLength() > 0) ) 1240 { 1241 // create the parser map entry 1242 FormulaOpCodeMapEntry aEntry; 1243 aEntry.Name = orFuncInfo.maOoxFuncName; 1244 aEntry.Token = aIt->second; 1245 maParserMap.push_back( aEntry ); 1246 } 1247 } 1248 else 1249 { 1250 // ignore entries for functions unknown by Calc *and* by Excel 1251 bIsValid = orFuncInfo.maOoxFuncName.getLength() == 0; 1252 } 1253 } 1254 else if( orFuncInfo.mnBiffFuncId == BIFF_FUNC_EXTERNCALL ) 1255 { 1256 orFuncInfo.mnApiOpCode = OPCODE_EXTERNAL; 1257 bIsValid = true; 1258 } 1259 else if( orFuncInfo.maOoxFuncName.getLength() > 0 ) 1260 { 1261 orFuncInfo.mnApiOpCode = OPCODE_BAD; 1262 bIsValid = true; 1263 } 1264 1265 if( !bIsValid || (orFuncInfo.mnApiOpCode == OPCODE_UNKNOWN) || (orFuncInfo.mnApiOpCode < 0) ) 1266 orFuncInfo.mnApiOpCode = OPCODE_NONAME; 1267 return bIsValid; 1268 } 1269 1270 bool OpCodeProviderImpl::initFuncOpCodes( const ApiTokenMap& rIntFuncTokenMap, const ApiTokenMap& rExtFuncTokenMap, const FunctionInfoVector& rFuncInfos ) 1271 { 1272 bool bIsValid = true; 1273 for( FunctionInfoVector::const_iterator aIt = rFuncInfos.begin(), aEnd = rFuncInfos.end(); aIt != aEnd; ++aIt ) 1274 { 1275 FunctionInfoRef xFuncInfo = *aIt; 1276 // set API opcode from ODF function name 1277 bIsValid &= initFuncOpCode( *xFuncInfo, xFuncInfo->mbExternal ? rExtFuncTokenMap : rIntFuncTokenMap ); 1278 // insert the function info into the maps 1279 if( (xFuncInfo->mnApiOpCode != OPCODE_NONAME) && (xFuncInfo->mnApiOpCode != OPCODE_BAD) ) 1280 { 1281 if( (xFuncInfo->mnApiOpCode == OPCODE_EXTERNAL) && (xFuncInfo->maExtProgName.getLength() > 0) ) 1282 maExtProgFuncs[ xFuncInfo->maExtProgName ] = xFuncInfo; 1283 else 1284 maOpCodeFuncs[ xFuncInfo->mnApiOpCode ] = xFuncInfo; 1285 } 1286 } 1287 return bIsValid; 1288 } 1289 1290 // ---------------------------------------------------------------------------- 1291 1292 OpCodeProvider::OpCodeProvider( const Reference< XMultiServiceFactory >& rxModelFactory, 1293 FilterType eFilter, BiffType eBiff, bool bImportFilter ) : 1294 FunctionProvider( eFilter, eBiff, bImportFilter ), 1295 mxOpCodeImpl( new OpCodeProviderImpl( getFuncs(), rxModelFactory ) ) 1296 { 1297 } 1298 1299 OpCodeProvider::~OpCodeProvider() 1300 { 1301 } 1302 1303 const ApiOpCodes& OpCodeProvider::getOpCodes() const 1304 { 1305 return *mxOpCodeImpl; 1306 } 1307 1308 const FunctionInfo* OpCodeProvider::getFuncInfoFromApiToken( const ApiToken& rToken ) const 1309 { 1310 const FunctionInfo* pFuncInfo = 0; 1311 if( (rToken.OpCode == mxOpCodeImpl->OPCODE_EXTERNAL) && rToken.Data.has< OUString >() ) 1312 pFuncInfo = mxOpCodeImpl->maExtProgFuncs.get( rToken.Data.get< OUString >() ).get(); 1313 else if( (rToken.OpCode == mxOpCodeImpl->OPCODE_MACRO) && rToken.Data.has< OUString >() ) 1314 pFuncInfo = getFuncInfoFromMacroName( rToken.Data.get< OUString >() ); 1315 else if( (rToken.OpCode == mxOpCodeImpl->OPCODE_BAD) && rToken.Data.has< OUString >() ) 1316 pFuncInfo = getFuncInfoFromOoxFuncName( rToken.Data.get< OUString >() ); 1317 else 1318 pFuncInfo = mxOpCodeImpl->maOpCodeFuncs.get( rToken.OpCode ).get(); 1319 return pFuncInfo; 1320 } 1321 1322 Sequence< FormulaOpCodeMapEntry > OpCodeProvider::getOoxParserMap() const 1323 { 1324 return ContainerHelper::vectorToSequence( mxOpCodeImpl->maParserMap ); 1325 } 1326 1327 // API formula parser wrapper ================================================= 1328 1329 ApiParserWrapper::ApiParserWrapper( 1330 const Reference< XMultiServiceFactory >& rxModelFactory, const OpCodeProvider& rOpCodeProv ) : 1331 OpCodeProvider( rOpCodeProv ) 1332 { 1333 if( rxModelFactory.is() ) try 1334 { 1335 mxParser.set( rxModelFactory->createInstance( CREATE_OUSTRING( "com.sun.star.sheet.FormulaParser" ) ), UNO_QUERY_THROW ); 1336 } 1337 catch( Exception& ) 1338 { 1339 } 1340 OSL_ENSURE( mxParser.is(), "ApiParserWrapper::ApiParserWrapper - cannot create API formula parser object" ); 1341 maParserProps.set( mxParser ); 1342 maParserProps.setProperty( PROP_CompileEnglish, true ); 1343 maParserProps.setProperty( PROP_FormulaConvention, ::com::sun::star::sheet::AddressConvention::XL_OOX ); 1344 maParserProps.setProperty( PROP_IgnoreLeadingSpaces, false ); 1345 maParserProps.setProperty( PROP_OpCodeMap, getOoxParserMap() ); 1346 } 1347 1348 ApiTokenSequence ApiParserWrapper::parseFormula( const OUString& rFormula, const CellAddress& rRefPos ) 1349 { 1350 ApiTokenSequence aTokenSeq; 1351 if( mxParser.is() ) try 1352 { 1353 aTokenSeq = mxParser->parseFormula( rFormula, rRefPos ); 1354 } 1355 catch( Exception& ) 1356 { 1357 } 1358 return aTokenSeq; 1359 } 1360 1361 // formula parser/printer base class for filters ============================== 1362 1363 namespace { 1364 1365 bool lclConvertToCellAddress( CellAddress& orAddress, const SingleReference& rSingleRef, sal_Int32 nForbiddenFlags, sal_Int32 nFilterBySheet ) 1366 { 1367 orAddress = CellAddress( static_cast< sal_Int16 >( rSingleRef.Sheet ), 1368 rSingleRef.Column, rSingleRef.Row ); 1369 return 1370 !getFlag( rSingleRef.Flags, nForbiddenFlags ) && 1371 ((nFilterBySheet < 0) || (nFilterBySheet == rSingleRef.Sheet)); 1372 } 1373 1374 bool lclConvertToCellRange( CellRangeAddress& orRange, const ComplexReference& rComplexRef, sal_Int32 nForbiddenFlags, sal_Int32 nFilterBySheet ) 1375 { 1376 orRange = CellRangeAddress( static_cast< sal_Int16 >( rComplexRef.Reference1.Sheet ), 1377 rComplexRef.Reference1.Column, rComplexRef.Reference1.Row, 1378 rComplexRef.Reference2.Column, rComplexRef.Reference2.Row ); 1379 return 1380 !getFlag( rComplexRef.Reference1.Flags, nForbiddenFlags ) && 1381 !getFlag( rComplexRef.Reference2.Flags, nForbiddenFlags ) && 1382 (rComplexRef.Reference1.Sheet == rComplexRef.Reference2.Sheet) && 1383 ((nFilterBySheet < 0) || (nFilterBySheet == rComplexRef.Reference1.Sheet)); 1384 } 1385 1386 enum TokenToRangeListState { STATE_REF, STATE_SEP, STATE_OPEN, STATE_CLOSE, STATE_ERROR }; 1387 1388 TokenToRangeListState lclProcessRef( ApiCellRangeList& orRanges, const Any& rData, bool bAllowRelative, sal_Int32 nFilterBySheet ) 1389 { 1390 using namespace ::com::sun::star::sheet::ReferenceFlags; 1391 const sal_Int32 FORBIDDEN_FLAGS_DEL = COLUMN_DELETED | ROW_DELETED | SHEET_DELETED; 1392 const sal_Int32 FORBIDDEN_FLAGS_REL = FORBIDDEN_FLAGS_DEL | COLUMN_RELATIVE | ROW_RELATIVE | SHEET_RELATIVE | RELATIVE_NAME; 1393 1394 sal_Int32 nForbiddenFlags = bAllowRelative ? FORBIDDEN_FLAGS_DEL : FORBIDDEN_FLAGS_REL; 1395 SingleReference aSingleRef; 1396 if( rData >>= aSingleRef ) 1397 { 1398 CellAddress aAddress; 1399 // ignore invalid addresses (with #REF! errors), but do not stop parsing 1400 if( lclConvertToCellAddress( aAddress, aSingleRef, nForbiddenFlags, nFilterBySheet ) ) 1401 orRanges.push_back( CellRangeAddress( aAddress.Sheet, aAddress.Column, aAddress.Row, aAddress.Column, aAddress.Row ) ); 1402 return STATE_REF; 1403 } 1404 ComplexReference aComplexRef; 1405 if( rData >>= aComplexRef ) 1406 { 1407 CellRangeAddress aRange; 1408 // ignore invalid ranges (with #REF! errors), but do not stop parsing 1409 if( lclConvertToCellRange( aRange, aComplexRef, nForbiddenFlags, nFilterBySheet ) ) 1410 orRanges.push_back( aRange ); 1411 return STATE_REF; 1412 } 1413 return STATE_ERROR; 1414 } 1415 1416 TokenToRangeListState lclProcessOpen( sal_Int32& ornParenLevel ) 1417 { 1418 ++ornParenLevel; 1419 return STATE_OPEN; 1420 } 1421 1422 TokenToRangeListState lclProcessClose( sal_Int32& ornParenLevel ) 1423 { 1424 --ornParenLevel; 1425 return (ornParenLevel >= 0) ? STATE_CLOSE : STATE_ERROR; 1426 } 1427 1428 } // namespace 1429 1430 // ---------------------------------------------------------------------------- 1431 1432 FormulaProcessorBase::FormulaProcessorBase( const WorkbookHelper& rHelper ) : 1433 OpCodeProvider( rHelper.getBaseFilter().getModelFactory(), rHelper.getFilterType(), rHelper.getBiff(), rHelper.getBaseFilter().isImportFilter() ), 1434 ApiOpCodes( getOpCodes() ), 1435 WorkbookHelper( rHelper ) 1436 { 1437 } 1438 1439 // ---------------------------------------------------------------------------- 1440 1441 OUString FormulaProcessorBase::generateAddress2dString( const CellAddress& rAddress, bool bAbsolute ) 1442 { 1443 return generateAddress2dString( BinAddress( rAddress ), bAbsolute ); 1444 } 1445 1446 OUString FormulaProcessorBase::generateAddress2dString( const BinAddress& rAddress, bool bAbsolute ) 1447 { 1448 OUStringBuffer aBuffer; 1449 // column 1450 for( sal_Int32 nTemp = rAddress.mnCol; nTemp >= 0; (nTemp /= 26) -= 1 ) 1451 aBuffer.insert( 0, sal_Unicode( 'A' + (nTemp % 26) ) ); 1452 if( bAbsolute ) 1453 aBuffer.insert( 0, sal_Unicode( '$' ) ); 1454 // row 1455 if( bAbsolute ) 1456 aBuffer.append( sal_Unicode( '$' ) ); 1457 aBuffer.append( static_cast< sal_Int32 >( rAddress.mnRow + 1 ) ); 1458 return aBuffer.makeStringAndClear(); 1459 } 1460 1461 OUString FormulaProcessorBase::generateRange2dString( const CellRangeAddress& rRange, bool bAbsolute ) 1462 { 1463 return generateRange2dString( BinRange( rRange ), bAbsolute ); 1464 } 1465 1466 OUString FormulaProcessorBase::generateRange2dString( const BinRange& rRange, bool bAbsolute ) 1467 { 1468 OUStringBuffer aBuffer( generateAddress2dString( rRange.maFirst, bAbsolute ) ); 1469 if( (rRange.getColCount() > 1) || (rRange.getRowCount() > 1) ) 1470 aBuffer.append( sal_Unicode( ':' ) ).append( generateAddress2dString( rRange.maLast, bAbsolute ) ); 1471 return aBuffer.makeStringAndClear(); 1472 } 1473 1474 OUString FormulaProcessorBase::generateRangeList2dString( const ApiCellRangeList& rRanges, 1475 bool bAbsolute, sal_Unicode cSeparator, bool bEncloseMultiple ) 1476 { 1477 OUStringBuffer aBuffer; 1478 for( ApiCellRangeList::const_iterator aIt = rRanges.begin(), aEnd = rRanges.end(); aIt != aEnd; ++aIt ) 1479 { 1480 if( aBuffer.getLength() > 0 ) 1481 aBuffer.append( cSeparator ); 1482 aBuffer.append( generateRange2dString( *aIt, bAbsolute ) ); 1483 } 1484 if( bEncloseMultiple && (rRanges.size() > 1) ) 1485 aBuffer.insert( 0, sal_Unicode( '(' ) ).append( sal_Unicode( ')' ) ); 1486 return aBuffer.makeStringAndClear(); 1487 } 1488 1489 // ---------------------------------------------------------------------------- 1490 1491 OUString FormulaProcessorBase::generateApiAddressString( const CellAddress& rAddress ) const 1492 { 1493 OUString aCellName; 1494 PropertySet aCellProp( getCellFromDoc( rAddress ) ); 1495 aCellProp.getProperty( aCellName, PROP_AbsoluteName ); 1496 OSL_ENSURE( aCellName.getLength() > 0, "FormulaProcessorBase::generateApiAddressString - cannot create cell address string" ); 1497 return aCellName; 1498 } 1499 1500 OUString FormulaProcessorBase::generateApiRangeString( const CellRangeAddress& rRange ) const 1501 { 1502 OUString aRangeName; 1503 PropertySet aRangeProp( getCellRangeFromDoc( rRange ) ); 1504 aRangeProp.getProperty( aRangeName, PROP_AbsoluteName ); 1505 OSL_ENSURE( aRangeName.getLength() > 0, "FormulaProcessorBase::generateApiRangeString - cannot create cell range string" ); 1506 return aRangeName; 1507 } 1508 1509 OUString FormulaProcessorBase::generateApiRangeListString( const ApiCellRangeList& rRanges ) const 1510 { 1511 OUStringBuffer aBuffer; 1512 for( ApiCellRangeList::const_iterator aIt = rRanges.begin(), aEnd = rRanges.end(); aIt != aEnd; ++aIt ) 1513 { 1514 OUString aRangeName = generateApiRangeString( *aIt ); 1515 if( aRangeName.getLength() > 0 ) 1516 { 1517 if( aBuffer.getLength() > 0 ) 1518 aBuffer.append( API_TOKEN_SEP ); 1519 aBuffer.append( aRangeName ); 1520 } 1521 } 1522 return aBuffer.makeStringAndClear(); 1523 } 1524 1525 OUString FormulaProcessorBase::generateApiString( const OUString& rString ) 1526 { 1527 OUString aRetString = rString; 1528 sal_Int32 nQuotePos = aRetString.getLength(); 1529 while( (nQuotePos = aRetString.lastIndexOf( '"', nQuotePos )) >= 0 ) 1530 aRetString = aRetString.replaceAt( nQuotePos, 1, CREATE_OUSTRING( "\"\"" ) ); 1531 return OUStringBuffer().append( sal_Unicode( '"' ) ).append( aRetString ).append( sal_Unicode( '"' ) ).makeStringAndClear(); 1532 } 1533 1534 OUString FormulaProcessorBase::generateApiArray( const Matrix< Any >& rMatrix ) 1535 { 1536 OSL_ENSURE( !rMatrix.empty(), "FormulaProcessorBase::generateApiArray - missing matrix values" ); 1537 OUStringBuffer aBuffer; 1538 aBuffer.append( API_TOKEN_ARRAY_OPEN ); 1539 for( size_t nRow = 0, nHeight = rMatrix.height(); nRow < nHeight; ++nRow ) 1540 { 1541 if( nRow > 0 ) 1542 aBuffer.append( API_TOKEN_ARRAY_ROWSEP ); 1543 for( Matrix< Any >::const_iterator aBeg = rMatrix.row_begin( nRow ), aIt = aBeg, aEnd = rMatrix.row_end( nRow ); aIt != aEnd; ++aIt ) 1544 { 1545 double fValue = 0.0; 1546 OUString aString; 1547 if( aIt != aBeg ) 1548 aBuffer.append( API_TOKEN_ARRAY_COLSEP ); 1549 if( *aIt >>= fValue ) 1550 aBuffer.append( fValue ); 1551 else if( *aIt >>= aString ) 1552 aBuffer.append( generateApiString( aString ) ); 1553 else 1554 aBuffer.appendAscii( "\"\"" ); 1555 } 1556 } 1557 aBuffer.append( API_TOKEN_ARRAY_CLOSE ); 1558 return aBuffer.makeStringAndClear(); 1559 } 1560 1561 // ---------------------------------------------------------------------------- 1562 1563 Any FormulaProcessorBase::extractReference( const ApiTokenSequence& rTokens ) const 1564 { 1565 ApiTokenIterator aTokenIt( rTokens, OPCODE_SPACES, true ); 1566 if( aTokenIt.is() && (aTokenIt->OpCode == OPCODE_PUSH) ) 1567 { 1568 Any aRefAny = aTokenIt->Data; 1569 if( !(++aTokenIt).is() && (aRefAny.has< SingleReference >() || aRefAny.has< ComplexReference >()) ) 1570 return aRefAny; 1571 } 1572 return Any(); 1573 } 1574 1575 bool FormulaProcessorBase::extractCellAddress( CellAddress& orAddress, 1576 const ApiTokenSequence& rTokens, bool bAllowRelative ) const 1577 { 1578 CellRangeAddress aRange; 1579 if( extractCellRange( aRange, rTokens, bAllowRelative ) && (aRange.StartColumn == aRange.EndColumn) && (aRange.StartRow == aRange.EndRow) ) 1580 { 1581 orAddress.Sheet = aRange.Sheet; 1582 orAddress.Column = aRange.StartColumn; 1583 orAddress.Row = aRange.StartRow; 1584 return true; 1585 } 1586 return false; 1587 } 1588 1589 bool FormulaProcessorBase::extractCellRange( CellRangeAddress& orRange, 1590 const ApiTokenSequence& rTokens, bool bAllowRelative ) const 1591 { 1592 ApiCellRangeList aRanges; 1593 lclProcessRef( aRanges, extractReference( rTokens ), bAllowRelative, -1 ); 1594 if( !aRanges.empty() ) 1595 { 1596 orRange = aRanges.front(); 1597 return true; 1598 } 1599 return false; 1600 } 1601 1602 void FormulaProcessorBase::extractCellRangeList( ApiCellRangeList& orRanges, 1603 const ApiTokenSequence& rTokens, bool bAllowRelative, sal_Int32 nFilterBySheet ) const 1604 { 1605 orRanges.clear(); 1606 TokenToRangeListState eState = STATE_OPEN; 1607 sal_Int32 nParenLevel = 0; 1608 for( ApiTokenIterator aIt( rTokens, OPCODE_SPACES, true ); aIt.is() && (eState != STATE_ERROR); ++aIt ) 1609 { 1610 sal_Int32 nOpCode = aIt->OpCode; 1611 switch( eState ) 1612 { 1613 // #i107275# accept OPCODE_SEP and OPCODE_LIST as separator token 1614 case STATE_REF: 1615 if( nOpCode == OPCODE_SEP ) eState = STATE_SEP; 1616 else if( nOpCode == OPCODE_LIST ) eState = STATE_SEP; 1617 else if( nOpCode == OPCODE_CLOSE ) eState = lclProcessClose( nParenLevel ); 1618 else eState = STATE_ERROR; 1619 break; 1620 case STATE_SEP: 1621 if( nOpCode == OPCODE_PUSH ) eState = lclProcessRef( orRanges, aIt->Data, bAllowRelative, nFilterBySheet ); 1622 else if( nOpCode == OPCODE_SEP ) eState = STATE_SEP; 1623 else if( nOpCode == OPCODE_LIST ) eState = STATE_SEP; 1624 else if( nOpCode == OPCODE_OPEN ) eState = lclProcessOpen( nParenLevel ); 1625 else if( nOpCode == OPCODE_CLOSE ) eState = lclProcessClose( nParenLevel ); 1626 else eState = STATE_ERROR; 1627 break; 1628 case STATE_OPEN: 1629 if( nOpCode == OPCODE_PUSH ) eState = lclProcessRef( orRanges, aIt->Data, bAllowRelative, nFilterBySheet ); 1630 else if( nOpCode == OPCODE_SEP ) eState = STATE_SEP; 1631 else if( nOpCode == OPCODE_LIST ) eState = STATE_SEP; 1632 else if( nOpCode == OPCODE_OPEN ) eState = lclProcessOpen( nParenLevel ); 1633 else if( nOpCode == OPCODE_CLOSE ) eState = lclProcessClose( nParenLevel ); 1634 else eState = STATE_ERROR; 1635 break; 1636 case STATE_CLOSE: 1637 if( nOpCode == OPCODE_SEP ) eState = STATE_SEP; 1638 else if( nOpCode == OPCODE_LIST ) eState = STATE_SEP; 1639 else if( nOpCode == OPCODE_CLOSE ) eState = lclProcessClose( nParenLevel ); 1640 else eState = STATE_ERROR; 1641 break; 1642 default:; 1643 } 1644 } 1645 1646 if( eState == STATE_ERROR ) 1647 orRanges.clear(); 1648 else 1649 getAddressConverter().validateCellRangeList( orRanges, false ); 1650 } 1651 1652 bool FormulaProcessorBase::extractString( OUString& orString, const ApiTokenSequence& rTokens ) const 1653 { 1654 ApiTokenIterator aTokenIt( rTokens, OPCODE_SPACES, true ); 1655 return aTokenIt.is() && (aTokenIt->OpCode == OPCODE_PUSH) && (aTokenIt->Data >>= orString) && !(++aTokenIt).is(); 1656 } 1657 1658 bool FormulaProcessorBase::extractSpecialTokenInfo( ApiSpecialTokenInfo& orTokenInfo, const ApiTokenSequence& rTokens ) const 1659 { 1660 ApiTokenIterator aTokenIt( rTokens, OPCODE_SPACES, true ); 1661 return aTokenIt.is() && (aTokenIt->OpCode == OPCODE_BAD) && (aTokenIt->Data >>= orTokenInfo); 1662 } 1663 1664 void FormulaProcessorBase::convertStringToStringList( 1665 ApiTokenSequence& orTokens, sal_Unicode cStringSep, bool bTrimLeadingSpaces ) const 1666 { 1667 OUString aString; 1668 if( extractString( aString, orTokens ) && (aString.getLength() > 0) ) 1669 { 1670 ::std::vector< ApiToken > aNewTokens; 1671 sal_Int32 nPos = 0; 1672 sal_Int32 nLen = aString.getLength(); 1673 while( (0 <= nPos) && (nPos < nLen) ) 1674 { 1675 OUString aEntry = aString.getToken( 0, cStringSep, nPos ); 1676 if( bTrimLeadingSpaces ) 1677 { 1678 sal_Int32 nStart = 0; 1679 while( (nStart < aEntry.getLength()) && (aEntry[ nStart ] == ' ') ) ++nStart; 1680 aEntry = aEntry.copy( nStart ); 1681 } 1682 if( !aNewTokens.empty() ) 1683 aNewTokens.push_back( ApiToken( OPCODE_SEP, Any() ) ); 1684 aNewTokens.push_back( ApiToken( OPCODE_PUSH, Any( aEntry ) ) ); 1685 } 1686 orTokens = ContainerHelper::vectorToSequence( aNewTokens ); 1687 } 1688 } 1689 1690 // ============================================================================ 1691 1692 } // namespace xls 1693 } // namespace oox 1694