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