1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: formulabase.cxx,v $
10 * $Revision: 1.5.20.7 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/xls/formulabase.hxx"
33 #include <rtl/strbuf.hxx>
34 #include <rtl/ustrbuf.hxx>
35 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36 #include <com/sun/star/table/XCellRange.hpp>
37 #include <com/sun/star/sheet/AddressConvention.hpp>
38 #include <com/sun/star/sheet/ReferenceFlags.hpp>
39 #include <com/sun/star/sheet/SingleReference.hpp>
40 #include <com/sun/star/sheet/ComplexReference.hpp>
41 #include <com/sun/star/sheet/FormulaLanguage.hpp>
42 #include <com/sun/star/sheet/FormulaMapGroup.hpp>
43 #include <com/sun/star/sheet/FormulaMapGroupSpecialOffset.hpp>
44 #include <com/sun/star/sheet/XFormulaOpCodeMapper.hpp>
45 #include <com/sun/star/sheet/XFormulaParser.hpp>
46 #include <com/sun/star/sheet/XFormulaTokens.hpp>
47 #include "properties.hxx"
48 #include "oox/helper/recordinputstream.hxx"
49 #include "oox/core/filterbase.hxx"
50 #include "oox/xls/biffinputstream.hxx"
53 using ::rtl::OStringBuffer
;
54 using ::rtl::OUString
;
55 using ::rtl::OUStringBuffer
;
56 using ::rtl::OStringToOUString
;
57 using ::rtl::OUStringToOString
;
58 using ::com::sun::star::lang::XMultiServiceFactory
;
59 using ::com::sun::star::uno::Any
;
60 using ::com::sun::star::uno::Reference
;
61 using ::com::sun::star::uno::Sequence
;
62 using ::com::sun::star::uno::Exception
;
63 using ::com::sun::star::uno::UNO_QUERY
;
64 using ::com::sun::star::uno::UNO_QUERY_THROW
;
65 using ::com::sun::star::table::CellAddress
;
66 using ::com::sun::star::table::CellRangeAddress
;
67 using ::com::sun::star::table::XCellRange
;
68 using ::com::sun::star::sheet::SingleReference
;
69 using ::com::sun::star::sheet::ComplexReference
;
70 using ::com::sun::star::sheet::FormulaToken
;
71 using ::com::sun::star::sheet::FormulaOpCodeMapEntry
;
72 using ::com::sun::star::sheet::XSpreadsheetDocument
;
73 using ::com::sun::star::sheet::XFormulaOpCodeMapper
;
74 using ::com::sun::star::sheet::XFormulaTokens
;
79 // reference helpers ==========================================================
81 BinSingleRef2d::BinSingleRef2d() :
89 void BinSingleRef2d::setOobData( sal_uInt16 nCol
, sal_Int32 nRow
, bool bRelativeAsOffset
)
91 mnCol
= nCol
& OOBIN_TOK_REF_COLMASK
;
92 mnRow
= nRow
& OOBIN_TOK_REF_ROWMASK
;
93 mbColRel
= getFlag( nCol
, OOBIN_TOK_REF_COLREL
);
94 mbRowRel
= getFlag( nCol
, OOBIN_TOK_REF_ROWREL
);
95 if( bRelativeAsOffset
&& mbColRel
&& (mnCol
> (OOBIN_TOK_REF_COLMASK
>> 1)) )
96 mnCol
-= (OOBIN_TOK_REF_COLMASK
+ 1);
97 if( bRelativeAsOffset
&& mbRowRel
&& (mnRow
> (OOBIN_TOK_REF_ROWMASK
>> 1)) )
98 mnRow
-= (OOBIN_TOK_REF_ROWMASK
+ 1);
101 void BinSingleRef2d::setBiff2Data( sal_uInt8 nCol
, sal_uInt16 nRow
, bool bRelativeAsOffset
)
104 mnRow
= nRow
& BIFF_TOK_REF_ROWMASK
;
105 mbColRel
= getFlag( nRow
, BIFF_TOK_REF_COLREL
);
106 mbRowRel
= getFlag( nRow
, BIFF_TOK_REF_ROWREL
);
107 if( bRelativeAsOffset
&& mbColRel
&& (mnCol
>= 0x80) )
109 if( bRelativeAsOffset
&& mbRowRel
&& (mnRow
> (BIFF_TOK_REF_ROWMASK
>> 1)) )
110 mnRow
-= (BIFF_TOK_REF_ROWMASK
+ 1);
113 void BinSingleRef2d::setBiff8Data( sal_uInt16 nCol
, sal_uInt16 nRow
, bool bRelativeAsOffset
)
115 mnCol
= nCol
& BIFF_TOK_REF_COLMASK
;
117 mbColRel
= getFlag( nCol
, BIFF_TOK_REF_COLREL
);
118 mbRowRel
= getFlag( nCol
, BIFF_TOK_REF_ROWREL
);
119 if( bRelativeAsOffset
&& mbColRel
&& (mnCol
> (BIFF_TOK_REF_COLMASK
>> 1)) )
120 mnCol
-= (BIFF_TOK_REF_COLMASK
+ 1);
121 if( bRelativeAsOffset
&& mbRowRel
&& (mnRow
>= 0x8000) )
125 void BinSingleRef2d::readOobData( RecordInputStream
& rStrm
, bool bRelativeAsOffset
)
129 rStrm
>> nRow
>> nCol
;
130 setOobData( nCol
, nRow
, bRelativeAsOffset
);
133 void BinSingleRef2d::readBiff2Data( BiffInputStream
& rStrm
, bool bRelativeAsOffset
)
137 rStrm
>> nRow
>> nCol
;
138 setBiff2Data( nCol
, nRow
, bRelativeAsOffset
);
141 void BinSingleRef2d::readBiff8Data( BiffInputStream
& rStrm
, bool bRelativeAsOffset
)
143 sal_uInt16 nRow
, nCol
;
144 rStrm
>> nRow
>> nCol
;
145 setBiff8Data( nCol
, nRow
, bRelativeAsOffset
);
148 // ----------------------------------------------------------------------------
150 void BinComplexRef2d::readOobData( RecordInputStream
& rStrm
, bool bRelativeAsOffset
)
152 sal_Int32 nRow1
, nRow2
;
153 sal_uInt16 nCol1
, nCol2
;
154 rStrm
>> nRow1
>> nRow2
>> nCol1
>> nCol2
;
155 maRef1
.setOobData( nCol1
, nRow1
, bRelativeAsOffset
);
156 maRef2
.setOobData( nCol2
, nRow2
, bRelativeAsOffset
);
159 void BinComplexRef2d::readBiff2Data( BiffInputStream
& rStrm
, bool bRelativeAsOffset
)
161 sal_uInt16 nRow1
, nRow2
;
162 sal_uInt8 nCol1
, nCol2
;
163 rStrm
>> nRow1
>> nRow2
>> nCol1
>> nCol2
;
164 maRef1
.setBiff2Data( nCol1
, nRow1
, bRelativeAsOffset
);
165 maRef2
.setBiff2Data( nCol2
, nRow2
, bRelativeAsOffset
);
168 void BinComplexRef2d::readBiff8Data( BiffInputStream
& rStrm
, bool bRelativeAsOffset
)
170 sal_uInt16 nRow1
, nRow2
, nCol1
, nCol2
;
171 rStrm
>> nRow1
>> nRow2
>> nCol1
>> nCol2
;
172 maRef1
.setBiff8Data( nCol1
, nRow1
, bRelativeAsOffset
);
173 maRef2
.setBiff8Data( nCol2
, nRow2
, bRelativeAsOffset
);
176 // token vector, sequence =====================================================
178 ApiTokenVector::ApiTokenVector()
182 Any
& ApiTokenVector::append( sal_Int32 nOpCode
)
184 resize( size() + 1 );
185 back().OpCode
= nOpCode
;
189 // token sequence iterator ====================================================
191 ApiTokenIterator::ApiTokenIterator( const ApiTokenSequence
& rTokens
, sal_Int32 nSpacesOpCode
, bool bSkipSpaces
) :
192 mpToken( rTokens
.getConstArray() ),
193 mpTokenEnd( rTokens
.getConstArray() + rTokens
.getLength() ),
194 mnSpacesOpCode( nSpacesOpCode
),
195 mbSkipSpaces( bSkipSpaces
)
200 ApiTokenIterator::ApiTokenIterator( const ApiTokenIterator
& rIter
, bool bSkipSpaces
) :
201 mpToken( rIter
.mpToken
),
202 mpTokenEnd( rIter
.mpTokenEnd
),
203 mnSpacesOpCode( rIter
.mnSpacesOpCode
),
204 mbSkipSpaces( bSkipSpaces
)
209 ApiTokenIterator
& ApiTokenIterator::operator++()
219 void ApiTokenIterator::skipSpaces()
222 while( is() && (mpToken
->OpCode
== mnSpacesOpCode
) )
226 // function data ==============================================================
230 const size_t FUNCINFO_PARAMINFOCOUNT
= 5; /// Number of parameter type entries.
232 const sal_uInt16 FUNCFLAG_VOLATILE
= 0x0001; /// Result is volatile (e.g. NOW() function).
233 const sal_uInt16 FUNCFLAG_IMPORTONLY
= 0x0002; /// Only used in import filter.
234 const sal_uInt16 FUNCFLAG_EXPORTONLY
= 0x0004; /// Only used in export filter.
235 const sal_uInt16 FUNCFLAG_MACROCALL
= 0x0008; /// Function is simulated by macro call in Excel.
236 const sal_uInt16 FUNCFLAG_EXTERNAL
= 0x0010; /// Function is external in Calc.
237 const sal_uInt16 FUNCFLAG_MACROFUNC
= 0x0020; /// Function is a macro-sheet function.
238 const sal_uInt16 FUNCFLAG_MACROCMD
= 0x0040; /// Function is a macro-sheet command.
239 const sal_uInt16 FUNCFLAG_ALWAYSVAR
= 0x0080; /// Function is always represented by a tFuncVar token.
240 const sal_uInt16 FUNCFLAG_PARAMPAIRS
= 0x0100; /// Optional parameters are expected to appear in pairs.
242 const sal_uInt16 FUNCFLAG_FUNCLIBMASK
= 0xF000; /// Mask for function library bits.
243 const sal_uInt16 FUNCFLAG_EUROTOOL
= 0x1000; /// Function is part of the EuroTool add-in.
245 typedef ::boost::shared_ptr
< FunctionInfo
> FunctionInfoRef
;
249 const sal_Char
* mpcOdfFuncName
; /// ODF function name.
250 const sal_Char
* mpcOoxFuncName
; /// OOXML function name.
251 sal_uInt16 mnOobFuncId
; /// OOBIN function identifier.
252 sal_uInt16 mnBiffFuncId
; /// BIFF function identifier.
253 sal_uInt8 mnMinParamCount
; /// Minimum number of parameters.
254 sal_uInt8 mnMaxParamCount
; /// Maximum number of parameters.
255 sal_uInt8 mnRetClass
; /// BIFF token class of the return value.
256 FunctionParamInfo mpParamInfos
[ FUNCINFO_PARAMINFOCOUNT
]; /// Information about all parameters.
257 sal_uInt16 mnFlags
; /// Additional flags.
259 inline bool isSupported( bool bImportFilter
) const;
262 inline bool FunctionData::isSupported( bool bImportFilter
) const
264 /* For import filters: the FUNCFLAG_EXPORTONLY flag must not be set,
265 for export filters: the FUNCFLAG_IMPORTONLY flag must not be set. */
266 return !getFlag( mnFlags
, bImportFilter
? FUNCFLAG_EXPORTONLY
: FUNCFLAG_IMPORTONLY
);
269 const sal_uInt16 NOID
= SAL_MAX_UINT16
; /// No BIFF/OOBIN function identifier available.
270 const sal_uInt8 MX
= SAL_MAX_UINT8
; /// Maximum parameter count.
272 // abbreviations for function return token class
273 const sal_uInt8 R
= BIFF_TOKCLASS_REF
;
274 const sal_uInt8 V
= BIFF_TOKCLASS_VAL
;
275 const sal_uInt8 A
= BIFF_TOKCLASS_ARR
;
277 // abbreviations for parameter infos
278 #define RO { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_ORG, false }
279 #define RV { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_VAL, false }
280 #define RA { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_ARR, false }
281 #define RR { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_RPT, false }
282 #define RX { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_RPX, false }
283 #define VO { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_ORG, true }
284 #define VV { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_VAL, true }
285 #define VA { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_ARR, true }
286 #define VR { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_RPT, true }
287 #define VX { FUNC_PARAM_REGULAR, FUNC_PARAMCONV_RPX, true }
288 #define RO_E { FUNC_PARAM_EXCELONLY, FUNC_PARAMCONV_ORG, false }
289 #define VR_E { FUNC_PARAM_EXCELONLY, FUNC_PARAMCONV_RPT, true }
290 #define C { FUNC_PARAM_CALCONLY, FUNC_PARAMCONV_ORG, false }
292 // Note: parameter types of all macro sheet functions (FUNCFLAG_MACROFUNC/FUNCFLAG_MACROCMD) untested!
294 /** Functions new in BIFF2. */
295 static const FunctionData saFuncTableBiff2
[] =
297 { "COUNT", "COUNT", 0, 0, 0, MX
, V
, { RX
}, 0 },
298 { "IF", "IF", 1, 1, 2, 3, R
, { VO
, RO
}, 0 },
299 { "ISNA", "ISNA", 2, 2, 1, 1, V
, { VR
}, 0 },
300 { "ISERROR", "ISERROR", 3, 3, 1, 1, V
, { VR
}, 0 },
301 { "SUM", "SUM", 4, 4, 0, MX
, V
, { RX
}, 0 },
302 { "AVERAGE", "AVERAGE", 5, 5, 1, MX
, V
, { RX
}, 0 },
303 { "MIN", "MIN", 6, 6, 1, MX
, V
, { RX
}, 0 },
304 { "MAX", "MAX", 7, 7, 1, MX
, V
, { RX
}, 0 },
305 { "ROW", "ROW", 8, 8, 0, 1, V
, { RO
}, 0 },
306 { "COLUMN", "COLUMN", 9, 9, 0, 1, V
, { RO
}, 0 },
307 { "NA", "NA", 10, 10, 0, 0, V
, {}, 0 },
308 { "NPV", "NPV", 11, 11, 2, MX
, V
, { VR
, RX
}, 0 },
309 { "STDEV", "STDEV", 12, 12, 1, MX
, V
, { RX
}, 0 },
310 { "DOLLAR", "DOLLAR", 13, 13, 1, 2, V
, { VR
}, 0 },
311 { "FIXED", "FIXED", 14, 14, 1, 2, V
, { VR
, VR
, C
}, 0 },
312 { "SIN", "SIN", 15, 15, 1, 1, V
, { VR
}, 0 },
313 { "COS", "COS", 16, 16, 1, 1, V
, { VR
}, 0 },
314 { "TAN", "TAN", 17, 17, 1, 1, V
, { VR
}, 0 },
315 { "COT", "TAN", 17, 17, 1, 1, V
, { VR
}, FUNCFLAG_EXPORTONLY
},
316 { "ATAN", "ATAN", 18, 18, 1, 1, V
, { VR
}, 0 },
317 { "ACOT", "ATAN", 18, 18, 1, 1, V
, { VR
}, FUNCFLAG_EXPORTONLY
},
318 { "PI", "PI", 19, 19, 0, 0, V
, {}, 0 },
319 { "SQRT", "SQRT", 20, 20, 1, 1, V
, { VR
}, 0 },
320 { "EXP", "EXP", 21, 21, 1, 1, V
, { VR
}, 0 },
321 { "LN", "LN", 22, 22, 1, 1, V
, { VR
}, 0 },
322 { "LOG10", "LOG10", 23, 23, 1, 1, V
, { VR
}, 0 },
323 { "ABS", "ABS", 24, 24, 1, 1, V
, { VR
}, 0 },
324 { "INT", "INT", 25, 25, 1, 1, V
, { VR
}, 0 },
325 { "SIGN", "SIGN", 26, 26, 1, 1, V
, { VR
}, 0 },
326 { "ROUND", "ROUND", 27, 27, 2, 2, V
, { VR
}, 0 },
327 { "LOOKUP", "LOOKUP", 28, 28, 2, 3, V
, { VR
, RA
}, 0 },
328 { "INDEX", "INDEX", 29, 29, 2, 4, R
, { RA
, VV
}, 0 },
329 { "REPT", "REPT", 30, 30, 2, 2, V
, { VR
}, 0 },
330 { "MID", "MID", 31, 31, 3, 3, V
, { VR
}, 0 },
331 { "LEN", "LEN", 32, 32, 1, 1, V
, { VR
}, 0 },
332 { "VALUE", "VALUE", 33, 33, 1, 1, V
, { VR
}, 0 },
333 { "TRUE", "TRUE", 34, 34, 0, 0, V
, {}, 0 },
334 { "FALSE", "FALSE", 35, 35, 0, 0, V
, {}, 0 },
335 { "AND", "AND", 36, 36, 1, MX
, V
, { RX
}, 0 },
336 { "OR", "OR", 37, 37, 1, MX
, V
, { RX
}, 0 },
337 { "NOT", "NOT", 38, 38, 1, 1, V
, { VR
}, 0 },
338 { "MOD", "MOD", 39, 39, 2, 2, V
, { VR
}, 0 },
339 { "DCOUNT", "DCOUNT", 40, 40, 3, 3, V
, { RO
, RR
}, 0 },
340 { "DSUM", "DSUM", 41, 41, 3, 3, V
, { RO
, RR
}, 0 },
341 { "DAVERAGE", "DAVERAGE", 42, 42, 3, 3, V
, { RO
, RR
}, 0 },
342 { "DMIN", "DMIN", 43, 43, 3, 3, V
, { RO
, RR
}, 0 },
343 { "DMAX", "DMAX", 44, 44, 3, 3, V
, { RO
, RR
}, 0 },
344 { "DSTDEV", "DSTDEV", 45, 45, 3, 3, V
, { RO
, RR
}, 0 },
345 { "VAR", "VAR", 46, 46, 1, MX
, V
, { RX
}, 0 },
346 { "DVAR", "DVAR", 47, 47, 3, 3, V
, { RO
, RR
}, 0 },
347 { "TEXT", "TEXT", 48, 48, 2, 2, V
, { VR
}, 0 },
348 { "LINEST", "LINEST", 49, 49, 1, 2, A
, { RA
, RA
, C
, C
}, 0 },
349 { "TREND", "TREND", 50, 50, 1, 3, A
, { RA
, RA
, RA
, C
}, 0 },
350 { "LOGEST", "LOGEST", 51, 51, 1, 2, A
, { RA
, RA
, C
, C
}, 0 },
351 { "GROWTH", "GROWTH", 52, 52, 1, 3, A
, { RA
, RA
, RA
, C
}, 0 },
352 { 0, "RETURN", 55, 55, 0, 1, R
, { RO
}, FUNCFLAG_MACROFUNC
},
353 { "PV", "PV", 56, 56, 3, 5, V
, { VR
}, 0 },
354 { "FV", "FV", 57, 57, 3, 5, V
, { VR
}, 0 },
355 { "NPER", "NPER", 58, 58, 3, 5, V
, { VR
}, 0 },
356 { "PMT", "PMT", 59, 59, 3, 5, V
, { VR
}, 0 },
357 { "RATE", "RATE", 60, 60, 3, 6, V
, { VR
}, 0 },
358 { "MIRR", "MIRR", 61, 61, 3, 3, V
, { RA
, VR
}, 0 },
359 { "IRR", "IRR", 62, 62, 1, 2, V
, { RA
, VR
}, 0 },
360 { "RAND", "RAND", 63, 63, 0, 0, V
, {}, FUNCFLAG_VOLATILE
},
361 { "MATCH", "MATCH", 64, 64, 2, 3, V
, { VR
, RX
, RR
}, 0 },
362 { "DATE", "DATE", 65, 65, 3, 3, V
, { VR
}, 0 },
363 { "TIME", "TIME", 66, 66, 3, 3, V
, { VR
}, 0 },
364 { "DAY", "DAY", 67, 67, 1, 1, V
, { VR
}, 0 },
365 { "MONTH", "MONTH", 68, 68, 1, 1, V
, { VR
}, 0 },
366 { "YEAR", "YEAR", 69, 69, 1, 1, V
, { VR
}, 0 },
367 { "WEEKDAY", "WEEKDAY", 70, 70, 1, 1, V
, { VR
, C
}, 0 },
368 { "HOUR", "HOUR", 71, 71, 1, 1, V
, { VR
}, 0 },
369 { "MINUTE", "MINUTE", 72, 72, 1, 1, V
, { VR
}, 0 },
370 { "SECOND", "SECOND", 73, 73, 1, 1, V
, { VR
}, 0 },
371 { "NOW", "NOW", 74, 74, 0, 0, V
, {}, FUNCFLAG_VOLATILE
},
372 { "AREAS", "AREAS", 75, 75, 1, 1, V
, { RO
}, 0 },
373 { "ROWS", "ROWS", 76, 76, 1, 1, V
, { RO
}, 0 },
374 { "COLUMNS", "COLUMNS", 77, 77, 1, 1, V
, { RO
}, 0 },
375 { "OFFSET", "OFFSET", 78, 78, 3, 5, R
, { RO
, VR
}, FUNCFLAG_VOLATILE
},
376 { 0, "ABSREF", 79, 79, 2, 2, R
, { VR
, RO
}, FUNCFLAG_MACROFUNC
},
377 { "SEARCH", "SEARCH", 82, 82, 2, 3, V
, { VR
}, 0 },
378 { "TRANSPOSE", "TRANSPOSE", 83, 83, 1, 1, A
, { VO
}, 0 },
379 { "TYPE", "TYPE", 86, 86, 1, 1, V
, { VX
}, 0 },
380 { 0, "ACTIVE.CELL", 94, 94, 0, 0, R
, {}, FUNCFLAG_MACROFUNC
},
381 { "ATAN2", "ATAN2", 97, 97, 2, 2, V
, { VR
}, 0 },
382 { "ASIN", "ASIN", 98, 98, 1, 1, V
, { VR
}, 0 },
383 { "ACOS", "ACOS", 99, 99, 1, 1, V
, { VR
}, 0 },
384 { "CHOOSE", "CHOOSE", 100, 100, 2, MX
, R
, { VO
, RO
}, 0 },
385 { "HLOOKUP", "HLOOKUP", 101, 101, 3, 3, V
, { VV
, RO
, RO
, C
}, 0 },
386 { "VLOOKUP", "VLOOKUP", 102, 102, 3, 3, V
, { VV
, RO
, RO
, C
}, 0 },
387 { "ISREF", "ISREF", 105, 105, 1, 1, V
, { RX
}, 0 },
388 { "LOG", "LOG", 109, 109, 1, 2, V
, { VR
}, 0 },
389 { "CHAR", "CHAR", 111, 111, 1, 1, V
, { VR
}, 0 },
390 { "LOWER", "LOWER", 112, 112, 1, 1, V
, { VR
}, 0 },
391 { "UPPER", "UPPER", 113, 113, 1, 1, V
, { VR
}, 0 },
392 { "PROPER", "PROPER", 114, 114, 1, 1, V
, { VR
}, 0 },
393 { "LEFT", "LEFT", 115, 115, 1, 2, V
, { VR
}, 0 },
394 { "RIGHT", "RIGHT", 116, 116, 1, 2, V
, { VR
}, 0 },
395 { "EXACT", "EXACT", 117, 117, 2, 2, V
, { VR
}, 0 },
396 { "TRIM", "TRIM", 118, 118, 1, 1, V
, { VR
}, 0 },
397 { "REPLACE", "REPLACE", 119, 119, 4, 4, V
, { VR
}, 0 },
398 { "SUBSTITUTE", "SUBSTITUTE", 120, 120, 3, 4, V
, { VR
}, 0 },
399 { "CODE", "CODE", 121, 121, 1, 1, V
, { VR
}, 0 },
400 { "FIND", "FIND", 124, 124, 2, 3, V
, { VR
}, 0 },
401 { "CELL", "CELL", 125, 125, 1, 2, V
, { VV
, RO
}, FUNCFLAG_VOLATILE
},
402 { "ISERR", "ISERR", 126, 126, 1, 1, V
, { VR
}, 0 },
403 { "ISTEXT", "ISTEXT", 127, 127, 1, 1, V
, { VR
}, 0 },
404 { "ISNUMBER", "ISNUMBER", 128, 128, 1, 1, V
, { VR
}, 0 },
405 { "ISBLANK", "ISBLANK", 129, 129, 1, 1, V
, { VR
}, 0 },
406 { "T", "T", 130, 130, 1, 1, V
, { RO
}, 0 },
407 { "N", "N", 131, 131, 1, 1, V
, { RO
}, 0 },
408 { "DATEVALUE", "DATEVALUE", 140, 140, 1, 1, V
, { VR
}, 0 },
409 { "TIMEVALUE", "TIMEVALUE", 141, 141, 1, 1, V
, { VR
}, 0 },
410 { "SLN", "SLN", 142, 142, 3, 3, V
, { VR
}, 0 },
411 { "SYD", "SYD", 143, 143, 4, 4, V
, { VR
}, 0 },
412 { "DDB", "DDB", 144, 144, 4, 5, V
, { VR
}, 0 },
413 { "INDIRECT", "INDIRECT", 148, 148, 1, 2, R
, { VR
}, FUNCFLAG_VOLATILE
},
414 { 0, "ADD.BAR", 151, 151, 0, 0, V
, {}, FUNCFLAG_MACROFUNC
| FUNCFLAG_ALWAYSVAR
},
415 { 0, "ADD.MENU", 152, 152, 2, 2, V
, { VR
, RO
}, FUNCFLAG_MACROFUNC
| FUNCFLAG_ALWAYSVAR
},
416 { 0, "ADD.COMMAND", 153, 153, 3, 3, V
, { VR
, RO
}, FUNCFLAG_MACROFUNC
| FUNCFLAG_ALWAYSVAR
},
417 { "CLEAN", "CLEAN", 162, 162, 1, 1, V
, { VR
}, 0 },
418 { "MDETERM", "MDETERM", 163, 163, 1, 1, V
, { VA
}, 0 },
419 { "MINVERSE", "MINVERSE", 164, 164, 1, 1, A
, { VA
}, 0 },
420 { "MMULT", "MMULT", 165, 165, 2, 2, A
, { VA
}, 0 },
421 { "IPMT", "IPMT", 167, 167, 4, 6, V
, { VR
}, 0 },
422 { "PPMT", "PPMT", 168, 168, 4, 6, V
, { VR
}, 0 },
423 { "COUNTA", "COUNTA", 169, 169, 0, MX
, V
, { RX
}, 0 },
424 { "PRODUCT", "PRODUCT", 183, 183, 0, MX
, V
, { RX
}, 0 },
425 { "FACT", "FACT", 184, 184, 1, 1, V
, { VR
}, 0 },
426 { "DPRODUCT", "DPRODUCT", 189, 189, 3, 3, V
, { RO
, RR
}, 0 },
427 { "ISNONTEXT", "ISNONTEXT", 190, 190, 1, 1, V
, { VR
}, 0 },
428 { "STDEVP", "STDEVP", 193, 193, 1, MX
, V
, { RX
}, 0 },
429 { "VARP", "VARP", 194, 194, 1, MX
, V
, { RX
}, 0 },
430 { "DSTDEVP", "DSTDEVP", 195, 195, 3, 3, V
, { RO
, RR
}, 0 },
431 { "DVARP", "DVARP", 196, 196, 3, 3, V
, { RO
, RR
}, 0 },
432 { "TRUNC", "TRUNC", 197, 197, 1, 1, V
, { VR
, C
}, 0 },
433 { "ISLOGICAL", "ISLOGICAL", 198, 198, 1, 1, V
, { VR
}, 0 },
434 { "DCOUNTA", "DCOUNTA", 199, 199, 3, 3, V
, { RO
, RR
}, 0 },
435 { 0, "EXTERN.CALL", 255, 255, 1, MX
, R
, { RO_E
, RO
}, FUNCFLAG_IMPORTONLY
},
437 // *** macro sheet commands ***
439 { 0, "A1.R1C1", 30, 30, 0, 1, V
, { VR
}, FUNCFLAG_MACROCMD
},
440 { 0, "ADD.ARROW", 81, 81, 0, 0, V
, {}, FUNCFLAG_MACROCMD
},
441 { 0, "ACTIVATE", 103, 103, 0, 2, V
, { VR
}, FUNCFLAG_MACROCMD
},
442 { 0, "ACTIVATE.NEXT", 104, 104, 0, 0, V
, {}, FUNCFLAG_MACROCMD
},
443 { 0, "ACTIVATE.PREV", 105, 105, 0, 0, V
, {}, FUNCFLAG_MACROCMD
}
446 /** Functions new in BIFF3. */
447 static const FunctionData saFuncTableBiff3
[] =
449 { "LINEST", "LINEST", 49, 49, 1, 4, A
, { RA
, RA
, VV
}, 0 }, // BIFF2: 1-2, BIFF3: 1-4
450 { "TREND", "TREND", 50, 50, 1, 4, A
, { RA
, RA
, RA
, VV
}, 0 }, // BIFF2: 1-3, BIFF3: 1-4
451 { "LOGEST", "LOGEST", 51, 51, 1, 4, A
, { RA
, RA
, VV
}, 0 }, // BIFF2: 1-2, BIFF3: 1-4
452 { "GROWTH", "GROWTH", 52, 52, 1, 4, A
, { RA
, RA
, RA
, VV
}, 0 }, // BIFF2: 1-3, BIFF3: 1-4
453 { 0, "ADD.BAR", 151, 151, 0, 1, V
, { VR
}, FUNCFLAG_MACROFUNC
}, // BIFF2: 0, BIFF3: 0-1
454 { 0, "ADD.MENU", 152, 152, 2, 3, V
, { VR
, RO
}, FUNCFLAG_MACROFUNC
}, // BIFF2: 2, BIFF3: 2-3
455 { 0, "ADD.COMMAND", 153, 153, 3, 4, V
, { VR
, RO
}, FUNCFLAG_MACROFUNC
}, // BIFF2: 3, BIFF3: 3-4
456 { "TRUNC", "TRUNC", 197, 197, 1, 2, V
, { VR
}, 0 }, // BIFF2: 1, BIFF3: 1-2
457 { "DOLLAR", "USDOLLAR", 204, 204, 1, 2, V
, { VR
}, FUNCFLAG_IMPORTONLY
},
458 { 0/*"FIND"*/, "FINDB", 205, 205, 2, 3, V
, { VR
}, 0 },
459 { 0/*"SEARCH"*/, "SEARCHB", 206, 206, 2, 3, V
, { VR
}, 0 },
460 { 0/*"REPLACE"*/, "REPLACEB", 207, 207, 4, 4, V
, { VR
}, 0 },
461 { 0/*"LEFT"*/, "LEFTB", 208, 208, 1, 2, V
, { VR
}, 0 },
462 { 0/*"RIGHT"*/, "RIGHTB", 209, 209, 1, 2, V
, { VR
}, 0 },
463 { 0/*"MID"*/, "MIDB", 210, 210, 3, 3, V
, { VR
}, 0 },
464 { 0/*"LEN"*/, "LENB", 211, 211, 1, 1, V
, { VR
}, 0 },
465 { "ROUNDUP", "ROUNDUP", 212, 212, 2, 2, V
, { VR
}, 0 },
466 { "ROUNDDOWN", "ROUNDDOWN", 213, 213, 2, 2, V
, { VR
}, 0 },
467 { "ASC", "ASC", 214, 214, 1, 1, V
, { VR
}, 0 },
468 { "JIS", "DBCS", 215, 215, 1, 1, V
, { VR
}, 0 },
469 { "ADDRESS", "ADDRESS", 219, 219, 2, 5, V
, { VR
}, 0 },
470 { "DAYS360", "DAYS360", 220, 220, 2, 2, V
, { VR
, VR
, C
}, 0 },
471 { "TODAY", "TODAY", 221, 221, 0, 0, V
, {}, FUNCFLAG_VOLATILE
},
472 { "VDB", "VDB", 222, 222, 5, 7, V
, { VR
}, 0 },
473 { "MEDIAN", "MEDIAN", 227, 227, 1, MX
, V
, { RX
}, 0 },
474 { "SUMPRODUCT", "SUMPRODUCT", 228, 228, 1, MX
, V
, { VA
}, 0 },
475 { "SINH", "SINH", 229, 229, 1, 1, V
, { VR
}, 0 },
476 { "COSH", "COSH", 230, 230, 1, 1, V
, { VR
}, 0 },
477 { "TANH", "TANH", 231, 231, 1, 1, V
, { VR
}, 0 },
478 { "COTH", "TANH", 231, 231, 1, 1, V
, { VR
}, FUNCFLAG_EXPORTONLY
},
479 { "ASINH", "ASINH", 232, 232, 1, 1, V
, { VR
}, 0 },
480 { "ACOSH", "ACOSH", 233, 233, 1, 1, V
, { VR
}, 0 },
481 { "ATANH", "ATANH", 234, 234, 1, 1, V
, { VR
}, 0 },
482 { "ACOTH", "ATANH", 234, 234, 1, 1, V
, { VR
}, FUNCFLAG_EXPORTONLY
},
483 { "DGET", "DGET", 235, 235, 3, 3, V
, { RO
, RR
}, 0 },
484 { "INFO", "INFO", 244, 244, 1, 1, V
, { VR
}, FUNCFLAG_VOLATILE
}
487 /** Functions new in BIFF4. */
488 static const FunctionData saFuncTableBiff4
[] =
490 { "FIXED", "FIXED", 14, 14, 1, 3, V
, { VR
}, 0 }, // BIFF2-3: 1-2, BIFF4: 1-3
491 { "RANK", "RANK", 216, 216, 2, 3, V
, { VR
, RO
, VR
}, 0 },
492 { "DB", "DB", 247, 247, 4, 5, V
, { VR
}, 0 },
493 { "FREQUENCY", "FREQUENCY", 252, 252, 2, 2, A
, { RA
}, 0 },
494 { "ORG.OPENOFFICE.ERRORTYPE","ERROR.TYPE", 261, 261, 1, 1, V
, { VR
}, 0 },
495 { "AVEDEV", "AVEDEV", 269, 269, 1, MX
, V
, { RX
}, 0 },
496 { "BETADIST", "BETADIST", 270, 270, 3, 5, V
, { VR
}, 0 },
497 { "GAMMALN", "GAMMALN", 271, 271, 1, 1, V
, { VR
}, 0 },
498 { "BETAINV", "BETAINV", 272, 272, 3, 5, V
, { VR
}, 0 },
499 { "BINOMDIST", "BINOMDIST", 273, 273, 4, 4, V
, { VR
}, 0 },
500 { "LEGACY.CHIDIST", "CHIDIST", 274, 274, 2, 2, V
, { VR
}, 0 },
501 { "LEGACY.CHIINV", "CHIINV", 275, 275, 2, 2, V
, { VR
}, 0 },
502 { "COMBIN", "COMBIN", 276, 276, 2, 2, V
, { VR
}, 0 },
503 { "CONFIDENCE", "CONFIDENCE", 277, 277, 3, 3, V
, { VR
}, 0 },
504 { "CRITBINOM", "CRITBINOM", 278, 278, 3, 3, V
, { VR
}, 0 },
505 { "EVEN", "EVEN", 279, 279, 1, 1, V
, { VR
}, 0 },
506 { "EXPONDIST", "EXPONDIST", 280, 280, 3, 3, V
, { VR
}, 0 },
507 { "LEGACY.FDIST", "FDIST", 281, 281, 3, 3, V
, { VR
}, 0 },
508 { "LEGACY.FINV", "FINV", 282, 282, 3, 3, V
, { VR
}, 0 },
509 { "FISHER", "FISHER", 283, 283, 1, 1, V
, { VR
}, 0 },
510 { "FISHERINV", "FISHERINV", 284, 284, 1, 1, V
, { VR
}, 0 },
511 { "FLOOR", "FLOOR", 285, 285, 2, 2, V
, { VR
, VR
, C
}, 0 },
512 { "GAMMADIST", "GAMMADIST", 286, 286, 4, 4, V
, { VR
}, 0 },
513 { "GAMMAINV", "GAMMAINV", 287, 287, 3, 3, V
, { VR
}, 0 },
514 { "CEILING", "CEILING", 288, 288, 2, 2, V
, { VR
, VR
, C
}, 0 },
515 { "HYPGEOMDIST", "HYPGEOMDIST", 289, 289, 4, 4, V
, { VR
}, 0 },
516 { "LOGNORMDIST", "LOGNORMDIST", 290, 290, 3, 3, V
, { VR
}, 0 },
517 { "LOGINV", "LOGINV", 291, 291, 3, 3, V
, { VR
}, 0 },
518 { "NEGBINOMDIST", "NEGBINOMDIST", 292, 292, 3, 3, V
, { VR
}, 0 },
519 { "NORMDIST", "NORMDIST", 293, 293, 4, 4, V
, { VR
}, 0 },
520 { "LEGACY.NORMSDIST", "NORMSDIST", 294, 294, 1, 1, V
, { VR
}, 0 },
521 { "NORMINV", "NORMINV", 295, 295, 3, 3, V
, { VR
}, 0 },
522 { "LEGACY.NORMSINV", "NORMSINV", 296, 296, 1, 1, V
, { VR
}, 0 },
523 { "STANDARDIZE", "STANDARDIZE", 297, 297, 3, 3, V
, { VR
}, 0 },
524 { "ODD", "ODD", 298, 298, 1, 1, V
, { VR
}, 0 },
525 { "PERMUT", "PERMUT", 299, 299, 2, 2, V
, { VR
}, 0 },
526 { "POISSON", "POISSON", 300, 300, 3, 3, V
, { VR
}, 0 },
527 { "TDIST", "TDIST", 301, 301, 3, 3, V
, { VR
}, 0 },
528 { "WEIBULL", "WEIBULL", 302, 302, 4, 4, V
, { VR
}, 0 },
529 { "SUMXMY2", "SUMXMY2", 303, 303, 2, 2, V
, { VA
}, 0 },
530 { "SUMX2MY2", "SUMX2MY2", 304, 304, 2, 2, V
, { VA
}, 0 },
531 { "SUMX2PY2", "SUMX2PY2", 305, 305, 2, 2, V
, { VA
}, 0 },
532 { "LEGACY.CHITEST", "CHITEST", 306, 306, 2, 2, V
, { VA
}, 0 },
533 { "CORREL", "CORREL", 307, 307, 2, 2, V
, { VA
}, 0 },
534 { "COVAR", "COVAR", 308, 308, 2, 2, V
, { VA
}, 0 },
535 { "FORECAST", "FORECAST", 309, 309, 3, 3, V
, { VR
, VA
}, 0 },
536 { "FTEST", "FTEST", 310, 310, 2, 2, V
, { VA
}, 0 },
537 { "INTERCEPT", "INTERCEPT", 311, 311, 2, 2, V
, { VA
}, 0 },
538 { "PEARSON", "PEARSON", 312, 312, 2, 2, V
, { VA
}, 0 },
539 { "RSQ", "RSQ", 313, 313, 2, 2, V
, { VA
}, 0 },
540 { "STEYX", "STEYX", 314, 314, 2, 2, V
, { VA
}, 0 },
541 { "SLOPE", "SLOPE", 315, 315, 2, 2, V
, { VA
}, 0 },
542 { "TTEST", "TTEST", 316, 316, 4, 4, V
, { VA
, VA
, VR
}, 0 },
543 { "PROB", "PROB", 317, 317, 3, 4, V
, { VA
, VA
, VR
}, 0 },
544 { "DEVSQ", "DEVSQ", 318, 318, 1, MX
, V
, { RX
}, 0 },
545 { "GEOMEAN", "GEOMEAN", 319, 319, 1, MX
, V
, { RX
}, 0 },
546 { "HARMEAN", "HARMEAN", 320, 320, 1, MX
, V
, { RX
}, 0 },
547 { "SUMSQ", "SUMSQ", 321, 321, 0, MX
, V
, { RX
}, 0 },
548 { "KURT", "KURT", 322, 322, 1, MX
, V
, { RX
}, 0 },
549 { "SKEW", "SKEW", 323, 323, 1, MX
, V
, { RX
}, 0 },
550 { "ZTEST", "ZTEST", 324, 324, 2, 3, V
, { RX
, VR
}, 0 },
551 { "LARGE", "LARGE", 325, 325, 2, 2, V
, { RX
, VR
}, 0 },
552 { "SMALL", "SMALL", 326, 326, 2, 2, V
, { RX
, VR
}, 0 },
553 { "QUARTILE", "QUARTILE", 327, 327, 2, 2, V
, { RX
, VR
}, 0 },
554 { "PERCENTILE", "PERCENTILE", 328, 328, 2, 2, V
, { RX
, VR
}, 0 },
555 { "PERCENTRANK", "PERCENTRANK", 329, 329, 2, 3, V
, { RX
, VR
, VR_E
}, 0 },
556 { "MODE", "MODE", 330, 330, 1, MX
, V
, { VA
}, 0 },
557 { "TRIMMEAN", "TRIMMEAN", 331, 331, 2, 2, V
, { RX
, VR
}, 0 },
558 { "TINV", "TINV", 332, 332, 2, 2, V
, { VR
}, 0 },
560 // *** Analysis add-in ***
562 { "HEX2BIN", "HEX2BIN", 384, NOID
, 1, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
563 { "HEX2DEC", "HEX2DEC", 385, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
564 { "HEX2OCT", "HEX2OCT", 386, NOID
, 1, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
565 { "DEC2BIN", "DEC2BIN", 387, NOID
, 1, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
566 { "DEC2HEX", "DEC2HEX", 388, NOID
, 1, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
567 { "DEC2OCT", "DEC2OCT", 389, NOID
, 1, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
568 { "OCT2BIN", "OCT2BIN", 390, NOID
, 1, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
569 { "OCT2HEX", "OCT2HEX", 391, NOID
, 1, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
570 { "OCT2DEC", "OCT2DEC", 392, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
571 { "BIN2DEC", "BIN2DEC", 393, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
572 { "BIN2OCT", "BIN2OCT", 394, NOID
, 1, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
573 { "BIN2HEX", "BIN2HEX", 395, NOID
, 1, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
574 { "IMSUB", "IMSUB", 396, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
575 { "IMDIV", "IMDIV", 397, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
576 { "IMPOWER", "IMPOWER", 398, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
577 { "IMABS", "IMABS", 399, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
578 { "IMSQRT", "IMSQRT", 400, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
579 { "IMLN", "IMLN", 401, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
580 { "IMLOG2", "IMLOG2", 402, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
581 { "IMLOG10", "IMLOG10", 403, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
582 { "IMSIN", "IMSIN", 404, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
583 { "IMCOS", "IMCOS", 405, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
584 { "IMEXP", "IMEXP", 406, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
585 { "IMARGUMENT", "IMARGUMENT", 407, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
586 { "IMCONJUGATE", "IMCONJUGATE", 408, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
587 { "IMAGINARY", "IMAGINARY", 409, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
588 { "IMREAL", "IMREAL", 410, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
589 { "COMPLEX", "COMPLEX", 411, NOID
, 2, 3, V
, { RR
}, FUNCFLAG_EXTERNAL
},
590 { "IMSUM", "IMSUM", 412, NOID
, 1, MX
, V
, { RX
}, FUNCFLAG_EXTERNAL
},
591 { "IMPRODUCT", "IMPRODUCT", 413, NOID
, 1, MX
, V
, { RX
}, FUNCFLAG_EXTERNAL
},
592 { "SERIESSUM", "SERIESSUM", 414, NOID
, 4, 4, V
, { RR
, RR
, RR
, RX
}, FUNCFLAG_EXTERNAL
},
593 { "FACTDOUBLE", "FACTDOUBLE", 415, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
594 { "SQRTPI", "SQRTPI", 416, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
595 { "QUOTIENT", "QUOTIENT", 417, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
596 { "DELTA", "DELTA", 418, NOID
, 1, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
597 { "GESTEP", "GESTEP", 419, NOID
, 1, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
598 { "ISEVEN", "ISEVEN", 420, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
}, // Calc: builtin and add-in
599 { "ISODD", "ISODD", 421, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
}, // Calc: builtin and add-in
600 { "MROUND", "MROUND", 422, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
601 { "ERF", "ERF", 423, NOID
, 1, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
602 { "ERFC", "ERFC", 424, NOID
, 1, 1, V
, { RR
}, FUNCFLAG_EXTERNAL
},
603 { "BESSELJ", "BESSELJ", 425, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
604 { "BESSELK", "BESSELK", 426, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
605 { "BESSELY", "BESSELY", 427, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
606 { "BESSELI", "BESSELI", 428, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
607 { "XIRR", "XIRR", 429, NOID
, 2, 3, V
, { RX
, RX
, RR
}, FUNCFLAG_EXTERNAL
},
608 { "XNPV", "XNPV", 430, NOID
, 3, 3, V
, { RR
, RX
, RX
}, FUNCFLAG_EXTERNAL
},
609 { "PRICEMAT", "PRICEMAT", 431, NOID
, 5, 6, V
, { RR
}, FUNCFLAG_EXTERNAL
},
610 { "YIELDMAT", "YIELDMAT", 432, NOID
, 5, 6, V
, { RR
}, FUNCFLAG_EXTERNAL
},
611 { "INTRATE", "INTRATE", 433, NOID
, 4, 5, V
, { RR
}, FUNCFLAG_EXTERNAL
},
612 { "RECEIVED", "RECEIVED", 434, NOID
, 4, 5, V
, { RR
}, FUNCFLAG_EXTERNAL
},
613 { "DISC", "DISC", 435, NOID
, 4, 5, V
, { RR
}, FUNCFLAG_EXTERNAL
},
614 { "PRICEDISC", "PRICEDISC", 436, NOID
, 4, 5, V
, { RR
}, FUNCFLAG_EXTERNAL
},
615 { "YIELDDISC", "YIELDDISC", 437, NOID
, 4, 5, V
, { RR
}, FUNCFLAG_EXTERNAL
},
616 { "TBILLEQ", "TBILLEQ", 438, NOID
, 3, 3, V
, { RR
}, FUNCFLAG_EXTERNAL
},
617 { "TBILLPRICE", "TBILLPRICE", 439, NOID
, 3, 3, V
, { RR
}, FUNCFLAG_EXTERNAL
},
618 { "TBILLYIELD", "TBILLYIELD", 440, NOID
, 3, 3, V
, { RR
}, FUNCFLAG_EXTERNAL
},
619 { "PRICE", "PRICE", 441, NOID
, 6, 7, V
, { RR
}, FUNCFLAG_EXTERNAL
},
620 { "YIELD", "YIELD", 442, NOID
, 6, 7, V
, { RR
}, FUNCFLAG_EXTERNAL
},
621 { "DOLLARDE", "DOLLARDE", 443, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
622 { "DOLLARFR", "DOLLARFR", 444, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
623 { "NOMINAL", "NOMINAL", 445, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
}, // Calc: builtin and add-in
624 { "EFFECT", "EFFECT", 446, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
}, // Calc: builtin and add-in
625 { "CUMPRINC", "CUMPRINC", 447, NOID
, 6, 6, V
, { RR
}, FUNCFLAG_EXTERNAL
}, // Calc: builtin and add-in
626 { "CUMIPMT", "CUMIPMT", 448, NOID
, 6, 6, V
, { RR
}, FUNCFLAG_EXTERNAL
}, // Calc: builtin and add-in
627 { "EDATE", "EDATE", 449, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
628 { "EOMONTH", "EOMONTH", 450, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
629 { "YEARFRAC", "YEARFRAC", 451, NOID
, 2, 3, V
, { RR
}, FUNCFLAG_EXTERNAL
},
630 { "COUPDAYBS", "COUPDAYBS", 452, NOID
, 3, 4, V
, { RR
}, FUNCFLAG_EXTERNAL
},
631 { "COUPDAYS", "COUPDAYS", 453, NOID
, 3, 4, V
, { RR
}, FUNCFLAG_EXTERNAL
},
632 { "COUPDAYSNC", "COUPDAYSNC", 454, NOID
, 3, 4, V
, { RR
}, FUNCFLAG_EXTERNAL
},
633 { "COUPNCD", "COUPNCD", 455, NOID
, 3, 4, V
, { RR
}, FUNCFLAG_EXTERNAL
},
634 { "COUPNUM", "COUPNUM", 456, NOID
, 3, 4, V
, { RR
}, FUNCFLAG_EXTERNAL
},
635 { "COUPPCD", "COUPPCD", 457, NOID
, 3, 4, V
, { RR
}, FUNCFLAG_EXTERNAL
},
636 { "DURATION", "DURATION", 458, NOID
, 5, 6, V
, { RR
}, FUNCFLAG_EXTERNAL
}, // Calc: builtin and add-in
637 { "MDURATION", "MDURATION", 459, NOID
, 5, 6, V
, { RR
}, FUNCFLAG_EXTERNAL
},
638 { "ODDLPRICE", "ODDLPRICE", 460, NOID
, 7, 8, V
, { RR
}, FUNCFLAG_EXTERNAL
},
639 { "ODDLYIELD", "ODDLYIELD", 461, NOID
, 8, 9, V
, { RR
}, FUNCFLAG_EXTERNAL
},
640 { "ODDFPRICE", "ODDFPRICE", 462, NOID
, 8, 9, V
, { RR
}, FUNCFLAG_EXTERNAL
},
641 { "ODDFYIELD", "ODDFYIELD", 463, NOID
, 8, 9, V
, { RR
}, FUNCFLAG_EXTERNAL
},
642 { "RANDBETWEEN", "RANDBETWEEN", 464, NOID
, 2, 2, V
, { RR
}, FUNCFLAG_VOLATILE
| FUNCFLAG_EXTERNAL
},
643 { "WEEKNUM", "WEEKNUM", 465, NOID
, 1, 2, V
, { RR
}, FUNCFLAG_EXTERNAL
},
644 { "AMORDEGRC", "AMORDEGRC", 466, NOID
, 6, 7, V
, { RR
}, FUNCFLAG_EXTERNAL
},
645 { "AMORLINC", "AMORLINC", 467, NOID
, 6, 7, V
, { RR
}, FUNCFLAG_EXTERNAL
},
646 { "CONVERT", "CONVERT", 468, NOID
, 3, 3, V
, { RR
}, FUNCFLAG_EXTERNAL
}, // Calc: builtin and add-in
647 { "ACCRINT", "ACCRINT", 469, NOID
, 6, 7, V
, { RR
}, FUNCFLAG_EXTERNAL
},
648 { "ACCRINTM", "ACCRINTM", 470, NOID
, 4, 5, V
, { RR
}, FUNCFLAG_EXTERNAL
},
649 { "WORKDAY", "WORKDAY", 471, NOID
, 2, 3, V
, { RR
, RR
, RX
, C
}, FUNCFLAG_EXTERNAL
},
650 { "NETWORKDAYS", "NETWORKDAYS", 472, NOID
, 2, 3, V
, { RR
, RR
, RX
, C
}, FUNCFLAG_EXTERNAL
},
651 { "GCD", "GCD", 473, NOID
, 1, MX
, V
, { RX
}, FUNCFLAG_EXTERNAL
}, // Calc: builtin and add-in
652 { "MULTINOMIAL", "MULTINOMIAL", 474, NOID
, 1, MX
, V
, { RX
}, FUNCFLAG_EXTERNAL
},
653 { "LCM", "LCM", 475, NOID
, 1, MX
, V
, { RX
}, FUNCFLAG_EXTERNAL
}, // Calc: builtin and add-in
654 { "FVSCHEDULE", "FVSCHEDULE", 476, NOID
, 2, 2, V
, { RR
, RX
}, FUNCFLAG_EXTERNAL
},
656 // *** macro sheet commands ***
658 { 0, "ACTIVATE.NEXT", 104, 104, 0, 1, V
, { VR
}, FUNCFLAG_MACROCMD
}, // BIFF2-3: 0, BIFF4: 0-1
659 { 0, "ACTIVATE.PREV", 105, 105, 0, 1, V
, { VR
}, FUNCFLAG_MACROCMD
} // BIFF2-3: 0, BIFF4: 0-1
662 /** Functions new in BIFF5/BIFF7. */
663 static const FunctionData saFuncTableBiff5
[] =
665 { "WEEKDAY", "WEEKDAY", 70, 70, 1, 2, V
, { VR
}, 0 }, // BIFF2-4: 1, BIFF5: 1-2
666 { "HLOOKUP", "HLOOKUP", 101, 101, 3, 4, V
, { VV
, RO
, RO
, VV
}, 0 }, // BIFF2-4: 3, BIFF5: 3-4
667 { "VLOOKUP", "VLOOKUP", 102, 102, 3, 4, V
, { VV
, RO
, RO
, VV
}, 0 }, // BIFF2-4: 3, BIFF5: 3-4
668 { 0, "ADD.MENU", 152, 152, 2, 4, V
, { VR
, RO
, RO
, VR
}, FUNCFLAG_MACROFUNC
}, // BIFF3-4: 2-3, BIFF5: 2-4
669 { 0, "ADD.COMMAND", 153, 153, 3, 5, V
, { VR
, RO
, RO
, RO
, VR
}, FUNCFLAG_MACROFUNC
}, // BIFF3-4: 3-4, BIFF5: 3-5
670 { "DAYS360", "DAYS360", 220, 220, 2, 3, V
, { VR
}, 0 }, // BIFF3-4: 2, BIFF5: 2-3
671 { 0, "EXTERN.CALL", 255, 255, 1, MX
, R
, { RO_E
, RO
}, FUNCFLAG_EXPORTONLY
}, // MACRO or EXTERNAL
672 { "CONCATENATE", "CONCATENATE", 336, 336, 0, MX
, V
, { VR
}, 0 },
673 { "POWER", "POWER", 337, 337, 2, 2, V
, { VR
}, 0 },
674 { "RADIANS", "RADIANS", 342, 342, 1, 1, V
, { VR
}, 0 },
675 { "DEGREES", "DEGREES", 343, 343, 1, 1, V
, { VR
}, 0 },
676 { "SUBTOTAL", "SUBTOTAL", 344, 344, 2, MX
, V
, { VR
, RO
}, 0 },
677 { "SUMIF", "SUMIF", 345, 345, 2, 3, V
, { RO
, VR
, RO
}, 0 },
678 { "COUNTIF", "COUNTIF", 346, 346, 2, 2, V
, { RO
, VR
}, 0 },
679 { "COUNTBLANK", "COUNTBLANK", 347, 347, 1, 1, V
, { RO
}, 0 },
680 { "ISPMT", "ISPMT", 350, 350, 4, 4, V
, { VR
}, 0 },
681 { 0, "DATEDIF", 351, 351, 3, 3, V
, { VR
}, FUNCFLAG_IMPORTONLY
}, // not supported in Calc
682 { 0, "DATESTRING", 352, 352, 1, 1, V
, { VR
}, FUNCFLAG_IMPORTONLY
}, // not supported in Calc, missing in OOX spec
683 { 0, "NUMBERSTRING", 353, 353, 2, 2, V
, { VR
}, FUNCFLAG_IMPORTONLY
}, // not supported in Calc, missing in OOX spec
684 { "ROMAN", "ROMAN", 354, 354, 1, 2, V
, { VR
}, 0 },
686 // *** EuroTool add-in ***
688 { "EUROCONVERT", "EUROCONVERT", NOID
, NOID
, 3, 5, V
, { VR
}, FUNCFLAG_EUROTOOL
},
690 // *** macro sheet commands ***
692 { 0, "ADD.CHART.AUTOFORMAT", 390, 390, 0, 2, V
, { VR
}, FUNCFLAG_MACROCMD
},
693 { 0, "ADD.LIST.ITEM", 451, 451, 0, 2, V
, { VR
}, FUNCFLAG_MACROCMD
},
694 { 0, "ACTIVE.CELL.FONT", 476, 476, 0, 14, V
, { VR
}, FUNCFLAG_MACROCMD
}
697 /** Functions new in BIFF8. */
698 static const FunctionData saFuncTableBiff8
[] =
700 { "GETPIVOTDATA", "GETPIVOTDATA", 358, 358, 2, MX
, V
, { RR
, RR
, VR
, VR
}, FUNCFLAG_IMPORTONLY
| FUNCFLAG_PARAMPAIRS
},
701 { "HYPERLINK", "HYPERLINK", 359, 359, 1, 2, V
, { VV
, VO
}, 0 },
702 { 0, "PHONETIC", 360, 360, 1, 1, V
, { RO
}, FUNCFLAG_IMPORTONLY
},
703 { "AVERAGEA", "AVERAGEA", 361, 361, 1, MX
, V
, { RX
}, 0 },
704 { "MAXA", "MAXA", 362, 362, 1, MX
, V
, { RX
}, 0 },
705 { "MINA", "MINA", 363, 363, 1, MX
, V
, { RX
}, 0 },
706 { "STDEVPA", "STDEVPA", 364, 364, 1, MX
, V
, { RX
}, 0 },
707 { "VARPA", "VARPA", 365, 365, 1, MX
, V
, { RX
}, 0 },
708 { "STDEVA", "STDEVA", 366, 366, 1, MX
, V
, { RX
}, 0 },
709 { "VARA", "VARA", 367, 367, 1, MX
, V
, { RX
}, 0 },
710 { "COM.MICROSOFT.BAHTTEXT", "BAHTTEXT", 368, 368, 1, 1, V
, { VR
}, FUNCFLAG_MACROCALL
},
711 { 0, "THAIDAYOFWEEK", 369, 369, 1, 1, V
, { VR
}, FUNCFLAG_MACROCALL
},
712 { 0, "THAIDIGIT", 370, 370, 1, 1, V
, { VR
}, FUNCFLAG_MACROCALL
},
713 { 0, "THAIMONTHOFYEAR", 371, 371, 1, 1, V
, { VR
}, FUNCFLAG_MACROCALL
},
714 { 0, "THAINUMSOUND", 372, 372, 1, 1, V
, { VR
}, FUNCFLAG_MACROCALL
},
715 { 0, "THAINUMSTRING", 373, 373, 1, 1, V
, { VR
}, FUNCFLAG_MACROCALL
},
716 { 0, "THAISTRINGLENGTH", 374, 374, 1, 1, V
, { VR
}, FUNCFLAG_MACROCALL
},
717 { 0, "ISTHAIDIGIT", 375, 375, 1, 1, V
, { VR
}, FUNCFLAG_MACROCALL
},
718 { 0, "ROUNDBAHTDOWN", 376, 376, 1, 1, V
, { VR
}, FUNCFLAG_MACROCALL
},
719 { 0, "ROUNDBAHTUP", 377, 377, 1, 1, V
, { VR
}, FUNCFLAG_MACROCALL
},
720 { 0, "THAIYEAR", 378, 378, 1, 1, V
, { VR
}, FUNCFLAG_MACROCALL
},
721 { 0, "RTD", 379, 379, 3, 3, A
, { VR
, VR
, RO
}, 0 }
724 /** Functions new in OOX. */
725 static const FunctionData saFuncTableOox
[] =
727 { 0, "CUBEVALUE", 380, NOID
, 1, MX
, V
, { VR
, RX
}, 0 },
728 { 0, "CUBEMEMBER", 381, NOID
, 2, 3, V
, { VR
, RX
, VR
}, 0 },
729 { 0, "CUBEMEMBERPROPERTY", 382, NOID
, 3, 3, V
, { VR
}, 0 },
730 { 0, "CUBERANKEDMEMBER", 383, NOID
, 3, 4, V
, { VR
}, 0 },
731 { 0, "CUBEKPIMEMBER", 477, NOID
, 3, 4, V
, { VR
}, 0 },
732 { 0, "CUBESET", 478, NOID
, 2, 5, V
, { VR
, RX
, VR
}, 0 },
733 { 0, "CUBESETCOUNT", 479, NOID
, 1, 1, V
, { VR
}, 0 },
734 { 0, "IFERROR", 480, NOID
, 2, 2, V
, { VO
, RO
}, 0 },
735 { 0, "COUNTIFS", 481, NOID
, 2, MX
, V
, { RO
, VR
}, FUNCFLAG_PARAMPAIRS
},
736 { 0, "SUMIFS", 482, NOID
, 3, MX
, V
, { RO
, RO
, VR
}, FUNCFLAG_PARAMPAIRS
},
737 { 0, "AVERAGEIF", 483, NOID
, 2, 3, V
, { RO
, VR
, RO
}, 0 },
738 { 0, "AVERAGEIFS", 484, NOID
, 3, MX
, V
, { RO
, RO
, VR
}, 0 }
741 /** Functions defined by OpenFormula, but not supported by Calc or by Excel. */
742 static const FunctionData saFuncTableOdf
[] =
744 { "ARABIC", 0, NOID
, NOID
, 1, 1, V
, { VR
}, 0 },
745 { "B", 0, NOID
, NOID
, 3, 4, V
, { VR
}, 0 },
746 { "BASE", 0, NOID
, NOID
, 2, 3, V
, { VR
}, 0 },
747 { "BITAND", 0, NOID
, NOID
, 2, 2, V
, { VR
}, 0 },
748 { "BITLSHIFT", 0, NOID
, NOID
, 2, 2, V
, { VR
}, 0 },
749 { "BITOR", 0, NOID
, NOID
, 2, 2, V
, { VR
}, 0 },
750 { "BITRSHIFT", 0, NOID
, NOID
, 2, 2, V
, { VR
}, 0 },
751 { "BITXOR", 0, NOID
, NOID
, 2, 2, V
, { VR
}, 0 },
752 { "CHISQDIST", 0, NOID
, NOID
, 2, 3, V
, { VR
}, 0 },
753 { "CHISQINV", 0, NOID
, NOID
, 2, 2, V
, { VR
}, 0 },
754 { "COMBINA", 0, NOID
, NOID
, 2, 2, V
, { VR
}, 0 },
755 { "DAYS", 0, NOID
, NOID
, 2, 2, V
, { VR
}, 0 },
756 { "DDE", 0, NOID
, NOID
, 3, 4, V
, { VR
}, 0 },
757 { "DECIMAL", 0, NOID
, NOID
, 2, 2, V
, { VR
}, 0 },
758 { "FDIST", 0, NOID
, NOID
, 3, 4, V
, { VR
}, 0 },
759 { "FINV", 0, NOID
, NOID
, 3, 3, V
, { VR
}, 0 },
760 { "FORMULA", 0, NOID
, NOID
, 1, 1, V
, { RO
}, 0 },
761 { "GAMMA", 0, NOID
, NOID
, 1, 1, V
, { VR
}, 0 },
762 { "GAUSS", 0, NOID
, NOID
, 1, 1, V
, { VR
}, 0 },
763 { "IFNA", 0, NOID
, NOID
, 2, 2, V
, { VR
, RO
}, 0 },
764 { "ISFORMULA", 0, NOID
, NOID
, 1, 1, V
, { RO
}, 0 },
765 { "ISOWEEKNUM", 0, NOID
, NOID
, 1, 2, V
, { VR
}, 0 },
766 { "MULTIPLE.OPERATIONS", 0, NOID
, NOID
, 3, 5, V
, { RO
}, 0 },
767 { "MUNIT", 0, NOID
, NOID
, 1, 1, A
, { VR
}, 0 },
768 { "NUMBERVALUE", 0, NOID
, NOID
, 2, 2, V
, { VR
}, 0 },
769 { "PDURATION", 0, NOID
, NOID
, 3, 3, V
, { VR
}, 0 },
770 { "PERMUTATIONA", 0, NOID
, NOID
, 2, 2, V
, { VR
}, 0 },
771 { "PHI", 0, NOID
, NOID
, 1, 1, V
, { VR
}, 0 },
772 { "RRI", 0, NOID
, NOID
, 3, 3, V
, { VR
}, 0 },
773 { "SHEET", 0, NOID
, NOID
, 1, 1, V
, { RO
}, 0 },
774 { "SHEETS", 0, NOID
, NOID
, 0, 1, V
, { RO
}, 0 },
775 { "SKEWP", 0, NOID
, NOID
, 1, MX
, V
, { RX
}, 0 },
776 { "UNICHAR", 0, NOID
, NOID
, 1, 1, V
, { VR
}, 0 },
777 { "UNICODE", 0, NOID
, NOID
, 1, 1, V
, { VR
}, 0 },
778 { "XOR", 0, NOID
, NOID
, 1, MX
, V
, { RX
}, 0 }
781 // ----------------------------------------------------------------------------
783 const sal_Unicode API_TOKEN_OPEN
= '(';
784 const sal_Unicode API_TOKEN_CLOSE
= ')';
785 const sal_Unicode API_TOKEN_SEP
= ';';
787 const sal_Unicode API_TOKEN_ARRAY_OPEN
= '{';
788 const sal_Unicode API_TOKEN_ARRAY_CLOSE
= '}';
789 const sal_Unicode API_TOKEN_ARRAY_ROWSEP
= '|';
790 const sal_Unicode API_TOKEN_ARRAY_COLSEP
= ';';
794 // function info parameter class iterator =====================================
796 FunctionParamInfoIterator::FunctionParamInfoIterator( const FunctionInfo
& rFuncInfo
) :
797 mpParamInfo( rFuncInfo
.mpParamInfos
),
798 mpParamInfoEnd( rFuncInfo
.mpParamInfos
+ FUNCINFO_PARAMINFOCOUNT
),
799 mbParamPairs( rFuncInfo
.mbParamPairs
)
801 OSL_ENSURE( !mbParamPairs
|| (mpParamInfo
+ 1 < mpParamInfoEnd
),
802 "FunctionParamInfoIterator::FunctionParamInfoIterator - expecting at least 2 infos for paired parameters" );
805 const FunctionParamInfo
& FunctionParamInfoIterator::getParamInfo() const
807 static const FunctionParamInfo saInvalidInfo
= { FUNC_PARAM_NONE
, FUNC_PARAMCONV_ORG
, false };
808 return mpParamInfo
? *mpParamInfo
: saInvalidInfo
;
811 bool FunctionParamInfoIterator::isCalcOnlyParam() const
813 return mpParamInfo
&& (mpParamInfo
->meValid
== FUNC_PARAM_CALCONLY
);
816 bool FunctionParamInfoIterator::isExcelOnlyParam() const
818 return mpParamInfo
&& (mpParamInfo
->meValid
== FUNC_PARAM_EXCELONLY
);
821 FunctionParamInfoIterator
& FunctionParamInfoIterator::operator++()
825 // move pointer to next entry, if something explicit follows
826 if( (mpParamInfo
+ 1 < mpParamInfoEnd
) && (mpParamInfo
[ 1 ].meValid
!= FUNC_PARAM_NONE
) )
828 // points to last info, but parameter pairs expected, move to previous info
829 else if( mbParamPairs
)
831 // if last parameter type is 'Excel-only' or 'Calc-only', do not repeat it
832 else if( isExcelOnlyParam() || isCalcOnlyParam() )
834 // otherwise: repeat last parameter class
839 // function provider ==========================================================
841 struct FunctionProviderImpl
843 typedef RefMap
< OUString
, FunctionInfo
> FuncNameMap
;
844 typedef RefMap
< sal_uInt16
, FunctionInfo
> FuncIdMap
;
846 FunctionInfoVector maFuncs
; /// All function infos in one list.
847 FuncNameMap maOdfFuncs
; /// Maps ODF function names to function data.
848 FuncNameMap maOoxFuncs
; /// Maps OOXML function names to function data.
849 FuncIdMap maOobFuncs
; /// Maps OOBIN function indexes to function data.
850 FuncIdMap maBiffFuncs
; /// Maps BIFF function indexes to function data.
851 FuncNameMap maMacroFuncs
; /// Maps macro function names to function data.
853 explicit FunctionProviderImpl( FilterType eFilter
, BiffType eBiff
, bool bImportFilter
);
856 /** Creates and inserts a function info struct from the passed function data. */
857 void initFunc( const FunctionData
& rFuncData
, sal_uInt8 nMaxParam
);
859 /** Initializes the members from the passed function data list. */
861 const FunctionData
* pBeg
, const FunctionData
* pEnd
,
862 sal_uInt8 nMaxParam
, bool bImportFilter
);
865 // ----------------------------------------------------------------------------
867 FunctionProviderImpl::FunctionProviderImpl( FilterType eFilter
, BiffType eBiff
, bool bImportFilter
)
869 OSL_ENSURE( bImportFilter
, "FunctionProviderImpl::FunctionProviderImpl - need special handling for macro call functions" );
870 sal_uInt8 nMaxParam
= 0;
874 nMaxParam
= OOX_MAX_PARAMCOUNT
;
875 eBiff
= BIFF8
; // insert all BIFF function tables, then the OOX table
878 nMaxParam
= BIFF_MAX_PARAMCOUNT
;
881 OSL_ENSURE( false, "FunctionProviderImpl::FunctionProviderImpl - invalid filter type" );
884 OSL_ENSURE( eBiff
!= BIFF_UNKNOWN
, "FunctionProviderImpl::FunctionProviderImpl - invalid BIFF type" );
886 /* Add functions supported in the current BIFF version only. Function
887 tables from later BIFF versions may overwrite single functions from
890 initFuncs( saFuncTableBiff2
, STATIC_ARRAY_END( saFuncTableBiff2
), nMaxParam
, bImportFilter
);
892 initFuncs( saFuncTableBiff3
, STATIC_ARRAY_END( saFuncTableBiff3
), nMaxParam
, bImportFilter
);
894 initFuncs( saFuncTableBiff4
, STATIC_ARRAY_END( saFuncTableBiff4
), nMaxParam
, bImportFilter
);
896 initFuncs( saFuncTableBiff5
, STATIC_ARRAY_END( saFuncTableBiff5
), nMaxParam
, bImportFilter
);
898 initFuncs( saFuncTableBiff8
, STATIC_ARRAY_END( saFuncTableBiff8
), nMaxParam
, bImportFilter
);
899 if( eFilter
== FILTER_OOX
)
900 initFuncs( saFuncTableOox
, STATIC_ARRAY_END( saFuncTableOox
), nMaxParam
, bImportFilter
);
903 void FunctionProviderImpl::initFunc( const FunctionData
& rFuncData
, sal_uInt8 nMaxParam
)
905 // create a function info object
906 FunctionInfoRef
xFuncInfo( new FunctionInfo
);
907 if( rFuncData
.mpcOdfFuncName
)
908 xFuncInfo
->maOdfFuncName
= OUString::createFromAscii( rFuncData
.mpcOdfFuncName
);
909 if( rFuncData
.mpcOoxFuncName
)
910 xFuncInfo
->maOoxFuncName
= OUString::createFromAscii( rFuncData
.mpcOoxFuncName
);
911 if( getFlag( rFuncData
.mnFlags
, FUNCFLAG_MACROCALL
) )
912 xFuncInfo
->maBiffMacroName
= CREATE_OUSTRING( "_xlfn." ) + xFuncInfo
->maOoxFuncName
;
913 switch( rFuncData
.mnFlags
& FUNCFLAG_FUNCLIBMASK
)
915 case FUNCFLAG_EUROTOOL
: xFuncInfo
->meFuncLibType
= FUNCLIB_EUROTOOL
; break;
916 default: xFuncInfo
->meFuncLibType
= FUNCLIB_UNKNOWN
;
918 xFuncInfo
->mnApiOpCode
= -1;
919 xFuncInfo
->mnOobFuncId
= rFuncData
.mnOobFuncId
;
920 xFuncInfo
->mnBiffFuncId
= rFuncData
.mnBiffFuncId
;
921 xFuncInfo
->mnMinParamCount
= rFuncData
.mnMinParamCount
;
922 xFuncInfo
->mnMaxParamCount
= (rFuncData
.mnMaxParamCount
== MX
) ? nMaxParam
: rFuncData
.mnMaxParamCount
;
923 xFuncInfo
->mnRetClass
= rFuncData
.mnRetClass
;
924 xFuncInfo
->mpParamInfos
= rFuncData
.mpParamInfos
;
925 xFuncInfo
->mbParamPairs
= getFlag( rFuncData
.mnFlags
, FUNCFLAG_PARAMPAIRS
);
926 xFuncInfo
->mbVolatile
= getFlag( rFuncData
.mnFlags
, FUNCFLAG_VOLATILE
);
927 xFuncInfo
->mbExternal
= getFlag( rFuncData
.mnFlags
, FUNCFLAG_EXTERNAL
);
928 bool bMacroCmd
= getFlag( rFuncData
.mnFlags
, FUNCFLAG_MACROCMD
);
929 xFuncInfo
->mbMacroFunc
= bMacroCmd
|| getFlag( rFuncData
.mnFlags
, FUNCFLAG_MACROFUNC
);
930 xFuncInfo
->mbVarParam
= bMacroCmd
|| (rFuncData
.mnMinParamCount
!= rFuncData
.mnMaxParamCount
) || getFlag( rFuncData
.mnFlags
, FUNCFLAG_ALWAYSVAR
);
932 setFlag( xFuncInfo
->mnOobFuncId
, BIFF_TOK_FUNCVAR_CMD
, bMacroCmd
);
933 setFlag( xFuncInfo
->mnBiffFuncId
, BIFF_TOK_FUNCVAR_CMD
, bMacroCmd
);
935 // insert the function info into the member maps
936 maFuncs
.push_back( xFuncInfo
);
937 if( xFuncInfo
->maOdfFuncName
.getLength() > 0 )
938 maOdfFuncs
[ xFuncInfo
->maOdfFuncName
] = xFuncInfo
;
939 if( xFuncInfo
->maOoxFuncName
.getLength() > 0 )
940 maOoxFuncs
[ xFuncInfo
->maOoxFuncName
] = xFuncInfo
;
941 if( xFuncInfo
->mnOobFuncId
!= NOID
)
942 maOobFuncs
[ xFuncInfo
->mnOobFuncId
] = xFuncInfo
;
943 if( xFuncInfo
->mnBiffFuncId
!= NOID
)
944 maBiffFuncs
[ xFuncInfo
->mnBiffFuncId
] = xFuncInfo
;
945 if( xFuncInfo
->maBiffMacroName
.getLength() > 0 )
946 maMacroFuncs
[ xFuncInfo
->maBiffMacroName
] = xFuncInfo
;
949 void FunctionProviderImpl::initFuncs( const FunctionData
* pBeg
, const FunctionData
* pEnd
, sal_uInt8 nMaxParam
, bool bImportFilter
)
951 for( const FunctionData
* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
952 if( pIt
->isSupported( bImportFilter
) )
953 initFunc( *pIt
, nMaxParam
);
956 // ----------------------------------------------------------------------------
958 FunctionProvider::FunctionProvider( FilterType eFilter
, BiffType eBiff
, bool bImportFilter
) :
959 mxFuncImpl( new FunctionProviderImpl( eFilter
, eBiff
, bImportFilter
) )
963 FunctionProvider::~FunctionProvider()
967 const FunctionInfo
* FunctionProvider::getFuncInfoFromOdfFuncName( const OUString
& rFuncName
) const
969 return mxFuncImpl
->maOdfFuncs
.get( rFuncName
).get();
972 const FunctionInfo
* FunctionProvider::getFuncInfoFromOoxFuncName( const OUString
& rFuncName
) const
974 return mxFuncImpl
->maOoxFuncs
.get( rFuncName
).get();
977 const FunctionInfo
* FunctionProvider::getFuncInfoFromOobFuncId( sal_uInt16 nFuncId
) const
979 return mxFuncImpl
->maOobFuncs
.get( nFuncId
).get();
982 const FunctionInfo
* FunctionProvider::getFuncInfoFromBiffFuncId( sal_uInt16 nFuncId
) const
984 return mxFuncImpl
->maBiffFuncs
.get( nFuncId
).get();
987 const FunctionInfo
* FunctionProvider::getFuncInfoFromMacroName( const OUString
& rFuncName
) const
989 return mxFuncImpl
->maMacroFuncs
.get( rFuncName
).get();
992 FunctionLibraryType
FunctionProvider::getFuncLibTypeFromLibraryName( const OUString
& rLibraryName
) const
994 #define OOX_XLS_IS_LIBNAME( libname, basename ) (libname.equalsIgnoreAsciiCaseAscii( basename ".XLA" ) || libname.equalsIgnoreAsciiCaseAscii( basename ".XLAM" ))
996 // the EUROTOOL add-in containing the EUROCONVERT function
997 if( OOX_XLS_IS_LIBNAME( rLibraryName
, "EUROTOOL" ) )
998 return FUNCLIB_EUROTOOL
;
1000 #undef OOX_XLS_IS_LIBNAME
1002 // default: unknown library
1003 return FUNCLIB_UNKNOWN
;
1006 const FunctionInfoVector
& FunctionProvider::getFuncs() const
1008 return mxFuncImpl
->maFuncs
;
1011 // op-code and function provider ==============================================
1013 struct OpCodeProviderImpl
: public ApiOpCodes
1015 typedef RefMap
< sal_Int32
, FunctionInfo
> OpCodeFuncMap
;
1016 typedef RefMap
< OUString
, FunctionInfo
> FuncNameMap
;
1017 typedef ::std::vector
< FormulaOpCodeMapEntry
> OpCodeEntryVector
;
1019 OpCodeFuncMap maOpCodeFuncs
; /// Maps API function op-codes to function data.
1020 FuncNameMap maExtProgFuncs
; /// Maps programmatical API function names to function data.
1021 OpCodeEntryVector maParserMap
; /// OOXML token mapping for formula parser service.
1023 explicit OpCodeProviderImpl(
1024 const FunctionInfoVector
& rFuncInfos
,
1025 const Reference
< XMultiServiceFactory
>& rxFactory
);
1028 typedef ::std::map
< OUString
, ApiToken
> ApiTokenMap
;
1029 typedef Sequence
< FormulaOpCodeMapEntry
> OpCodeEntrySequence
;
1031 static bool fillEntrySeq( OpCodeEntrySequence
& orEntrySeq
, const Reference
< XFormulaOpCodeMapper
>& rxMapper
, sal_Int32 nMapGroup
);
1032 static bool fillTokenMap( ApiTokenMap
& orTokenMap
, OpCodeEntrySequence
& orEntrySeq
, const Reference
< XFormulaOpCodeMapper
>& rxMapper
, sal_Int32 nMapGroup
);
1033 bool fillFuncTokenMaps( ApiTokenMap
& orIntFuncTokenMap
, ApiTokenMap
& orExtFuncTokenMap
, OpCodeEntrySequence
& orEntrySeq
, const Reference
< XFormulaOpCodeMapper
>& rxMapper
) const;
1035 static bool initOpCode( sal_Int32
& ornOpCode
, const OpCodeEntrySequence
& rEntrySeq
, sal_Int32 nSpecialId
);
1036 bool initOpCode( sal_Int32
& ornOpCode
, const ApiTokenMap
& rTokenMap
, const OUString
& rOdfName
, const OUString
& rOoxName
);
1037 bool initOpCode( sal_Int32
& ornOpCode
, const ApiTokenMap
& rTokenMap
, const sal_Char
* pcOdfName
, const sal_Char
* pcOoxName
);
1038 bool initOpCode( sal_Int32
& ornOpCode
, const ApiTokenMap
& rTokenMap
, sal_Unicode cOdfName
, sal_Unicode cOoxName
);
1040 bool initFuncOpCode( FunctionInfo
& orFuncInfo
, const ApiTokenMap
& rFuncTokenMap
);
1041 bool initFuncOpCodes( const ApiTokenMap
& rIntFuncTokenMap
, const ApiTokenMap
& rExtFuncTokenMap
, const FunctionInfoVector
& rFuncInfos
);
1044 // ----------------------------------------------------------------------------
1046 OpCodeProviderImpl::OpCodeProviderImpl( const FunctionInfoVector
& rFuncInfos
,
1047 const Reference
< XMultiServiceFactory
>& rxFactory
)
1049 if( rxFactory
.is() ) try
1051 Reference
< XFormulaOpCodeMapper
> xMapper( rxFactory
->createInstance(
1052 CREATE_OUSTRING( "com.sun.star.sheet.FormulaOpCodeMapper" ) ), UNO_QUERY_THROW
);
1054 // op-codes provided as attributes
1055 OPCODE_UNKNOWN
= xMapper
->getOpCodeUnknown();
1056 OPCODE_EXTERNAL
= xMapper
->getOpCodeExternal();
1058 using namespace ::com::sun::star::sheet::FormulaMapGroup
;
1059 using namespace ::com::sun::star::sheet::FormulaMapGroupSpecialOffset
;
1061 OpCodeEntrySequence aEntrySeq
;
1062 ApiTokenMap aTokenMap
, aExtFuncTokenMap
;
1065 fillEntrySeq( aEntrySeq
, xMapper
, SPECIAL
) &&
1066 initOpCode( OPCODE_PUSH
, aEntrySeq
, PUSH
) &&
1067 initOpCode( OPCODE_MISSING
, aEntrySeq
, MISSING
) &&
1068 initOpCode( OPCODE_SPACES
, aEntrySeq
, SPACES
) &&
1069 initOpCode( OPCODE_NAME
, aEntrySeq
, NAME
) &&
1070 initOpCode( OPCODE_DBAREA
, aEntrySeq
, DB_AREA
) &&
1071 initOpCode( OPCODE_NLR
, aEntrySeq
, COL_ROW_NAME
) &&
1072 initOpCode( OPCODE_MACRO
, aEntrySeq
, MACRO
) &&
1073 initOpCode( OPCODE_BAD
, aEntrySeq
, BAD
) &&
1074 initOpCode( OPCODE_NONAME
, aEntrySeq
, NO_NAME
) &&
1076 fillTokenMap( aTokenMap
, aEntrySeq
, xMapper
, SEPARATORS
) &&
1077 initOpCode( OPCODE_OPEN
, aTokenMap
, API_TOKEN_OPEN
, '(' ) &&
1078 initOpCode( OPCODE_CLOSE
, aTokenMap
, API_TOKEN_CLOSE
, ')' ) &&
1079 initOpCode( OPCODE_SEP
, aTokenMap
, API_TOKEN_SEP
, ',' ) &&
1081 fillTokenMap( aTokenMap
, aEntrySeq
, xMapper
, ARRAY_SEPARATORS
) &&
1082 initOpCode( OPCODE_ARRAY_OPEN
, aTokenMap
, API_TOKEN_ARRAY_OPEN
, '{' ) &&
1083 initOpCode( OPCODE_ARRAY_CLOSE
, aTokenMap
, API_TOKEN_ARRAY_CLOSE
, '}' ) &&
1084 initOpCode( OPCODE_ARRAY_ROWSEP
, aTokenMap
, API_TOKEN_ARRAY_ROWSEP
, ';' ) &&
1085 initOpCode( OPCODE_ARRAY_COLSEP
, aTokenMap
, API_TOKEN_ARRAY_COLSEP
, ',' ) &&
1087 fillTokenMap( aTokenMap
, aEntrySeq
, xMapper
, UNARY_OPERATORS
) &&
1088 initOpCode( OPCODE_PLUS_SIGN
, aTokenMap
, '+', '\0' ) && // same op-code as OPCODE_ADD
1089 initOpCode( OPCODE_MINUS_SIGN
, aTokenMap
, '-', '-' ) &&
1090 initOpCode( OPCODE_PERCENT
, aTokenMap
, '%', '%' ) &&
1092 fillTokenMap( aTokenMap
, aEntrySeq
, xMapper
, BINARY_OPERATORS
) &&
1093 initOpCode( OPCODE_ADD
, aTokenMap
, '+', '+' ) &&
1094 initOpCode( OPCODE_SUB
, aTokenMap
, '-', '-' ) &&
1095 initOpCode( OPCODE_MULT
, aTokenMap
, '*', '*' ) &&
1096 initOpCode( OPCODE_DIV
, aTokenMap
, '/', '/' ) &&
1097 initOpCode( OPCODE_POWER
, aTokenMap
, '^', '^' ) &&
1098 initOpCode( OPCODE_CONCAT
, aTokenMap
, '&', '&' ) &&
1099 initOpCode( OPCODE_EQUAL
, aTokenMap
, '=', '=' ) &&
1100 initOpCode( OPCODE_NOT_EQUAL
, aTokenMap
, "<>", "<>" ) &&
1101 initOpCode( OPCODE_LESS
, aTokenMap
, '<', '<' ) &&
1102 initOpCode( OPCODE_LESS_EQUAL
, aTokenMap
, "<=", "<=" ) &&
1103 initOpCode( OPCODE_GREATER
, aTokenMap
, '>', '>' ) &&
1104 initOpCode( OPCODE_GREATER_EQUAL
, aTokenMap
, ">=", ">=" ) &&
1105 initOpCode( OPCODE_INTERSECT
, aTokenMap
, '!', ' ' ) &&
1106 initOpCode( OPCODE_LIST
, aTokenMap
, '~', ',' ) &&
1107 initOpCode( OPCODE_RANGE
, aTokenMap
, ':', ':' ) &&
1109 fillFuncTokenMaps( aTokenMap
, aExtFuncTokenMap
, aEntrySeq
, xMapper
) &&
1110 initFuncOpCodes( aTokenMap
, aExtFuncTokenMap
, rFuncInfos
) &&
1111 initOpCode( OPCODE_DDE
, aTokenMap
, "DDE", 0 );
1113 OSL_ENSURE( bIsValid
, "OpCodeProviderImpl::OpCodeProviderImpl - opcodes not initialized" );
1116 // OPCODE_PLUS_SIGN and OPCODE_ADD should be equal, otherwise "+" has to be passed above
1117 OSL_ENSURE( OPCODE_PLUS_SIGN
== OPCODE_ADD
, "OpCodeProviderImpl::OpCodeProviderImpl - need opcode mapping for OPCODE_PLUS_SIGN" );
1121 OSL_ENSURE( false, "OpCodeProviderImpl::OpCodeProviderImpl - cannot receive formula opcode mapper" );
1125 bool OpCodeProviderImpl::fillEntrySeq( OpCodeEntrySequence
& orEntrySeq
,
1126 const Reference
< XFormulaOpCodeMapper
>& rxMapper
, sal_Int32 nMapGroup
)
1130 orEntrySeq
= rxMapper
->getAvailableMappings( ::com::sun::star::sheet::FormulaLanguage::ODFF
, nMapGroup
);
1131 return orEntrySeq
.hasElements();
1139 bool OpCodeProviderImpl::fillTokenMap( ApiTokenMap
& orTokenMap
, OpCodeEntrySequence
& orEntrySeq
,
1140 const Reference
< XFormulaOpCodeMapper
>& rxMapper
, sal_Int32 nMapGroup
)
1143 if( fillEntrySeq( orEntrySeq
, rxMapper
, nMapGroup
) )
1145 const FormulaOpCodeMapEntry
* pEntry
= orEntrySeq
.getConstArray();
1146 const FormulaOpCodeMapEntry
* pEntryEnd
= pEntry
+ orEntrySeq
.getLength();
1147 for( ; pEntry
!= pEntryEnd
; ++pEntry
)
1148 orTokenMap
[ pEntry
->Name
] = pEntry
->Token
;
1150 return orEntrySeq
.hasElements();
1153 bool OpCodeProviderImpl::fillFuncTokenMaps( ApiTokenMap
& orIntFuncTokenMap
, ApiTokenMap
& orExtFuncTokenMap
, OpCodeEntrySequence
& orEntrySeq
, const Reference
< XFormulaOpCodeMapper
>& rxMapper
) const
1155 orIntFuncTokenMap
.clear();
1156 orExtFuncTokenMap
.clear();
1157 if( fillEntrySeq( orEntrySeq
, rxMapper
, ::com::sun::star::sheet::FormulaMapGroup::FUNCTIONS
) )
1159 const FormulaOpCodeMapEntry
* pEntry
= orEntrySeq
.getConstArray();
1160 const FormulaOpCodeMapEntry
* pEntryEnd
= pEntry
+ orEntrySeq
.getLength();
1161 for( ; pEntry
!= pEntryEnd
; ++pEntry
)
1162 ((pEntry
->Token
.OpCode
== OPCODE_EXTERNAL
) ? orExtFuncTokenMap
: orIntFuncTokenMap
)[ pEntry
->Name
] = pEntry
->Token
;
1164 return orEntrySeq
.hasElements();
1167 bool OpCodeProviderImpl::initOpCode( sal_Int32
& ornOpCode
, const OpCodeEntrySequence
& rEntrySeq
, sal_Int32 nSpecialId
)
1169 if( (0 <= nSpecialId
) && (nSpecialId
< rEntrySeq
.getLength()) )
1171 ornOpCode
= rEntrySeq
[ nSpecialId
].Token
.OpCode
;
1175 OStringBuffer( "OpCodeProviderImpl::initOpCode - opcode for special offset " ).
1176 append( nSpecialId
).append( " not found" ).getStr() );
1180 bool OpCodeProviderImpl::initOpCode( sal_Int32
& ornOpCode
, const ApiTokenMap
& rTokenMap
, const OUString
& rOdfName
, const OUString
& rOoxName
)
1182 ApiTokenMap::const_iterator aIt
= rTokenMap
.find( rOdfName
);
1183 if( aIt
!= rTokenMap
.end() )
1185 ornOpCode
= aIt
->second
.OpCode
;
1186 if( rOoxName
.getLength() > 0 )
1188 FormulaOpCodeMapEntry aEntry
;
1189 aEntry
.Name
= rOoxName
;
1190 aEntry
.Token
.OpCode
= ornOpCode
;
1191 maParserMap
.push_back( aEntry
);
1196 OStringBuffer( "OpCodeProviderImpl::initOpCode - opcode for \"" ).
1197 append( OUStringToOString( rOdfName
, RTL_TEXTENCODING_ASCII_US
) ).
1198 append( "\" not found" ).getStr() );
1202 bool OpCodeProviderImpl::initOpCode( sal_Int32
& ornOpCode
, const ApiTokenMap
& rTokenMap
, const sal_Char
* pcOdfName
, const sal_Char
* pcOoxName
)
1205 if( pcOoxName
) aOoxName
= OUString::createFromAscii( pcOoxName
);
1206 return initOpCode( ornOpCode
, rTokenMap
, OUString::createFromAscii( pcOdfName
), aOoxName
);
1209 bool OpCodeProviderImpl::initOpCode( sal_Int32
& ornOpCode
, const ApiTokenMap
& rTokenMap
, sal_Unicode cOdfName
, sal_Unicode cOoxName
)
1212 if( cOoxName
) aOoxName
= OUString( cOoxName
);
1213 return initOpCode( ornOpCode
, rTokenMap
, OUString( cOdfName
), aOoxName
);
1216 bool OpCodeProviderImpl::initFuncOpCode( FunctionInfo
& orFuncInfo
, const ApiTokenMap
& rFuncTokenMap
)
1218 bool bIsValid
= false;
1219 if( orFuncInfo
.maOdfFuncName
.getLength() > 0 )
1221 ApiTokenMap::const_iterator aIt
= rFuncTokenMap
.find( orFuncInfo
.maOdfFuncName
);
1222 if( aIt
!= rFuncTokenMap
.end() )
1224 orFuncInfo
.mnApiOpCode
= aIt
->second
.OpCode
;
1226 (orFuncInfo
.mnApiOpCode
>= 0) &&
1227 (orFuncInfo
.mnApiOpCode
!= OPCODE_UNKNOWN
) &&
1228 (orFuncInfo
.mnApiOpCode
!= OPCODE_NONAME
);
1229 OSL_ENSURE( bIsValid
,
1230 OStringBuffer( "OpCodeProviderImpl::initFuncOpCode - no valid opcode for ODF function \"" ).
1231 append( OUStringToOString( orFuncInfo
.maOdfFuncName
, RTL_TEXTENCODING_ASCII_US
) ).
1232 append( '"' ).getStr() );
1234 if( bIsValid
&& (orFuncInfo
.mnApiOpCode
== OPCODE_EXTERNAL
) )
1236 bIsValid
= (aIt
->second
.Data
>>= orFuncInfo
.maExtProgName
) && (orFuncInfo
.maExtProgName
.getLength() > 0);
1237 OSL_ENSURE( bIsValid
,
1238 OStringBuffer( "OpCodeProviderImpl::initFuncOpCode - no programmatical name for external function \"" ).
1239 append( OUStringToOString( orFuncInfo
.maOdfFuncName
, RTL_TEXTENCODING_ASCII_US
) ).
1240 append( '"' ).getStr() );
1243 // add to parser map, if OOX function name exists
1244 if( bIsValid
&& (orFuncInfo
.maOoxFuncName
.getLength() > 0) )
1246 // create the parser map entry
1247 FormulaOpCodeMapEntry aEntry
;
1248 aEntry
.Name
= orFuncInfo
.maOoxFuncName
;
1249 aEntry
.Token
= aIt
->second
;
1250 maParserMap
.push_back( aEntry
);
1254 else if( orFuncInfo
.mnBiffFuncId
== BIFF_FUNC_EXTERNCALL
)
1256 orFuncInfo
.mnApiOpCode
= OPCODE_EXTERNAL
;
1259 else if( orFuncInfo
.maOoxFuncName
.getLength() > 0 )
1261 orFuncInfo
.mnApiOpCode
= OPCODE_BAD
;
1265 if( !bIsValid
|| (orFuncInfo
.mnApiOpCode
== OPCODE_UNKNOWN
) || (orFuncInfo
.mnApiOpCode
< 0) )
1266 orFuncInfo
.mnApiOpCode
= OPCODE_NONAME
;
1270 bool OpCodeProviderImpl::initFuncOpCodes( const ApiTokenMap
& rIntFuncTokenMap
, const ApiTokenMap
& rExtFuncTokenMap
, const FunctionInfoVector
& rFuncInfos
)
1272 bool bIsValid
= true;
1273 for( FunctionInfoVector::const_iterator aIt
= rFuncInfos
.begin(), aEnd
= rFuncInfos
.end(); aIt
!= aEnd
; ++aIt
)
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
)
1281 if( (xFuncInfo
->mnApiOpCode
== OPCODE_EXTERNAL
) && (xFuncInfo
->maExtProgName
.getLength() > 0) )
1282 maExtProgFuncs
[ xFuncInfo
->maExtProgName
] = xFuncInfo
;
1284 maOpCodeFuncs
[ xFuncInfo
->mnApiOpCode
] = xFuncInfo
;
1290 // ----------------------------------------------------------------------------
1292 OpCodeProvider::OpCodeProvider( const Reference
< XMultiServiceFactory
>& rxFactory
,
1293 FilterType eFilter
, BiffType eBiff
, bool bImportFilter
) :
1294 FunctionProvider( eFilter
, eBiff
, bImportFilter
),
1295 mxOpCodeImpl( new OpCodeProviderImpl( getFuncs(), rxFactory
) )
1299 OpCodeProvider::~OpCodeProvider()
1303 const ApiOpCodes
& OpCodeProvider::getOpCodes() const
1305 return *mxOpCodeImpl
;
1308 const FunctionInfo
* OpCodeProvider::getFuncInfoFromApiToken( const ApiToken
& rToken
) const
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
>() );
1318 pFuncInfo
= mxOpCodeImpl
->maOpCodeFuncs
.get( rToken
.OpCode
).get();
1322 Sequence
< FormulaOpCodeMapEntry
> OpCodeProvider::getOoxParserMap() const
1324 return ContainerHelper::vectorToSequence( mxOpCodeImpl
->maParserMap
);
1327 // API formula parser wrapper =================================================
1329 ApiParserWrapper::ApiParserWrapper(
1330 const Reference
< XMultiServiceFactory
>& rxFactory
, const OpCodeProvider
& rOpCodeProv
) :
1331 OpCodeProvider( rOpCodeProv
)
1333 if( rxFactory
.is() ) try
1335 mxParser
.set( rxFactory
->createInstance( CREATE_OUSTRING( "com.sun.star.sheet.FormulaParser" ) ), UNO_QUERY_THROW
);
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() );
1348 ApiTokenSequence
ApiParserWrapper::parseFormula( const OUString
& rFormula
, const CellAddress
& rRefPos
)
1350 ApiTokenSequence aTokenSeq
;
1351 if( mxParser
.is() ) try
1353 aTokenSeq
= mxParser
->parseFormula( rFormula
, rRefPos
);
1361 // formula contexts ===========================================================
1363 FormulaContext::FormulaContext( bool bRelativeAsOffset
, bool b2dRefsAs3dRefs
, bool bAllowNulChars
) :
1364 maBaseAddress( 0, 0, 0 ),
1365 mbRelativeAsOffset( bRelativeAsOffset
),
1366 mb2dRefsAs3dRefs( b2dRefsAs3dRefs
),
1367 mbAllowNulChars( bAllowNulChars
)
1371 FormulaContext::~FormulaContext()
1375 void FormulaContext::setSharedFormula( const CellAddress
& )
1379 // ----------------------------------------------------------------------------
1381 TokensFormulaContext::TokensFormulaContext( bool bRelativeAsOffset
, bool b2dRefsAs3dRefs
, bool bAllowNulChars
) :
1382 FormulaContext( bRelativeAsOffset
, b2dRefsAs3dRefs
, bAllowNulChars
)
1386 void TokensFormulaContext::setTokens( const ApiTokenSequence
& rTokens
)
1391 // ----------------------------------------------------------------------------
1393 SimpleFormulaContext::SimpleFormulaContext( const Reference
< XFormulaTokens
>& rxTokens
,
1394 bool bRelativeAsOffset
, bool b2dRefsAs3dRefs
, bool bAllowNulChars
) :
1395 FormulaContext( bRelativeAsOffset
, b2dRefsAs3dRefs
, bAllowNulChars
),
1396 mxTokens( rxTokens
)
1398 OSL_ENSURE( mxTokens
.is(), "SimpleFormulaContext::SimpleFormulaContext - missing XFormulaTokens interface" );
1401 void SimpleFormulaContext::setTokens( const ApiTokenSequence
& rTokens
)
1403 mxTokens
->setTokens( rTokens
);
1406 // formula parser/printer base class for filters ==============================
1410 bool lclConvertToCellAddress( CellAddress
& orAddress
, const SingleReference
& rSingleRef
, sal_Int32 nForbiddenFlags
, sal_Int32 nFilterBySheet
)
1412 orAddress
= CellAddress( static_cast< sal_Int16
>( rSingleRef
.Sheet
),
1413 rSingleRef
.Column
, rSingleRef
.Row
);
1415 !getFlag( rSingleRef
.Flags
, nForbiddenFlags
) &&
1416 ((nFilterBySheet
< 0) || (nFilterBySheet
== rSingleRef
.Sheet
));
1419 bool lclConvertToCellRange( CellRangeAddress
& orRange
, const ComplexReference
& rComplexRef
, sal_Int32 nForbiddenFlags
, sal_Int32 nFilterBySheet
)
1421 orRange
= CellRangeAddress( static_cast< sal_Int16
>( rComplexRef
.Reference1
.Sheet
),
1422 rComplexRef
.Reference1
.Column
, rComplexRef
.Reference1
.Row
,
1423 rComplexRef
.Reference2
.Column
, rComplexRef
.Reference2
.Row
);
1425 !getFlag( rComplexRef
.Reference1
.Flags
, nForbiddenFlags
) &&
1426 !getFlag( rComplexRef
.Reference2
.Flags
, nForbiddenFlags
) &&
1427 (rComplexRef
.Reference1
.Sheet
== rComplexRef
.Reference2
.Sheet
) &&
1428 ((nFilterBySheet
< 0) || (nFilterBySheet
== rComplexRef
.Reference1
.Sheet
));
1431 enum TokenToRangeListState
{ STATE_REF
, STATE_SEP
, STATE_OPEN
, STATE_CLOSE
, STATE_ERROR
};
1433 TokenToRangeListState
lclProcessRef( ApiCellRangeList
& orRanges
, const Any
& rData
, bool bAllowRelative
, sal_Int32 nFilterBySheet
)
1435 using namespace ::com::sun::star::sheet::ReferenceFlags
;
1436 const sal_Int32 FORBIDDEN_FLAGS_DEL
= COLUMN_DELETED
| ROW_DELETED
| SHEET_DELETED
;
1437 const sal_Int32 FORBIDDEN_FLAGS_REL
= FORBIDDEN_FLAGS_DEL
| COLUMN_RELATIVE
| ROW_RELATIVE
| SHEET_RELATIVE
| RELATIVE_NAME
;
1439 sal_Int32 nForbiddenFlags
= bAllowRelative
? FORBIDDEN_FLAGS_DEL
: FORBIDDEN_FLAGS_REL
;
1440 SingleReference aSingleRef
;
1441 if( rData
>>= aSingleRef
)
1443 CellAddress aAddress
;
1444 // ignore invalid addresses (with #REF! errors), but do not stop parsing
1445 if( lclConvertToCellAddress( aAddress
, aSingleRef
, nForbiddenFlags
, nFilterBySheet
) )
1446 orRanges
.push_back( CellRangeAddress( aAddress
.Sheet
, aAddress
.Column
, aAddress
.Row
, aAddress
.Column
, aAddress
.Row
) );
1449 ComplexReference aComplexRef
;
1450 if( rData
>>= aComplexRef
)
1452 CellRangeAddress aRange
;
1453 // ignore invalid ranges (with #REF! errors), but do not stop parsing
1454 if( lclConvertToCellRange( aRange
, aComplexRef
, nForbiddenFlags
, nFilterBySheet
) )
1455 orRanges
.push_back( aRange
);
1461 TokenToRangeListState
lclProcessOpen( sal_Int32
& ornParenLevel
)
1467 TokenToRangeListState
lclProcessClose( sal_Int32
& ornParenLevel
)
1470 return (ornParenLevel
>= 0) ? STATE_CLOSE
: STATE_ERROR
;
1475 // ----------------------------------------------------------------------------
1477 FormulaProcessorBase::FormulaProcessorBase( const WorkbookHelper
& rHelper
) :
1478 OpCodeProvider( rHelper
.getDocumentFactory(), rHelper
.getFilterType(), rHelper
.getBiff(), rHelper
.getBaseFilter().isImportFilter() ),
1479 ApiOpCodes( getOpCodes() ),
1480 WorkbookHelper( rHelper
)
1484 // ----------------------------------------------------------------------------
1486 OUString
FormulaProcessorBase::generateAddress2dString( const CellAddress
& rAddress
, bool bAbsolute
)
1488 return generateAddress2dString( BinAddress( rAddress
), bAbsolute
);
1491 OUString
FormulaProcessorBase::generateAddress2dString( const BinAddress
& rAddress
, bool bAbsolute
)
1493 OUStringBuffer aBuffer
;
1495 for( sal_Int32 nTemp
= rAddress
.mnCol
; nTemp
>= 0; (nTemp
/= 26) -= 1 )
1496 aBuffer
.insert( 0, sal_Unicode( 'A' + (nTemp
% 26) ) );
1498 aBuffer
.insert( 0, sal_Unicode( '$' ) );
1501 aBuffer
.append( sal_Unicode( '$' ) );
1502 aBuffer
.append( static_cast< sal_Int32
>( rAddress
.mnRow
+ 1 ) );
1503 return aBuffer
.makeStringAndClear();
1506 OUString
FormulaProcessorBase::generateRange2dString( const CellRangeAddress
& rRange
, bool bAbsolute
)
1508 return generateRange2dString( BinRange( rRange
), bAbsolute
);
1511 OUString
FormulaProcessorBase::generateRange2dString( const BinRange
& rRange
, bool bAbsolute
)
1513 OUStringBuffer
aBuffer( generateAddress2dString( rRange
.maFirst
, bAbsolute
) );
1514 if( (rRange
.getColCount() > 1) || (rRange
.getRowCount() > 1) )
1515 aBuffer
.append( sal_Unicode( ':' ) ).append( generateAddress2dString( rRange
.maLast
, bAbsolute
) );
1516 return aBuffer
.makeStringAndClear();
1519 OUString
FormulaProcessorBase::generateRangeList2dString( const ApiCellRangeList
& rRanges
,
1520 bool bAbsolute
, sal_Unicode cSeparator
, bool bEncloseMultiple
)
1522 OUStringBuffer aBuffer
;
1523 for( ApiCellRangeList::const_iterator aIt
= rRanges
.begin(), aEnd
= rRanges
.end(); aIt
!= aEnd
; ++aIt
)
1525 if( aBuffer
.getLength() > 0 )
1526 aBuffer
.append( cSeparator
);
1527 aBuffer
.append( generateRange2dString( *aIt
, bAbsolute
) );
1529 if( bEncloseMultiple
&& (rRanges
.size() > 1) )
1530 aBuffer
.insert( 0, sal_Unicode( '(' ) ).append( sal_Unicode( ')' ) );
1531 return aBuffer
.makeStringAndClear();
1534 // ----------------------------------------------------------------------------
1536 OUString
FormulaProcessorBase::generateApiAddressString( const CellAddress
& rAddress
) const
1539 PropertySet
aCellProp( getCellFromDoc( rAddress
) );
1540 aCellProp
.getProperty( aCellName
, PROP_AbsoluteName
);
1541 OSL_ENSURE( aCellName
.getLength() > 0, "FormulaProcessorBase::generateApiAddressString - cannot create cell address string" );
1545 OUString
FormulaProcessorBase::generateApiRangeString( const CellRangeAddress
& rRange
) const
1547 OUString aRangeName
;
1548 PropertySet
aRangeProp( getCellRangeFromDoc( rRange
) );
1549 aRangeProp
.getProperty( aRangeName
, PROP_AbsoluteName
);
1550 OSL_ENSURE( aRangeName
.getLength() > 0, "FormulaProcessorBase::generateApiRangeString - cannot create cell range string" );
1554 OUString
FormulaProcessorBase::generateApiRangeListString( const ApiCellRangeList
& rRanges
) const
1556 OUStringBuffer aBuffer
;
1557 for( ApiCellRangeList::const_iterator aIt
= rRanges
.begin(), aEnd
= rRanges
.end(); aIt
!= aEnd
; ++aIt
)
1559 OUString aRangeName
= generateApiRangeString( *aIt
);
1560 if( aRangeName
.getLength() > 0 )
1562 if( aBuffer
.getLength() > 0 )
1563 aBuffer
.append( API_TOKEN_SEP
);
1564 aBuffer
.append( aRangeName
);
1567 return aBuffer
.makeStringAndClear();
1570 OUString
FormulaProcessorBase::generateApiString( const OUString
& rString
)
1572 OUString aRetString
= rString
;
1573 sal_Int32 nQuotePos
= aRetString
.getLength();
1574 while( (nQuotePos
= aRetString
.lastIndexOf( '"', nQuotePos
)) >= 0 )
1575 aRetString
= aRetString
.replaceAt( nQuotePos
, 1, CREATE_OUSTRING( "\"\"" ) );
1576 return OUStringBuffer().append( sal_Unicode( '"' ) ).append( aRetString
).append( sal_Unicode( '"' ) ).makeStringAndClear();
1579 OUString
FormulaProcessorBase::generateApiArray( const Matrix
< Any
>& rMatrix
)
1581 OSL_ENSURE( !rMatrix
.empty(), "FormulaProcessorBase::generateApiArray - missing matrix values" );
1582 OUStringBuffer aBuffer
;
1583 aBuffer
.append( API_TOKEN_ARRAY_OPEN
);
1584 for( size_t nRow
= 0, nHeight
= rMatrix
.height(); nRow
< nHeight
; ++nRow
)
1587 aBuffer
.append( API_TOKEN_ARRAY_ROWSEP
);
1588 for( Matrix
< Any
>::const_iterator aBeg
= rMatrix
.row_begin( nRow
), aIt
= aBeg
, aEnd
= rMatrix
.row_end( nRow
); aIt
!= aEnd
; ++aIt
)
1590 double fValue
= 0.0;
1593 aBuffer
.append( API_TOKEN_ARRAY_COLSEP
);
1594 if( *aIt
>>= fValue
)
1595 aBuffer
.append( fValue
);
1596 else if( *aIt
>>= aString
)
1597 aBuffer
.append( generateApiString( aString
) );
1599 aBuffer
.appendAscii( "\"\"" );
1602 aBuffer
.append( API_TOKEN_ARRAY_CLOSE
);
1603 return aBuffer
.makeStringAndClear();
1606 // ----------------------------------------------------------------------------
1608 Any
FormulaProcessorBase::extractReference( const ApiTokenSequence
& rTokens
) const
1610 ApiTokenIterator
aTokenIt( rTokens
, OPCODE_SPACES
, true );
1611 if( aTokenIt
.is() && (aTokenIt
->OpCode
== OPCODE_PUSH
) )
1613 Any aRefAny
= aTokenIt
->Data
;
1614 if( !(++aTokenIt
).is() && (aRefAny
.has
< SingleReference
>() || aRefAny
.has
< ComplexReference
>()) )
1620 bool FormulaProcessorBase::extractCellAddress( CellAddress
& orAddress
,
1621 const ApiTokenSequence
& rTokens
, bool bAllowRelative
) const
1623 CellRangeAddress aRange
;
1624 if( extractCellRange( aRange
, rTokens
, bAllowRelative
) && (aRange
.StartColumn
== aRange
.EndColumn
) && (aRange
.StartRow
== aRange
.EndRow
) )
1626 orAddress
.Sheet
= aRange
.Sheet
;
1627 orAddress
.Column
= aRange
.StartColumn
;
1628 orAddress
.Row
= aRange
.StartRow
;
1634 bool FormulaProcessorBase::extractCellRange( CellRangeAddress
& orRange
,
1635 const ApiTokenSequence
& rTokens
, bool bAllowRelative
) const
1637 ApiCellRangeList aRanges
;
1638 lclProcessRef( aRanges
, extractReference( rTokens
), bAllowRelative
, -1 );
1639 if( !aRanges
.empty() )
1641 orRange
= aRanges
.front();
1647 void FormulaProcessorBase::extractCellRangeList( ApiCellRangeList
& orRanges
,
1648 const ApiTokenSequence
& rTokens
, bool bAllowRelative
, sal_Int32 nFilterBySheet
) const
1651 TokenToRangeListState eState
= STATE_OPEN
;
1652 sal_Int32 nParenLevel
= 0;
1653 for( ApiTokenIterator
aIt( rTokens
, OPCODE_SPACES
, true ); aIt
.is() && (eState
!= STATE_ERROR
); ++aIt
)
1655 sal_Int32 nOpCode
= aIt
->OpCode
;
1659 if( nOpCode
== OPCODE_LIST
) eState
= STATE_SEP
;
1660 else if( nOpCode
== OPCODE_CLOSE
) eState
= lclProcessClose( nParenLevel
);
1661 else eState
= STATE_ERROR
;
1664 if( nOpCode
== OPCODE_PUSH
) eState
= lclProcessRef( orRanges
, aIt
->Data
, bAllowRelative
, nFilterBySheet
);
1665 else if( nOpCode
== OPCODE_LIST
) eState
= STATE_SEP
;
1666 else if( nOpCode
== OPCODE_OPEN
) eState
= lclProcessOpen( nParenLevel
);
1667 else if( nOpCode
== OPCODE_CLOSE
) eState
= lclProcessClose( nParenLevel
);
1668 else eState
= STATE_ERROR
;
1671 if( nOpCode
== OPCODE_PUSH
) eState
= lclProcessRef( orRanges
, aIt
->Data
, bAllowRelative
, nFilterBySheet
);
1672 else if( nOpCode
== OPCODE_LIST
) eState
= STATE_SEP
;
1673 else if( nOpCode
== OPCODE_OPEN
) eState
= lclProcessOpen( nParenLevel
);
1674 else if( nOpCode
== OPCODE_CLOSE
) eState
= lclProcessClose( nParenLevel
);
1675 else eState
= STATE_ERROR
;
1678 if( nOpCode
== OPCODE_LIST
) eState
= STATE_SEP
;
1679 else if( nOpCode
== OPCODE_CLOSE
) eState
= lclProcessClose( nParenLevel
);
1680 else eState
= STATE_ERROR
;
1686 if( eState
== STATE_ERROR
)
1689 getAddressConverter().validateCellRangeList( orRanges
, false );
1692 bool FormulaProcessorBase::extractString( OUString
& orString
, const ApiTokenSequence
& rTokens
) const
1694 ApiTokenIterator
aTokenIt( rTokens
, OPCODE_SPACES
, true );
1695 return aTokenIt
.is() && (aTokenIt
->OpCode
== OPCODE_PUSH
) && (aTokenIt
->Data
>>= orString
) && !(++aTokenIt
).is();
1698 void FormulaProcessorBase::convertStringToStringList(
1699 ApiTokenSequence
& orTokens
, sal_Unicode cStringSep
, bool bTrimLeadingSpaces
) const
1702 if( extractString( aString
, orTokens
) && (aString
.getLength() > 0) )
1704 ::std::vector
< ApiToken
> aNewTokens
;
1706 sal_Int32 nLen
= aString
.getLength();
1707 while( (0 <= nPos
) && (nPos
< nLen
) )
1709 OUString aEntry
= aString
.getToken( 0, cStringSep
, nPos
);
1710 if( bTrimLeadingSpaces
)
1712 sal_Int32 nStart
= 0;
1713 while( (nStart
< aEntry
.getLength()) && (aEntry
[ nStart
] == ' ') ) ++nStart
;
1714 aEntry
= aEntry
.copy( nStart
);
1716 if( !aNewTokens
.empty() )
1717 aNewTokens
.push_back( ApiToken( OPCODE_SEP
, Any() ) );
1718 aNewTokens
.push_back( ApiToken( OPCODE_PUSH
, Any( aEntry
) ) );
1720 orTokens
= ContainerHelper::vectorToSequence( aNewTokens
);
1724 // ============================================================================