File indexing completed on 2024-05-12 16:35:33
0001 /* This file is part of the KDE project 0002 Copyright (C) 1998-2002 The KSpread Team <calligra-devel@kde.org> 0003 Copyright (C) 2005 Tomas Mecir <mecirt@gmail.com> 0004 Copyright 2007 Sascha Pfau <MrPeacock@gmail.com> 0005 Copyright (C) 2010 Carlos Licea <carlos@kdab.com> 0006 Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 0007 Contact: Suresh Chande suresh.chande@nokia.com 0008 0009 This library is free software; you can redistribute it and/or 0010 modify it under the terms of the GNU Library General Public 0011 License as published by the Free Software Foundation; only 0012 version 2 of the License. 0013 0014 This library is distributed in the hope that it will be useful, 0015 but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0017 Library General Public License for more details. 0018 0019 You should have received a copy of the GNU Library General Public License 0020 along with this library; see the file COPYING.LIB. If not, write to 0021 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0022 Boston, MA 02110-1301, USA. 0023 */ 0024 0025 // built-in math functions 0026 #include "MathModule.h" 0027 0028 // needed for RANDBINOM and so 0029 #include <math.h> 0030 #include <qmath.h> 0031 0032 #include "SheetsDebug.h" 0033 #include "FunctionModuleRegistry.h" 0034 #include "Function.h" 0035 #include "FunctionRepository.h" 0036 #include "ValueCalc.h" 0037 #include "ValueConverter.h" 0038 0039 // needed for SUBTOTAL: 0040 #include "Cell.h" 0041 #include "Sheet.h" 0042 #include "RowColumnFormat.h" 0043 #include "RowFormatStorage.h" 0044 0045 // needed by MDETERM and MINVERSE 0046 // Don't show this warning: it's an issue in eigen 0047 #ifdef __GNUC__ 0048 #pragma GCC diagnostic ignored "-Wunused-local-typedefs" 0049 #endif 0050 0051 #include <Eigen/LU> 0052 0053 using namespace Calligra::Sheets; 0054 0055 // RANDBINOM and RANDNEGBINOM won't support arbitrary precision 0056 0057 // prototypes 0058 Value func_abs(valVector args, ValueCalc *calc, FuncExtra *); 0059 Value func_ceil(valVector args, ValueCalc *calc, FuncExtra *); 0060 Value func_ceiling(valVector args, ValueCalc *calc, FuncExtra *); 0061 Value func_count(valVector args, ValueCalc *calc, FuncExtra *); 0062 Value func_counta(valVector args, ValueCalc *calc, FuncExtra *); 0063 Value func_countblank(valVector args, ValueCalc *calc, FuncExtra *); 0064 Value func_countif(valVector args, ValueCalc *calc, FuncExtra *); 0065 Value func_countifs(valVector args, ValueCalc *calc, FuncExtra *e); 0066 Value func_cur(valVector args, ValueCalc *calc, FuncExtra *); 0067 Value func_div(valVector args, ValueCalc *calc, FuncExtra *); 0068 Value func_eps(valVector args, ValueCalc *calc, FuncExtra *); 0069 Value func_even(valVector args, ValueCalc *calc, FuncExtra *); 0070 Value func_exp(valVector args, ValueCalc *calc, FuncExtra *); 0071 Value func_fact(valVector args, ValueCalc *calc, FuncExtra *); 0072 Value func_factdouble(valVector args, ValueCalc *calc, FuncExtra *); 0073 Value func_fib(valVector args, ValueCalc *calc, FuncExtra *); 0074 Value func_floor(valVector args, ValueCalc *calc, FuncExtra *); 0075 Value func_gamma(valVector args, ValueCalc *calc, FuncExtra *); 0076 Value func_gcd(valVector args, ValueCalc *calc, FuncExtra *); 0077 Value func_int(valVector args, ValueCalc *calc, FuncExtra *); 0078 Value func_inv(valVector args, ValueCalc *calc, FuncExtra *); 0079 Value func_kproduct(valVector args, ValueCalc *calc, FuncExtra *); 0080 Value func_lcm(valVector args, ValueCalc *calc, FuncExtra *); 0081 Value func_ln(valVector args, ValueCalc *calc, FuncExtra *); 0082 Value func_log2(valVector args, ValueCalc *calc, FuncExtra *); 0083 Value func_log10(valVector args, ValueCalc *calc, FuncExtra *); 0084 Value func_logn(valVector args, ValueCalc *calc, FuncExtra *); 0085 Value func_max(valVector args, ValueCalc *calc, FuncExtra *); 0086 Value func_maxa(valVector args, ValueCalc *calc, FuncExtra *); 0087 Value func_mdeterm(valVector args, ValueCalc *calc, FuncExtra *); 0088 Value func_min(valVector args, ValueCalc *calc, FuncExtra *); 0089 Value func_mina(valVector args, ValueCalc *calc, FuncExtra *); 0090 Value func_minverse(valVector args, ValueCalc* calc, FuncExtra*); 0091 Value func_mmult(valVector args, ValueCalc *calc, FuncExtra *); 0092 Value func_mod(valVector args, ValueCalc *calc, FuncExtra *); 0093 Value func_mround(valVector args, ValueCalc *calc, FuncExtra *); 0094 Value func_mult(valVector args, ValueCalc *calc, FuncExtra *); 0095 Value func_multinomial(valVector args, ValueCalc *calc, FuncExtra *); 0096 Value func_munit(valVector args, ValueCalc* calc, FuncExtra*); 0097 Value func_odd(valVector args, ValueCalc *calc, FuncExtra *); 0098 Value func_pow(valVector args, ValueCalc *calc, FuncExtra *); 0099 Value func_quotient(valVector args, ValueCalc *calc, FuncExtra *); 0100 Value func_product(valVector args, ValueCalc *calc, FuncExtra *); 0101 Value func_rand(valVector args, ValueCalc *calc, FuncExtra *); 0102 Value func_randbetween(valVector args, ValueCalc *calc, FuncExtra *); 0103 Value func_randbernoulli(valVector args, ValueCalc *calc, FuncExtra *); 0104 Value func_randbinom(valVector args, ValueCalc *calc, FuncExtra *); 0105 Value func_randexp(valVector args, ValueCalc *calc, FuncExtra *); 0106 Value func_randnegbinom(valVector args, ValueCalc *calc, FuncExtra *); 0107 Value func_randnorm(valVector args, ValueCalc *calc, FuncExtra *); 0108 Value func_randpoisson(valVector args, ValueCalc *calc, FuncExtra *); 0109 Value func_rootn(valVector args, ValueCalc *calc, FuncExtra *); 0110 Value func_round(valVector args, ValueCalc *calc, FuncExtra *); 0111 Value func_rounddown(valVector args, ValueCalc *calc, FuncExtra *); 0112 Value func_roundup(valVector args, ValueCalc *calc, FuncExtra *); 0113 Value func_seriessum(valVector args, ValueCalc *calc, FuncExtra *); 0114 Value func_sign(valVector args, ValueCalc *calc, FuncExtra *); 0115 Value func_sqrt(valVector args, ValueCalc *calc, FuncExtra *); 0116 Value func_sqrtpi(valVector args, ValueCalc *calc, FuncExtra *); 0117 Value func_subtotal(valVector args, ValueCalc *calc, FuncExtra *); 0118 Value func_sum(valVector args, ValueCalc *calc, FuncExtra *); 0119 Value func_suma(valVector args, ValueCalc *calc, FuncExtra *); 0120 Value func_sumif(valVector args, ValueCalc *calc, FuncExtra *); 0121 Value func_sumifs(valVector args, ValueCalc *calc, FuncExtra *); //here 0122 Value func_sumsq(valVector args, ValueCalc *calc, FuncExtra *); 0123 Value func_transpose(valVector args, ValueCalc *calc, FuncExtra *); 0124 Value func_trunc(valVector args, ValueCalc *calc, FuncExtra *); 0125 0126 0127 // Value func_multipleOP (valVector args, ValueCalc *calc, FuncExtra *); 0128 0129 0130 CALLIGRA_SHEETS_EXPORT_FUNCTION_MODULE("kspreadmathmodule.json", MathModule) 0131 0132 0133 MathModule::MathModule(QObject* parent, const QVariantList&) 0134 : FunctionModule(parent) 0135 { 0136 Function *f; 0137 0138 /* 0139 f = new Function ("MULTIPLEOPERATIONS", func_multipleOP); 0140 add(f); 0141 */ 0142 0143 // functions that don't take array parameters 0144 f = new Function("ABS", func_abs); 0145 add(f); 0146 f = new Function("CEIL", func_ceil); 0147 add(f); 0148 f = new Function("CEILING", func_ceiling); 0149 f->setParamCount(1, 3); 0150 add(f); 0151 f = new Function("CUR", func_cur); 0152 add(f); 0153 f = new Function("EPS", func_eps); 0154 f->setParamCount(0); 0155 add(f); 0156 f = new Function("EVEN", func_even); 0157 add(f); 0158 f = new Function("EXP", func_exp); 0159 add(f); 0160 f = new Function("FACT", func_fact); 0161 add(f); 0162 f = new Function("FACTDOUBLE", func_factdouble); 0163 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETFACTDOUBLE"); 0164 add(f); 0165 f = new Function("FIB", func_fib); // Calligra Sheets-specific, like Quattro-Pro's FIB 0166 add(f); 0167 f = new Function("FLOOR", func_floor); 0168 f->setParamCount(1, 3); 0169 add(f); 0170 f = new Function("GAMMA", func_gamma); 0171 add(f); 0172 f = new Function("INT", func_int); 0173 add(f); 0174 f = new Function("INV", func_inv); 0175 add(f); 0176 f = new Function("LN", func_ln); 0177 add(f); 0178 f = new Function("LOG", func_logn); 0179 f->setParamCount(1, 2); 0180 add(f); 0181 f = new Function("LOG2", func_log2); 0182 add(f); 0183 f = new Function("LOG10", func_log10); 0184 add(f); 0185 f = new Function("LOGN", func_logn); 0186 f->setParamCount(2); 0187 add(f); 0188 f = new Function("MOD", func_mod); 0189 f->setParamCount(2); 0190 add(f); 0191 f = new Function("MROUND", func_mround); 0192 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETMROUND"); 0193 f->setParamCount(2); 0194 add(f); 0195 f = new Function("MULTINOMIAL", func_multinomial); 0196 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETMULTINOMIAL"); 0197 f->setParamCount(1, -1); 0198 add(f); 0199 f = new Function("ODD", func_odd); 0200 add(f); 0201 f = new Function("POW", func_pow); 0202 f->setParamCount(2); 0203 add(f); 0204 f = new Function("POWER", func_pow); 0205 f->setParamCount(2); 0206 add(f); 0207 f = new Function("QUOTIENT", func_quotient); 0208 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETQUOTIENT"); 0209 f->setParamCount(2); 0210 add(f); 0211 f = new Function("RAND", func_rand); 0212 f->setParamCount(0); 0213 add(f); 0214 f = new Function("RANDBERNOULLI", func_randbernoulli); 0215 add(f); 0216 f = new Function("RANDBETWEEN", func_randbetween); 0217 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETRANDBETWEEN"); 0218 f->setParamCount(2); 0219 add(f); 0220 f = new Function("RANDBINOM", func_randbinom); 0221 f->setParamCount(2); 0222 add(f); 0223 f = new Function("RANDEXP", func_randexp); 0224 add(f); 0225 f = new Function("RANDNEGBINOM", func_randnegbinom); 0226 f->setParamCount(2); 0227 add(f); 0228 f = new Function("RANDNORM", func_randnorm); 0229 f->setParamCount(2); 0230 add(f); 0231 f = new Function("RANDPOISSON", func_randpoisson); 0232 add(f); 0233 f = new Function("ROOTN", func_rootn); 0234 f->setParamCount(2); 0235 add(f); 0236 f = new Function("ROUND", func_round); 0237 f->setParamCount(1, 2); 0238 add(f); 0239 f = new Function("ROUNDDOWN", func_rounddown); 0240 f->setParamCount(1, 2); 0241 add(f); 0242 f = new Function("ROUNDUP", func_roundup); 0243 f->setParamCount(1, 2); 0244 add(f); 0245 f = new Function("SIGN", func_sign); 0246 add(f); 0247 f = new Function("SQRT", func_sqrt); 0248 add(f); 0249 f = new Function("SQRTPI", func_sqrtpi); 0250 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETSQRTPI"); 0251 add(f); 0252 f = new Function("TRUNC", func_trunc); 0253 f->setParamCount(1, 2); 0254 add(f); 0255 0256 // functions that operate over arrays 0257 f = new Function("COUNT", func_count); 0258 f->setParamCount(1, -1); 0259 f->setAcceptArray(); 0260 add(f); 0261 f = new Function("COUNTA", func_counta); 0262 f->setParamCount(1, -1); 0263 f->setAcceptArray(); 0264 add(f); 0265 f = new Function("COUNTBLANK", func_countblank); 0266 f->setParamCount(1, -1); 0267 f->setAcceptArray(); 0268 add(f); 0269 f = new Function("COUNTIF", func_countif); 0270 f->setParamCount(2); 0271 f->setAcceptArray(); 0272 f->setNeedsExtra(true); 0273 add(f); 0274 f = new Function("COUNTIFS", func_countifs); 0275 f->setParamCount(2, -1); 0276 f->setAcceptArray(); 0277 f->setNeedsExtra(true); 0278 add(f); 0279 f = new Function("DIV", func_div); 0280 f->setParamCount(1, -1); 0281 f->setAcceptArray(); 0282 add(f); 0283 f = new Function("G_PRODUCT", func_kproduct); // Gnumeric compatibility 0284 f->setParamCount(1, -1); 0285 f->setAcceptArray(); 0286 add(f); 0287 f = new Function("GCD", func_gcd); 0288 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETGCD"); 0289 f->setParamCount(1, -1); 0290 f->setAcceptArray(); 0291 add(f); 0292 f = new Function("KPRODUCT", func_kproduct); 0293 f->setParamCount(1, -1); 0294 f->setAcceptArray(); 0295 add(f); 0296 f = new Function("LCM", func_lcm); 0297 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETLCM"); 0298 f->setParamCount(1, -1); 0299 f->setAcceptArray(); 0300 add(f); 0301 f = new Function("MAX", func_max); 0302 f->setParamCount(1, -1); 0303 f->setAcceptArray(); 0304 add(f); 0305 f = new Function("MAXA", func_maxa); 0306 f->setParamCount(1, -1); 0307 f->setAcceptArray(); 0308 add(f); 0309 f = new Function("MDETERM", func_mdeterm); 0310 f->setParamCount(1); 0311 f->setAcceptArray(); 0312 add(f); 0313 f = new Function("MIN", func_min); 0314 f->setParamCount(1, -1); 0315 f->setAcceptArray(); 0316 add(f); 0317 f = new Function("MINA", func_mina); 0318 f->setParamCount(1, -1); 0319 f->setAcceptArray(); 0320 add(f); 0321 f = new Function("MINVERSE", func_minverse); 0322 f->setParamCount(1); 0323 f->setAcceptArray(); 0324 add(f); 0325 f = new Function("MMULT", func_mmult); 0326 f->setParamCount(2); 0327 f->setAcceptArray(); 0328 add(f); 0329 f = new Function("MULTIPLY", func_product); // same as PRODUCT 0330 f->setParamCount(1, -1); 0331 f->setAcceptArray(); 0332 add(f); 0333 f = new Function("MUNIT", func_munit); 0334 f->setParamCount(1); 0335 add(f); 0336 f = new Function("PRODUCT", func_product); 0337 f->setParamCount(1, -1); 0338 f->setAcceptArray(); 0339 add(f); 0340 f = new Function("SERIESSUM", func_seriessum); 0341 f->setParamCount(3, -1); 0342 f->setAcceptArray(); 0343 add(f); 0344 f = new Function("SUM", func_sum); 0345 f->setParamCount(1, -1); 0346 f->setAcceptArray(); 0347 add(f); 0348 f = new Function("SUMA", func_suma); 0349 f->setParamCount(1, -1); 0350 f->setAcceptArray(); 0351 add(f); 0352 f = new Function("SUBTOTAL", func_subtotal); 0353 f->setParamCount(2); 0354 f->setAcceptArray(); 0355 f->setNeedsExtra(true); 0356 add(f); 0357 f = new Function("SUMIF", func_sumif); 0358 f->setParamCount(2, 3); 0359 f->setAcceptArray(); 0360 f->setNeedsExtra(true); 0361 add(f); 0362 f = new Function("SUMIFS", func_sumifs); 0363 f->setParamCount(3, -1); 0364 f->setAcceptArray(); 0365 f->setNeedsExtra(true); 0366 add(f); 0367 f = new Function("SUMSQ", func_sumsq); 0368 f->setParamCount(1, -1); 0369 f->setAcceptArray(); 0370 add(f); 0371 f = new Function("TRANSPOSE", func_transpose); 0372 f->setParamCount(1); 0373 f->setAcceptArray(); 0374 add(f); 0375 } 0376 0377 QString MathModule::descriptionFileName() const 0378 { 0379 return QString("math.xml"); 0380 } 0381 0382 0383 // Function: SQRT 0384 Value func_sqrt(valVector args, ValueCalc *calc, FuncExtra *) 0385 { 0386 Value arg = args[0]; 0387 if (calc->gequal(arg, Value(0.0))) 0388 return calc->sqrt(arg); 0389 else 0390 return Value::errorVALUE(); 0391 } 0392 0393 // Function: SQRTPI 0394 Value func_sqrtpi(valVector args, ValueCalc *calc, FuncExtra *) 0395 { 0396 // sqrt (val * PI) 0397 Value arg = args[0]; 0398 if (calc->gequal(arg, Value(0.0))) 0399 return calc->sqrt(calc->mul(args[0], calc->pi())); 0400 else 0401 return Value::errorVALUE(); 0402 } 0403 0404 // Function: ROOTN 0405 Value func_rootn(valVector args, ValueCalc *calc, FuncExtra *) 0406 { 0407 return calc->pow(args[0], calc->div(Value(1), args[1])); 0408 } 0409 0410 // Function: CUR 0411 Value func_cur(valVector args, ValueCalc *calc, FuncExtra *) 0412 { 0413 return calc->pow(args[0], Value(1.0 / 3.0)); 0414 } 0415 0416 // Function: ABS 0417 Value func_abs(valVector args, ValueCalc *calc, FuncExtra *) 0418 { 0419 return calc->abs(args[0]); 0420 } 0421 0422 // Function: exp 0423 Value func_exp(valVector args, ValueCalc *calc, FuncExtra *) 0424 { 0425 return calc->exp(args[0]); 0426 } 0427 0428 // Function: ceil 0429 Value func_ceil(valVector args, ValueCalc *calc, FuncExtra *) 0430 { 0431 return calc->roundUp(args[0], Value(0)); 0432 } 0433 0434 // Function: ceiling 0435 Value func_ceiling(valVector args, ValueCalc *calc, FuncExtra *) 0436 { 0437 Value number = args[0]; 0438 Value res; 0439 if (args.count() >= 2) 0440 res = args[1]; 0441 else 0442 res = calc->gequal(number, Value(0.0)) ? Value(1.0) : Value(-1.0); 0443 bool mode = (args.count() >= 3) ? calc->isZero (args[2]) : true; 0444 0445 // short-circuit, and allow CEILING(0;0) to give 0 (which is correct) 0446 // instead of DIV0 error 0447 if (calc->isZero(number)) 0448 return Value(0.0); 0449 0450 if (calc->isZero(res)) 0451 return Value::errorDIV0(); 0452 0453 Value d = calc->div(number, res); 0454 if (calc->greater(Value(0), d)) 0455 return Value::errorNUM(); 0456 0457 Value rud = calc->roundDown(d); 0458 if (calc->approxEqual(rud, d)) 0459 d = calc->mul(rud, res); 0460 else 0461 { 0462 // positive number or mode is 0 - round up 0463 if ((!mode) || calc->gequal (number, Value(0))) rud = calc->roundUp(d); 0464 d = calc->mul (rud, res); 0465 } 0466 0467 return d; 0468 } 0469 0470 // Function: FLOOR 0471 Value func_floor(valVector args, ValueCalc *calc, FuncExtra *) 0472 { 0473 if (calc->approxEqual(args[0], Value(0.0))) 0474 return Value(0); 0475 Number number = args[0].asFloat(); 0476 0477 Number significance; 0478 if (args.count() >= 2) { // we have the optional "significance" argument 0479 significance = args[1].asFloat(); 0480 // Sign of number and significance must match. 0481 if (calc->gequal(args[0], Value(0.0)) != calc->gequal(args[1], Value(0.0))) 0482 return Value::errorVALUE(); 0483 } else // use 1 or -1, depending on the sign of the first argument 0484 significance = calc->gequal(args[0], Value(0.0)) ? 1.0 : -1.0; 0485 if (calc->approxEqual(Value(significance), Value(0.0))) 0486 return Value(0); 0487 0488 const bool mode = (args.count() == 3) ? (args[2].asFloat() != 0.0) : false; 0489 0490 Number result; 0491 if (mode) // round towards zero 0492 result = ((int)(number / significance)) * significance; 0493 else { // round towards negative infinity 0494 result = number / significance; // always positive, because signs match 0495 if (calc->gequal(args[0], Value(0.0))) // positive values 0496 result = floor(result) * significance; 0497 else // negative values 0498 result = ceil(result) * significance; 0499 } 0500 return Value(result); 0501 } 0502 0503 // Function: GAMMA 0504 Value func_gamma(valVector args, ValueCalc *calc, FuncExtra *) 0505 { 0506 return calc->GetGamma(args[0]); 0507 } 0508 0509 // Function: ln 0510 Value func_ln(valVector args, ValueCalc *calc, FuncExtra *) 0511 { 0512 if ((args [0].isNumber() == false) || args[0].asFloat() <= 0) 0513 return Value::errorNUM(); 0514 return calc->ln(args[0]); 0515 } 0516 0517 // Function: LOGn 0518 Value func_logn(valVector args, ValueCalc *calc, FuncExtra *) 0519 { 0520 if (args [0].isError()) 0521 return args [0]; 0522 if (args [0].isEmpty()) 0523 return Value::errorNUM(); 0524 if (args [0].isNumber() == false) 0525 return Value::errorVALUE(); 0526 if (args[0].asFloat() <= 0) 0527 return Value::errorNUM(); 0528 if (args.count() == 2) { 0529 if (args [1].isError()) 0530 return args [1]; 0531 if (args [1].isEmpty()) 0532 return Value::errorNUM(); 0533 if (args [1].isNumber() == false) 0534 return Value::errorVALUE(); 0535 if (args [1].asFloat() <= 0) 0536 return Value::errorNUM(); 0537 return calc->log(args[0], args[1]); 0538 } else 0539 return calc->log(args[0]); 0540 } 0541 0542 // Function: LOG2 0543 Value func_log2(valVector args, ValueCalc *calc, FuncExtra *) 0544 { 0545 return calc->log(args[0], Value(2.0)); 0546 } 0547 0548 // Function: LOG10 0549 Value func_log10(valVector args, ValueCalc *calc, FuncExtra *) 0550 { 0551 if (args [0].isError()) 0552 return args [0]; 0553 if ((args [0].isNumber() == false) || (args[0].asFloat() <= 0)) 0554 return Value::errorNUM(); 0555 return calc->log(args[0]); 0556 } 0557 0558 // Function: sum 0559 Value func_sum(valVector args, ValueCalc *calc, FuncExtra *) 0560 { 0561 return calc->sum(args, false); 0562 } 0563 0564 // Function: suma 0565 Value func_suma(valVector args, ValueCalc *calc, FuncExtra *) 0566 { 0567 return calc->sum(args, true); 0568 } 0569 0570 // Function: SUMIF 0571 Value func_sumif(valVector args, ValueCalc *calc, FuncExtra *e) 0572 { 0573 Value checkRange = args[0]; 0574 QString condition = calc->conv()->asString(args[1]).asString(); 0575 Condition cond; 0576 calc->getCond(cond, Value(condition)); 0577 0578 if (args.count() == 3) { 0579 Cell sumRangeStart(e->regions[2].firstSheet(), e->regions[2].firstRange().topLeft()); 0580 return calc->sumIf(sumRangeStart, checkRange, cond); 0581 } else { 0582 return calc->sumIf(checkRange, cond); 0583 } 0584 } 0585 0586 //Function: SUMIFS 0587 Value func_sumifs(valVector args, ValueCalc *calc, FuncExtra *e) 0588 { 0589 int lim = (int) (args.count()-1)/2; 0590 0591 QList<Value> c_Range; 0592 QStringList condition; 0593 QList<Condition> cond; 0594 0595 c_Range.append(args.value(0)); //first element - range to be operated on 0596 0597 for (int i = 1; i < args.count(); i += 2) { 0598 c_Range.append(args[i]); 0599 condition.append(calc->conv()->asString(args[i+1]).asString()); 0600 Condition c; 0601 calc->getCond(c, Value(condition.last())); 0602 cond.append(c); 0603 } 0604 Cell sumRangeStart(e->sheet, e->ranges[2].col1, e->ranges[2].row1); 0605 return calc->sumIfs(sumRangeStart, c_Range, cond, lim); 0606 } 0607 0608 // Function: product 0609 Value func_product(valVector args, ValueCalc *calc, FuncExtra *) 0610 { 0611 return calc->product(args, Value(0.0)); 0612 } 0613 0614 // Function: seriessum 0615 Value func_seriessum(valVector args, ValueCalc *calc, FuncExtra *) 0616 { 0617 double fX = calc->conv()->asFloat(args[0]).asFloat(); 0618 double fN = calc->conv()->asFloat(args[1]).asFloat(); 0619 double fM = calc->conv()->asFloat(args[2]).asFloat(); 0620 0621 if (fX == 0.0 && fN == 0.0) 0622 return Value::errorNUM(); 0623 0624 double res = 0.0; 0625 0626 if (fX != 0.0) { 0627 0628 for (unsigned int i = 0 ; i < args[3].count(); i++) { 0629 res += args[3].element(i).asFloat() * pow(fX, fN); 0630 fN += fM; 0631 } 0632 } 0633 0634 return Value(res); 0635 } 0636 0637 // Function: kproduct 0638 Value func_kproduct(valVector args, ValueCalc *calc, FuncExtra *) 0639 { 0640 return calc->product(args, Value(1.0)); 0641 } 0642 0643 // Function: DIV 0644 Value func_div(valVector args, ValueCalc *calc, FuncExtra *) 0645 { 0646 Value val = args[0]; 0647 for (int i = 1; i < args.count(); ++i) { 0648 val = calc->div(val, args[i]); 0649 if (val.isError()) 0650 return val; 0651 } 0652 return val; 0653 } 0654 0655 // Function: SUMSQ 0656 Value func_sumsq(valVector args, ValueCalc *calc, FuncExtra *) 0657 { 0658 Value res; 0659 calc->arrayWalk(args, res, calc->awFunc("sumsq"), Value(0)); 0660 return res; 0661 } 0662 0663 // Function: MAX 0664 Value func_max(valVector args, ValueCalc *calc, FuncExtra *) 0665 { 0666 Value m = calc->max(args, false); 0667 return m.isEmpty() ? Value(0.0) : m; 0668 } 0669 0670 // Function: MAXA 0671 Value func_maxa(valVector args, ValueCalc *calc, FuncExtra *) 0672 { 0673 Value m = calc->max(args); 0674 return m.isEmpty() ? Value(0.0) : m; 0675 } 0676 0677 // Function: MIN 0678 Value func_min(valVector args, ValueCalc *calc, FuncExtra *) 0679 { 0680 Value m = calc->min(args, false); 0681 return m.isEmpty() ? Value(0.0) : m; 0682 } 0683 0684 // Function: MINA 0685 Value func_mina(valVector args, ValueCalc *calc, FuncExtra *) 0686 { 0687 Value m = calc->min(args, true); 0688 return m.isEmpty() ? Value(0.0) : m; 0689 } 0690 0691 // Function: INT 0692 Value func_int(valVector args, ValueCalc *calc, FuncExtra *) 0693 { 0694 return calc->conv()->asInteger(args[0]); 0695 } 0696 0697 // Function: QUOTIENT 0698 Value func_quotient(valVector args, ValueCalc *calc, FuncExtra *) 0699 { 0700 if (calc->isZero(args[1])) 0701 return Value::errorDIV0(); 0702 0703 double res = calc->conv()->toFloat(calc->div(args[0], args[1])); 0704 if (res < 0) 0705 res = ceil(res); 0706 else 0707 res = floor(res); 0708 0709 return Value(res); 0710 } 0711 0712 0713 // Function: eps 0714 Value func_eps(valVector, ValueCalc *calc, FuncExtra *) 0715 { 0716 return calc->eps(); 0717 } 0718 0719 Value func_randexp(valVector args, ValueCalc *calc, FuncExtra *) 0720 { 0721 // -1 * d * log (random) 0722 return calc->mul(calc->mul(args[0], Value(-1)), calc->random()); 0723 } 0724 0725 Value func_randbinom(valVector args, ValueCalc *calc, FuncExtra *) 0726 { 0727 // this function will not support arbitrary precision 0728 0729 double d = numToDouble(calc->conv()->toFloat(args[0])); 0730 int tr = calc->conv()->toInteger(args[1]); 0731 0732 if (d < 0 || d > 1) 0733 return Value::errorVALUE(); 0734 0735 if (tr < 0) 0736 return Value::errorVALUE(); 0737 0738 // taken from gnumeric 0739 double x = pow(1 - d, tr); 0740 double r = (double) rand() / (RAND_MAX + 1.0); 0741 double t = x; 0742 int i = 0; 0743 0744 while (r > t) { 0745 x *= (((tr - i) * d) / ((1 + i) * (1 - d))); 0746 i++; 0747 t += x; 0748 } 0749 0750 return Value(i); 0751 } 0752 0753 Value func_randnegbinom(valVector args, ValueCalc *calc, FuncExtra *) 0754 { 0755 // this function will not support arbitrary precision 0756 0757 double d = numToDouble(calc->conv()->toFloat(args[0])); 0758 int f = calc->conv()->toInteger(args[1]); 0759 0760 if (d < 0 || d > 1) 0761 return Value::errorVALUE(); 0762 0763 if (f < 0) 0764 return Value::errorVALUE(); 0765 0766 0767 // taken from Gnumeric 0768 double x = pow(d, f); 0769 double r = (double) rand() / (RAND_MAX + 1.0); 0770 double t = x; 0771 int i = 0; 0772 0773 while (r > t) { 0774 x *= (((f + i) * (1 - d)) / (1 + i)) ; 0775 i++; 0776 t += x; 0777 } 0778 0779 return Value(i); 0780 } 0781 0782 Value func_randbernoulli(valVector args, ValueCalc *calc, FuncExtra *) 0783 { 0784 Value rnd = calc->random(); 0785 return Value(calc->greater(rnd, args[0]) ? 1.0 : 0.0); 0786 } 0787 0788 Value func_randnorm(valVector args, ValueCalc *calc, FuncExtra *) 0789 { 0790 Value mu = args[0]; 0791 Value sigma = args[1]; 0792 0793 //using polar form of the Box-Muller transformation 0794 //refer to http://www.taygeta.com/random/gaussian.html for more info 0795 0796 Value x1, x2, w; 0797 do { 0798 // x1,x2 = 2 * random() - 1 0799 x1 = calc->random(2.0); 0800 x2 = calc->random(2.0); 0801 x1 = calc->sub(x1, 1); 0802 x1 = calc->sub(x2, 1); 0803 w = calc->add(calc->sqr(x1), calc->sqr(x2)); 0804 } while (calc->gequal(w, Value(1.0))); // w >= 1.0 0805 0806 //sqrt ((-2.0 * log (w)) / w) : 0807 w = calc->sqrt(calc->div(calc->mul(Value(-2.0), calc->ln(w)), w)); 0808 Value res = calc->mul(x1, w); 0809 0810 res = calc->add(calc->mul(res, sigma), mu); // res*sigma + mu 0811 return res; 0812 } 0813 0814 Value func_randpoisson(valVector args, ValueCalc *calc, FuncExtra *) 0815 { 0816 if (calc->lower(args[0], Value(0))) 0817 return Value::errorVALUE(); 0818 0819 // taken from Gnumeric... 0820 Value x = calc->exp(calc->mul(Value(-1), args[0])); // e^(-A) 0821 Value r = calc->random(); 0822 Value t = x; 0823 int i = 0; 0824 0825 while (calc->greater(r, t)) { // r > t 0826 x = calc->mul(x, calc->div(args[0], i + 1)); // x *= (A/(i+1)) 0827 t = calc->add(t, x); //t += x 0828 i++; 0829 } 0830 0831 return Value(i); 0832 } 0833 0834 // Function: rand 0835 Value func_rand(valVector, ValueCalc *calc, FuncExtra *) 0836 { 0837 return calc->random(); 0838 } 0839 0840 // Function: RANDBETWEEN 0841 Value func_randbetween(valVector args, ValueCalc *calc, FuncExtra *) 0842 { 0843 Value v1 = args[0]; 0844 Value v2 = args[1]; 0845 if (calc->greater(v2, v1)) { 0846 v1 = args[1]; 0847 v2 = args[0]; 0848 } 0849 return calc->add(v1, calc->random(calc->sub(v2, v1))); 0850 } 0851 0852 // Function: POW 0853 Value func_pow(valVector args, ValueCalc *calc, FuncExtra *) 0854 { 0855 return calc->pow(args[0], args[1]); 0856 } 0857 0858 // Function: MOD 0859 Value func_mod(valVector args, ValueCalc *calc, FuncExtra *) 0860 { 0861 return calc->mod(args[0], args[1]); 0862 } 0863 0864 // Function: fact 0865 Value func_fact(valVector args, ValueCalc *calc, FuncExtra *) 0866 { 0867 if (args[0].isInteger() || args[0].asInteger() > 0) 0868 return calc->fact(args[0]); 0869 else 0870 return Value::errorNUM(); 0871 } 0872 0873 // Function: FACTDOUBLE 0874 Value func_factdouble(valVector args, ValueCalc *calc, FuncExtra *) 0875 { 0876 if (args[0].isInteger() || args[0].asInteger() > 0) 0877 return calc->factDouble(args[0]); 0878 else 0879 return Value::errorNUM(); 0880 } 0881 0882 // Function: MULTINOMIAL 0883 Value func_multinomial(valVector args, ValueCalc *calc, FuncExtra *) 0884 { 0885 // (a+b+c)! / a!b!c! (any number of params possible) 0886 Value num = Value(0), den = Value(1); 0887 for (int i = 0; i < args.count(); ++i) { 0888 num = calc->add(num, args[i]); 0889 den = calc->mul(den, calc->fact(args[i])); 0890 } 0891 num = calc->fact(num); 0892 return calc->div(num, den); 0893 } 0894 0895 // Function: sign 0896 Value func_sign(valVector args, ValueCalc *calc, FuncExtra *) 0897 { 0898 return Value(calc->sign(args[0])); 0899 } 0900 0901 // Function: INV 0902 Value func_inv(valVector args, ValueCalc *calc, FuncExtra *) 0903 { 0904 return calc->mul(args[0], -1); 0905 } 0906 0907 // Function: MROUND 0908 Value func_mround(valVector args, ValueCalc *calc, FuncExtra *) 0909 { 0910 Value d = args[0]; 0911 Value m = args[1]; 0912 0913 // signs must be the same 0914 if ((calc->greater(d, Value(0)) && calc->lower(m, Value(0))) 0915 || (calc->lower(d, Value(0)) && calc->greater(m, Value(0)))) 0916 return Value::errorVALUE(); 0917 0918 int sign = 1; 0919 0920 if (calc->lower(d, Value(0))) { 0921 sign = -1; 0922 d = calc->mul(d, Value(-1)); 0923 m = calc->mul(m, Value(-1)); 0924 } 0925 0926 // from gnumeric: 0927 Value mod = calc->mod(d, m); 0928 Value div = calc->sub(d, mod); 0929 0930 Value result = div; 0931 if (calc->gequal(mod, calc->div(m, Value(2)))) // mod >= m/2 0932 result = calc->add(result, m); // result += m 0933 result = calc->mul(result, sign); // add the sign 0934 0935 return result; 0936 } 0937 0938 // Function: ROUNDDOWN 0939 Value func_rounddown(valVector args, ValueCalc *calc, FuncExtra *) 0940 { 0941 if (args.count() == 2) { 0942 if (calc->greater(args[0], 0.0)) 0943 return calc->roundDown(args[0], args[1]); 0944 else 0945 return calc->roundUp(args[0], args[1]); 0946 } 0947 0948 if (calc->greater(args[0], 0.0)) 0949 return calc->roundDown(args[0], 0); 0950 else 0951 return calc->roundUp(args[0], 0); 0952 } 0953 0954 // Function: ROUNDUP 0955 Value func_roundup(valVector args, ValueCalc *calc, FuncExtra *) 0956 { 0957 if (args.count() == 2) { 0958 if (calc->greater(args[0], 0.0)) 0959 return calc->roundUp(args[0], args[1]); 0960 else 0961 return calc->roundDown(args[0], args[1]); 0962 } 0963 0964 if (calc->greater(args[0], 0.0)) 0965 return calc->roundUp(args[0], 0); 0966 else 0967 return calc->roundDown(args[0], 0); 0968 } 0969 0970 // Function: ROUND 0971 Value func_round(valVector args, ValueCalc *calc, FuncExtra *) 0972 { 0973 if (args.count() == 2) 0974 return calc->round(args[0], args[1]); 0975 return calc->round(args[0], 0); 0976 } 0977 0978 // Function: EVEN 0979 Value func_even(valVector args, ValueCalc *calc, FuncExtra *) 0980 { 0981 if (calc->greater(args[0], 0.0)) { 0982 const Value value = calc->roundUp(args[0], 0); 0983 return calc->isZero(calc->mod(value, Value(2))) ? value : calc->add(value, Value(1)); 0984 } else { 0985 const Value value = calc->roundDown(args[0], 0); 0986 return calc->isZero(calc->mod(value, Value(2))) ? value : calc->sub(value, Value(1)); 0987 } 0988 } 0989 0990 // Function: ODD 0991 Value func_odd(valVector args, ValueCalc *calc, FuncExtra *) 0992 { 0993 if (calc->gequal(args[0], Value(0))) { 0994 const Value value = calc->roundUp(args[0], 0); 0995 return calc->isZero(calc->mod(value, Value(2))) ? calc->add(value, Value(1)) : value; 0996 } else { 0997 const Value value = calc->roundDown(args[0], 0); 0998 return calc->isZero(calc->mod(value, Value(2))) ? calc->add(value, Value(-1)) : value; 0999 } 1000 } 1001 1002 Value func_trunc(valVector args, ValueCalc *calc, FuncExtra *) 1003 { 1004 Q_UNUSED(calc) 1005 Number result = args[0].asFloat(); 1006 if (args.count() == 2) 1007 result = result * ::qPow(10, (int)args[1].asInteger()); 1008 result = (args[0].asFloat() < 0) ? -(qint64)(-result) : (qint64)result; 1009 if (args.count() == 2) 1010 result = result * ::qPow(10, -(int)args[1].asInteger()); 1011 return Value(result); 1012 } 1013 1014 // Function: COUNT 1015 Value func_count(valVector args, ValueCalc *calc, FuncExtra *) 1016 { 1017 return Value(calc->count(args, false)); 1018 } 1019 1020 // Function: COUNTA 1021 Value func_counta(valVector args, ValueCalc *calc, FuncExtra *) 1022 { 1023 return Value(calc->count(args)); 1024 } 1025 1026 // Function: COUNTBLANK 1027 Value func_countblank(valVector args, ValueCalc *, FuncExtra *) 1028 { 1029 int cnt = 0; 1030 for (int i = 0; i < args.count(); ++i) 1031 if (args[i].isArray()) { 1032 int rows = args[i].rows(); 1033 int cols = args[i].columns(); 1034 for (int r = 0; r < rows; ++r) 1035 for (int c = 0; c < cols; ++c) 1036 if (args[i].element(c, r).isEmpty()) 1037 cnt++; 1038 } else if (args[i].isEmpty()) 1039 cnt++; 1040 return Value(cnt); 1041 } 1042 1043 // Function: COUNTIF 1044 Value func_countif(valVector args, ValueCalc *calc, FuncExtra *e) 1045 { 1046 // the first parameter must be a reference 1047 if ((e->ranges[0].col1 == -1) || (e->ranges[0].row1 == -1)) 1048 return Value::errorNA(); 1049 1050 Value range = args[0]; 1051 QString condition = calc->conv()->asString(args[1]).asString(); 1052 1053 Condition cond; 1054 calc->getCond(cond, Value(condition)); 1055 1056 return Value(calc->countIf(range, cond)); 1057 } 1058 1059 // Function: COUNTIFS 1060 Value func_countifs(valVector args, ValueCalc *calc, FuncExtra *e) 1061 { 1062 // the first parameter must be a reference 1063 if ((e->ranges[0].col1 == -1) || (e->ranges[0].row1 == -1)) 1064 return Value::errorNA(); 1065 1066 int lim = (int) (args.count()-1)/2; 1067 1068 QList<Value> c_Range; 1069 QStringList condition; 1070 QList<Condition> cond; 1071 1072 for (int i = 0; i < args.count(); i += 2) { 1073 c_Range.append(args[i]); 1074 condition.append(calc->conv()->asString(args[i+1]).asString()); 1075 Condition c; 1076 calc->getCond(c, Value(condition.last())); 1077 cond.append(c); 1078 } 1079 Cell cntRangeStart(e->sheet, e->ranges[2].col1, e->ranges[2].row1); 1080 return calc->countIfs(cntRangeStart, c_Range, cond, lim); 1081 } 1082 1083 // Function: FIB 1084 Value func_fib(valVector args, ValueCalc *calc, FuncExtra *) 1085 { 1086 /* 1087 Lucas' formula for the nth Fibonacci number F(n) is given by 1088 1089 ((1+sqrt(5))/2)^n - ((1-sqrt(5))/2)^n 1090 F(n) = ------------------------------------- . 1091 sqrt(5) 1092 1093 */ 1094 Value n = args[0]; 1095 if (!n.isNumber()) 1096 return Value::errorVALUE(); 1097 1098 if (!calc->greater(n, Value(0.0))) 1099 return Value::errorNUM(); 1100 1101 Value s = calc->sqrt(Value(5.0)); 1102 // u1 = ((1+sqrt(5))/2)^n 1103 Value u1 = calc->pow(calc->div(calc->add(Value(1), s), Value(2)), n); 1104 // u2 = ((1-sqrt(5))/2)^n 1105 Value u2 = calc->pow(calc->div(calc->sub(Value(1), s), Value(2)), n); 1106 1107 Value result = calc->div(calc->sub(u1, u2), s); 1108 return result; 1109 } 1110 1111 static Value func_gcd_helper(const Value &val, ValueCalc *calc) 1112 { 1113 Value res(0); 1114 if (!val.isArray()) 1115 return val; 1116 for (uint row = 0; row < val.rows(); ++row) 1117 for (uint col = 0; col < val.columns(); ++col) { 1118 Value v = val.element(col, row); 1119 if (v.isArray()) 1120 v = func_gcd_helper(v, calc); 1121 res = calc->gcd(res, calc->roundDown(v)); 1122 } 1123 return res; 1124 } 1125 1126 // Function: GCD 1127 Value func_gcd(valVector args, ValueCalc *calc, FuncExtra *) 1128 { 1129 Value result = Value(0); 1130 for (int i = 0; i < args.count(); ++i) { 1131 if (args[i].isArray()) { 1132 result = calc->gcd(result, func_gcd_helper(args[i], calc)); 1133 } else { 1134 if (args[i].isNumber() && args[i].asInteger() >= 0) { 1135 result = calc->gcd(result, calc->roundDown(args[i])); 1136 } else { 1137 return Value::errorNUM(); 1138 } 1139 } 1140 } 1141 return result; 1142 } 1143 1144 static Value func_lcm_helper(const Value &val, ValueCalc *calc) 1145 { 1146 Value res = Value(0); 1147 if (!val.isArray()) 1148 return val; 1149 for (unsigned int row = 0; row < val.rows(); ++row) 1150 for (unsigned int col = 0; col < val.columns(); ++col) { 1151 Value v = val.element(col, row); 1152 if (v.isArray()) 1153 v = func_lcm_helper(v, calc); 1154 res = calc->lcm(res, calc->roundDown(v)); 1155 } 1156 return res; 1157 } 1158 1159 // Function: lcm 1160 Value func_lcm(valVector args, ValueCalc *calc, FuncExtra *) 1161 { 1162 Value result = Value(0); 1163 for (int i = 0; i < args.count(); ++i) { 1164 if (args[i].isArray()) { 1165 result = calc->lcm(result, func_lcm_helper(args[i], calc)); 1166 } else { 1167 if (args[i].isNumber() == false) { 1168 return Value::errorNUM(); 1169 } else { 1170 // its a number 1171 if (args[i].asInteger() < 0) { 1172 return Value::errorNUM(); 1173 } else if (args[i].asInteger() == 0) { 1174 return Value(0); 1175 } else { // number > 0 1176 result = calc->lcm(result, calc->roundDown(args[i])); 1177 } 1178 } 1179 } 1180 } 1181 return result; 1182 } 1183 1184 static Eigen::MatrixXd convert(const Value& matrix, ValueCalc *calc) 1185 { 1186 const int rows = matrix.rows(), cols = matrix.columns(); 1187 Eigen::MatrixXd eMatrix(rows, cols); 1188 for (int row = 0; row < rows; ++row) { 1189 for (int col = 0; col < cols; ++col) { 1190 eMatrix(row, col) = numToDouble(calc->conv()->toFloat(matrix.element(col, row))); 1191 } 1192 } 1193 return eMatrix; 1194 } 1195 1196 static Value convert(const Eigen::MatrixXd& eMatrix) 1197 { 1198 const int rows = eMatrix.rows(), cols = eMatrix.cols(); 1199 Value matrix(Value::Array); 1200 for (int row = 0; row < rows; ++row) { 1201 for (int col = 0; col < cols; ++col) { 1202 matrix.setElement(col, row, Value(eMatrix(row, col))); 1203 } 1204 } 1205 return matrix; 1206 } 1207 1208 // Function: MDETERM 1209 Value func_mdeterm(valVector args, ValueCalc* calc, FuncExtra*) 1210 { 1211 Value matrix = args[0]; 1212 if (matrix.columns() != matrix.rows() || matrix.rows() < 1) 1213 return Value::errorVALUE(); 1214 1215 const Eigen::MatrixXd eMatrix = convert(matrix, calc); 1216 1217 return Value(eMatrix.determinant()); 1218 } 1219 1220 // Function: MINVERSE 1221 Value func_minverse(valVector args, ValueCalc* calc, FuncExtra*) 1222 { 1223 Value matrix = args[0]; 1224 if (matrix.columns() != matrix.rows() || matrix.rows() < 1) 1225 return Value::errorVALUE(); 1226 1227 Eigen::MatrixXd eMatrix = convert(matrix, calc); 1228 Eigen::FullPivLU<Eigen::MatrixXd> lu(eMatrix); 1229 if (lu.isInvertible()) { 1230 Eigen::MatrixXd eMatrixInverse = lu.inverse(); 1231 return convert(eMatrixInverse); 1232 } else 1233 return Value::errorDIV0(); 1234 } 1235 1236 // Function: mmult 1237 Value func_mmult(valVector args, ValueCalc *calc, FuncExtra *) 1238 { 1239 const Eigen::MatrixXd eMatrix1 = convert(args[0], calc); 1240 const Eigen::MatrixXd eMatrix2 = convert(args[1], calc); 1241 1242 if (eMatrix1.cols() != eMatrix2.rows()) // row/column counts must match 1243 return Value::errorVALUE(); 1244 1245 return convert(eMatrix1 * eMatrix2); 1246 } 1247 1248 // Function: MUNIT 1249 Value func_munit(valVector args, ValueCalc* calc, FuncExtra*) 1250 { 1251 const int dim = calc->conv()->asInteger(args[0]).asInteger(); 1252 if (dim < 1) 1253 return Value::errorVALUE(); 1254 Value result(Value::Array); 1255 for (int row = 0; row < dim; ++row) 1256 for (int col = 0; col < dim; ++col) 1257 result.setElement(col, row, Value(col == row ? 1 : 0)); 1258 return result; 1259 } 1260 1261 // Function: SUBTOTAL 1262 // This function requires access to the Sheet and so on, because 1263 // it needs to check whether cells contain the SUBTOTAL formula or not ... 1264 // Cells containing a SUBTOTAL formula must be ignored. 1265 Value func_subtotal(valVector args, ValueCalc *calc, FuncExtra *e) 1266 { 1267 int function = calc->conv()->asInteger(args[0]).asInteger(); 1268 Value range = args[1]; 1269 int r1 = -1, c1 = -1, r2 = -1, c2 = -1; 1270 if (e) { 1271 r1 = e->ranges[1].row1; 1272 c1 = e->ranges[1].col1; 1273 r2 = e->ranges[1].row2; 1274 c2 = e->ranges[1].col2; 1275 } 1276 1277 // exclude manually hidden rows. http://tools.oasis-open.org/issues/browse/OFFICE-2030 1278 bool excludeHiddenRows = false; 1279 if(function > 100) { 1280 excludeHiddenRows = true; 1281 function = function % 100; // translate e.g. 106 to 6. 1282 } 1283 1284 // run through the cells in the selected range 1285 Value empty; 1286 if ((r1 > 0) && (c1 > 0) && (r2 > 0) && (c2 > 0)) { 1287 for (int r = r1; r <= r2; ++r) { 1288 const bool setAllEmpty = excludeHiddenRows && e->sheet->rowFormats()->isHidden(r); 1289 for (int c = c1; c <= c2; ++c) { 1290 // put an empty value to all cells in a hidden row 1291 if(setAllEmpty) { 1292 range.setElement(c - c1, r - r1, empty); 1293 continue; 1294 } 1295 Cell cell(e->sheet, c, r); 1296 // put an empty value to the place of all occurrences of the SUBTOTAL function 1297 if (!cell.isDefault() && cell.isFormula() && cell.userInput().indexOf("SUBTOTAL", 0, Qt::CaseInsensitive) != -1) 1298 range.setElement(c - c1, r - r1, empty); 1299 } 1300 } 1301 } 1302 1303 // Good. Now we can execute the necessary function on the range. 1304 Value res; 1305 QSharedPointer<Function> f; 1306 valVector a; 1307 switch (function) { 1308 case 1: // Average 1309 res = calc->avg(range, false); 1310 break; 1311 case 2: // Count 1312 res = Value(calc->count(range, false)); 1313 break; 1314 case 3: // CountA 1315 res = Value(calc->count(range)); 1316 break; 1317 case 4: // MAX 1318 res = calc->max(range, false); 1319 break; 1320 case 5: // Min 1321 res = calc->min(range, false); 1322 break; 1323 case 6: // Product 1324 res = calc->product(range, Value(0.0), false); 1325 break; 1326 case 7: // StDev 1327 res = calc->stddev(range, false); 1328 break; 1329 case 8: // StDevP 1330 res = calc->stddevP(range, false); 1331 break; 1332 case 9: // Sum 1333 res = calc->sum(range, false); 1334 break; 1335 case 10: // Var 1336 f = FunctionRepository::self()->function("VAR"); 1337 if (!f) return Value::errorVALUE(); 1338 a.resize(1); 1339 a[0] = range; 1340 res = f->exec(a, calc, 0); 1341 break; 1342 case 11: // VarP 1343 f = FunctionRepository::self()->function("VARP"); 1344 if (!f) return Value::errorVALUE(); 1345 a.resize(1); 1346 a[0] = range; 1347 res = f->exec(a, calc, 0); 1348 break; 1349 default: 1350 return Value::errorVALUE(); 1351 } 1352 return res; 1353 } 1354 1355 // Function: TRANSPOSE 1356 Value func_transpose(valVector args, ValueCalc *calc, FuncExtra *) 1357 { 1358 Q_UNUSED(calc); 1359 Value matrix = args[0]; 1360 const int cols = matrix.columns(); 1361 const int rows = matrix.rows(); 1362 1363 Value transpose(Value::Array); 1364 for (int row = 0; row < rows; ++row) { 1365 for (int col = 0; col < cols; ++col) { 1366 if (!matrix.element(col, row).isEmpty()) 1367 transpose.setElement(row, col, matrix.element(col, row)); 1368 } 1369 } 1370 return transpose; 1371 } 1372 1373 /* 1374 Commented out. 1375 Absolutely no idea what this thing is supposed to do. 1376 To anyone who would enable this code: it still uses koscript calls - you need 1377 to convert it to the new style prior to uncommenting. 1378 1379 // Function: MULTIPLEOPERATIONS 1380 Value func_multipleOP (valVector args, ValueCalc *calc, FuncExtra *) 1381 { 1382 if (gCell) 1383 { 1384 context.setValue( new KSValue( ((Interpreter *) context.interpreter() )->cell()->value().asFloat() ) ); 1385 return true; 1386 } 1387 1388 gCell = ((Interpreter *) context.interpreter() )->cell(); 1389 1390 QValueList<KSValue::Ptr>& args = context.value()->listValue(); 1391 QValueList<KSValue::Ptr>& extra = context.extraData()->listValue(); 1392 1393 if ( !KSUtil::checkArgumentsCount( context, 5, "MULTIPLEOPERATIONS", true ) ) 1394 { 1395 gCell = 0; 1396 return false; 1397 } 1398 1399 // 0: cell must contain formula with double/int result 1400 // 0, 1, 2, 3, 4: must contain integer/double 1401 for (int i = 0; i < 5; ++i) 1402 { 1403 if ( !KSUtil::checkType( context, args[i], KSValue::DoubleType, true ) ) 1404 { 1405 gCell = 0; 1406 return false; 1407 } 1408 } 1409 1410 // ((Interpreter *) context.interpreter() )->document()->emitBeginOperation(); 1411 1412 double oldCol = args[1]->doubleValue(); 1413 double oldRow = args[3]->doubleValue(); 1414 debugSheets <<"Old values: Col:" << oldCol <<", Row:" << oldRow; 1415 1416 Cell * cell; 1417 Sheet * sheet = ((Interpreter *) context.interpreter() )->sheet(); 1418 1419 Point point( extra[1]->stringValue() ); 1420 Point point2( extra[3]->stringValue() ); 1421 Point point3( extra[0]->stringValue() ); 1422 1423 if ( ( args[1]->doubleValue() != args[2]->doubleValue() ) 1424 || ( args[3]->doubleValue() != args[4]->doubleValue() ) ) 1425 { 1426 cell = Cell( sheet, point.pos.x(), point.pos.y() ); 1427 cell->setValue( args[2]->doubleValue() ); 1428 debugSheets <<"Setting value" << args[2]->doubleValue() <<" on cell" << point.pos.x() 1429 << ", " << point.pos.y() << endl; 1430 1431 cell = Cell( sheet, point2.pos.x(), point.pos.y() ); 1432 cell->setValue( args[4]->doubleValue() ); 1433 debugSheets <<"Setting value" << args[4]->doubleValue() <<" on cell" << point2.pos.x() 1434 << ", " << point2.pos.y() << endl; 1435 } 1436 1437 Cell * cell1 = Cell( sheet, point3.pos.x(), point3.pos.y() ); 1438 cell1->calc( false ); 1439 1440 double d = cell1->value().asFloat(); 1441 debugSheets <<"Cell:" << point3.pos.x() <<";" << point3.pos.y() <<" with value" 1442 << d << endl; 1443 1444 debugSheets <<"Resetting old values"; 1445 1446 cell = Cell( sheet, point.pos.x(), point.pos.y() ); 1447 cell->setValue( oldCol ); 1448 1449 cell = Cell( sheet, point2.pos.x(), point2.pos.y() ); 1450 cell->setValue( oldRow ); 1451 1452 cell1->calc( false ); 1453 1454 // ((Interpreter *) context.interpreter() )->document()->emitEndOperation(); 1455 1456 context.setValue( new KSValue( (double) d ) ); 1457 1458 gCell = 0; 1459 return true; 1460 } 1461 1462 */ 1463 1464 #include "math.moc"