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