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 <config_features.h> 21 22 #include <interpre.hxx> 23 24 #include <rangelst.hxx> 25 #include <rtl/math.hxx> 26 #include <sfx2/app.hxx> 27 #include <sfx2/docfile.hxx> 28 #include <sfx2/objsh.hxx> 29 #include <sfx2/docfilt.hxx> 30 #include <basic/sbmeth.hxx> 31 #include <basic/sbmod.hxx> 32 #include <basic/sbstar.hxx> 33 #include <basic/sbx.hxx> 34 #include <basic/sbxobj.hxx> 35 #include <basic/sbuno.hxx> 36 #include <svl/zforlist.hxx> 37 #include <svl/sharedstringpool.hxx> 38 #include <unotools/charclass.hxx> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <signal.h> 42 43 #include <com/sun/star/table/XCellRange.hpp> 44 #include <com/sun/star/sheet/XSheetCellRange.hpp> 45 46 #include <global.hxx> 47 #include <dbdata.hxx> 48 #include <formulacell.hxx> 49 #include <callform.hxx> 50 #include <addincol.hxx> 51 #include <document.hxx> 52 #include <dociter.hxx> 53 #include <docoptio.hxx> 54 #include <scmatrix.hxx> 55 #include <adiasync.hxx> 56 #include <sc.hrc> 57 #include <cellsuno.hxx> 58 #include <optuno.hxx> 59 #include <rangeseq.hxx> 60 #include <addinlis.hxx> 61 #include <jumpmatrix.hxx> 62 #include <parclass.hxx> 63 #include <externalrefmgr.hxx> 64 #include <formula/FormulaCompiler.hxx> 65 #include <macromgr.hxx> 66 #include <doubleref.hxx> 67 #include <queryparam.hxx> 68 #include <tokenarray.hxx> 69 #include <compiler.hxx> 70 71 #include <math.h> 72 #include <float.h> 73 #include <map> 74 #include <algorithm> 75 #include <basic/basmgr.hxx> 76 #include <vbahelper/vbaaccesshelper.hxx> 77 #include <memory> 78 #include <stack> 79 80 using namespace com::sun::star; 81 using namespace formula; 82 using ::std::unique_ptr; 83 84 #define ADDIN_MAXSTRLEN 256 85 86 thread_local std::unique_ptr<ScTokenStack> ScInterpreter::pGlobalStack; 87 thread_local bool ScInterpreter::bGlobalStackInUse = false; 88 89 // document access functions 90 91 void ScInterpreter::ReplaceCell( ScAddress& rPos ) 92 { 93 size_t ListSize = pDok->m_TableOpList.size(); 94 for ( size_t i = 0; i < ListSize; ++i ) 95 { 96 ScInterpreterTableOpParams *const pTOp = pDok->m_TableOpList[ i ]; 97 if ( rPos == pTOp->aOld1 ) 98 { 99 rPos = pTOp->aNew1; 100 return ; 101 } 102 else if ( rPos == pTOp->aOld2 ) 103 { 104 rPos = pTOp->aNew2; 105 return ; 106 } 107 } 108 } 109 110 bool ScInterpreter::IsTableOpInRange( const ScRange& rRange ) 111 { 112 if ( rRange.aStart == rRange.aEnd ) 113 return false; // not considered to be a range in TableOp sense 114 115 // we can't replace a single cell in a range 116 size_t ListSize = pDok->m_TableOpList.size(); 117 for ( size_t i = 0; i < ListSize; ++i ) 118 { 119 ScInterpreterTableOpParams *const pTOp = pDok->m_TableOpList[ i ]; 120 if ( rRange.In( pTOp->aOld1 ) ) 121 return true; 122 if ( rRange.In( pTOp->aOld2 ) ) 123 return true; 124 } 125 return false; 126 } 127 128 sal_uInt32 ScInterpreter::GetCellNumberFormat( const ScAddress& rPos, ScRefCellValue& rCell ) 129 { 130 sal_uInt32 nFormat; 131 FormulaError nErr; 132 if (rCell.isEmpty()) 133 { 134 nFormat = pDok->GetNumberFormat( mrContext, rPos ); 135 nErr = FormulaError::NONE; 136 } 137 else 138 { 139 if (rCell.meType == CELLTYPE_FORMULA) 140 nErr = rCell.mpFormula->GetErrCode(); 141 else 142 nErr = FormulaError::NONE; 143 nFormat = pDok->GetNumberFormat( mrContext, rPos ); 144 } 145 146 SetError(nErr); 147 return nFormat; 148 } 149 150 /// Only ValueCell, formula cells already store the result rounded. 151 double ScInterpreter::GetValueCellValue( const ScAddress& rPos, double fOrig ) 152 { 153 if ( bCalcAsShown && fOrig != 0.0 ) 154 { 155 sal_uInt32 nFormat = pDok->GetNumberFormat( mrContext, rPos ); 156 fOrig = pDok->RoundValueAsShown( fOrig, nFormat, &mrContext ); 157 } 158 return fOrig; 159 } 160 161 FormulaError ScInterpreter::GetCellErrCode( const ScRefCellValue& rCell ) 162 { 163 return rCell.meType == CELLTYPE_FORMULA ? rCell.mpFormula->GetErrCode() : FormulaError::NONE; 164 } 165 166 double ScInterpreter::ConvertStringToValue( const OUString& rStr ) 167 { 168 FormulaError nError = FormulaError::NONE; 169 double fValue = ScGlobal::ConvertStringToValue( rStr, maCalcConfig, nError, mnStringNoValueError, 170 pFormatter, nCurFmtType); 171 if (nError != FormulaError::NONE) 172 SetError(nError); 173 return fValue; 174 } 175 176 double ScInterpreter::ConvertStringToValue( const OUString& rStr, FormulaError& rError, SvNumFormatType& rCurFmtType ) 177 { 178 return ScGlobal::ConvertStringToValue( rStr, maCalcConfig, rError, mnStringNoValueError, pFormatter, rCurFmtType); 179 } 180 181 double ScInterpreter::GetCellValue( const ScAddress& rPos, ScRefCellValue& rCell ) 182 { 183 FormulaError nErr = nGlobalError; 184 nGlobalError = FormulaError::NONE; 185 double nVal = GetCellValueOrZero(rPos, rCell); 186 if ( nGlobalError == FormulaError::NONE || nGlobalError == FormulaError::CellNoValue ) 187 nGlobalError = nErr; 188 return nVal; 189 } 190 191 double ScInterpreter::GetCellValueOrZero( const ScAddress& rPos, ScRefCellValue& rCell ) 192 { 193 double fValue = 0.0; 194 195 CellType eType = rCell.meType; 196 switch (eType) 197 { 198 case CELLTYPE_FORMULA: 199 { 200 ScFormulaCell* pFCell = rCell.mpFormula; 201 FormulaError nErr = pFCell->GetErrCode(); 202 if( nErr == FormulaError::NONE ) 203 { 204 if (pFCell->IsValue()) 205 { 206 fValue = pFCell->GetValue(); 207 pDok->GetNumberFormatInfo( mrContext, nCurFmtType, nCurFmtIndex, 208 rPos ); 209 } 210 else 211 { 212 fValue = ConvertStringToValue(pFCell->GetString().getString()); 213 } 214 } 215 else 216 { 217 fValue = 0.0; 218 SetError(nErr); 219 } 220 } 221 break; 222 case CELLTYPE_VALUE: 223 { 224 fValue = rCell.mfValue; 225 nCurFmtIndex = pDok->GetNumberFormat( mrContext, rPos ); 226 nCurFmtType = pFormatter->GetType( nCurFmtIndex ); 227 if ( bCalcAsShown && fValue != 0.0 ) 228 fValue = pDok->RoundValueAsShown( fValue, nCurFmtIndex, &mrContext ); 229 } 230 break; 231 case CELLTYPE_STRING: 232 case CELLTYPE_EDIT: 233 { 234 // SUM(A1:A2) differs from A1+A2. No good. But people insist on 235 // it ... #i5658# 236 OUString aStr = rCell.getString(pDok); 237 fValue = ConvertStringToValue( aStr ); 238 } 239 break; 240 case CELLTYPE_NONE: 241 fValue = 0.0; // empty or broadcaster cell 242 break; 243 } 244 245 return fValue; 246 } 247 248 void ScInterpreter::GetCellString( svl::SharedString& rStr, ScRefCellValue& rCell ) 249 { 250 FormulaError nErr = FormulaError::NONE; 251 252 switch (rCell.meType) 253 { 254 case CELLTYPE_STRING: 255 case CELLTYPE_EDIT: 256 rStr = mrStrPool.intern(rCell.getString(pDok)); 257 break; 258 case CELLTYPE_FORMULA: 259 { 260 ScFormulaCell* pFCell = rCell.mpFormula; 261 nErr = pFCell->GetErrCode(); 262 if (pFCell->IsValue()) 263 { 264 rStr = GetStringFromDouble( pFCell->GetValue() ); 265 } 266 else 267 rStr = pFCell->GetString(); 268 } 269 break; 270 case CELLTYPE_VALUE: 271 { 272 rStr = GetStringFromDouble( rCell.mfValue ); 273 } 274 break; 275 default: 276 rStr = svl::SharedString::getEmptyString(); 277 break; 278 } 279 280 SetError(nErr); 281 } 282 283 bool ScInterpreter::CreateDoubleArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, 284 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt8* pCellArr) 285 { 286 287 // Old Add-Ins are hard limited to sal_uInt16 values. 288 static_assert(MAXCOLCOUNT <= SAL_MAX_UINT16, "Add check for columns > SAL_MAX_UINT16!"); 289 if (nRow1 > SAL_MAX_UINT16 || nRow2 > SAL_MAX_UINT16) 290 return false; 291 292 sal_uInt16 nCount = 0; 293 sal_uInt16* p = reinterpret_cast<sal_uInt16*>(pCellArr); 294 *p++ = static_cast<sal_uInt16>(nCol1); 295 *p++ = static_cast<sal_uInt16>(nRow1); 296 *p++ = static_cast<sal_uInt16>(nTab1); 297 *p++ = static_cast<sal_uInt16>(nCol2); 298 *p++ = static_cast<sal_uInt16>(nRow2); 299 *p++ = static_cast<sal_uInt16>(nTab2); 300 sal_uInt16* pCount = p; 301 *p++ = 0; 302 sal_uInt16 nPos = 14; 303 SCTAB nTab = nTab1; 304 ScAddress aAdr; 305 while (nTab <= nTab2) 306 { 307 aAdr.SetTab( nTab ); 308 SCROW nRow = nRow1; 309 while (nRow <= nRow2) 310 { 311 aAdr.SetRow( nRow ); 312 SCCOL nCol = nCol1; 313 while (nCol <= nCol2) 314 { 315 aAdr.SetCol( nCol ); 316 317 ScRefCellValue aCell(*pDok, aAdr); 318 if (!aCell.isEmpty()) 319 { 320 FormulaError nErr = FormulaError::NONE; 321 double nVal = 0.0; 322 bool bOk = true; 323 switch (aCell.meType) 324 { 325 case CELLTYPE_VALUE : 326 nVal = GetValueCellValue(aAdr, aCell.mfValue); 327 break; 328 case CELLTYPE_FORMULA : 329 if (aCell.mpFormula->IsValue()) 330 { 331 nErr = aCell.mpFormula->GetErrCode(); 332 nVal = aCell.mpFormula->GetValue(); 333 } 334 else 335 bOk = false; 336 break; 337 default : 338 bOk = false; 339 break; 340 } 341 if (bOk) 342 { 343 if ((nPos + (4 * sizeof(sal_uInt16)) + sizeof(double)) > MAXARRSIZE) 344 return false; 345 *p++ = static_cast<sal_uInt16>(nCol); 346 *p++ = static_cast<sal_uInt16>(nRow); 347 *p++ = static_cast<sal_uInt16>(nTab); 348 *p++ = static_cast<sal_uInt16>(nErr); 349 memcpy( p, &nVal, sizeof(double)); 350 nPos += 8 + sizeof(double); 351 p = reinterpret_cast<sal_uInt16*>( pCellArr + nPos ); 352 nCount++; 353 } 354 } 355 nCol++; 356 } 357 nRow++; 358 } 359 nTab++; 360 } 361 *pCount = nCount; 362 return true; 363 } 364 365 bool ScInterpreter::CreateStringArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, 366 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, 367 sal_uInt8* pCellArr) 368 { 369 370 // Old Add-Ins are hard limited to sal_uInt16 values. 371 static_assert(MAXCOLCOUNT <= SAL_MAX_UINT16, "Add check for columns > SAL_MAX_UINT16!"); 372 if (nRow1 > SAL_MAX_UINT16 || nRow2 > SAL_MAX_UINT16) 373 return false; 374 375 sal_uInt16 nCount = 0; 376 sal_uInt16* p = reinterpret_cast<sal_uInt16*>(pCellArr); 377 *p++ = static_cast<sal_uInt16>(nCol1); 378 *p++ = static_cast<sal_uInt16>(nRow1); 379 *p++ = static_cast<sal_uInt16>(nTab1); 380 *p++ = static_cast<sal_uInt16>(nCol2); 381 *p++ = static_cast<sal_uInt16>(nRow2); 382 *p++ = static_cast<sal_uInt16>(nTab2); 383 sal_uInt16* pCount = p; 384 *p++ = 0; 385 sal_uInt16 nPos = 14; 386 SCTAB nTab = nTab1; 387 while (nTab <= nTab2) 388 { 389 SCROW nRow = nRow1; 390 while (nRow <= nRow2) 391 { 392 SCCOL nCol = nCol1; 393 while (nCol <= nCol2) 394 { 395 ScRefCellValue aCell(*pDok, ScAddress(nCol, nRow, nTab)); 396 if (!aCell.isEmpty()) 397 { 398 OUString aStr; 399 FormulaError nErr = FormulaError::NONE; 400 bool bOk = true; 401 switch (aCell.meType) 402 { 403 case CELLTYPE_STRING: 404 case CELLTYPE_EDIT: 405 aStr = aCell.getString(pDok); 406 break; 407 case CELLTYPE_FORMULA: 408 if (!aCell.mpFormula->IsValue()) 409 { 410 nErr = aCell.mpFormula->GetErrCode(); 411 aStr = aCell.mpFormula->GetString().getString(); 412 } 413 else 414 bOk = false; 415 break; 416 default : 417 bOk = false; 418 break; 419 } 420 if (bOk) 421 { 422 OString aTmp(OUStringToOString(aStr, 423 osl_getThreadTextEncoding())); 424 // Old Add-Ins are limited to sal_uInt16 string 425 // lengths, and room for pad byte check. 426 if ( aTmp.getLength() > SAL_MAX_UINT16 - 2 ) 427 return false; 428 // Append a 0-pad-byte if string length is odd 429 // MUST be sal_uInt16 430 sal_uInt16 nStrLen = static_cast<sal_uInt16>(aTmp.getLength()); 431 sal_uInt16 nLen = ( nStrLen + 2 ) & ~1; 432 433 if ((static_cast<sal_uLong>(nPos) + (5 * sizeof(sal_uInt16)) + nLen) > MAXARRSIZE) 434 return false; 435 *p++ = static_cast<sal_uInt16>(nCol); 436 *p++ = static_cast<sal_uInt16>(nRow); 437 *p++ = static_cast<sal_uInt16>(nTab); 438 *p++ = static_cast<sal_uInt16>(nErr); 439 *p++ = nLen; 440 memcpy( p, aTmp.getStr(), nStrLen + 1); 441 nPos += 10 + nStrLen + 1; 442 sal_uInt8* q = ( pCellArr + nPos ); 443 if( (nStrLen & 1) == 0 ) 444 { 445 *q++ = 0; 446 nPos++; 447 } 448 p = reinterpret_cast<sal_uInt16*>( pCellArr + nPos ); 449 nCount++; 450 } 451 } 452 nCol++; 453 } 454 nRow++; 455 } 456 nTab++; 457 } 458 *pCount = nCount; 459 return true; 460 } 461 462 bool ScInterpreter::CreateCellArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, 463 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, 464 sal_uInt8* pCellArr) 465 { 466 467 // Old Add-Ins are hard limited to sal_uInt16 values. 468 static_assert(MAXCOLCOUNT <= SAL_MAX_UINT16, "Add check for columns > SAL_MAX_UINT16!"); 469 if (nRow1 > SAL_MAX_UINT16 || nRow2 > SAL_MAX_UINT16) 470 return false; 471 472 sal_uInt16 nCount = 0; 473 sal_uInt16* p = reinterpret_cast<sal_uInt16*>(pCellArr); 474 *p++ = static_cast<sal_uInt16>(nCol1); 475 *p++ = static_cast<sal_uInt16>(nRow1); 476 *p++ = static_cast<sal_uInt16>(nTab1); 477 *p++ = static_cast<sal_uInt16>(nCol2); 478 *p++ = static_cast<sal_uInt16>(nRow2); 479 *p++ = static_cast<sal_uInt16>(nTab2); 480 sal_uInt16* pCount = p; 481 *p++ = 0; 482 sal_uInt16 nPos = 14; 483 SCTAB nTab = nTab1; 484 ScAddress aAdr; 485 while (nTab <= nTab2) 486 { 487 aAdr.SetTab( nTab ); 488 SCROW nRow = nRow1; 489 while (nRow <= nRow2) 490 { 491 aAdr.SetRow( nRow ); 492 SCCOL nCol = nCol1; 493 while (nCol <= nCol2) 494 { 495 aAdr.SetCol( nCol ); 496 ScRefCellValue aCell(*pDok, aAdr); 497 if (!aCell.isEmpty()) 498 { 499 FormulaError nErr = FormulaError::NONE; 500 sal_uInt16 nType = 0; // 0 = number; 1 = string 501 double nVal = 0.0; 502 OUString aStr; 503 bool bOk = true; 504 switch (aCell.meType) 505 { 506 case CELLTYPE_STRING : 507 case CELLTYPE_EDIT : 508 aStr = aCell.getString(pDok); 509 nType = 1; 510 break; 511 case CELLTYPE_VALUE : 512 nVal = GetValueCellValue(aAdr, aCell.mfValue); 513 break; 514 case CELLTYPE_FORMULA : 515 nErr = aCell.mpFormula->GetErrCode(); 516 if (aCell.mpFormula->IsValue()) 517 nVal = aCell.mpFormula->GetValue(); 518 else 519 aStr = aCell.mpFormula->GetString().getString(); 520 break; 521 default : 522 bOk = false; 523 break; 524 } 525 if (bOk) 526 { 527 if ((nPos + (5 * sizeof(sal_uInt16))) > MAXARRSIZE) 528 return false; 529 *p++ = static_cast<sal_uInt16>(nCol); 530 *p++ = static_cast<sal_uInt16>(nRow); 531 *p++ = static_cast<sal_uInt16>(nTab); 532 *p++ = static_cast<sal_uInt16>(nErr); 533 *p++ = nType; 534 nPos += 10; 535 if (nType == 0) 536 { 537 if ((nPos + sizeof(double)) > MAXARRSIZE) 538 return false; 539 memcpy( p, &nVal, sizeof(double)); 540 nPos += sizeof(double); 541 } 542 else 543 { 544 OString aTmp(OUStringToOString(aStr, 545 osl_getThreadTextEncoding())); 546 // Old Add-Ins are limited to sal_uInt16 string 547 // lengths, and room for pad byte check. 548 if ( aTmp.getLength() > SAL_MAX_UINT16 - 2 ) 549 return false; 550 // Append a 0-pad-byte if string length is odd 551 // MUST be sal_uInt16 552 sal_uInt16 nStrLen = static_cast<sal_uInt16>(aTmp.getLength()); 553 sal_uInt16 nLen = ( nStrLen + 2 ) & ~1; 554 if ( (static_cast<sal_uLong>(nPos) + 2 + nLen) > MAXARRSIZE) 555 return false; 556 *p++ = nLen; 557 memcpy( p, aTmp.getStr(), nStrLen + 1); 558 nPos += 2 + nStrLen + 1; 559 sal_uInt8* q = ( pCellArr + nPos ); 560 if( (nStrLen & 1) == 0 ) 561 { 562 *q++ = 0; 563 nPos++; 564 } 565 } 566 nCount++; 567 p = reinterpret_cast<sal_uInt16*>( pCellArr + nPos ); 568 } 569 } 570 nCol++; 571 } 572 nRow++; 573 } 574 nTab++; 575 } 576 *pCount = nCount; 577 return true; 578 } 579 580 // Stack operations 581 582 // Also releases a TempToken if appropriate. 583 584 void ScInterpreter::PushWithoutError( const FormulaToken& r ) 585 { 586 if ( sp >= MAXSTACK ) 587 SetError( FormulaError::StackOverflow ); 588 else 589 { 590 r.IncRef(); 591 if( sp >= maxsp ) 592 maxsp = sp + 1; 593 else 594 pStack[ sp ]->DecRef(); 595 pStack[ sp ] = &r; 596 ++sp; 597 } 598 } 599 600 void ScInterpreter::Push( const FormulaToken& r ) 601 { 602 if ( sp >= MAXSTACK ) 603 SetError( FormulaError::StackOverflow ); 604 else 605 { 606 if (nGlobalError != FormulaError::NONE) 607 { 608 if (r.GetType() == svError) 609 PushWithoutError( r); 610 else 611 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError)); 612 } 613 else 614 PushWithoutError( r); 615 } 616 } 617 618 void ScInterpreter::PushTempToken( FormulaToken* p ) 619 { 620 if ( sp >= MAXSTACK ) 621 { 622 SetError( FormulaError::StackOverflow ); 623 // p may be a dangling pointer hereafter! 624 p->DeleteIfZeroRef(); 625 } 626 else 627 { 628 if (nGlobalError != FormulaError::NONE) 629 { 630 if (p->GetType() == svError) 631 { 632 p->SetError( nGlobalError); 633 PushTempTokenWithoutError( p); 634 } 635 else 636 { 637 // p may be a dangling pointer hereafter! 638 p->DeleteIfZeroRef(); 639 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError)); 640 } 641 } 642 else 643 PushTempTokenWithoutError( p); 644 } 645 } 646 647 void ScInterpreter::PushTempTokenWithoutError( const FormulaToken* p ) 648 { 649 p->IncRef(); 650 if ( sp >= MAXSTACK ) 651 { 652 SetError( FormulaError::StackOverflow ); 653 // p may be a dangling pointer hereafter! 654 p->DecRef(); 655 } 656 else 657 { 658 if( sp >= maxsp ) 659 maxsp = sp + 1; 660 else 661 pStack[ sp ]->DecRef(); 662 pStack[ sp ] = p; 663 ++sp; 664 } 665 } 666 667 void ScInterpreter::PushTokenRef( const formula::FormulaConstTokenRef& x ) 668 { 669 if ( sp >= MAXSTACK ) 670 { 671 SetError( FormulaError::StackOverflow ); 672 } 673 else 674 { 675 if (nGlobalError != FormulaError::NONE) 676 { 677 if (x->GetType() == svError && x->GetError() == nGlobalError) 678 PushTempTokenWithoutError( x.get()); 679 else 680 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError)); 681 } 682 else 683 PushTempTokenWithoutError( x.get()); 684 } 685 } 686 687 void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString, 688 const ScAddress & rAddress, SvNumFormatType * pRetTypeExpr, sal_uInt32 * pRetIndexExpr, bool bFinalResult ) 689 { 690 ScRefCellValue aCell(*pDok, rAddress); 691 if (aCell.hasEmptyValue()) 692 { 693 bool bInherited = (aCell.meType == CELLTYPE_FORMULA); 694 if (pRetTypeExpr && pRetIndexExpr) 695 pDok->GetNumberFormatInfo(mrContext, *pRetTypeExpr, *pRetIndexExpr, rAddress); 696 PushTempToken( new ScEmptyCellToken( bInherited, bDisplayEmptyAsString)); 697 return; 698 } 699 700 FormulaError nErr = FormulaError::NONE; 701 if (aCell.meType == CELLTYPE_FORMULA) 702 nErr = aCell.mpFormula->GetErrCode(); 703 704 if (nErr != FormulaError::NONE) 705 { 706 PushError( nErr); 707 if (pRetTypeExpr) 708 *pRetTypeExpr = SvNumFormatType::UNDEFINED; 709 if (pRetIndexExpr) 710 *pRetIndexExpr = 0; 711 } 712 else if (aCell.hasString()) 713 { 714 svl::SharedString aRes; 715 GetCellString( aRes, aCell); 716 PushString( aRes); 717 if (pRetTypeExpr) 718 *pRetTypeExpr = SvNumFormatType::TEXT; 719 if (pRetIndexExpr) 720 *pRetIndexExpr = 0; 721 } 722 else 723 { 724 double fVal = GetCellValue(rAddress, aCell); 725 if (bFinalResult) 726 { 727 TreatDoubleError( fVal); 728 if (!IfErrorPushError()) 729 PushTempTokenWithoutError( CreateFormulaDoubleToken( fVal)); 730 } 731 else 732 { 733 PushDouble( fVal); 734 } 735 if (pRetTypeExpr) 736 *pRetTypeExpr = nCurFmtType; 737 if (pRetIndexExpr) 738 *pRetIndexExpr = nCurFmtIndex; 739 } 740 } 741 742 // Simply throw away TOS. 743 744 void ScInterpreter::Pop() 745 { 746 if( sp ) 747 sp--; 748 else 749 SetError(FormulaError::UnknownStackVariable); 750 } 751 752 // Simply throw away TOS and set error code, used with ocIsError et al. 753 754 void ScInterpreter::PopError() 755 { 756 if( sp ) 757 { 758 sp--; 759 if (pStack[sp]->GetType() == svError) 760 nGlobalError = pStack[sp]->GetError(); 761 } 762 else 763 SetError(FormulaError::UnknownStackVariable); 764 } 765 766 FormulaConstTokenRef ScInterpreter::PopToken() 767 { 768 if (sp) 769 { 770 sp--; 771 const FormulaToken* p = pStack[ sp ]; 772 if (p->GetType() == svError) 773 nGlobalError = p->GetError(); 774 return p; 775 } 776 else 777 SetError(FormulaError::UnknownStackVariable); 778 return nullptr; 779 } 780 781 double ScInterpreter::PopDouble() 782 { 783 nCurFmtType = SvNumFormatType::NUMBER; 784 nCurFmtIndex = 0; 785 if( sp ) 786 { 787 --sp; 788 const FormulaToken* p = pStack[ sp ]; 789 switch (p->GetType()) 790 { 791 case svError: 792 nGlobalError = p->GetError(); 793 break; 794 case svDouble: 795 { 796 SvNumFormatType nType = static_cast<SvNumFormatType>(p->GetDoubleType()); 797 if (nType != SvNumFormatType::ALL && nType != SvNumFormatType::UNDEFINED) 798 nCurFmtType = nType; 799 return p->GetDouble(); 800 } 801 case svEmptyCell: 802 case svMissing: 803 return 0.0; 804 default: 805 SetError( FormulaError::IllegalArgument); 806 } 807 } 808 else 809 SetError( FormulaError::UnknownStackVariable); 810 return 0.0; 811 } 812 813 svl::SharedString ScInterpreter::PopString() 814 { 815 nCurFmtType = SvNumFormatType::TEXT; 816 nCurFmtIndex = 0; 817 if( sp ) 818 { 819 --sp; 820 const FormulaToken* p = pStack[ sp ]; 821 switch (p->GetType()) 822 { 823 case svError: 824 nGlobalError = p->GetError(); 825 break; 826 case svString: 827 return p->GetString(); 828 case svEmptyCell: 829 case svMissing: 830 return svl::SharedString::getEmptyString(); 831 default: 832 SetError( FormulaError::IllegalArgument); 833 } 834 } 835 else 836 SetError( FormulaError::UnknownStackVariable); 837 838 return svl::SharedString::getEmptyString(); 839 } 840 841 void ScInterpreter::ValidateRef( const ScSingleRefData & rRef ) 842 { 843 SCCOL nCol; 844 SCROW nRow; 845 SCTAB nTab; 846 SingleRefToVars( rRef, nCol, nRow, nTab); 847 } 848 849 void ScInterpreter::ValidateRef( const ScComplexRefData & rRef ) 850 { 851 ValidateRef( rRef.Ref1); 852 ValidateRef( rRef.Ref2); 853 } 854 855 void ScInterpreter::ValidateRef( const ScRefList & rRefList ) 856 { 857 ScRefList::const_iterator it( rRefList.begin()); 858 ScRefList::const_iterator end( rRefList.end()); 859 for ( ; it != end; ++it) 860 { 861 ValidateRef( *it); 862 } 863 } 864 865 void ScInterpreter::SingleRefToVars( const ScSingleRefData & rRef, 866 SCCOL & rCol, SCROW & rRow, SCTAB & rTab ) 867 { 868 if ( rRef.IsColRel() ) 869 rCol = aPos.Col() + rRef.Col(); 870 else 871 rCol = rRef.Col(); 872 873 if ( rRef.IsRowRel() ) 874 rRow = aPos.Row() + rRef.Row(); 875 else 876 rRow = rRef.Row(); 877 878 if ( rRef.IsTabRel() ) 879 rTab = aPos.Tab() + rRef.Tab(); 880 else 881 rTab = rRef.Tab(); 882 883 if( !ValidCol( rCol) || rRef.IsColDeleted() ) 884 { 885 SetError( FormulaError::NoRef ); 886 rCol = 0; 887 } 888 if( !ValidRow( rRow) || rRef.IsRowDeleted() ) 889 { 890 SetError( FormulaError::NoRef ); 891 rRow = 0; 892 } 893 if( !ValidTab( rTab, pDok->GetTableCount() - 1) || rRef.IsTabDeleted() ) 894 { 895 SetError( FormulaError::NoRef ); 896 rTab = 0; 897 } 898 } 899 900 void ScInterpreter::PopSingleRef(SCCOL& rCol, SCROW &rRow, SCTAB& rTab) 901 { 902 ScAddress aAddr(rCol, rRow, rTab); 903 PopSingleRef(aAddr); 904 rCol = aAddr.Col(); 905 rRow = aAddr.Row(); 906 rTab = aAddr.Tab(); 907 } 908 909 void ScInterpreter::PopSingleRef( ScAddress& rAdr ) 910 { 911 if( sp ) 912 { 913 --sp; 914 const FormulaToken* p = pStack[ sp ]; 915 switch (p->GetType()) 916 { 917 case svError: 918 nGlobalError = p->GetError(); 919 break; 920 case svSingleRef: 921 { 922 const ScSingleRefData* pRefData = p->GetSingleRef(); 923 if (pRefData->IsDeleted()) 924 { 925 SetError( FormulaError::NoRef); 926 break; 927 } 928 929 SCCOL nCol; 930 SCROW nRow; 931 SCTAB nTab; 932 SingleRefToVars( *pRefData, nCol, nRow, nTab); 933 rAdr.Set( nCol, nRow, nTab ); 934 if (!pDok->m_TableOpList.empty()) 935 ReplaceCell( rAdr ); 936 } 937 break; 938 default: 939 SetError( FormulaError::IllegalParameter); 940 } 941 } 942 else 943 SetError( FormulaError::UnknownStackVariable); 944 } 945 946 void ScInterpreter::DoubleRefToVars( const formula::FormulaToken* p, 947 SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1, 948 SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2 ) 949 { 950 const ScComplexRefData& rCRef = *p->GetDoubleRef(); 951 SingleRefToVars( rCRef.Ref1, rCol1, rRow1, rTab1); 952 SingleRefToVars( rCRef.Ref2, rCol2, rRow2, rTab2); 953 if (rCol2 < rCol1) 954 std::swap( rCol2, rCol1); 955 if (rRow2 < rRow1) 956 std::swap( rRow2, rRow1); 957 if (rTab2 < rTab1) 958 std::swap( rTab2, rTab1); 959 if (!pDok->m_TableOpList.empty()) 960 { 961 ScRange aRange( rCol1, rRow1, rTab1, rCol2, rRow2, rTab2 ); 962 if ( IsTableOpInRange( aRange ) ) 963 SetError( FormulaError::IllegalParameter ); 964 } 965 } 966 967 ScDBRangeBase* ScInterpreter::PopDBDoubleRef() 968 { 969 StackVar eType = GetStackType(); 970 switch (eType) 971 { 972 case svUnknown: 973 SetError(FormulaError::UnknownStackVariable); 974 break; 975 case svError: 976 PopError(); 977 break; 978 case svDoubleRef: 979 { 980 SCCOL nCol1, nCol2; 981 SCROW nRow1, nRow2; 982 SCTAB nTab1, nTab2; 983 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); 984 if (nGlobalError != FormulaError::NONE) 985 break; 986 return new ScDBInternalRange(pDok, 987 ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2)); 988 } 989 case svMatrix: 990 case svExternalDoubleRef: 991 { 992 ScMatrixRef pMat; 993 if (eType == svMatrix) 994 pMat = PopMatrix(); 995 else 996 PopExternalDoubleRef(pMat); 997 if (nGlobalError != FormulaError::NONE) 998 break; 999 return new ScDBExternalRange(pDok, pMat); 1000 } 1001 default: 1002 SetError( FormulaError::IllegalParameter); 1003 } 1004 1005 return nullptr; 1006 } 1007 1008 void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1, 1009 SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2) 1010 { 1011 if( sp ) 1012 { 1013 --sp; 1014 const FormulaToken* p = pStack[ sp ]; 1015 switch (p->GetType()) 1016 { 1017 case svError: 1018 nGlobalError = p->GetError(); 1019 break; 1020 case svDoubleRef: 1021 DoubleRefToVars( p, rCol1, rRow1, rTab1, rCol2, rRow2, rTab2); 1022 break; 1023 default: 1024 SetError( FormulaError::IllegalParameter); 1025 } 1026 } 1027 else 1028 SetError( FormulaError::UnknownStackVariable); 1029 } 1030 1031 void ScInterpreter::DoubleRefToRange( const ScComplexRefData & rCRef, 1032 ScRange & rRange, bool bDontCheckForTableOp ) 1033 { 1034 SCCOL nCol; 1035 SCROW nRow; 1036 SCTAB nTab; 1037 SingleRefToVars( rCRef.Ref1, nCol, nRow, nTab); 1038 rRange.aStart.Set( nCol, nRow, nTab ); 1039 SingleRefToVars( rCRef.Ref2, nCol, nRow, nTab); 1040 rRange.aEnd.Set( nCol, nRow, nTab ); 1041 rRange.PutInOrder(); 1042 if (!pDok->m_TableOpList.empty() && !bDontCheckForTableOp) 1043 { 1044 if ( IsTableOpInRange( rRange ) ) 1045 SetError( FormulaError::IllegalParameter ); 1046 } 1047 } 1048 1049 void ScInterpreter::PopDoubleRef( ScRange & rRange, short & rParam, size_t & rRefInList ) 1050 { 1051 if (sp) 1052 { 1053 const formula::FormulaToken* pToken = pStack[ sp-1 ]; 1054 switch (pToken->GetType()) 1055 { 1056 case svError: 1057 nGlobalError = pToken->GetError(); 1058 break; 1059 case svDoubleRef: 1060 { 1061 --sp; 1062 const ScComplexRefData* pRefData = pToken->GetDoubleRef(); 1063 if (pRefData->IsDeleted()) 1064 { 1065 SetError( FormulaError::NoRef); 1066 break; 1067 } 1068 DoubleRefToRange( *pRefData, rRange); 1069 break; 1070 } 1071 case svRefList: 1072 { 1073 const ScRefList* pList = pToken->GetRefList(); 1074 if (rRefInList < pList->size()) 1075 { 1076 DoubleRefToRange( (*pList)[rRefInList], rRange); 1077 if (++rRefInList < pList->size()) 1078 ++rParam; 1079 else 1080 { 1081 --sp; 1082 rRefInList = 0; 1083 } 1084 } 1085 else 1086 { 1087 --sp; 1088 rRefInList = 0; 1089 SetError( FormulaError::IllegalParameter); 1090 } 1091 } 1092 break; 1093 default: 1094 SetError( FormulaError::IllegalParameter); 1095 } 1096 } 1097 else 1098 SetError( FormulaError::UnknownStackVariable); 1099 } 1100 1101 void ScInterpreter::PopDoubleRef( ScRange& rRange, bool bDontCheckForTableOp ) 1102 { 1103 if( sp ) 1104 { 1105 --sp; 1106 const FormulaToken* p = pStack[ sp ]; 1107 switch (p->GetType()) 1108 { 1109 case svError: 1110 nGlobalError = p->GetError(); 1111 break; 1112 case svDoubleRef: 1113 DoubleRefToRange( *p->GetDoubleRef(), rRange, bDontCheckForTableOp); 1114 break; 1115 default: 1116 SetError( FormulaError::IllegalParameter); 1117 } 1118 } 1119 else 1120 SetError( FormulaError::UnknownStackVariable); 1121 } 1122 1123 void ScInterpreter::PopExternalSingleRef(sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef) 1124 { 1125 if (!sp) 1126 { 1127 SetError(FormulaError::UnknownStackVariable); 1128 return; 1129 } 1130 1131 --sp; 1132 const FormulaToken* p = pStack[sp]; 1133 StackVar eType = p->GetType(); 1134 1135 if (eType == svError) 1136 { 1137 nGlobalError = p->GetError(); 1138 return; 1139 } 1140 1141 if (eType != svExternalSingleRef) 1142 { 1143 SetError( FormulaError::IllegalParameter); 1144 return; 1145 } 1146 1147 rFileId = p->GetIndex(); 1148 rTabName = p->GetString().getString(); 1149 rRef = *p->GetSingleRef(); 1150 } 1151 1152 void ScInterpreter::PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt) 1153 { 1154 sal_uInt16 nFileId; 1155 OUString aTabName; 1156 ScSingleRefData aData; 1157 PopExternalSingleRef(nFileId, aTabName, aData, rToken, pFmt); 1158 } 1159 1160 void ScInterpreter::PopExternalSingleRef( 1161 sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef, 1162 ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt) 1163 { 1164 PopExternalSingleRef(rFileId, rTabName, rRef); 1165 if (nGlobalError != FormulaError::NONE) 1166 return; 1167 1168 ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager(); 1169 const OUString* pFile = pRefMgr->getExternalFileName(rFileId); 1170 if (!pFile) 1171 { 1172 SetError(FormulaError::NoName); 1173 return; 1174 } 1175 1176 if (rRef.IsTabRel()) 1177 { 1178 OSL_FAIL("ScCompiler::GetToken: external single reference must have an absolute table reference!"); 1179 SetError(FormulaError::NoRef); 1180 return; 1181 } 1182 1183 ScAddress aAddr = rRef.toAbs(aPos); 1184 ScExternalRefCache::CellFormat aFmt; 1185 ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken( 1186 rFileId, rTabName, aAddr, &aPos, nullptr, &aFmt); 1187 1188 if (!xNew) 1189 { 1190 SetError(FormulaError::NoRef); 1191 return; 1192 } 1193 1194 if (xNew->GetType() == svError) 1195 SetError( xNew->GetError()); 1196 1197 rToken = xNew; 1198 if (pFmt) 1199 *pFmt = aFmt; 1200 } 1201 1202 void ScInterpreter::PopExternalDoubleRef(sal_uInt16& rFileId, OUString& rTabName, ScComplexRefData& rRef) 1203 { 1204 if (!sp) 1205 { 1206 SetError(FormulaError::UnknownStackVariable); 1207 return; 1208 } 1209 1210 --sp; 1211 const FormulaToken* p = pStack[sp]; 1212 StackVar eType = p->GetType(); 1213 1214 if (eType == svError) 1215 { 1216 nGlobalError = p->GetError(); 1217 return; 1218 } 1219 1220 if (eType != svExternalDoubleRef) 1221 { 1222 SetError( FormulaError::IllegalParameter); 1223 return; 1224 } 1225 1226 rFileId = p->GetIndex(); 1227 rTabName = p->GetString().getString(); 1228 rRef = *p->GetDoubleRef(); 1229 } 1230 1231 void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray) 1232 { 1233 sal_uInt16 nFileId; 1234 OUString aTabName; 1235 ScComplexRefData aData; 1236 PopExternalDoubleRef(nFileId, aTabName, aData); 1237 if (nGlobalError != FormulaError::NONE) 1238 return; 1239 1240 GetExternalDoubleRef(nFileId, aTabName, aData, rArray); 1241 if (nGlobalError != FormulaError::NONE) 1242 return; 1243 } 1244 1245 void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat) 1246 { 1247 ScExternalRefCache::TokenArrayRef pArray; 1248 PopExternalDoubleRef(pArray); 1249 if (nGlobalError != FormulaError::NONE) 1250 return; 1251 1252 // For now, we only support single range data for external 1253 // references, which means the array should only contain a 1254 // single matrix token. 1255 formula::FormulaToken* p = pArray->FirstToken(); 1256 if (!p || p->GetType() != svMatrix) 1257 SetError( FormulaError::IllegalParameter); 1258 else 1259 { 1260 rMat = p->GetMatrix(); 1261 if (!rMat) 1262 SetError( FormulaError::UnknownVariable); 1263 } 1264 } 1265 1266 void ScInterpreter::GetExternalDoubleRef( 1267 sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rData, ScExternalRefCache::TokenArrayRef& rArray) 1268 { 1269 ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager(); 1270 const OUString* pFile = pRefMgr->getExternalFileName(nFileId); 1271 if (!pFile) 1272 { 1273 SetError(FormulaError::NoName); 1274 return; 1275 } 1276 if (rData.Ref1.IsTabRel() || rData.Ref2.IsTabRel()) 1277 { 1278 OSL_FAIL("ScCompiler::GetToken: external double reference must have an absolute table reference!"); 1279 SetError(FormulaError::NoRef); 1280 return; 1281 } 1282 1283 ScComplexRefData aData(rData); 1284 ScRange aRange = aData.toAbs(aPos); 1285 if (!ValidColRow(aRange.aStart.Col(), aRange.aStart.Row()) || !ValidColRow(aRange.aEnd.Col(), aRange.aEnd.Row())) 1286 { 1287 SetError(FormulaError::NoRef); 1288 return; 1289 } 1290 1291 ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens( 1292 nFileId, rTabName, aRange, &aPos); 1293 1294 if (!pArray) 1295 { 1296 SetError(FormulaError::IllegalArgument); 1297 return; 1298 } 1299 1300 formula::FormulaTokenArrayPlainIterator aIter(*pArray); 1301 formula::FormulaToken* pToken = aIter.First(); 1302 assert(pToken); 1303 if (pToken->GetType() == svError) 1304 { 1305 SetError( pToken->GetError()); 1306 return; 1307 } 1308 if (pToken->GetType() != svMatrix) 1309 { 1310 SetError(FormulaError::IllegalArgument); 1311 return; 1312 } 1313 1314 if (aIter.Next()) 1315 { 1316 // Can't handle more than one matrix per parameter. 1317 SetError( FormulaError::IllegalArgument); 1318 return; 1319 } 1320 1321 rArray = pArray; 1322 } 1323 1324 bool ScInterpreter::PopDoubleRefOrSingleRef( ScAddress& rAdr ) 1325 { 1326 switch ( GetStackType() ) 1327 { 1328 case svDoubleRef : 1329 { 1330 ScRange aRange; 1331 PopDoubleRef( aRange, true ); 1332 return DoubleRefToPosSingleRef( aRange, rAdr ); 1333 } 1334 case svSingleRef : 1335 { 1336 PopSingleRef( rAdr ); 1337 return true; 1338 } 1339 default: 1340 PopError(); 1341 SetError( FormulaError::NoRef ); 1342 } 1343 return false; 1344 } 1345 1346 void ScInterpreter::PopDoubleRefPushMatrix() 1347 { 1348 if ( GetStackType() == svDoubleRef ) 1349 { 1350 ScMatrixRef pMat = GetMatrix(); 1351 if ( pMat ) 1352 PushMatrix( pMat ); 1353 else 1354 PushIllegalParameter(); 1355 } 1356 else 1357 SetError( FormulaError::NoRef ); 1358 } 1359 1360 void ScInterpreter::PopRefListPushMatrixOrRef() 1361 { 1362 if ( GetStackType() == svRefList ) 1363 { 1364 FormulaConstTokenRef xTok = pStack[sp-1]; 1365 const std::vector<ScComplexRefData>* pv = xTok->GetRefList(); 1366 if (pv) 1367 { 1368 const size_t nEntries = pv->size(); 1369 if (nEntries == 1) 1370 { 1371 --sp; 1372 PushTempTokenWithoutError( new ScDoubleRefToken( (*pv)[0] )); 1373 } 1374 else if (bMatrixFormula) 1375 { 1376 // Only single cells can be stuffed into a column vector. 1377 // XXX NOTE: Excel doesn't do this but returns #VALUE! instead. 1378 // Though there's no compelling reason not to.. 1379 for (const auto & rRef : *pv) 1380 { 1381 if (rRef.Ref1 != rRef.Ref2) 1382 return; 1383 } 1384 ScMatrixRef xMat = GetNewMat( 1, nEntries, true); // init empty 1385 if (!xMat) 1386 return; 1387 for (size_t i=0; i < nEntries; ++i) 1388 { 1389 SCCOL nCol; SCROW nRow; SCTAB nTab; 1390 SingleRefToVars( (*pv)[i].Ref1, nCol, nRow, nTab); 1391 if (nGlobalError == FormulaError::NONE) 1392 { 1393 ScAddress aAdr( nCol, nRow, nTab); 1394 ScRefCellValue aCell( *pDok, aAdr); 1395 if (aCell.hasError()) 1396 xMat->PutError( aCell.mpFormula->GetErrCode(), 0, i); 1397 else if (aCell.hasEmptyValue()) 1398 xMat->PutEmpty( 0, i); 1399 else if (aCell.hasString()) 1400 xMat->PutString( mrStrPool.intern( aCell.getString( pDok)), 0, i); 1401 else 1402 xMat->PutDouble( aCell.getValue(), 0, i); 1403 } 1404 else 1405 { 1406 xMat->PutError( nGlobalError, 0, i); 1407 nGlobalError = FormulaError::NONE; 1408 } 1409 } 1410 --sp; 1411 PushMatrix( xMat); 1412 } 1413 } 1414 // else: keep token on stack, something will handle the error 1415 } 1416 else 1417 SetError( FormulaError::NoRef ); 1418 } 1419 1420 void ScInterpreter::ConvertMatrixJumpConditionToMatrix() 1421 { 1422 StackVar eStackType = GetStackType(); 1423 if (eStackType == svUnknown) 1424 return; // can't do anything, some caller will catch that 1425 if (eStackType == svMatrix) 1426 return; // already matrix, nothing to do 1427 1428 if (eStackType != svDoubleRef && GetStackType(2) != svJumpMatrix) 1429 return; // always convert svDoubleRef, others only in JumpMatrix context 1430 1431 GetTokenMatrixMap(); // make sure it exists, create if not. 1432 ScMatrixRef pMat = GetMatrix(); 1433 if ( pMat ) 1434 PushMatrix( pMat ); 1435 else 1436 PushIllegalParameter(); 1437 } 1438 1439 ScTokenMatrixMap* ScInterpreter::CreateTokenMatrixMap() 1440 { 1441 return new ScTokenMatrixMap; 1442 } 1443 1444 bool ScInterpreter::ConvertMatrixParameters() 1445 { 1446 sal_uInt16 nParams = pCur->GetParamCount(); 1447 OSL_ENSURE( nParams <= sp, "ConvertMatrixParameters: stack/param count mismatch"); 1448 SCSIZE nJumpCols = 0, nJumpRows = 0; 1449 for ( sal_uInt16 i=1; i <= nParams && i <= sp; ++i ) 1450 { 1451 const FormulaToken* p = pStack[ sp - i ]; 1452 if ( p->GetOpCode() != ocPush && p->GetOpCode() != ocMissing) 1453 { 1454 OSL_FAIL( "ConvertMatrixParameters: not a push"); 1455 } 1456 else 1457 { 1458 switch ( p->GetType() ) 1459 { 1460 case svDouble: 1461 case svString: 1462 case svSingleRef: 1463 case svExternalSingleRef: 1464 case svMissing: 1465 case svError: 1466 case svEmptyCell: 1467 // nothing to do 1468 break; 1469 case svMatrix: 1470 { 1471 if ( ScParameterClassification::GetParameterType( pCur, nParams - i) 1472 == formula::ParamClass::Value ) 1473 { // only if single value expected 1474 ScConstMatrixRef pMat = p->GetMatrix(); 1475 if ( !pMat ) 1476 SetError( FormulaError::UnknownVariable); 1477 else 1478 { 1479 SCSIZE nCols, nRows; 1480 pMat->GetDimensions( nCols, nRows); 1481 if ( nJumpCols < nCols ) 1482 nJumpCols = nCols; 1483 if ( nJumpRows < nRows ) 1484 nJumpRows = nRows; 1485 } 1486 } 1487 } 1488 break; 1489 case svDoubleRef: 1490 { 1491 formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i); 1492 if ( eType != formula::ParamClass::Reference && 1493 eType != formula::ParamClass::ReferenceOrRefArray && 1494 eType != formula::ParamClass::ReferenceOrForceArray && 1495 // For scalar Value: convert to Array/JumpMatrix 1496 // only if in array formula context, else (function 1497 // has ForceArray or ReferenceOrForceArray 1498 // parameter *somewhere else*) pick a normal 1499 // position dependent implicit intersection later. 1500 (eType != formula::ParamClass::Value || IsInArrayContext())) 1501 { 1502 SCCOL nCol1, nCol2; 1503 SCROW nRow1, nRow2; 1504 SCTAB nTab1, nTab2; 1505 DoubleRefToVars( p, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); 1506 // Make sure the map exists, created if not. 1507 GetTokenMatrixMap(); 1508 ScMatrixRef pMat = CreateMatrixFromDoubleRef( p, 1509 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); 1510 if (pMat) 1511 { 1512 if ( eType == formula::ParamClass::Value ) 1513 { // only if single value expected 1514 if ( nJumpCols < static_cast<SCSIZE>(nCol2 - nCol1 + 1) ) 1515 nJumpCols = static_cast<SCSIZE>(nCol2 - nCol1 + 1); 1516 if ( nJumpRows < static_cast<SCSIZE>(nRow2 - nRow1 + 1) ) 1517 nJumpRows = static_cast<SCSIZE>(nRow2 - nRow1 + 1); 1518 } 1519 formula::FormulaToken* pNew = new ScMatrixToken( pMat); 1520 pNew->IncRef(); 1521 pStack[ sp - i ] = pNew; 1522 p->DecRef(); // p may be dead now! 1523 } 1524 } 1525 } 1526 break; 1527 case svExternalDoubleRef: 1528 { 1529 formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i); 1530 if (eType == formula::ParamClass::Array) 1531 { 1532 sal_uInt16 nFileId = p->GetIndex(); 1533 OUString aTabName = p->GetString().getString(); 1534 const ScComplexRefData& rRef = *p->GetDoubleRef(); 1535 ScExternalRefCache::TokenArrayRef pArray; 1536 GetExternalDoubleRef(nFileId, aTabName, rRef, pArray); 1537 if (nGlobalError != FormulaError::NONE || !pArray) 1538 break; 1539 formula::FormulaToken* pTemp = pArray->FirstToken(); 1540 if (!pTemp) 1541 break; 1542 1543 ScMatrixRef pMat = pTemp->GetMatrix(); 1544 if (pMat) 1545 { 1546 formula::FormulaToken* pNew = new ScMatrixToken( pMat); 1547 pNew->IncRef(); 1548 pStack[ sp - i ] = pNew; 1549 p->DecRef(); // p may be dead now! 1550 } 1551 } 1552 } 1553 break; 1554 case svRefList: 1555 { 1556 formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i); 1557 if ( eType != formula::ParamClass::Reference && 1558 eType != formula::ParamClass::ReferenceOrRefArray && 1559 eType != formula::ParamClass::ReferenceOrForceArray && 1560 eType != formula::ParamClass::ForceArray) 1561 { 1562 // can't convert to matrix 1563 SetError( FormulaError::NoValue); 1564 } 1565 // else: the consuming function has to decide if and how to 1566 // handle a reference list argument in array context. 1567 } 1568 break; 1569 default: 1570 OSL_FAIL( "ConvertMatrixParameters: unknown parameter type"); 1571 } 1572 } 1573 } 1574 if( nJumpCols && nJumpRows ) 1575 { 1576 short nPC = aCode.GetPC(); 1577 short nStart = nPC - 1; // restart on current code (-1) 1578 short nNext = nPC; // next instruction after subroutine 1579 short nStop = nPC + 1; // stop subroutine before reaching that 1580 FormulaConstTokenRef xNew; 1581 ScTokenMatrixMap::const_iterator aMapIter; 1582 if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find( pCur)) != pTokenMatrixMap->end())) 1583 xNew = (*aMapIter).second; 1584 else 1585 { 1586 std::unique_ptr<ScJumpMatrix> pJumpMat( new ScJumpMatrix( pCur->GetOpCode(), nJumpCols, nJumpRows)); 1587 pJumpMat->SetAllJumps( 1.0, nStart, nNext, nStop); 1588 // pop parameters and store in ScJumpMatrix, push in JumpMatrix() 1589 ScTokenVec aParams(nParams); 1590 for ( sal_uInt16 i=1; i <= nParams && sp > 0; ++i ) 1591 { 1592 const FormulaToken* p = pStack[ --sp ]; 1593 p->IncRef(); 1594 // store in reverse order such that a push may simply iterate 1595 aParams[ nParams - i ] = p; 1596 } 1597 pJumpMat->SetJumpParameters( std::move(aParams) ); 1598 xNew = new ScJumpMatrixToken( std::move(pJumpMat) ); 1599 GetTokenMatrixMap().emplace(pCur, xNew); 1600 } 1601 PushTempTokenWithoutError( xNew.get()); 1602 // set continuation point of path for main code line 1603 aCode.Jump( nNext, nNext); 1604 return true; 1605 } 1606 return false; 1607 } 1608 1609 ScMatrixRef ScInterpreter::PopMatrix() 1610 { 1611 if( sp ) 1612 { 1613 --sp; 1614 const FormulaToken* p = pStack[ sp ]; 1615 switch (p->GetType()) 1616 { 1617 case svError: 1618 nGlobalError = p->GetError(); 1619 break; 1620 case svMatrix: 1621 { 1622 // ScMatrix itself maintains an im/mutable flag that should 1623 // be obeyed where necessary.. so we can return ScMatrixRef 1624 // here instead of ScConstMatrixRef. 1625 ScMatrix* pMat = const_cast<FormulaToken*>(p)->GetMatrix(); 1626 if ( pMat ) 1627 pMat->SetErrorInterpreter( this); 1628 else 1629 SetError( FormulaError::UnknownVariable); 1630 return pMat; 1631 } 1632 default: 1633 SetError( FormulaError::IllegalParameter); 1634 } 1635 } 1636 else 1637 SetError( FormulaError::UnknownStackVariable); 1638 return nullptr; 1639 } 1640 1641 sc::RangeMatrix ScInterpreter::PopRangeMatrix() 1642 { 1643 sc::RangeMatrix aRet; 1644 if (sp) 1645 { 1646 switch (pStack[sp-1]->GetType()) 1647 { 1648 case svMatrix: 1649 { 1650 --sp; 1651 const FormulaToken* p = pStack[sp]; 1652 aRet.mpMat = const_cast<FormulaToken*>(p)->GetMatrix(); 1653 if (aRet.mpMat) 1654 { 1655 aRet.mpMat->SetErrorInterpreter(this); 1656 if (p->GetByte() == MATRIX_TOKEN_HAS_RANGE) 1657 { 1658 const ScComplexRefData& rRef = *p->GetDoubleRef(); 1659 if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() && !rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel()) 1660 { 1661 aRet.mnCol1 = rRef.Ref1.Col(); 1662 aRet.mnRow1 = rRef.Ref1.Row(); 1663 aRet.mnTab1 = rRef.Ref1.Tab(); 1664 aRet.mnCol2 = rRef.Ref2.Col(); 1665 aRet.mnRow2 = rRef.Ref2.Row(); 1666 aRet.mnTab2 = rRef.Ref2.Tab(); 1667 } 1668 } 1669 } 1670 else 1671 SetError( FormulaError::UnknownVariable); 1672 } 1673 break; 1674 default: 1675 aRet.mpMat = PopMatrix(); 1676 } 1677 } 1678 return aRet; 1679 } 1680 1681 void ScInterpreter::QueryMatrixType(const ScMatrixRef& xMat, SvNumFormatType& rRetTypeExpr, sal_uInt32& rRetIndexExpr) 1682 { 1683 if (xMat) 1684 { 1685 SCSIZE nCols, nRows; 1686 xMat->GetDimensions(nCols, nRows); 1687 ScMatrixValue nMatVal = xMat->Get(0, 0); 1688 ScMatValType nMatValType = nMatVal.nType; 1689 if (ScMatrix::IsNonValueType( nMatValType)) 1690 { 1691 if ( xMat->IsEmptyPath( 0, 0)) 1692 { // result of empty FALSE jump path 1693 FormulaTokenRef xRes = CreateFormulaDoubleToken( 0.0); 1694 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get())); 1695 rRetTypeExpr = SvNumFormatType::LOGICAL; 1696 } 1697 else if ( xMat->IsEmptyResult( 0, 0)) 1698 { // empty formula result 1699 FormulaTokenRef xRes = new ScEmptyCellToken( true, true); // inherited, display empty 1700 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get())); 1701 } 1702 else if ( xMat->IsEmpty( 0, 0)) 1703 { // empty or empty cell 1704 FormulaTokenRef xRes = new ScEmptyCellToken( false, true); // not inherited, display empty 1705 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get())); 1706 } 1707 else 1708 { 1709 FormulaTokenRef xRes = new FormulaStringToken( nMatVal.GetString() ); 1710 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get())); 1711 rRetTypeExpr = SvNumFormatType::TEXT; 1712 } 1713 } 1714 else 1715 { 1716 FormulaError nErr = GetDoubleErrorValue( nMatVal.fVal); 1717 FormulaTokenRef xRes; 1718 if (nErr != FormulaError::NONE) 1719 xRes = new FormulaErrorToken( nErr); 1720 else 1721 xRes = CreateFormulaDoubleToken( nMatVal.fVal); 1722 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get())); 1723 if ( rRetTypeExpr != SvNumFormatType::LOGICAL ) 1724 rRetTypeExpr = SvNumFormatType::NUMBER; 1725 } 1726 rRetIndexExpr = 0; 1727 xMat->SetErrorInterpreter( nullptr); 1728 } 1729 else 1730 SetError( FormulaError::UnknownStackVariable); 1731 } 1732 1733 formula::FormulaToken* ScInterpreter::CreateFormulaDoubleToken( double fVal, SvNumFormatType nFmt ) 1734 { 1735 assert( mrContext.maTokens.size() == TOKEN_CACHE_SIZE ); 1736 1737 // Find a spare token 1738 for ( auto p : mrContext.maTokens ) 1739 { 1740 if (p && p->GetRef() == 1) 1741 { 1742 p->GetDoubleAsReference() = fVal; 1743 p->SetDoubleType( static_cast<sal_Int16>(nFmt) ); 1744 return p; 1745 } 1746 } 1747 1748 // Allocate a new token 1749 auto p = new FormulaTypedDoubleToken( fVal, static_cast<sal_Int16>(nFmt) ); 1750 if ( mrContext.maTokens[mrContext.mnTokenCachePos] ) 1751 mrContext.maTokens[mrContext.mnTokenCachePos]->DecRef(); 1752 mrContext.maTokens[mrContext.mnTokenCachePos] = p; 1753 p->IncRef(); 1754 mrContext.mnTokenCachePos = (mrContext.mnTokenCachePos + 1) % TOKEN_CACHE_SIZE; 1755 return p; 1756 } 1757 1758 formula::FormulaToken* ScInterpreter::CreateDoubleOrTypedToken( double fVal ) 1759 { 1760 // NumberFormat::NUMBER is the default untyped double. 1761 if (nFuncFmtType != SvNumFormatType::ALL && nFuncFmtType != SvNumFormatType::NUMBER && 1762 nFuncFmtType != SvNumFormatType::UNDEFINED) 1763 return CreateFormulaDoubleToken( fVal, nFuncFmtType); 1764 else 1765 return CreateFormulaDoubleToken( fVal); 1766 } 1767 1768 void ScInterpreter::PushDouble(double nVal) 1769 { 1770 TreatDoubleError( nVal ); 1771 if (!IfErrorPushError()) 1772 PushTempTokenWithoutError( CreateDoubleOrTypedToken( nVal)); 1773 } 1774 1775 void ScInterpreter::PushInt(int nVal) 1776 { 1777 if (!IfErrorPushError()) 1778 PushTempTokenWithoutError( CreateDoubleOrTypedToken( nVal)); 1779 } 1780 1781 void ScInterpreter::PushStringBuffer( const sal_Unicode* pString ) 1782 { 1783 if ( pString ) 1784 { 1785 svl::SharedString aSS = pDok->GetSharedStringPool().intern(OUString(pString)); 1786 PushString(aSS); 1787 } 1788 else 1789 PushString(svl::SharedString::getEmptyString()); 1790 } 1791 1792 void ScInterpreter::PushString( const OUString& rStr ) 1793 { 1794 PushString(pDok->GetSharedStringPool().intern(rStr)); 1795 } 1796 1797 void ScInterpreter::PushString( const svl::SharedString& rString ) 1798 { 1799 if (!IfErrorPushError()) 1800 PushTempTokenWithoutError( new FormulaStringToken( rString ) ); 1801 } 1802 1803 void ScInterpreter::PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab) 1804 { 1805 if (!IfErrorPushError()) 1806 { 1807 ScSingleRefData aRef; 1808 aRef.InitAddress(ScAddress(nCol,nRow,nTab)); 1809 PushTempTokenWithoutError( new ScSingleRefToken( aRef ) ); 1810 } 1811 } 1812 1813 void ScInterpreter::PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, 1814 SCCOL nCol2, SCROW nRow2, SCTAB nTab2) 1815 { 1816 if (!IfErrorPushError()) 1817 { 1818 ScComplexRefData aRef; 1819 aRef.InitRange(ScRange(nCol1,nRow1,nTab1,nCol2,nRow2,nTab2)); 1820 PushTempTokenWithoutError( new ScDoubleRefToken( aRef ) ); 1821 } 1822 } 1823 1824 void ScInterpreter::PushExternalSingleRef( 1825 sal_uInt16 nFileId, const OUString& rTabName, SCCOL nCol, SCROW nRow, SCTAB nTab) 1826 { 1827 if (!IfErrorPushError()) 1828 { 1829 ScSingleRefData aRef; 1830 aRef.InitAddress(ScAddress(nCol,nRow,nTab)); 1831 PushTempTokenWithoutError( new ScExternalSingleRefToken(nFileId, 1832 pDok->GetSharedStringPool().intern( rTabName), aRef)) ; 1833 } 1834 } 1835 1836 void ScInterpreter::PushExternalDoubleRef( 1837 sal_uInt16 nFileId, const OUString& rTabName, 1838 SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2) 1839 { 1840 if (!IfErrorPushError()) 1841 { 1842 ScComplexRefData aRef; 1843 aRef.InitRange(ScRange(nCol1,nRow1,nTab1,nCol2,nRow2,nTab2)); 1844 PushTempTokenWithoutError( new ScExternalDoubleRefToken(nFileId, 1845 pDok->GetSharedStringPool().intern( rTabName), aRef) ); 1846 } 1847 } 1848 1849 void ScInterpreter::PushSingleRef( const ScRefAddress& rRef ) 1850 { 1851 if (!IfErrorPushError()) 1852 { 1853 ScSingleRefData aRef; 1854 aRef.InitFromRefAddress( rRef, aPos); 1855 PushTempTokenWithoutError( new ScSingleRefToken( aRef ) ); 1856 } 1857 } 1858 1859 void ScInterpreter::PushDoubleRef( const ScRefAddress& rRef1, const ScRefAddress& rRef2 ) 1860 { 1861 if (!IfErrorPushError()) 1862 { 1863 ScComplexRefData aRef; 1864 aRef.InitFromRefAddresses( rRef1, rRef2, aPos); 1865 PushTempTokenWithoutError( new ScDoubleRefToken( aRef ) ); 1866 } 1867 } 1868 1869 void ScInterpreter::PushMatrix( const sc::RangeMatrix& rMat ) 1870 { 1871 if (!rMat.isRangeValid()) 1872 { 1873 // Just push the matrix part only. 1874 PushMatrix(rMat.mpMat); 1875 return; 1876 } 1877 1878 rMat.mpMat->SetErrorInterpreter(nullptr); 1879 nGlobalError = FormulaError::NONE; 1880 PushTempTokenWithoutError(new ScMatrixRangeToken(rMat)); 1881 } 1882 1883 void ScInterpreter::PushMatrix(const ScMatrixRef& pMat) 1884 { 1885 pMat->SetErrorInterpreter( nullptr); 1886 // No if (!IfErrorPushError()) because ScMatrix stores errors itself, 1887 // but with notifying ScInterpreter via nGlobalError, substituting it would 1888 // mean to inherit the error on all array elements in all following 1889 // operations. 1890 nGlobalError = FormulaError::NONE; 1891 PushTempTokenWithoutError( new ScMatrixToken( pMat ) ); 1892 } 1893 1894 void ScInterpreter::PushError( FormulaError nError ) 1895 { 1896 SetError( nError ); // only sets error if not already set 1897 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError)); 1898 } 1899 1900 void ScInterpreter::PushParameterExpected() 1901 { 1902 PushError( FormulaError::ParameterExpected); 1903 } 1904 1905 void ScInterpreter::PushIllegalParameter() 1906 { 1907 PushError( FormulaError::IllegalParameter); 1908 } 1909 1910 void ScInterpreter::PushIllegalArgument() 1911 { 1912 PushError( FormulaError::IllegalArgument); 1913 } 1914 1915 void ScInterpreter::PushNA() 1916 { 1917 PushError( FormulaError::NotAvailable); 1918 } 1919 1920 void ScInterpreter::PushNoValue() 1921 { 1922 PushError( FormulaError::NoValue); 1923 } 1924 1925 bool ScInterpreter::IsMissing() 1926 { 1927 return sp && pStack[sp - 1]->GetType() == svMissing; 1928 } 1929 1930 StackVar ScInterpreter::GetRawStackType() 1931 { 1932 StackVar eRes; 1933 if( sp ) 1934 { 1935 eRes = pStack[sp - 1]->GetType(); 1936 } 1937 else 1938 { 1939 SetError(FormulaError::UnknownStackVariable); 1940 eRes = svUnknown; 1941 } 1942 return eRes; 1943 } 1944 1945 StackVar ScInterpreter::GetStackType() 1946 { 1947 StackVar eRes; 1948 if( sp ) 1949 { 1950 eRes = pStack[sp - 1]->GetType(); 1951 if( eRes == svMissing || eRes == svEmptyCell ) 1952 eRes = svDouble; // default! 1953 } 1954 else 1955 { 1956 SetError(FormulaError::UnknownStackVariable); 1957 eRes = svUnknown; 1958 } 1959 return eRes; 1960 } 1961 1962 StackVar ScInterpreter::GetStackType( sal_uInt8 nParam ) 1963 { 1964 StackVar eRes; 1965 if( sp > nParam-1 ) 1966 { 1967 eRes = pStack[sp - nParam]->GetType(); 1968 if( eRes == svMissing || eRes == svEmptyCell ) 1969 eRes = svDouble; // default! 1970 } 1971 else 1972 eRes = svUnknown; 1973 return eRes; 1974 } 1975 1976 void ScInterpreter::ReverseStack( sal_uInt8 nParamCount ) 1977 { 1978 //reverse order of parameter stack 1979 assert( sp >= nParamCount && " less stack elements than parameters"); 1980 sal_uInt16 nStackParams = std::min<sal_uInt16>( sp, nParamCount); 1981 std::reverse( pStack+(sp-nStackParams), pStack+sp ); 1982 } 1983 1984 bool ScInterpreter::DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& rAdr ) 1985 { 1986 // Check for a singleton first - no implicit intersection for them. 1987 if( rRange.aStart == rRange.aEnd ) 1988 { 1989 rAdr = rRange.aStart; 1990 return true; 1991 } 1992 1993 bool bOk = false; 1994 1995 if ( pJumpMatrix ) 1996 { 1997 bOk = rRange.aStart.Tab() == rRange.aEnd.Tab(); 1998 if ( !bOk ) 1999 SetError( FormulaError::IllegalArgument); 2000 else 2001 { 2002 SCSIZE nC, nR; 2003 pJumpMatrix->GetPos( nC, nR); 2004 rAdr.SetCol( sal::static_int_cast<SCCOL>( rRange.aStart.Col() + nC ) ); 2005 rAdr.SetRow( sal::static_int_cast<SCROW>( rRange.aStart.Row() + nR ) ); 2006 rAdr.SetTab( rRange.aStart.Tab()); 2007 bOk = rRange.aStart.Col() <= rAdr.Col() && rAdr.Col() <= 2008 rRange.aEnd.Col() && rRange.aStart.Row() <= rAdr.Row() && 2009 rAdr.Row() <= rRange.aEnd.Row(); 2010 if ( !bOk ) 2011 SetError( FormulaError::NoValue); 2012 } 2013 return bOk; 2014 } 2015 2016 bOk = ScCompiler::DoubleRefToPosSingleRefScalarCase(rRange, rAdr, aPos); 2017 2018 if ( !bOk ) 2019 SetError( FormulaError::NoValue ); 2020 return bOk; 2021 } 2022 2023 double ScInterpreter::GetDoubleFromMatrix(const ScMatrixRef& pMat) 2024 { 2025 if (!pMat) 2026 return 0.0; 2027 2028 if ( !pJumpMatrix ) 2029 { 2030 double fVal = pMat->GetDoubleWithStringConversion( 0, 0); 2031 FormulaError nErr = GetDoubleErrorValue( fVal); 2032 if (nErr != FormulaError::NONE) 2033 { 2034 // Do not propagate the coded double error, but set nGlobalError in 2035 // case the matrix did not have an error interpreter set. 2036 SetError( nErr); 2037 fVal = 0.0; 2038 } 2039 return fVal; 2040 } 2041 2042 SCSIZE nCols, nRows, nC, nR; 2043 pMat->GetDimensions( nCols, nRows); 2044 pJumpMatrix->GetPos( nC, nR); 2045 // Use vector replication for single row/column arrays. 2046 if ( (nC < nCols || nCols == 1) && (nR < nRows || nRows == 1) ) 2047 { 2048 double fVal = pMat->GetDoubleWithStringConversion( nC, nR); 2049 FormulaError nErr = GetDoubleErrorValue( fVal); 2050 if (nErr != FormulaError::NONE) 2051 { 2052 // Do not propagate the coded double error, but set nGlobalError in 2053 // case the matrix did not have an error interpreter set. 2054 SetError( nErr); 2055 fVal = 0.0; 2056 } 2057 return fVal; 2058 } 2059 2060 SetError( FormulaError::NoValue); 2061 return 0.0; 2062 } 2063 2064 double ScInterpreter::GetDouble() 2065 { 2066 double nVal(0.0); 2067 switch( GetRawStackType() ) 2068 { 2069 case svDouble: 2070 nVal = PopDouble(); 2071 break; 2072 case svString: 2073 nVal = ConvertStringToValue( PopString().getString()); 2074 break; 2075 case svSingleRef: 2076 { 2077 ScAddress aAdr; 2078 PopSingleRef( aAdr ); 2079 ScRefCellValue aCell(*pDok, aAdr); 2080 nVal = GetCellValue(aAdr, aCell); 2081 } 2082 break; 2083 case svDoubleRef: 2084 { // generate position dependent SingleRef 2085 ScRange aRange; 2086 PopDoubleRef( aRange ); 2087 ScAddress aAdr; 2088 if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr ) ) 2089 { 2090 ScRefCellValue aCell(*pDok, aAdr); 2091 nVal = GetCellValue(aAdr, aCell); 2092 } 2093 else 2094 nVal = 0.0; 2095 } 2096 break; 2097 case svExternalSingleRef: 2098 { 2099 ScExternalRefCache::TokenRef pToken; 2100 PopExternalSingleRef(pToken); 2101 if (nGlobalError == FormulaError::NONE) 2102 { 2103 if (pToken->GetType() == svDouble || pToken->GetType() == svEmptyCell) 2104 nVal = pToken->GetDouble(); 2105 else 2106 nVal = ConvertStringToValue( pToken->GetString().getString()); 2107 } 2108 } 2109 break; 2110 case svExternalDoubleRef: 2111 { 2112 ScMatrixRef pMat; 2113 PopExternalDoubleRef(pMat); 2114 if (nGlobalError != FormulaError::NONE) 2115 break; 2116 2117 nVal = GetDoubleFromMatrix(pMat); 2118 } 2119 break; 2120 case svMatrix: 2121 { 2122 ScMatrixRef pMat = PopMatrix(); 2123 nVal = GetDoubleFromMatrix(pMat); 2124 } 2125 break; 2126 case svError: 2127 PopError(); 2128 nVal = 0.0; 2129 break; 2130 case svEmptyCell: 2131 case svMissing: 2132 Pop(); 2133 nVal = 0.0; 2134 break; 2135 default: 2136 PopError(); 2137 SetError( FormulaError::IllegalParameter); 2138 nVal = 0.0; 2139 } 2140 if ( nFuncFmtType == nCurFmtType ) 2141 nFuncFmtIndex = nCurFmtIndex; 2142 return nVal; 2143 } 2144 2145 double ScInterpreter::GetDoubleWithDefault(double nDefault) 2146 { 2147 bool bMissing = IsMissing(); 2148 double nResultVal = GetDouble(); 2149 if ( bMissing ) 2150 nResultVal = nDefault; 2151 return nResultVal; 2152 } 2153 2154 sal_Int32 ScInterpreter::double_to_int32(double fVal) 2155 { 2156 if (!rtl::math::isFinite(fVal)) 2157 { 2158 SetError( GetDoubleErrorValue( fVal)); 2159 return SAL_MAX_INT32; 2160 } 2161 if (fVal > 0.0) 2162 { 2163 fVal = rtl::math::approxFloor( fVal); 2164 if (fVal > SAL_MAX_INT32) 2165 { 2166 SetError( FormulaError::IllegalArgument); 2167 return SAL_MAX_INT32; 2168 } 2169 } 2170 else if (fVal < 0.0) 2171 { 2172 fVal = rtl::math::approxCeil( fVal); 2173 if (fVal < SAL_MIN_INT32) 2174 { 2175 SetError( FormulaError::IllegalArgument); 2176 return SAL_MAX_INT32; 2177 } 2178 } 2179 return static_cast<sal_Int32>(fVal); 2180 } 2181 2182 sal_Int32 ScInterpreter::GetInt32() 2183 { 2184 return double_to_int32(GetDouble()); 2185 } 2186 2187 sal_Int32 ScInterpreter::GetInt32WithDefault( sal_Int32 nDefault ) 2188 { 2189 bool bMissing = IsMissing(); 2190 double fVal = GetDouble(); 2191 if ( bMissing ) 2192 return nDefault; 2193 return double_to_int32(fVal); 2194 } 2195 2196 sal_Int16 ScInterpreter::GetInt16() 2197 { 2198 double fVal = GetDouble(); 2199 if (!rtl::math::isFinite(fVal)) 2200 { 2201 SetError( GetDoubleErrorValue( fVal)); 2202 return SAL_MAX_INT16; 2203 } 2204 if (fVal > 0.0) 2205 { 2206 fVal = rtl::math::approxFloor( fVal); 2207 if (fVal > SAL_MAX_INT16) 2208 { 2209 SetError( FormulaError::IllegalArgument); 2210 return SAL_MAX_INT16; 2211 } 2212 } 2213 else if (fVal < 0.0) 2214 { 2215 fVal = rtl::math::approxCeil( fVal); 2216 if (fVal < SAL_MIN_INT16) 2217 { 2218 SetError( FormulaError::IllegalArgument); 2219 return SAL_MAX_INT16; 2220 } 2221 } 2222 return static_cast<sal_Int16>(fVal); 2223 } 2224 2225 sal_uInt32 ScInterpreter::GetUInt32() 2226 { 2227 double fVal = rtl::math::approxFloor( GetDouble()); 2228 if (!rtl::math::isFinite(fVal)) 2229 { 2230 SetError( GetDoubleErrorValue( fVal)); 2231 return SAL_MAX_UINT32; 2232 } 2233 if (fVal < 0.0 || fVal > SAL_MAX_UINT32) 2234 { 2235 SetError( FormulaError::IllegalArgument); 2236 return SAL_MAX_UINT32; 2237 } 2238 return static_cast<sal_uInt32>(fVal); 2239 } 2240 2241 bool ScInterpreter::GetDoubleOrString( double& rDouble, svl::SharedString& rString ) 2242 { 2243 bool bDouble = true; 2244 switch( GetRawStackType() ) 2245 { 2246 case svDouble: 2247 rDouble = PopDouble(); 2248 break; 2249 case svString: 2250 rString = PopString(); 2251 bDouble = false; 2252 break; 2253 case svDoubleRef : 2254 case svSingleRef : 2255 { 2256 ScAddress aAdr; 2257 if (!PopDoubleRefOrSingleRef( aAdr)) 2258 { 2259 rDouble = 0.0; 2260 return true; // caller needs to check nGlobalError 2261 } 2262 ScRefCellValue aCell( *pDok, aAdr); 2263 if (aCell.hasNumeric()) 2264 { 2265 rDouble = GetCellValue( aAdr, aCell); 2266 } 2267 else 2268 { 2269 GetCellString( rString, aCell); 2270 bDouble = false; 2271 } 2272 } 2273 break; 2274 case svExternalSingleRef: 2275 case svExternalDoubleRef: 2276 case svMatrix: 2277 { 2278 ScMatValType nType = GetDoubleOrStringFromMatrix( rDouble, rString); 2279 bDouble = ScMatrix::IsValueType( nType); 2280 } 2281 break; 2282 case svError: 2283 PopError(); 2284 rDouble = 0.0; 2285 break; 2286 case svEmptyCell: 2287 case svMissing: 2288 Pop(); 2289 rDouble = 0.0; 2290 break; 2291 default: 2292 PopError(); 2293 SetError( FormulaError::IllegalParameter); 2294 rDouble = 0.0; 2295 } 2296 if ( nFuncFmtType == nCurFmtType ) 2297 nFuncFmtIndex = nCurFmtIndex; 2298 return bDouble; 2299 } 2300 2301 svl::SharedString ScInterpreter::GetString() 2302 { 2303 switch (GetRawStackType()) 2304 { 2305 case svError: 2306 PopError(); 2307 return svl::SharedString::getEmptyString(); 2308 case svMissing: 2309 case svEmptyCell: 2310 Pop(); 2311 return svl::SharedString::getEmptyString(); 2312 case svDouble: 2313 { 2314 return GetStringFromDouble( PopDouble() ); 2315 } 2316 case svString: 2317 return PopString(); 2318 case svSingleRef: 2319 { 2320 ScAddress aAdr; 2321 PopSingleRef( aAdr ); 2322 if (nGlobalError == FormulaError::NONE) 2323 { 2324 ScRefCellValue aCell(*pDok, aAdr); 2325 svl::SharedString aSS; 2326 GetCellString(aSS, aCell); 2327 return aSS; 2328 } 2329 else 2330 return svl::SharedString::getEmptyString(); 2331 } 2332 case svDoubleRef: 2333 { // generate position dependent SingleRef 2334 ScRange aRange; 2335 PopDoubleRef( aRange ); 2336 ScAddress aAdr; 2337 if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr ) ) 2338 { 2339 ScRefCellValue aCell(*pDok, aAdr); 2340 svl::SharedString aSS; 2341 GetCellString(aSS, aCell); 2342 return aSS; 2343 } 2344 else 2345 return svl::SharedString::getEmptyString(); 2346 } 2347 case svExternalSingleRef: 2348 { 2349 ScExternalRefCache::TokenRef pToken; 2350 PopExternalSingleRef(pToken); 2351 if (nGlobalError != FormulaError::NONE) 2352 return svl::SharedString::getEmptyString(); 2353 2354 if (pToken->GetType() == svDouble) 2355 { 2356 return GetStringFromDouble( pToken->GetDouble() ); 2357 } 2358 else // svString or svEmpty 2359 return pToken->GetString(); 2360 } 2361 case svExternalDoubleRef: 2362 { 2363 ScMatrixRef pMat; 2364 PopExternalDoubleRef(pMat); 2365 return GetStringFromMatrix(pMat); 2366 } 2367 case svMatrix: 2368 { 2369 ScMatrixRef pMat = PopMatrix(); 2370 return GetStringFromMatrix(pMat); 2371 } 2372 break; 2373 default: 2374 PopError(); 2375 SetError( FormulaError::IllegalArgument); 2376 } 2377 return svl::SharedString::getEmptyString(); 2378 } 2379 2380 svl::SharedString ScInterpreter::GetStringFromMatrix(const ScMatrixRef& pMat) 2381 { 2382 if ( !pMat ) 2383 ; // nothing 2384 else if ( !pJumpMatrix ) 2385 { 2386 return pMat->GetString( *pFormatter, 0, 0); 2387 } 2388 else 2389 { 2390 SCSIZE nCols, nRows, nC, nR; 2391 pMat->GetDimensions( nCols, nRows); 2392 pJumpMatrix->GetPos( nC, nR); 2393 // Use vector replication for single row/column arrays. 2394 if ( (nC < nCols || nCols == 1) && (nR < nRows || nRows == 1) ) 2395 return pMat->GetString( *pFormatter, nC, nR); 2396 2397 SetError( FormulaError::NoValue); 2398 } 2399 return svl::SharedString::getEmptyString(); 2400 } 2401 2402 ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix( 2403 double& rDouble, svl::SharedString& rString ) 2404 { 2405 2406 rDouble = 0.0; 2407 rString = svl::SharedString::getEmptyString(); 2408 ScMatValType nMatValType = ScMatValType::Empty; 2409 2410 ScMatrixRef pMat; 2411 StackVar eType = GetStackType(); 2412 if (eType == svExternalDoubleRef || eType == svExternalSingleRef || eType == svMatrix) 2413 { 2414 pMat = GetMatrix(); 2415 } 2416 else 2417 { 2418 PopError(); 2419 SetError( FormulaError::IllegalParameter); 2420 return nMatValType; 2421 } 2422 2423 ScMatrixValue nMatVal; 2424 if (!pMat) 2425 { 2426 // nothing 2427 } 2428 else if (!pJumpMatrix) 2429 { 2430 nMatVal = pMat->Get(0, 0); 2431 nMatValType = nMatVal.nType; 2432 } 2433 else 2434 { 2435 SCSIZE nCols, nRows, nC, nR; 2436 pMat->GetDimensions( nCols, nRows); 2437 pJumpMatrix->GetPos( nC, nR); 2438 // Use vector replication for single row/column arrays. 2439 if ( (nC < nCols || nCols == 1) && (nR < nRows || nRows == 1) ) 2440 { 2441 nMatVal = pMat->Get( nC, nR); 2442 nMatValType = nMatVal.nType; 2443 } 2444 else 2445 SetError( FormulaError::NoValue); 2446 } 2447 2448 if (ScMatrix::IsValueType( nMatValType)) 2449 { 2450 rDouble = nMatVal.fVal; 2451 FormulaError nError = nMatVal.GetError(); 2452 if (nError != FormulaError::NONE) 2453 SetError( nError); 2454 } 2455 else 2456 { 2457 rString = nMatVal.GetString(); 2458 } 2459 2460 return nMatValType; 2461 } 2462 2463 svl::SharedString ScInterpreter::GetStringFromDouble( double fVal ) 2464 { 2465 sal_uLong nIndex = pFormatter->GetStandardFormat( 2466 SvNumFormatType::NUMBER, 2467 ScGlobal::eLnge); 2468 OUString aStr; 2469 pFormatter->GetInputLineString(fVal, nIndex, aStr); 2470 return mrStrPool.intern(aStr); 2471 } 2472 2473 void ScInterpreter::ScDBGet() 2474 { 2475 bool bMissingField = false; 2476 unique_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) ); 2477 if (!pQueryParam) 2478 { 2479 // Failed to create query param. 2480 PushIllegalParameter(); 2481 return; 2482 } 2483 2484 pQueryParam->mbSkipString = false; 2485 ScDBQueryDataIterator aValIter(pDok, mrContext, std::move(pQueryParam)); 2486 ScDBQueryDataIterator::Value aValue; 2487 if (!aValIter.GetFirst(aValue) || aValue.mnError != FormulaError::NONE) 2488 { 2489 // No match found. 2490 PushNoValue(); 2491 return; 2492 } 2493 2494 ScDBQueryDataIterator::Value aValNext; 2495 if (aValIter.GetNext(aValNext) && aValNext.mnError == FormulaError::NONE) 2496 { 2497 // There should be only one unique match. 2498 PushIllegalArgument(); 2499 return; 2500 } 2501 2502 if (aValue.mbIsNumber) 2503 PushDouble(aValue.mfValue); 2504 else 2505 PushString(aValue.maString); 2506 } 2507 2508 void ScInterpreter::ScExternal() 2509 { 2510 sal_uInt8 nParamCount = GetByte(); 2511 OUString aUnoName; 2512 OUString aFuncName( ScGlobal::pCharClass->uppercase( pCur->GetExternal() ) ); 2513 LegacyFuncData* pLegacyFuncData = ScGlobal::GetLegacyFuncCollection()->findByName(aFuncName); 2514 if (pLegacyFuncData) 2515 { 2516 // Old binary non-UNO add-in function. 2517 // NOTE: parameter count is 1-based with the 0th "parameter" being the 2518 // return value, included in pLegacyFuncDatat->GetParamCount() 2519 if (nParamCount < MAXFUNCPARAM && nParamCount == pLegacyFuncData->GetParamCount() - 1) 2520 { 2521 ParamType eParamType[MAXFUNCPARAM]; 2522 void* ppParam[MAXFUNCPARAM]; 2523 double nVal[MAXFUNCPARAM]; 2524 sal_Char* pStr[MAXFUNCPARAM]; 2525 sal_uInt8* pCellArr[MAXFUNCPARAM]; 2526 short i; 2527 2528 for (i = 0; i < MAXFUNCPARAM; i++) 2529 { 2530 eParamType[i] = pLegacyFuncData->GetParamType(i); 2531 ppParam[i] = nullptr; 2532 nVal[i] = 0.0; 2533 pStr[i] = nullptr; 2534 pCellArr[i] = nullptr; 2535 } 2536 2537 for (i = nParamCount; (i > 0) && (nGlobalError == FormulaError::NONE); i--) 2538 { 2539 if (IsMissing()) 2540 { 2541 // Old binary Add-In can't distinguish between missing 2542 // omitted argument and 0 (or any other value). Force 2543 // error. 2544 SetError( FormulaError::ParameterExpected); 2545 break; // for 2546 } 2547 switch (eParamType[i]) 2548 { 2549 case ParamType::PTR_DOUBLE : 2550 { 2551 nVal[i-1] = GetDouble(); 2552 ppParam[i] = &nVal[i-1]; 2553 } 2554 break; 2555 case ParamType::PTR_STRING : 2556 { 2557 OString aStr(OUStringToOString(GetString().getString(), 2558 osl_getThreadTextEncoding())); 2559 if ( aStr.getLength() >= ADDIN_MAXSTRLEN ) 2560 SetError( FormulaError::StringOverflow ); 2561 else 2562 { 2563 pStr[i-1] = new sal_Char[ADDIN_MAXSTRLEN]; 2564 strncpy( pStr[i-1], aStr.getStr(), ADDIN_MAXSTRLEN ); 2565 pStr[i-1][ADDIN_MAXSTRLEN-1] = 0; 2566 ppParam[i] = pStr[i-1]; 2567 } 2568 } 2569 break; 2570 case ParamType::PTR_DOUBLE_ARR : 2571 { 2572 SCCOL nCol1; 2573 SCROW nRow1; 2574 SCTAB nTab1; 2575 SCCOL nCol2; 2576 SCROW nRow2; 2577 SCTAB nTab2; 2578 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); 2579 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE]; 2580 if (!CreateDoubleArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1])) 2581 SetError(FormulaError::CodeOverflow); 2582 else 2583 ppParam[i] = pCellArr[i-1]; 2584 } 2585 break; 2586 case ParamType::PTR_STRING_ARR : 2587 { 2588 SCCOL nCol1; 2589 SCROW nRow1; 2590 SCTAB nTab1; 2591 SCCOL nCol2; 2592 SCROW nRow2; 2593 SCTAB nTab2; 2594 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); 2595 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE]; 2596 if (!CreateStringArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1])) 2597 SetError(FormulaError::CodeOverflow); 2598 else 2599 ppParam[i] = pCellArr[i-1]; 2600 } 2601 break; 2602 case ParamType::PTR_CELL_ARR : 2603 { 2604 SCCOL nCol1; 2605 SCROW nRow1; 2606 SCTAB nTab1; 2607 SCCOL nCol2; 2608 SCROW nRow2; 2609 SCTAB nTab2; 2610 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); 2611 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE]; 2612 if (!CreateCellArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1])) 2613 SetError(FormulaError::CodeOverflow); 2614 else 2615 ppParam[i] = pCellArr[i-1]; 2616 } 2617 break; 2618 default : 2619 SetError(FormulaError::IllegalParameter); 2620 break; 2621 } 2622 } 2623 while ( i-- ) 2624 Pop(); // In case of error (otherwise i==0) pop all parameters 2625 2626 if (nGlobalError == FormulaError::NONE) 2627 { 2628 if ( pLegacyFuncData->GetAsyncType() == ParamType::NONE ) 2629 { 2630 switch ( eParamType[0] ) 2631 { 2632 case ParamType::PTR_DOUBLE : 2633 { 2634 double nErg = 0.0; 2635 ppParam[0] = &nErg; 2636 pLegacyFuncData->Call(ppParam); 2637 PushDouble(nErg); 2638 } 2639 break; 2640 case ParamType::PTR_STRING : 2641 { 2642 std::unique_ptr<sal_Char[]> pcErg(new sal_Char[ADDIN_MAXSTRLEN]); 2643 ppParam[0] = pcErg.get(); 2644 pLegacyFuncData->Call(ppParam); 2645 OUString aUni( pcErg.get(), strlen(pcErg.get()), osl_getThreadTextEncoding() ); 2646 PushString( aUni ); 2647 } 2648 break; 2649 default: 2650 PushError( FormulaError::UnknownState ); 2651 } 2652 } 2653 else 2654 { 2655 // enable asyncs after loading 2656 rArr.AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT ); 2657 // assure identical handler with identical call? 2658 double nErg = 0.0; 2659 ppParam[0] = &nErg; 2660 pLegacyFuncData->Call(ppParam); 2661 sal_uLong nHandle = sal_uLong( nErg ); 2662 if ( nHandle >= 65536 ) 2663 { 2664 ScAddInAsync* pAs = ScAddInAsync::Get( nHandle ); 2665 if ( !pAs ) 2666 { 2667 pAs = new ScAddInAsync(nHandle, pLegacyFuncData, pDok); 2668 pMyFormulaCell->StartListening( *pAs ); 2669 } 2670 else 2671 { 2672 pMyFormulaCell->StartListening( *pAs ); 2673 if ( !pAs->HasDocument( pDok ) ) 2674 pAs->AddDocument( pDok ); 2675 } 2676 if ( pAs->IsValid() ) 2677 { 2678 switch ( pAs->GetType() ) 2679 { 2680 case ParamType::PTR_DOUBLE : 2681 PushDouble( pAs->GetValue() ); 2682 break; 2683 case ParamType::PTR_STRING : 2684 PushString( pAs->GetString() ); 2685 break; 2686 default: 2687 PushError( FormulaError::UnknownState ); 2688 } 2689 } 2690 else 2691 PushNA(); 2692 } 2693 else 2694 PushNoValue(); 2695 } 2696 } 2697 2698 for (i = 0; i < MAXFUNCPARAM; i++) 2699 { 2700 delete[] pStr[i]; 2701 delete[] pCellArr[i]; 2702 } 2703 } 2704 else 2705 { 2706 while( nParamCount-- > 0) 2707 Pop(); 2708 PushIllegalParameter(); 2709 } 2710 } 2711 else if ( !( aUnoName = ScGlobal::GetAddInCollection()->FindFunction(aFuncName, false) ).isEmpty() ) 2712 { 2713 // bLocalFirst=false in FindFunction, cFunc should be the stored 2714 // internal name 2715 2716 ScUnoAddInCall aCall( *ScGlobal::GetAddInCollection(), aUnoName, nParamCount ); 2717 2718 if ( !aCall.ValidParamCount() ) 2719 SetError( FormulaError::IllegalParameter ); 2720 2721 if ( aCall.NeedsCaller() && GetError() == FormulaError::NONE ) 2722 { 2723 SfxObjectShell* pShell = pDok->GetDocumentShell(); 2724 if (pShell) 2725 aCall.SetCallerFromObjectShell( pShell ); 2726 else 2727 { 2728 // use temporary model object (without document) to supply options 2729 aCall.SetCaller( static_cast<beans::XPropertySet*>( 2730 new ScDocOptionsObj( pDok->GetDocOptions() ) ) ); 2731 } 2732 } 2733 2734 short nPar = nParamCount; 2735 while ( nPar > 0 && GetError() == FormulaError::NONE ) 2736 { 2737 --nPar; // 0 .. (nParamCount-1) 2738 2739 uno::Any aParam; 2740 if (IsMissing()) 2741 { 2742 // Add-In has to explicitly handle an omitted empty missing 2743 // argument, do not default to anything like GetDouble() would 2744 // do (e.g. 0). 2745 Pop(); 2746 aCall.SetParam( nPar, aParam ); 2747 continue; // while 2748 } 2749 2750 StackVar nStackType = GetStackType(); 2751 ScAddInArgumentType eType = aCall.GetArgType( nPar ); 2752 switch (eType) 2753 { 2754 case SC_ADDINARG_INTEGER: 2755 { 2756 sal_Int32 nVal = GetInt32(); 2757 if (nGlobalError == FormulaError::NONE) 2758 aParam <<= nVal; 2759 } 2760 break; 2761 2762 case SC_ADDINARG_DOUBLE: 2763 aParam <<= GetDouble(); 2764 break; 2765 2766 case SC_ADDINARG_STRING: 2767 aParam <<= GetString().getString(); 2768 break; 2769 2770 case SC_ADDINARG_INTEGER_ARRAY: 2771 switch( nStackType ) 2772 { 2773 case svDouble: 2774 case svString: 2775 case svSingleRef: 2776 { 2777 sal_Int32 nVal = GetInt32(); 2778 if (nGlobalError == FormulaError::NONE) 2779 { 2780 uno::Sequence<sal_Int32> aInner( &nVal, 1 ); 2781 uno::Sequence< uno::Sequence<sal_Int32> > aOuter( &aInner, 1 ); 2782 aParam <<= aOuter; 2783 } 2784 } 2785 break; 2786 case svDoubleRef: 2787 { 2788 ScRange aRange; 2789 PopDoubleRef( aRange ); 2790 if (!ScRangeToSequence::FillLongArray( aParam, pDok, aRange )) 2791 SetError(FormulaError::IllegalParameter); 2792 } 2793 break; 2794 case svMatrix: 2795 if (!ScRangeToSequence::FillLongArray( aParam, PopMatrix().get() )) 2796 SetError(FormulaError::IllegalParameter); 2797 break; 2798 default: 2799 PopError(); 2800 SetError(FormulaError::IllegalParameter); 2801 } 2802 break; 2803 2804 case SC_ADDINARG_DOUBLE_ARRAY: 2805 switch( nStackType ) 2806 { 2807 case svDouble: 2808 case svString: 2809 case svSingleRef: 2810 { 2811 double fVal = GetDouble(); 2812 uno::Sequence<double> aInner( &fVal, 1 ); 2813 uno::Sequence< uno::Sequence<double> > aOuter( &aInner, 1 ); 2814 aParam <<= aOuter; 2815 } 2816 break; 2817 case svDoubleRef: 2818 { 2819 ScRange aRange; 2820 PopDoubleRef( aRange ); 2821 if (!ScRangeToSequence::FillDoubleArray( aParam, pDok, aRange )) 2822 SetError(FormulaError::IllegalParameter); 2823 } 2824 break; 2825 case svMatrix: 2826 if (!ScRangeToSequence::FillDoubleArray( aParam, PopMatrix().get() )) 2827 SetError(FormulaError::IllegalParameter); 2828 break; 2829 default: 2830 PopError(); 2831 SetError(FormulaError::IllegalParameter); 2832 } 2833 break; 2834 2835 case SC_ADDINARG_STRING_ARRAY: 2836 switch( nStackType ) 2837 { 2838 case svDouble: 2839 case svString: 2840 case svSingleRef: 2841 { 2842 OUString aString = GetString().getString(); 2843 uno::Sequence<OUString> aInner( &aString, 1 ); 2844 uno::Sequence< uno::Sequence<OUString> > aOuter( &aInner, 1 ); 2845 aParam <<= aOuter; 2846 } 2847 break; 2848 case svDoubleRef: 2849 { 2850 ScRange aRange; 2851 PopDoubleRef( aRange ); 2852 if (!ScRangeToSequence::FillStringArray( aParam, pDok, aRange )) 2853 SetError(FormulaError::IllegalParameter); 2854 } 2855 break; 2856 case svMatrix: 2857 if (!ScRangeToSequence::FillStringArray( aParam, PopMatrix().get(), pFormatter )) 2858 SetError(FormulaError::IllegalParameter); 2859 break; 2860 default: 2861 PopError(); 2862 SetError(FormulaError::IllegalParameter); 2863 } 2864 break; 2865 2866 case SC_ADDINARG_MIXED_ARRAY: 2867 switch( nStackType ) 2868 { 2869 case svDouble: 2870 case svString: 2871 case svSingleRef: 2872 { 2873 uno::Any aElem; 2874 if ( nStackType == svDouble ) 2875 aElem <<= GetDouble(); 2876 else if ( nStackType == svString ) 2877 aElem <<= GetString().getString(); 2878 else 2879 { 2880 ScAddress aAdr; 2881 if ( PopDoubleRefOrSingleRef( aAdr ) ) 2882 { 2883 ScRefCellValue aCell(*pDok, aAdr); 2884 if (aCell.hasString()) 2885 { 2886 svl::SharedString aStr; 2887 GetCellString(aStr, aCell); 2888 aElem <<= aStr.getString(); 2889 } 2890 else 2891 aElem <<= GetCellValue(aAdr, aCell); 2892 } 2893 } 2894 uno::Sequence<uno::Any> aInner( &aElem, 1 ); 2895 uno::Sequence< uno::Sequence<uno::Any> > aOuter( &aInner, 1 ); 2896 aParam <<= aOuter; 2897 } 2898 break; 2899 case svDoubleRef: 2900 { 2901 ScRange aRange; 2902 PopDoubleRef( aRange ); 2903 if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange )) 2904 SetError(FormulaError::IllegalParameter); 2905 } 2906 break; 2907 case svMatrix: 2908 if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() )) 2909 SetError(FormulaError::IllegalParameter); 2910 break; 2911 default: 2912 PopError(); 2913 SetError(FormulaError::IllegalParameter); 2914 } 2915 break; 2916 2917 case SC_ADDINARG_VALUE_OR_ARRAY: 2918 switch( nStackType ) 2919 { 2920 case svDouble: 2921 aParam <<= GetDouble(); 2922 break; 2923 case svString: 2924 aParam <<= GetString().getString(); 2925 break; 2926 case svSingleRef: 2927 { 2928 ScAddress aAdr; 2929 if ( PopDoubleRefOrSingleRef( aAdr ) ) 2930 { 2931 ScRefCellValue aCell(*pDok, aAdr); 2932 if (aCell.hasString()) 2933 { 2934 svl::SharedString aStr; 2935 GetCellString(aStr, aCell); 2936 aParam <<= aStr.getString(); 2937 } 2938 else 2939 aParam <<= GetCellValue(aAdr, aCell); 2940 } 2941 } 2942 break; 2943 case svDoubleRef: 2944 { 2945 ScRange aRange; 2946 PopDoubleRef( aRange ); 2947 if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange )) 2948 SetError(FormulaError::IllegalParameter); 2949 } 2950 break; 2951 case svMatrix: 2952 if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() )) 2953 SetError(FormulaError::IllegalParameter); 2954 break; 2955 default: 2956 PopError(); 2957 SetError(FormulaError::IllegalParameter); 2958 } 2959 break; 2960 2961 case SC_ADDINARG_CELLRANGE: 2962 switch( nStackType ) 2963 { 2964 case svSingleRef: 2965 { 2966 ScAddress aAdr; 2967 PopSingleRef( aAdr ); 2968 ScRange aRange( aAdr ); 2969 uno::Reference<table::XCellRange> xObj = 2970 ScCellRangeObj::CreateRangeFromDoc( pDok, aRange ); 2971 if (xObj.is()) 2972 aParam <<= xObj; 2973 else 2974 SetError(FormulaError::IllegalParameter); 2975 } 2976 break; 2977 case svDoubleRef: 2978 { 2979 ScRange aRange; 2980 PopDoubleRef( aRange ); 2981 uno::Reference<table::XCellRange> xObj = 2982 ScCellRangeObj::CreateRangeFromDoc( pDok, aRange ); 2983 if (xObj.is()) 2984 { 2985 aParam <<= xObj; 2986 } 2987 else 2988 { 2989 SetError(FormulaError::IllegalParameter); 2990 } 2991 } 2992 break; 2993 default: 2994 PopError(); 2995 SetError(FormulaError::IllegalParameter); 2996 } 2997 break; 2998 2999 default: 3000 PopError(); 3001 SetError(FormulaError::IllegalParameter); 3002 } 3003 aCall.SetParam( nPar, aParam ); 3004 } 3005 3006 while (nPar-- > 0) 3007 { 3008 Pop(); // in case of error, remove remaining args 3009 } 3010 if ( GetError() == FormulaError::NONE ) 3011 { 3012 aCall.ExecuteCall(); 3013 3014 if ( aCall.HasVarRes() ) // handle async functions 3015 { 3016 rArr.AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT ); 3017 uno::Reference<sheet::XVolatileResult> xRes = aCall.GetVarRes(); 3018 ScAddInListener* pLis = ScAddInListener::Get( xRes ); 3019 if ( !pLis ) 3020 { 3021 pLis = ScAddInListener::CreateListener( xRes, pDok ); 3022 pMyFormulaCell->StartListening( *pLis ); 3023 } 3024 else 3025 { 3026 pMyFormulaCell->StartListening( *pLis ); 3027 if ( !pLis->HasDocument( pDok ) ) 3028 { 3029 pLis->AddDocument( pDok ); 3030 } 3031 } 3032 3033 aCall.SetResult( pLis->GetResult() ); // use result from async 3034 } 3035 3036 if ( aCall.GetErrCode() != FormulaError::NONE ) 3037 { 3038 PushError( aCall.GetErrCode() ); 3039 } 3040 else if ( aCall.HasMatrix() ) 3041 { 3042 PushMatrix( aCall.GetMatrix() ); 3043 } 3044 else if ( aCall.HasString() ) 3045 { 3046 PushString( aCall.GetString() ); 3047 } 3048 else 3049 { 3050 PushDouble( aCall.GetValue() ); 3051 } 3052 } 3053 else // error... 3054 PushError( GetError()); 3055 } 3056 else 3057 { 3058 while( nParamCount-- > 0) 3059 { 3060 Pop(); 3061 } 3062 PushError( FormulaError::NoAddin ); 3063 } 3064 } 3065 3066 void ScInterpreter::ScMissing() 3067 { 3068 if ( aCode.IsEndOfPath() ) 3069 PushTempToken( new ScEmptyCellToken( false, false ) ); 3070 else 3071 PushTempToken( new FormulaMissingToken ); 3072 } 3073 3074 #if HAVE_FEATURE_SCRIPTING 3075 3076 static uno::Any lcl_getSheetModule( const uno::Reference<table::XCellRange>& xCellRange, const ScDocument* pDok ) 3077 { 3078 uno::Reference< sheet::XSheetCellRange > xSheetRange( xCellRange, uno::UNO_QUERY_THROW ); 3079 uno::Reference< beans::XPropertySet > xProps( xSheetRange->getSpreadsheet(), uno::UNO_QUERY_THROW ); 3080 OUString sCodeName; 3081 xProps->getPropertyValue("CodeName") >>= sCodeName; 3082 // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible 3083 // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there 3084 // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at 3085 // the document in the future could fix this, especially IF the switching of the vba mode takes care to 3086 // create the special document module objects if they don't exist. 3087 BasicManager* pBasMgr = pDok->GetDocumentShell()->GetBasicManager(); 3088 3089 uno::Reference< uno::XInterface > xIf; 3090 if ( pBasMgr && !pBasMgr->GetName().isEmpty() ) 3091 { 3092 OUString sProj( "Standard" ); 3093 if ( !pDok->GetDocumentShell()->GetBasicManager()->GetName().isEmpty() ) 3094 { 3095 sProj = pDok->GetDocumentShell()->GetBasicManager()->GetName(); 3096 } 3097 StarBASIC* pBasic = pDok->GetDocumentShell()->GetBasicManager()->GetLib( sProj ); 3098 if ( pBasic ) 3099 { 3100 SbModule* pMod = pBasic->FindModule( sCodeName ); 3101 if ( pMod ) 3102 { 3103 xIf = pMod->GetUnoModule(); 3104 } 3105 } 3106 } 3107 return uno::makeAny( xIf ); 3108 } 3109 3110 static bool lcl_setVBARange( const ScRange& aRange, const ScDocument* pDok, SbxVariable* pPar ) 3111 { 3112 bool bOk = false; 3113 try 3114 { 3115 uno::Reference< uno::XInterface > xVBARange; 3116 uno::Reference<table::XCellRange> xCellRange = ScCellRangeObj::CreateRangeFromDoc( pDok, aRange ); 3117 uno::Sequence< uno::Any > aArgs(2); 3118 aArgs[0] = lcl_getSheetModule( xCellRange, pDok ); 3119 aArgs[1] <<= xCellRange; 3120 xVBARange = ooo::vba::createVBAUnoAPIServiceWithArgs( pDok->GetDocumentShell(), "ooo.vba.excel.Range", aArgs ); 3121 if ( xVBARange.is() ) 3122 { 3123 SbxObjectRef aObj = GetSbUnoObject( "A-Range", uno::Any( xVBARange ) ); 3124 SetSbUnoObjectDfltPropName( aObj.get() ); 3125 bOk = pPar->PutObject( aObj.get() ); 3126 } 3127 } 3128 catch( uno::Exception& ) 3129 { 3130 } 3131 return bOk; 3132 } 3133 3134 static bool lcl_isNumericResult( double& fVal, const SbxVariable* pVar ) 3135 { 3136 switch (pVar->GetType()) 3137 { 3138 case SbxINTEGER: 3139 case SbxLONG: 3140 case SbxSINGLE: 3141 case SbxDOUBLE: 3142 case SbxCURRENCY: 3143 case SbxDATE: 3144 case SbxUSHORT: 3145 case SbxULONG: 3146 case SbxINT: 3147 case SbxUINT: 3148 case SbxSALINT64: 3149 case SbxSALUINT64: 3150 case SbxDECIMAL: 3151 fVal = pVar->GetDouble(); 3152 return true; 3153 case SbxBOOL: 3154 fVal = (pVar->GetBool() ? 1.0 : 0.0); 3155 return true; 3156 default: 3157 ; // nothing 3158 } 3159 return false; 3160 } 3161 3162 #endif 3163 3164 void ScInterpreter::ScMacro() 3165 { 3166 3167 #if !HAVE_FEATURE_SCRIPTING 3168 PushNoValue(); // without DocShell no CallBasic 3169 return; 3170 #else 3171 SbxBase::ResetError(); 3172 3173 sal_uInt8 nParamCount = GetByte(); 3174 OUString aMacro( pCur->GetExternal() ); 3175 3176 SfxObjectShell* pDocSh = pDok->GetDocumentShell(); 3177 if ( !pDocSh ) 3178 { 3179 PushNoValue(); // without DocShell no CallBasic 3180 return; 3181 } 3182 3183 // no security queue beforehand (just CheckMacroWarn), moved to CallBasic 3184 3185 // If the Dok was loaded during a Basic-Calls, 3186 // is the Sbx-object created(?) 3187 // pDocSh->GetSbxObject(); 3188 3189 // search function with the name, 3190 // then assemble SfxObjectShell::CallBasic from aBasicStr, aMacroStr 3191 3192 StarBASIC* pRoot; 3193 3194 try 3195 { 3196 pRoot = pDocSh->GetBasic(); 3197 } 3198 catch (...) 3199 { 3200 pRoot = nullptr; 3201 } 3202 3203 SbxVariable* pVar = pRoot ? pRoot->Find(aMacro, SbxClassType::Method) : nullptr; 3204 if( !pVar || pVar->GetType() == SbxVOID || dynamic_cast<const SbMethod*>( pVar) == nullptr ) 3205 { 3206 PushError( FormulaError::NoMacro ); 3207 return; 3208 } 3209 3210 bool bVolatileMacro = false; 3211 SbMethod* pMethod = static_cast<SbMethod*>(pVar); 3212 3213 SbModule* pModule = pMethod->GetModule(); 3214 bool bUseVBAObjects = pModule->IsVBACompat(); 3215 SbxObject* pObject = pModule->GetParent(); 3216 OSL_ENSURE(dynamic_cast<const StarBASIC *>(pObject) != nullptr, "No Basic found!"); 3217 OUString aMacroStr = pObject->GetName() + "." + pModule->GetName() + "." + pMethod->GetName(); 3218 OUString aBasicStr; 3219 if (pRoot && bUseVBAObjects) 3220 { 3221 // just here to make sure the VBA objects when we run the macro during ODF import 3222 pRoot->getVBAGlobals(); 3223 } 3224 if (pObject->GetParent()) 3225 { 3226 aBasicStr = pObject->GetParent()->GetName(); // document BASIC 3227 } 3228 else 3229 { 3230 aBasicStr = SfxGetpApp()->GetName(); // application BASIC 3231 } 3232 // assemble a parameter array 3233 3234 SbxArrayRef refPar = new SbxArray; 3235 bool bOk = true; 3236 for( short i = nParamCount; i && bOk ; i-- ) 3237 { 3238 SbxVariable* pPar = refPar->Get( static_cast<sal_uInt16>(i) ); 3239 switch( GetStackType() ) 3240 { 3241 case svDouble: 3242 pPar->PutDouble( GetDouble() ); 3243 break; 3244 case svString: 3245 pPar->PutString( GetString().getString() ); 3246 break; 3247 case svExternalSingleRef: 3248 { 3249 ScExternalRefCache::TokenRef pToken; 3250 PopExternalSingleRef(pToken); 3251 if (nGlobalError != FormulaError::NONE) 3252 bOk = false; 3253 else 3254 { 3255 if ( pToken->GetType() == svString ) 3256 pPar->PutString( pToken->GetString().getString() ); 3257 else if ( pToken->GetType() == svDouble ) 3258 pPar->PutDouble( pToken->GetDouble() ); 3259 else 3260 { 3261 SetError( FormulaError::IllegalArgument ); 3262 bOk = false; 3263 } 3264 } 3265 } 3266 break; 3267 case svSingleRef: 3268 { 3269 ScAddress aAdr; 3270 PopSingleRef( aAdr ); 3271 if ( bUseVBAObjects ) 3272 { 3273 ScRange aRange( aAdr ); 3274 bOk = lcl_setVBARange( aRange, pDok, pPar ); 3275 } 3276 else 3277 { 3278 bOk = SetSbxVariable( pPar, aAdr ); 3279 } 3280 } 3281 break; 3282 case svDoubleRef: 3283 { 3284 SCCOL nCol1; 3285 SCROW nRow1; 3286 SCTAB nTab1; 3287 SCCOL nCol2; 3288 SCROW nRow2; 3289 SCTAB nTab2; 3290 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); 3291 if( nTab1 != nTab2 ) 3292 { 3293 SetError( FormulaError::IllegalParameter ); 3294 bOk = false; 3295 } 3296 else 3297 { 3298 if ( bUseVBAObjects ) 3299 { 3300 ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); 3301 bOk = lcl_setVBARange( aRange, pDok, pPar ); 3302 } 3303 else 3304 { 3305 SbxDimArrayRef refArray = new SbxDimArray; 3306 refArray->AddDim32( 1, nRow2 - nRow1 + 1 ); 3307 refArray->AddDim32( 1, nCol2 - nCol1 + 1 ); 3308 ScAddress aAdr( nCol1, nRow1, nTab1 ); 3309 for( SCROW nRow = nRow1; bOk && nRow <= nRow2; nRow++ ) 3310 { 3311 aAdr.SetRow( nRow ); 3312 sal_Int32 nIdx[ 2 ]; 3313 nIdx[ 0 ] = nRow-nRow1+1; 3314 for( SCCOL nCol = nCol1; bOk && nCol <= nCol2; nCol++ ) 3315 { 3316 aAdr.SetCol( nCol ); 3317 nIdx[ 1 ] = nCol-nCol1+1; 3318 SbxVariable* p = refArray->Get32( nIdx ); 3319 bOk = SetSbxVariable( p, aAdr ); 3320 } 3321 } 3322 pPar->PutObject( refArray.get() ); 3323 } 3324 } 3325 } 3326 break; 3327 case svExternalDoubleRef: 3328 case svMatrix: 3329 { 3330 ScMatrixRef pMat = GetMatrix(); 3331 SCSIZE nC, nR; 3332 if (pMat && nGlobalError == FormulaError::NONE) 3333 { 3334 pMat->GetDimensions(nC, nR); 3335 SbxDimArrayRef refArray = new SbxDimArray; 3336 refArray->AddDim32( 1, static_cast<sal_Int32>(nR) ); 3337 refArray->AddDim32( 1, static_cast<sal_Int32>(nC) ); 3338 for( SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++ ) 3339 { 3340 sal_Int32 nIdx[ 2 ]; 3341 nIdx[ 0 ] = static_cast<sal_Int32>(nMatRow+1); 3342 for( SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++ ) 3343 { 3344 nIdx[ 1 ] = static_cast<sal_Int32>(nMatCol+1); 3345 SbxVariable* p = refArray->Get32( nIdx ); 3346 if (pMat->IsStringOrEmpty(nMatCol, nMatRow)) 3347 { 3348 p->PutString( pMat->GetString(nMatCol, nMatRow).getString() ); 3349 } 3350 else 3351 { 3352 p->PutDouble( pMat->GetDouble(nMatCol, nMatRow)); 3353 } 3354 } 3355 } 3356 pPar->PutObject( refArray.get() ); 3357 } 3358 else 3359 { 3360 SetError( FormulaError::IllegalParameter ); 3361 } 3362 } 3363 break; 3364 default: 3365 SetError( FormulaError::IllegalParameter ); 3366 bOk = false; 3367 } 3368 } 3369 if( bOk ) 3370 { 3371 pDok->LockTable( aPos.Tab() ); 3372 SbxVariableRef refRes = new SbxVariable; 3373 pDok->IncMacroInterpretLevel(); 3374 ErrCode eRet = pDocSh->CallBasic( aMacroStr, aBasicStr, refPar.get(), refRes.get() ); 3375 pDok->DecMacroInterpretLevel(); 3376 pDok->UnlockTable( aPos.Tab() ); 3377 3378 ScMacroManager* pMacroMgr = pDok->GetMacroManager(); 3379 if (pMacroMgr) 3380 { 3381 bVolatileMacro = pMacroMgr->GetUserFuncVolatile( pMethod->GetName() ); 3382 pMacroMgr->AddDependentCell(pModule->GetName(), pMyFormulaCell); 3383 } 3384 3385 double fVal; 3386 SbxDataType eResType = refRes->GetType(); 3387 if( SbxBase::GetError() ) 3388 { 3389 SetError( FormulaError::NoValue); 3390 } 3391 if ( eRet != ERRCODE_NONE ) 3392 { 3393 PushNoValue(); 3394 } 3395 else if (lcl_isNumericResult( fVal, refRes.get())) 3396 { 3397 switch (eResType) 3398 { 3399 case SbxDATE: 3400 nFuncFmtType = SvNumFormatType::DATE; 3401 break; 3402 case SbxBOOL: 3403 nFuncFmtType = SvNumFormatType::LOGICAL; 3404 break; 3405 // Do not add SbxCURRENCY, we don't know which currency. 3406 default: 3407 ; // nothing 3408 } 3409 PushDouble( fVal ); 3410 } 3411 else if ( eResType & SbxARRAY ) 3412 { 3413 SbxBase* pElemObj = refRes->GetObject(); 3414 SbxDimArray* pDimArray = dynamic_cast<SbxDimArray*>(pElemObj); 3415 short nDim = pDimArray ? pDimArray->GetDims() : 0; 3416 if ( 1 <= nDim && nDim <= 2 ) 3417 { 3418 sal_Int32 nCs, nCe, nRs, nRe; 3419 SCSIZE nC, nR; 3420 SCCOL nColIdx; 3421 SCROW nRowIdx; 3422 if ( nDim == 1 ) 3423 { // array( cols ) one line, several columns 3424 pDimArray->GetDim32( 1, nCs, nCe ); 3425 nC = static_cast<SCSIZE>(nCe - nCs + 1); 3426 nRs = nRe = 0; 3427 nR = 1; 3428 nColIdx = 0; 3429 nRowIdx = 1; 3430 } 3431 else 3432 { // array( rows, cols ) 3433 pDimArray->GetDim32( 1, nRs, nRe ); 3434 nR = static_cast<SCSIZE>(nRe - nRs + 1); 3435 pDimArray->GetDim32( 2, nCs, nCe ); 3436 nC = static_cast<SCSIZE>(nCe - nCs + 1); 3437 nColIdx = 1; 3438 nRowIdx = 0; 3439 } 3440 ScMatrixRef pMat = GetNewMat( nC, nR); 3441 if ( pMat ) 3442 { 3443 SbxVariable* pV; 3444 for ( SCSIZE j=0; j < nR; j++ ) 3445 { 3446 sal_Int32 nIdx[ 2 ]; 3447 // in one-dimensional array( cols ) nIdx[1] 3448 // from SbxDimArray::Get is ignored 3449 nIdx[ nRowIdx ] = nRs + static_cast<sal_Int32>(j); 3450 for ( SCSIZE i=0; i < nC; i++ ) 3451 { 3452 nIdx[ nColIdx ] = nCs + static_cast<sal_Int32>(i); 3453 pV = pDimArray->Get32( nIdx ); 3454 if ( lcl_isNumericResult( fVal, pV) ) 3455 { 3456 pMat->PutDouble( fVal, i, j ); 3457 } 3458 else 3459 { 3460 pMat->PutString(mrStrPool.intern(pV->GetOUString()), i, j); 3461 } 3462 } 3463 } 3464 PushMatrix( pMat ); 3465 } 3466 else 3467 { 3468 PushIllegalArgument(); 3469 } 3470 } 3471 else 3472 { 3473 PushNoValue(); 3474 } 3475 } 3476 else 3477 { 3478 PushString( refRes->GetOUString() ); 3479 } 3480 } 3481 3482 if (bVolatileMacro && meVolatileType == NOT_VOLATILE) 3483 meVolatileType = VOLATILE_MACRO; 3484 #endif 3485 } 3486 3487 #if HAVE_FEATURE_SCRIPTING 3488 3489 bool ScInterpreter::SetSbxVariable( SbxVariable* pVar, const ScAddress& rPos ) 3490 { 3491 bool bOk = true; 3492 ScRefCellValue aCell(*pDok, rPos); 3493 if (!aCell.isEmpty()) 3494 { 3495 FormulaError nErr; 3496 double nVal; 3497 switch (aCell.meType) 3498 { 3499 case CELLTYPE_VALUE : 3500 nVal = GetValueCellValue(rPos, aCell.mfValue); 3501 pVar->PutDouble( nVal ); 3502 break; 3503 case CELLTYPE_STRING : 3504 case CELLTYPE_EDIT : 3505 pVar->PutString(aCell.getString(pDok)); 3506 break; 3507 case CELLTYPE_FORMULA : 3508 nErr = aCell.mpFormula->GetErrCode(); 3509 if( nErr == FormulaError::NONE ) 3510 { 3511 if (aCell.mpFormula->IsValue()) 3512 { 3513 nVal = aCell.mpFormula->GetValue(); 3514 pVar->PutDouble( nVal ); 3515 } 3516 else 3517 pVar->PutString(aCell.mpFormula->GetString().getString()); 3518 } 3519 else 3520 { 3521 SetError( nErr ); 3522 bOk = false; 3523 } 3524 break; 3525 default : 3526 pVar->PutEmpty(); 3527 } 3528 } 3529 else 3530 pVar->PutEmpty(); 3531 3532 return bOk; 3533 } 3534 3535 #endif 3536 3537 void ScInterpreter::ScTableOp() 3538 { 3539 sal_uInt8 nParamCount = GetByte(); 3540 if (nParamCount != 3 && nParamCount != 5) 3541 { 3542 PushIllegalParameter(); 3543 return; 3544 } 3545 std::unique_ptr<ScInterpreterTableOpParams> pTableOp(new ScInterpreterTableOpParams); 3546 if (nParamCount == 5) 3547 { 3548 PopSingleRef( pTableOp->aNew2 ); 3549 PopSingleRef( pTableOp->aOld2 ); 3550 } 3551 PopSingleRef( pTableOp->aNew1 ); 3552 PopSingleRef( pTableOp->aOld1 ); 3553 PopSingleRef( pTableOp->aFormulaPos ); 3554 3555 pTableOp->bValid = true; 3556 pDok->m_TableOpList.push_back(pTableOp.get()); 3557 pDok->IncInterpreterTableOpLevel(); 3558 3559 bool bReuseLastParams = (pDok->aLastTableOpParams == *pTableOp); 3560 if ( bReuseLastParams ) 3561 { 3562 pTableOp->aNotifiedFormulaPos = pDok->aLastTableOpParams.aNotifiedFormulaPos; 3563 pTableOp->bRefresh = true; 3564 for ( ::std::vector< ScAddress >::const_iterator iBroadcast( 3565 pTableOp->aNotifiedFormulaPos.begin() ); 3566 iBroadcast != pTableOp->aNotifiedFormulaPos.end(); 3567 ++iBroadcast ) 3568 { // emulate broadcast and indirectly collect cell pointers 3569 ScRefCellValue aCell(*pDok, *iBroadcast); 3570 if (aCell.meType == CELLTYPE_FORMULA) 3571 aCell.mpFormula->SetTableOpDirty(); 3572 } 3573 } 3574 else 3575 { // broadcast and indirectly collect cell pointers and positions 3576 pDok->SetTableOpDirty( pTableOp->aOld1 ); 3577 if ( nParamCount == 5 ) 3578 pDok->SetTableOpDirty( pTableOp->aOld2 ); 3579 } 3580 pTableOp->bCollectNotifications = false; 3581 3582 ScRefCellValue aCell(*pDok, pTableOp->aFormulaPos); 3583 if (aCell.meType == CELLTYPE_FORMULA) 3584 aCell.mpFormula->SetDirtyVar(); 3585 if (aCell.hasNumeric()) 3586 { 3587 PushDouble(GetCellValue(pTableOp->aFormulaPos, aCell)); 3588 } 3589 else 3590 { 3591 svl::SharedString aCellString; 3592 GetCellString(aCellString, aCell); 3593 PushString( aCellString ); 3594 } 3595 3596 auto const itr = 3597 ::std::find(pDok->m_TableOpList.begin(), pDok->m_TableOpList.end(), pTableOp.get()); 3598 if (itr != pDok->m_TableOpList.end()) 3599 { 3600 pDok->m_TableOpList.erase(itr); 3601 } 3602 3603 // set dirty again once more to be able to recalculate original 3604 for ( ::std::vector< ScFormulaCell* >::const_iterator iBroadcast( 3605 pTableOp->aNotifiedFormulaCells.begin() ); 3606 iBroadcast != pTableOp->aNotifiedFormulaCells.end(); 3607 ++iBroadcast ) 3608 { 3609 (*iBroadcast)->SetTableOpDirty(); 3610 } 3611 3612 // save these params for next incarnation 3613 if ( !bReuseLastParams ) 3614 pDok->aLastTableOpParams = *pTableOp; 3615 3616 if (aCell.meType == CELLTYPE_FORMULA) 3617 { 3618 aCell.mpFormula->SetDirtyVar(); 3619 aCell.mpFormula->GetErrCode(); // recalculate original 3620 } 3621 3622 // Reset all dirty flags so next incarnation does really collect all cell 3623 // pointers during notifications and not just non-dirty ones, which may 3624 // happen if a formula cell is used by more than one TableOp block. 3625 for ( ::std::vector< ScFormulaCell* >::const_iterator iBroadcast2( 3626 pTableOp->aNotifiedFormulaCells.begin() ); 3627 iBroadcast2 != pTableOp->aNotifiedFormulaCells.end(); 3628 ++iBroadcast2 ) 3629 { 3630 (*iBroadcast2)->ResetTableOpDirtyVar(); 3631 } 3632 pTableOp.reset(); 3633 3634 pDok->DecInterpreterTableOpLevel(); 3635 } 3636 3637 void ScInterpreter::ScDBArea() 3638 { 3639 ScDBData* pDBData = pDok->GetDBCollection()->getNamedDBs().findByIndex(pCur->GetIndex()); 3640 if (pDBData) 3641 { 3642 ScComplexRefData aRefData; 3643 aRefData.InitFlags(); 3644 ScRange aRange; 3645 pDBData->GetArea(aRange); 3646 aRange.aEnd.SetTab(aRange.aStart.Tab()); 3647 aRefData.SetRange(aRange, aPos); 3648 PushTempToken( new ScDoubleRefToken( aRefData ) ); 3649 } 3650 else 3651 PushError( FormulaError::NoName); 3652 } 3653 3654 void ScInterpreter::ScColRowNameAuto() 3655 { 3656 ScComplexRefData aRefData( *pCur->GetDoubleRef() ); 3657 ScRange aAbs = aRefData.toAbs(aPos); 3658 if (!ValidRange(aAbs)) 3659 { 3660 PushError( FormulaError::NoRef ); 3661 return; 3662 } 3663 3664 SCCOL nStartCol; 3665 SCROW nStartRow; 3666 3667 // maybe remember limit by using defined ColRowNameRange 3668 SCCOL nCol2 = aAbs.aEnd.Col(); 3669 SCROW nRow2 = aAbs.aEnd.Row(); 3670 // DataArea of the first cell 3671 nStartCol = aAbs.aStart.Col(); 3672 nStartRow = aAbs.aStart.Row(); 3673 aAbs.aEnd = aAbs.aStart; // Shrink to the top-left cell. 3674 3675 { 3676 // Expand to the data area. Only modify the end position. 3677 SCCOL nDACol1 = aAbs.aStart.Col(), nDACol2 = aAbs.aEnd.Col(); 3678 SCROW nDARow1 = aAbs.aStart.Row(), nDARow2 = aAbs.aEnd.Row(); 3679 pDok->GetDataArea(aAbs.aStart.Tab(), nDACol1, nDARow1, nDACol2, nDARow2, true, false); 3680 aAbs.aEnd.SetCol(nDACol2); 3681 aAbs.aEnd.SetRow(nDARow2); 3682 } 3683 3684 // corresponds with ScCompiler::GetToken 3685 if ( aRefData.Ref1.IsColRel() ) 3686 { // ColName 3687 aAbs.aEnd.SetCol(nStartCol); 3688 // maybe get previous limit by using defined ColRowNameRange 3689 if (aAbs.aEnd.Row() > nRow2) 3690 aAbs.aEnd.SetRow(nRow2); 3691 SCROW nMyRow; 3692 if ( aPos.Col() == nStartCol 3693 && nStartRow <= (nMyRow = aPos.Row()) && nMyRow <= aAbs.aEnd.Row()) 3694 { //Formula in the same column and within the range 3695 if ( nMyRow == nStartRow ) 3696 { // take the rest under the name 3697 nStartRow++; 3698 if ( nStartRow > MAXROW ) 3699 nStartRow = MAXROW; 3700 aAbs.aStart.SetRow(nStartRow); 3701 } 3702 else 3703 { // below the name to the formula cell 3704 aAbs.aEnd.SetRow(nMyRow - 1); 3705 } 3706 } 3707 } 3708 else 3709 { // RowName 3710 aAbs.aEnd.SetRow(nStartRow); 3711 // maybe get previous limit by using defined ColRowNameRange 3712 if (aAbs.aEnd.Col() > nCol2) 3713 aAbs.aEnd.SetCol(nCol2); 3714 SCCOL nMyCol; 3715 if ( aPos.Row() == nStartRow 3716 && nStartCol <= (nMyCol = aPos.Col()) && nMyCol <= aAbs.aEnd.Col()) 3717 { //Formula in the same column and within the range 3718 if ( nMyCol == nStartCol ) 3719 { // take the rest under the name 3720 nStartCol++; 3721 if ( nStartCol > MAXCOL ) 3722 nStartCol = MAXCOL; 3723 aAbs.aStart.SetCol(nStartCol); 3724 } 3725 else 3726 { // below the name to the formula cell 3727 aAbs.aEnd.SetCol(nMyCol - 1); 3728 } 3729 } 3730 } 3731 aRefData.SetRange(aAbs, aPos); 3732 PushTempToken( new ScDoubleRefToken( aRefData ) ); 3733 } 3734 3735 // --- internals ------------------------------------------------------------ 3736 3737 void ScInterpreter::ScTTT() 3738 { // temporary test, testing functions etc. 3739 sal_uInt8 nParamCount = GetByte(); 3740 // do something, count down nParamCount with Pops! 3741 3742 // clean up Stack 3743 while ( nParamCount-- > 0) 3744 Pop(); 3745 PushError(FormulaError::NoValue); 3746 } 3747 3748 ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, ScInterpreterContext& rContext, 3749 const ScAddress& rPos, ScTokenArray& r ) 3750 : aCode(r) 3751 , aPos(rPos) 3752 , rArr(r) 3753 , mrContext(rContext) 3754 , pDok(pDoc) 3755 , mpLinkManager(pDok->GetLinkManager()) 3756 , mrStrPool(pDoc->GetSharedStringPool()) 3757 , pJumpMatrix(nullptr) 3758 , pMyFormulaCell(pCell) 3759 , pFormatter(rContext.GetFormatTable()) 3760 , pCur(nullptr) 3761 , nGlobalError(FormulaError::NONE) 3762 , sp(0) 3763 , maxsp(0) 3764 , nFuncFmtIndex(0) 3765 , nCurFmtIndex(0) 3766 , nRetFmtIndex(0) 3767 , nFuncFmtType(SvNumFormatType::ALL) 3768 , nCurFmtType(SvNumFormatType::ALL) 3769 , nRetFmtType(SvNumFormatType::ALL) 3770 , mnStringNoValueError(FormulaError::NoValue) 3771 , mnSubTotalFlags(SubtotalFlags::NONE) 3772 , cPar(0) 3773 , bCalcAsShown(pDoc->GetDocOptions().IsCalcAsShown()) 3774 , meVolatileType(r.IsRecalcModeAlways() ? VOLATILE : NOT_VOLATILE) 3775 { 3776 MergeCalcConfig(); 3777 3778 if(pMyFormulaCell) 3779 { 3780 ScMatrixMode cMatFlag = pMyFormulaCell->GetMatrixFlag(); 3781 bMatrixFormula = ( cMatFlag == ScMatrixMode::Formula ); 3782 } 3783 else 3784 bMatrixFormula = false; 3785 3786 if (!bGlobalStackInUse) 3787 { 3788 bGlobalStackInUse = true; 3789 if (!pGlobalStack) 3790 pGlobalStack.reset(new ScTokenStack); 3791 pStackObj = pGlobalStack.get(); 3792 } 3793 else 3794 { 3795 pStackObj = new ScTokenStack; 3796 } 3797 pStack = pStackObj->pPointer; 3798 } 3799 3800 ScInterpreter::~ScInterpreter() 3801 { 3802 if ( pStackObj == pGlobalStack.get() ) 3803 bGlobalStackInUse = false; 3804 else 3805 delete pStackObj; 3806 } 3807 3808 ScCalcConfig& ScInterpreter::GetOrCreateGlobalConfig() 3809 { 3810 if (!mpGlobalConfig) 3811 mpGlobalConfig = new ScCalcConfig(); 3812 return *mpGlobalConfig; 3813 } 3814 3815 void ScInterpreter::SetGlobalConfig(const ScCalcConfig& rConfig) 3816 { 3817 GetOrCreateGlobalConfig() = rConfig; 3818 } 3819 3820 const ScCalcConfig& ScInterpreter::GetGlobalConfig() 3821 { 3822 return GetOrCreateGlobalConfig(); 3823 } 3824 3825 void ScInterpreter::MergeCalcConfig() 3826 { 3827 maCalcConfig = GetOrCreateGlobalConfig(); 3828 maCalcConfig.MergeDocumentSpecific( pDok->GetCalcConfig()); 3829 } 3830 3831 void ScInterpreter::GlobalExit() 3832 { 3833 OSL_ENSURE(!bGlobalStackInUse, "who is still using the TokenStack?"); 3834 pGlobalStack.reset(); 3835 } 3836 3837 namespace { 3838 3839 double applyImplicitIntersection(const sc::RangeMatrix& rMat, const ScAddress& rPos) 3840 { 3841 if (rMat.mnRow1 <= rPos.Row() && rPos.Row() <= rMat.mnRow2 && rMat.mnCol1 == rMat.mnCol2) 3842 { 3843 SCROW nOffset = rPos.Row() - rMat.mnRow1; 3844 return rMat.mpMat->GetDouble(0, nOffset); 3845 } 3846 3847 if (rMat.mnCol1 <= rPos.Col() && rPos.Col() <= rMat.mnCol2 && rMat.mnRow1 == rMat.mnRow2) 3848 { 3849 SCROW nOffset = rPos.Col() - rMat.mnCol1; 3850 return rMat.mpMat->GetDouble(nOffset, 0); 3851 } 3852 3853 double fVal; 3854 rtl::math::setNan(&fVal); 3855 return fVal; 3856 } 3857 3858 // Test for Functions that evaluate an error code and directly set nGlobalError to 0 3859 bool IsErrFunc(OpCode oc) 3860 { 3861 switch (oc) 3862 { 3863 case ocCount : 3864 case ocCount2 : 3865 case ocErrorType : 3866 case ocIsEmpty : 3867 case ocIsErr : 3868 case ocIsError : 3869 case ocIsFormula : 3870 case ocIsLogical : 3871 case ocIsNA : 3872 case ocIsNonString : 3873 case ocIsRef : 3874 case ocIsString : 3875 case ocIsValue : 3876 case ocN : 3877 case ocType : 3878 case ocIfError : 3879 case ocIfNA : 3880 case ocErrorType_ODF : 3881 case ocIfs_MS: 3882 case ocSwitch_MS: 3883 return true; 3884 default: 3885 return false; 3886 } 3887 } 3888 3889 } //namespace 3890 3891 StackVar ScInterpreter::Interpret() 3892 { 3893 SvNumFormatType nRetTypeExpr = SvNumFormatType::UNDEFINED; 3894 sal_uInt32 nRetIndexExpr = 0; 3895 sal_uInt16 nErrorFunction = 0; 3896 sal_uInt16 nErrorFunctionCount = 0; 3897 std::vector<sal_uInt16> aErrorFunctionStack; 3898 sal_uInt16 nStackBase; 3899 3900 nGlobalError = FormulaError::NONE; 3901 nStackBase = sp = maxsp = 0; 3902 nRetFmtType = SvNumFormatType::UNDEFINED; 3903 nFuncFmtType = SvNumFormatType::UNDEFINED; 3904 nFuncFmtIndex = nCurFmtIndex = nRetFmtIndex = 0; 3905 xResult = nullptr; 3906 pJumpMatrix = nullptr; 3907 mnSubTotalFlags = SubtotalFlags::NONE; 3908 ScTokenMatrixMap::const_iterator aTokenMatrixMapIter; 3909 3910 // Once upon a time we used to have FP exceptions on, and there was a 3911 // Windows printer driver that kept switching off exceptions, so we had to 3912 // switch them back on again every time. Who knows if there isn't a driver 3913 // that keeps switching exceptions on, now that we run with exceptions off, 3914 // so reassure exceptions are really off. 3915 SAL_MATH_FPEXCEPTIONS_OFF(); 3916 3917 OpCode eOp = ocNone; 3918 aCode.Reset(); 3919 while( ( pCur = aCode.Next() ) != nullptr 3920 && (nGlobalError == FormulaError::NONE || nErrorFunction <= nErrorFunctionCount) ) 3921 { 3922 eOp = pCur->GetOpCode(); 3923 cPar = pCur->GetByte(); 3924 if ( eOp == ocPush ) 3925 { 3926 // RPN code push without error 3927 PushWithoutError( *pCur ); 3928 nCurFmtType = SvNumFormatType::UNDEFINED; 3929 } 3930 else if (pTokenMatrixMap && 3931 !FormulaCompiler::IsOpCodeJumpCommand( eOp ) && 3932 ((aTokenMatrixMapIter = pTokenMatrixMap->find( pCur)) != 3933 pTokenMatrixMap->end()) && 3934 (*aTokenMatrixMapIter).second->GetType() != svJumpMatrix) 3935 { 3936 // Path already calculated, reuse result. 3937 nStackBase = sp - pCur->GetParamCount(); 3938 if ( nStackBase > sp ) 3939 nStackBase = sp; // underflow?!? 3940 sp = nStackBase; 3941 PushTokenRef( (*aTokenMatrixMapIter).second); 3942 } 3943 else 3944 { 3945 // previous expression determines the current number format 3946 nCurFmtType = nRetTypeExpr; 3947 nCurFmtIndex = nRetIndexExpr; 3948 // default function's format, others are set if needed 3949 nFuncFmtType = SvNumFormatType::NUMBER; 3950 nFuncFmtIndex = 0; 3951 3952 if (FormulaCompiler::IsOpCodeJumpCommand( eOp )) 3953 nStackBase = sp; // don't mess around with the jumps 3954 else 3955 { 3956 // Convert parameters to matrix if in array/matrix formula and 3957 // parameters of function indicate doing so. Create JumpMatrix 3958 // if necessary. 3959 if ( MatrixParameterConversion() ) 3960 { 3961 eOp = ocNone; // JumpMatrix created 3962 nStackBase = sp; 3963 } 3964 else if (sp >= pCur->GetParamCount()) 3965 nStackBase = sp - pCur->GetParamCount(); 3966 else 3967 nStackBase = sp; // underflow?!? 3968 } 3969 3970 switch( eOp ) 3971 { 3972 case ocSep: 3973 case ocClose: // pushed by the compiler 3974 case ocMissing : ScMissing(); break; 3975 case ocMacro : ScMacro(); break; 3976 case ocDBArea : ScDBArea(); break; 3977 case ocColRowNameAuto : ScColRowNameAuto(); break; 3978 case ocIf : ScIfJump(); break; 3979 case ocIfError : ScIfError( false ); break; 3980 case ocIfNA : ScIfError( true ); break; 3981 case ocChoose : ScChooseJump(); break; 3982 case ocAdd : ScAdd(); break; 3983 case ocSub : ScSub(); break; 3984 case ocMul : ScMul(); break; 3985 case ocDiv : ScDiv(); break; 3986 case ocAmpersand : ScAmpersand(); break; 3987 case ocPow : ScPow(); break; 3988 case ocEqual : ScEqual(); break; 3989 case ocNotEqual : ScNotEqual(); break; 3990 case ocLess : ScLess(); break; 3991 case ocGreater : ScGreater(); break; 3992 case ocLessEqual : ScLessEqual(); break; 3993 case ocGreaterEqual : ScGreaterEqual(); break; 3994 case ocAnd : ScAnd(); break; 3995 case ocOr : ScOr(); break; 3996 case ocXor : ScXor(); break; 3997 case ocIntersect : ScIntersect(); break; 3998 case ocRange : ScRangeFunc(); break; 3999 case ocUnion : ScUnionFunc(); break; 4000 case ocNot : ScNot(); break; 4001 case ocNegSub : 4002 case ocNeg : ScNeg(); break; 4003 case ocPercentSign : ScPercentSign(); break; 4004 case ocPi : ScPi(); break; 4005 case ocRandom : ScRandom(); break; 4006 case ocTrue : ScTrue(); break; 4007 case ocFalse : ScFalse(); break; 4008 case ocGetActDate : ScGetActDate(); break; 4009 case ocGetActTime : ScGetActTime(); break; 4010 case ocNotAvail : PushError( FormulaError::NotAvailable); break; 4011 case ocDeg : ScDeg(); break; 4012 case ocRad : ScRad(); break; 4013 case ocSin : ScSin(); break; 4014 case ocCos : ScCos(); break; 4015 case ocTan : ScTan(); break; 4016 case ocCot : ScCot(); break; 4017 case ocArcSin : ScArcSin(); break; 4018 case ocArcCos : ScArcCos(); break; 4019 case ocArcTan : ScArcTan(); break; 4020 case ocArcCot : ScArcCot(); break; 4021 case ocSinHyp : ScSinHyp(); break; 4022 case ocCosHyp : ScCosHyp(); break; 4023 case ocTanHyp : ScTanHyp(); break; 4024 case ocCotHyp : ScCotHyp(); break; 4025 case ocArcSinHyp : ScArcSinHyp(); break; 4026 case ocArcCosHyp : ScArcCosHyp(); break; 4027 case ocArcTanHyp : ScArcTanHyp(); break; 4028 case ocArcCotHyp : ScArcCotHyp(); break; 4029 case ocCosecant : ScCosecant(); break; 4030 case ocSecant : ScSecant(); break; 4031 case ocCosecantHyp : ScCosecantHyp(); break; 4032 case ocSecantHyp : ScSecantHyp(); break; 4033 case ocExp : ScExp(); break; 4034 case ocLn : ScLn(); break; 4035 case ocLog10 : ScLog10(); break; 4036 case ocSqrt : ScSqrt(); break; 4037 case ocFact : ScFact(); break; 4038 case ocGetYear : ScGetYear(); break; 4039 case ocGetMonth : ScGetMonth(); break; 4040 case ocGetDay : ScGetDay(); break; 4041 case ocGetDayOfWeek : ScGetDayOfWeek(); break; 4042 case ocWeek : ScGetWeekOfYear(); break; 4043 case ocIsoWeeknum : ScGetIsoWeekOfYear(); break; 4044 case ocWeeknumOOo : ScWeeknumOOo(); break; 4045 case ocEasterSunday : ScEasterSunday(); break; 4046 case ocNetWorkdays : ScNetWorkdays( false); break; 4047 case ocNetWorkdays_MS : ScNetWorkdays( true ); break; 4048 case ocWorkday_MS : ScWorkday_MS(); break; 4049 case ocGetHour : ScGetHour(); break; 4050 case ocGetMin : ScGetMin(); break; 4051 case ocGetSec : ScGetSec(); break; 4052 case ocPlusMinus : ScPlusMinus(); break; 4053 case ocAbs : ScAbs(); break; 4054 case ocInt : ScInt(); break; 4055 case ocEven : ScEven(); break; 4056 case ocOdd : ScOdd(); break; 4057 case ocPhi : ScPhi(); break; 4058 case ocGauss : ScGauss(); break; 4059 case ocStdNormDist : ScStdNormDist(); break; 4060 case ocStdNormDist_MS : ScStdNormDist_MS(); break; 4061 case ocFisher : ScFisher(); break; 4062 case ocFisherInv : ScFisherInv(); break; 4063 case ocIsEmpty : ScIsEmpty(); break; 4064 case ocIsString : ScIsString(); break; 4065 case ocIsNonString : ScIsNonString(); break; 4066 case ocIsLogical : ScIsLogical(); break; 4067 case ocType : ScType(); break; 4068 case ocCell : ScCell(); break; 4069 case ocIsRef : ScIsRef(); break; 4070 case ocIsValue : ScIsValue(); break; 4071 case ocIsFormula : ScIsFormula(); break; 4072 case ocFormula : ScFormula(); break; 4073 case ocIsNA : ScIsNV(); break; 4074 case ocIsErr : ScIsErr(); break; 4075 case ocIsError : ScIsError(); break; 4076 case ocIsEven : ScIsEven(); break; 4077 case ocIsOdd : ScIsOdd(); break; 4078 case ocN : ScN(); break; 4079 case ocGetDateValue : ScGetDateValue(); break; 4080 case ocGetTimeValue : ScGetTimeValue(); break; 4081 case ocCode : ScCode(); break; 4082 case ocTrim : ScTrim(); break; 4083 case ocUpper : ScUpper(); break; 4084 case ocProper : ScProper(); break; 4085 case ocLower : ScLower(); break; 4086 case ocLen : ScLen(); break; 4087 case ocT : ScT(); break; 4088 case ocClean : ScClean(); break; 4089 case ocValue : ScValue(); break; 4090 case ocNumberValue : ScNumberValue(); break; 4091 case ocChar : ScChar(); break; 4092 case ocArcTan2 : ScArcTan2(); break; 4093 case ocMod : ScMod(); break; 4094 case ocPower : ScPower(); break; 4095 case ocRound : ScRound(); break; 4096 case ocRoundSig : ScRoundSignificant(); break; 4097 case ocRoundUp : ScRoundUp(); break; 4098 case ocTrunc : 4099 case ocRoundDown : ScRoundDown(); break; 4100 case ocCeil : ScCeil( true ); break; 4101 case ocCeil_MS : ScCeil_MS(); break; 4102 case ocCeil_Precise : 4103 case ocCeil_ISO : ScCeil_Precise(); break; 4104 case ocCeil_Math : ScCeil( false ); break; 4105 case ocFloor : ScFloor( true ); break; 4106 case ocFloor_MS : ScFloor_MS(); break; 4107 case ocFloor_Precise : ScFloor_Precise(); break; 4108 case ocFloor_Math : ScFloor( false ); break; 4109 case ocSumProduct : ScSumProduct(); break; 4110 case ocSumSQ : ScSumSQ(); break; 4111 case ocSumX2MY2 : ScSumX2MY2(); break; 4112 case ocSumX2DY2 : ScSumX2DY2(); break; 4113 case ocSumXMY2 : ScSumXMY2(); break; 4114 case ocRawSubtract : ScRawSubtract(); break; 4115 case ocLog : ScLog(); break; 4116 case ocGCD : ScGCD(); break; 4117 case ocLCM : ScLCM(); break; 4118 case ocGetDate : ScGetDate(); break; 4119 case ocGetTime : ScGetTime(); break; 4120 case ocGetDiffDate : ScGetDiffDate(); break; 4121 case ocGetDiffDate360 : ScGetDiffDate360(); break; 4122 case ocGetDateDif : ScGetDateDif(); break; 4123 case ocMin : ScMin() ; break; 4124 case ocMinA : ScMin( true ); break; 4125 case ocMax : ScMax(); break; 4126 case ocMaxA : ScMax( true ); break; 4127 case ocSum : ScSum(); break; 4128 case ocProduct : ScProduct(); break; 4129 case ocNPV : ScNPV(); break; 4130 case ocIRR : ScIRR(); break; 4131 case ocMIRR : ScMIRR(); break; 4132 case ocISPMT : ScISPMT(); break; 4133 case ocAverage : ScAverage() ; break; 4134 case ocAverageA : ScAverage( true ); break; 4135 case ocCount : ScCount(); break; 4136 case ocCount2 : ScCount2(); break; 4137 case ocVar : 4138 case ocVarS : ScVar(); break; 4139 case ocVarA : ScVar( true ); break; 4140 case ocVarP : 4141 case ocVarP_MS : ScVarP(); break; 4142 case ocVarPA : ScVarP( true ); break; 4143 case ocStDev : 4144 case ocStDevS : ScStDev(); break; 4145 case ocStDevA : ScStDev( true ); break; 4146 case ocStDevP : 4147 case ocStDevP_MS : ScStDevP(); break; 4148 case ocStDevPA : ScStDevP( true ); break; 4149 case ocPV : ScPV(); break; 4150 case ocSYD : ScSYD(); break; 4151 case ocDDB : ScDDB(); break; 4152 case ocDB : ScDB(); break; 4153 case ocVBD : ScVDB(); break; 4154 case ocPDuration : ScPDuration(); break; 4155 case ocSLN : ScSLN(); break; 4156 case ocPMT : ScPMT(); break; 4157 case ocColumns : ScColumns(); break; 4158 case ocRows : ScRows(); break; 4159 case ocSheets : ScSheets(); break; 4160 case ocColumn : ScColumn(); break; 4161 case ocRow : ScRow(); break; 4162 case ocSheet : ScSheet(); break; 4163 case ocRRI : ScRRI(); break; 4164 case ocFV : ScFV(); break; 4165 case ocNper : ScNper(); break; 4166 case ocRate : ScRate(); break; 4167 case ocFilterXML : ScFilterXML(); break; 4168 case ocWebservice : ScWebservice(); break; 4169 case ocEncodeURL : ScEncodeURL(); break; 4170 case ocColor : ScColor(); break; 4171 case ocErf_MS : ScErf(); break; 4172 case ocErfc_MS : ScErfc(); break; 4173 case ocIpmt : ScIpmt(); break; 4174 case ocPpmt : ScPpmt(); break; 4175 case ocCumIpmt : ScCumIpmt(); break; 4176 case ocCumPrinc : ScCumPrinc(); break; 4177 case ocEffect : ScEffect(); break; 4178 case ocNominal : ScNominal(); break; 4179 case ocSubTotal : ScSubTotal(); break; 4180 case ocAggregate : ScAggregate(); break; 4181 case ocDBSum : ScDBSum(); break; 4182 case ocDBCount : ScDBCount(); break; 4183 case ocDBCount2 : ScDBCount2(); break; 4184 case ocDBAverage : ScDBAverage(); break; 4185 case ocDBGet : ScDBGet(); break; 4186 case ocDBMax : ScDBMax(); break; 4187 case ocDBMin : ScDBMin(); break; 4188 case ocDBProduct : ScDBProduct(); break; 4189 case ocDBStdDev : ScDBStdDev(); break; 4190 case ocDBStdDevP : ScDBStdDevP(); break; 4191 case ocDBVar : ScDBVar(); break; 4192 case ocDBVarP : ScDBVarP(); break; 4193 case ocIndirect : ScIndirect(); break; 4194 case ocAddress : ScAddressFunc(); break; 4195 case ocMatch : ScMatch(); break; 4196 case ocCountEmptyCells : ScCountEmptyCells(); break; 4197 case ocCountIf : ScCountIf(); break; 4198 case ocSumIf : ScSumIf(); break; 4199 case ocAverageIf : ScAverageIf(); break; 4200 case ocSumIfs : ScSumIfs(); break; 4201 case ocAverageIfs : ScAverageIfs(); break; 4202 case ocCountIfs : ScCountIfs(); break; 4203 case ocLookup : ScLookup(); break; 4204 case ocVLookup : ScVLookup(); break; 4205 case ocHLookup : ScHLookup(); break; 4206 case ocIndex : ScIndex(); break; 4207 case ocMultiArea : ScMultiArea(); break; 4208 case ocOffset : ScOffset(); break; 4209 case ocAreas : ScAreas(); break; 4210 case ocCurrency : ScCurrency(); break; 4211 case ocReplace : ScReplace(); break; 4212 case ocFixed : ScFixed(); break; 4213 case ocFind : ScFind(); break; 4214 case ocExact : ScExact(); break; 4215 case ocLeft : ScLeft(); break; 4216 case ocRight : ScRight(); break; 4217 case ocSearch : ScSearch(); break; 4218 case ocMid : ScMid(); break; 4219 case ocText : ScText(); break; 4220 case ocSubstitute : ScSubstitute(); break; 4221 case ocRegex : ScRegex(); break; 4222 case ocRept : ScRept(); break; 4223 case ocConcat : ScConcat(); break; 4224 case ocConcat_MS : ScConcat_MS(); break; 4225 case ocTextJoin_MS : ScTextJoin_MS(); break; 4226 case ocIfs_MS : ScIfs_MS(); break; 4227 case ocSwitch_MS : ScSwitch_MS(); break; 4228 case ocMinIfs_MS : ScMinIfs_MS(); break; 4229 case ocMaxIfs_MS : ScMaxIfs_MS(); break; 4230 case ocMatValue : ScMatValue(); break; 4231 case ocMatrixUnit : ScEMat(); break; 4232 case ocMatDet : ScMatDet(); break; 4233 case ocMatInv : ScMatInv(); break; 4234 case ocMatMult : ScMatMult(); break; 4235 case ocMatTrans : ScMatTrans(); break; 4236 case ocMatRef : ScMatRef(); break; 4237 case ocB : ScB(); break; 4238 case ocNormDist : ScNormDist( 3 ); break; 4239 case ocNormDist_MS : ScNormDist( 4 ); break; 4240 case ocExpDist : 4241 case ocExpDist_MS : ScExpDist(); break; 4242 case ocBinomDist : 4243 case ocBinomDist_MS : ScBinomDist(); break; 4244 case ocPoissonDist : ScPoissonDist( true ); break; 4245 case ocPoissonDist_MS : ScPoissonDist( false ); break; 4246 case ocCombin : ScCombin(); break; 4247 case ocCombinA : ScCombinA(); break; 4248 case ocPermut : ScPermut(); break; 4249 case ocPermutationA : ScPermutationA(); break; 4250 case ocHypGeomDist : ScHypGeomDist( 4 ); break; 4251 case ocHypGeomDist_MS : ScHypGeomDist( 5 ); break; 4252 case ocLogNormDist : ScLogNormDist( 1 ); break; 4253 case ocLogNormDist_MS : ScLogNormDist( 4 ); break; 4254 case ocTDist : ScTDist(); break; 4255 case ocTDist_MS : ScTDist_MS(); break; 4256 case ocTDist_RT : ScTDist_T( 1 ); break; 4257 case ocTDist_2T : ScTDist_T( 2 ); break; 4258 case ocFDist : 4259 case ocFDist_RT : ScFDist(); break; 4260 case ocFDist_LT : ScFDist_LT(); break; 4261 case ocChiDist : ScChiDist( true ); break; 4262 case ocChiDist_MS : ScChiDist( false ); break; 4263 case ocChiSqDist : ScChiSqDist(); break; 4264 case ocChiSqDist_MS : ScChiSqDist_MS(); break; 4265 case ocStandard : ScStandard(); break; 4266 case ocAveDev : ScAveDev(); break; 4267 case ocDevSq : ScDevSq(); break; 4268 case ocKurt : ScKurt(); break; 4269 case ocSkew : ScSkew(); break; 4270 case ocSkewp : ScSkewp(); break; 4271 case ocModalValue : ScModalValue(); break; 4272 case ocModalValue_MS : ScModalValue_MS( true ); break; 4273 case ocModalValue_Multi : ScModalValue_MS( false ); break; 4274 case ocMedian : ScMedian(); break; 4275 case ocGeoMean : ScGeoMean(); break; 4276 case ocHarMean : ScHarMean(); break; 4277 case ocWeibull : 4278 case ocWeibull_MS : ScWeibull(); break; 4279 case ocBinomInv : 4280 case ocCritBinom : ScCritBinom(); break; 4281 case ocNegBinomVert : ScNegBinomDist(); break; 4282 case ocNegBinomDist_MS : ScNegBinomDist_MS(); break; 4283 case ocNoName : ScNoName(); break; 4284 case ocBad : ScBadName(); break; 4285 case ocZTest : 4286 case ocZTest_MS : ScZTest(); break; 4287 case ocTTest : 4288 case ocTTest_MS : ScTTest(); break; 4289 case ocFTest : 4290 case ocFTest_MS : ScFTest(); break; 4291 case ocRank : 4292 case ocRank_Eq : ScRank( false ); break; 4293 case ocRank_Avg : ScRank( true ); break; 4294 case ocPercentile : 4295 case ocPercentile_Inc : ScPercentile( true ); break; 4296 case ocPercentile_Exc : ScPercentile( false ); break; 4297 case ocPercentrank : 4298 case ocPercentrank_Inc : ScPercentrank( true ); break; 4299 case ocPercentrank_Exc : ScPercentrank( false ); break; 4300 case ocLarge : ScLarge(); break; 4301 case ocSmall : ScSmall(); break; 4302 case ocFrequency : ScFrequency(); break; 4303 case ocQuartile : 4304 case ocQuartile_Inc : ScQuartile( true ); break; 4305 case ocQuartile_Exc : ScQuartile( false ); break; 4306 case ocNormInv : 4307 case ocNormInv_MS : ScNormInv(); break; 4308 case ocSNormInv : 4309 case ocSNormInv_MS : ScSNormInv(); break; 4310 case ocConfidence : 4311 case ocConfidence_N : ScConfidence(); break; 4312 case ocConfidence_T : ScConfidenceT(); break; 4313 case ocTrimMean : ScTrimMean(); break; 4314 case ocProb : ScProbability(); break; 4315 case ocCorrel : ScCorrel(); break; 4316 case ocCovar : 4317 case ocCovarianceP : ScCovarianceP(); break; 4318 case ocCovarianceS : ScCovarianceS(); break; 4319 case ocPearson : ScPearson(); break; 4320 case ocRSQ : ScRSQ(); break; 4321 case ocSTEYX : ScSTEYX(); break; 4322 case ocSlope : ScSlope(); break; 4323 case ocIntercept : ScIntercept(); break; 4324 case ocTrend : ScTrend(); break; 4325 case ocGrowth : ScGrowth(); break; 4326 case ocLinest : ScLinest(); break; 4327 case ocLogest : ScLogest(); break; 4328 case ocForecast_LIN : 4329 case ocForecast : ScForecast(); break; 4330 case ocForecast_ETS_ADD : ScForecast_Ets( etsAdd ); break; 4331 case ocForecast_ETS_SEA : ScForecast_Ets( etsSeason ); break; 4332 case ocForecast_ETS_MUL : ScForecast_Ets( etsMult ); break; 4333 case ocForecast_ETS_PIA : ScForecast_Ets( etsPIAdd ); break; 4334 case ocForecast_ETS_PIM : ScForecast_Ets( etsPIMult ); break; 4335 case ocForecast_ETS_STA : ScForecast_Ets( etsStatAdd ); break; 4336 case ocForecast_ETS_STM : ScForecast_Ets( etsStatMult ); break; 4337 case ocGammaLn : 4338 case ocGammaLn_MS : ScLogGamma(); break; 4339 case ocGamma : ScGamma(); break; 4340 case ocGammaDist : ScGammaDist( true ); break; 4341 case ocGammaDist_MS : ScGammaDist( false ); break; 4342 case ocGammaInv : 4343 case ocGammaInv_MS : ScGammaInv(); break; 4344 case ocChiTest : 4345 case ocChiTest_MS : ScChiTest(); break; 4346 case ocChiInv : 4347 case ocChiInv_MS : ScChiInv(); break; 4348 case ocChiSqInv : 4349 case ocChiSqInv_MS : ScChiSqInv(); break; 4350 case ocTInv : 4351 case ocTInv_2T : ScTInv( 2 ); break; 4352 case ocTInv_MS : ScTInv( 4 ); break; 4353 case ocFInv : 4354 case ocFInv_RT : ScFInv(); break; 4355 case ocFInv_LT : ScFInv_LT(); break; 4356 case ocLogInv : 4357 case ocLogInv_MS : ScLogNormInv(); break; 4358 case ocBetaDist : ScBetaDist(); break; 4359 case ocBetaDist_MS : ScBetaDist_MS(); break; 4360 case ocBetaInv : 4361 case ocBetaInv_MS : ScBetaInv(); break; 4362 case ocExternal : ScExternal(); break; 4363 case ocTableOp : ScTableOp(); break; 4364 case ocStop : break; 4365 case ocErrorType : ScErrorType(); break; 4366 case ocErrorType_ODF : ScErrorType_ODF(); break; 4367 case ocCurrent : ScCurrent(); break; 4368 case ocStyle : ScStyle(); break; 4369 case ocDde : ScDde(); break; 4370 case ocBase : ScBase(); break; 4371 case ocDecimal : ScDecimal(); break; 4372 case ocConvertOOo : ScConvertOOo(); break; 4373 case ocEuroConvert : ScEuroConvert(); break; 4374 case ocRoman : ScRoman(); break; 4375 case ocArabic : ScArabic(); break; 4376 case ocInfo : ScInfo(); break; 4377 case ocHyperLink : ScHyperLink(); break; 4378 case ocBahtText : ScBahtText(); break; 4379 case ocGetPivotData : ScGetPivotData(); break; 4380 case ocJis : ScJis(); break; 4381 case ocAsc : ScAsc(); break; 4382 case ocLenB : ScLenB(); break; 4383 case ocRightB : ScRightB(); break; 4384 case ocLeftB : ScLeftB(); break; 4385 case ocMidB : ScMidB(); break; 4386 case ocReplaceB : ScReplaceB(); break; 4387 case ocFindB : ScFindB(); break; 4388 case ocSearchB : ScSearchB(); break; 4389 case ocUnicode : ScUnicode(); break; 4390 case ocUnichar : ScUnichar(); break; 4391 case ocBitAnd : ScBitAnd(); break; 4392 case ocBitOr : ScBitOr(); break; 4393 case ocBitXor : ScBitXor(); break; 4394 case ocBitRshift : ScBitRshift(); break; 4395 case ocBitLshift : ScBitLshift(); break; 4396 case ocTTT : ScTTT(); break; 4397 case ocDebugVar : ScDebugVar(); break; 4398 case ocNone : nFuncFmtType = SvNumFormatType::UNDEFINED; break; 4399 default : PushError( FormulaError::UnknownOpCode); break; 4400 } 4401 4402 // If the function pushed a subroutine as result, continue with 4403 // execution of the subroutine. 4404 if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall) 4405 { 4406 Pop(); continue; 4407 } 4408 4409 if (FormulaCompiler::IsOpCodeVolatile(eOp)) 4410 meVolatileType = VOLATILE; 4411 4412 // Remember result matrix in case it could be reused. 4413 if (pTokenMatrixMap && sp && GetStackType() == svMatrix) 4414 pTokenMatrixMap->emplace(pCur, pStack[sp-1]); 4415 4416 // outer function determines format of an expression 4417 if ( nFuncFmtType != SvNumFormatType::UNDEFINED ) 4418 { 4419 nRetTypeExpr = nFuncFmtType; 4420 // Inherit the format index for currency, date or time formats. 4421 switch (nFuncFmtType) 4422 { 4423 case SvNumFormatType::CURRENCY: 4424 case SvNumFormatType::DATE: 4425 case SvNumFormatType::TIME: 4426 case SvNumFormatType::DATETIME: 4427 nRetIndexExpr = nFuncFmtIndex; 4428 break; 4429 default: 4430 nRetIndexExpr = 0; 4431 } 4432 } 4433 } 4434 4435 // Need a clean stack environment for the JumpMatrix to work. 4436 if (nGlobalError != FormulaError::NONE && eOp != ocPush && sp > nStackBase + 1) 4437 { 4438 // Not all functions pop all parameters in case an error is 4439 // generated. Clean up stack. Assumes that every function pushes a 4440 // result, may be arbitrary in case of error. 4441 FormulaConstTokenRef xLocalResult = pStack[ sp - 1 ]; 4442 while (sp > nStackBase) 4443 Pop(); 4444 PushTokenRef( xLocalResult ); 4445 } 4446 4447 bool bGotResult; 4448 do 4449 { 4450 bGotResult = false; 4451 sal_uInt8 nLevel = 0; 4452 if ( GetStackType( ++nLevel ) == svJumpMatrix ) 4453 ; // nothing 4454 else if ( GetStackType( ++nLevel ) == svJumpMatrix ) 4455 ; // nothing 4456 else 4457 nLevel = 0; 4458 if ( nLevel == 1 || (nLevel == 2 && aCode.IsEndOfPath()) ) 4459 { 4460 if (nLevel == 1) 4461 aErrorFunctionStack.push_back( nErrorFunction); 4462 bGotResult = JumpMatrix( nLevel ); 4463 if (aErrorFunctionStack.empty()) 4464 assert(!"ScInterpreter::Interpret - aErrorFunctionStack empty in JumpMatrix context"); 4465 else 4466 { 4467 nErrorFunction = aErrorFunctionStack.back(); 4468 if (bGotResult) 4469 aErrorFunctionStack.pop_back(); 4470 } 4471 } 4472 else 4473 pJumpMatrix = nullptr; 4474 } while ( bGotResult ); 4475 4476 if( IsErrFunc(eOp) ) 4477 ++nErrorFunction; 4478 4479 if ( nGlobalError != FormulaError::NONE ) 4480 { 4481 if ( !nErrorFunctionCount ) 4482 { // count of errorcode functions in formula 4483 FormulaTokenArrayPlainIterator aIter(rArr); 4484 for ( FormulaToken* t = aIter.FirstRPN(); t; t = aIter.NextRPN() ) 4485 { 4486 if ( IsErrFunc(t->GetOpCode()) ) 4487 ++nErrorFunctionCount; 4488 } 4489 } 4490 if ( nErrorFunction >= nErrorFunctionCount ) 4491 ++nErrorFunction; // that's it, error => terminate 4492 } 4493 } 4494 4495 // End: obtain result 4496 4497 bool bForcedResultType; 4498 switch (eOp) 4499 { 4500 case ocGetDateValue: 4501 case ocGetTimeValue: 4502 // Force final result of DATEVALUE and TIMEVALUE to number type, 4503 // which so far was date or time for calculations. 4504 nRetTypeExpr = nFuncFmtType = SvNumFormatType::NUMBER; 4505 nRetIndexExpr = nFuncFmtIndex = 0; 4506 bForcedResultType = true; 4507 break; 4508 default: 4509 bForcedResultType = false; 4510 } 4511 4512 if (sp == 1) 4513 { 4514 pCur = pStack[ sp-1 ]; 4515 if( pCur->GetOpCode() == ocPush ) 4516 { 4517 // An svRefList can be resolved if it a) contains just one 4518 // reference, or b) in array context contains an array of single 4519 // cell references. 4520 if (pCur->GetType() == svRefList) 4521 { 4522 PopRefListPushMatrixOrRef(); 4523 pCur = pStack[ sp-1 ]; 4524 } 4525 switch( pCur->GetType() ) 4526 { 4527 case svEmptyCell: 4528 ; // nothing 4529 break; 4530 case svError: 4531 nGlobalError = pCur->GetError(); 4532 break; 4533 case svDouble : 4534 { 4535 // If typed, pop token to obtain type information and 4536 // push a plain untyped double so the result token to 4537 // be transferred to the formula cell result does not 4538 // unnecessarily duplicate the information. 4539 if (pCur->GetDoubleType() != 0) 4540 { 4541 const double fVal = PopDouble(); 4542 if (!bForcedResultType) 4543 { 4544 if (nCurFmtType != nFuncFmtType) 4545 nRetIndexExpr = 0; // carry format index only for matching type 4546 nRetTypeExpr = nFuncFmtType = nCurFmtType; 4547 } 4548 PushTempToken( CreateFormulaDoubleToken( fVal)); 4549 } 4550 if ( nFuncFmtType == SvNumFormatType::UNDEFINED ) 4551 { 4552 nRetTypeExpr = SvNumFormatType::NUMBER; 4553 nRetIndexExpr = 0; 4554 } 4555 } 4556 break; 4557 case svString : 4558 nRetTypeExpr = SvNumFormatType::TEXT; 4559 nRetIndexExpr = 0; 4560 break; 4561 case svSingleRef : 4562 { 4563 ScAddress aAdr; 4564 PopSingleRef( aAdr ); 4565 if( nGlobalError == FormulaError::NONE) 4566 PushCellResultToken( false, aAdr, &nRetTypeExpr, &nRetIndexExpr, true); 4567 } 4568 break; 4569 case svRefList : 4570 PopError(); // maybe #REF! takes precedence over #VALUE! 4571 PushError( FormulaError::NoValue); 4572 break; 4573 case svDoubleRef : 4574 { 4575 if ( bMatrixFormula ) 4576 { // create matrix for {=A1:A5} 4577 PopDoubleRefPushMatrix(); 4578 ScMatrixRef xMat = PopMatrix(); 4579 QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr); 4580 } 4581 else 4582 { 4583 ScRange aRange; 4584 PopDoubleRef( aRange ); 4585 ScAddress aAdr; 4586 if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr)) 4587 PushCellResultToken( false, aAdr, &nRetTypeExpr, &nRetIndexExpr, true); 4588 } 4589 } 4590 break; 4591 case svExternalDoubleRef: 4592 { 4593 ScMatrixRef xMat; 4594 PopExternalDoubleRef(xMat); 4595 QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr); 4596 } 4597 break; 4598 case svMatrix : 4599 { 4600 sc::RangeMatrix aMat = PopRangeMatrix(); 4601 if (aMat.isRangeValid()) 4602 { 4603 // This matrix represents a range reference. Apply implicit intersection. 4604 double fVal = applyImplicitIntersection(aMat, aPos); 4605 if (rtl::math::isNan(fVal)) 4606 PushNoValue(); 4607 else 4608 PushInt(fVal); 4609 } 4610 else 4611 // This is a normal matrix. 4612 QueryMatrixType(aMat.mpMat, nRetTypeExpr, nRetIndexExpr); 4613 } 4614 break; 4615 case svExternalSingleRef: 4616 { 4617 FormulaTokenRef xToken; 4618 ScExternalRefCache::CellFormat aFmt; 4619 PopExternalSingleRef(xToken, &aFmt); 4620 if (nGlobalError != FormulaError::NONE) 4621 break; 4622 4623 PushTokenRef(xToken); 4624 4625 if (aFmt.mbIsSet) 4626 { 4627 nFuncFmtType = aFmt.mnType; 4628 nFuncFmtIndex = aFmt.mnIndex; 4629 } 4630 } 4631 break; 4632 default : 4633 SetError( FormulaError::UnknownStackVariable); 4634 } 4635 } 4636 else 4637 SetError( FormulaError::UnknownStackVariable); 4638 } 4639 else if (sp > 1) 4640 SetError( FormulaError::OperatorExpected); 4641 else 4642 SetError( FormulaError::NoCode); 4643 4644 if (bForcedResultType || nRetTypeExpr != SvNumFormatType::UNDEFINED) 4645 { 4646 nRetFmtType = nRetTypeExpr; 4647 nRetFmtIndex = nRetIndexExpr; 4648 } 4649 else if( nFuncFmtType != SvNumFormatType::UNDEFINED ) 4650 { 4651 nRetFmtType = nFuncFmtType; 4652 nRetFmtIndex = nFuncFmtIndex; 4653 } 4654 else 4655 nRetFmtType = SvNumFormatType::NUMBER; 4656 4657 if (nGlobalError != FormulaError::NONE && GetStackType() != svError ) 4658 PushError( nGlobalError); 4659 4660 // THE final result. 4661 xResult = PopToken(); 4662 if (!xResult) 4663 xResult = new FormulaErrorToken( FormulaError::UnknownStackVariable); 4664 4665 // release tokens in expression stack 4666 const FormulaToken** p = pStack; 4667 while( maxsp-- ) 4668 (*p++)->DecRef(); 4669 4670 StackVar eType = xResult->GetType(); 4671 if (eType == svMatrix) 4672 // Results are immutable in case they would be reused as input for new 4673 // interpreters. 4674 xResult.get()->GetMatrix()->SetImmutable(); 4675 return eType; 4676 } 4677 4678 void ScInterpreter::AssertFormulaMatrix() 4679 { 4680 bMatrixFormula = true; 4681 } 4682 4683 svl::SharedString ScInterpreter::GetStringResult() const 4684 { 4685 return xResult->GetString(); 4686 } 4687 4688 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 4689
