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