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