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