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