1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_features.h>
22 #include "interpre.hxx"
24 #include <rangelst.hxx>
25 #include <sfx2/app.hxx>
26 #include <sfx2/docfile.hxx>
27 #include <sfx2/objsh.hxx>
28 #include <sfx2/docfilt.hxx>
29 #include <basic/sbmeth.hxx>
30 #include <basic/sbmod.hxx>
31 #include <basic/sbstar.hxx>
32 #include <basic/sbx.hxx>
33 #include <basic/sbxobj.hxx>
34 #include <basic/sbuno.hxx>
35 #include <svl/zforlist.hxx>
36 #include <svl/sharedstringpool.hxx>
41 #include <com/sun/star/table/XCellRange.hpp>
42 #include <com/sun/star/sheet/XSheetCellRange.hpp>
43 #include <comphelper/processfactory.hxx>
47 #include "formulacell.hxx"
48 #include "callform.hxx"
49 #include "addincol.hxx"
50 #include "document.hxx"
51 #include "dociter.hxx"
52 #include "docoptio.hxx"
53 #include "scmatrix.hxx"
54 #include "adiasync.hxx"
56 #include "cellsuno.hxx"
58 #include "rangeseq.hxx"
59 #include "addinlis.hxx"
60 #include "jumpmatrix.hxx"
61 #include "parclass.hxx"
62 #include "externalrefmgr.hxx"
63 #include <formula/FormulaCompiler.hxx>
64 #include "macromgr.hxx"
65 #include "doubleref.hxx"
66 #include "queryparam.hxx"
67 #include "tokenarray.hxx"
74 #include <basic/basmgr.hxx>
75 #include <vbahelper/vbaaccesshelper.hxx>
77 #include <boost/scoped_array.hpp>
79 using namespace com::sun::star
;
80 using namespace formula
;
81 using ::std::unique_ptr
;
83 #define ADDIN_MAXSTRLEN 256
85 //-----------------------------static data -----------------
87 // document access functions
89 void ScInterpreter::ReplaceCell( ScAddress
& rPos
)
91 size_t ListSize
= pDok
->aTableOpList
.size();
92 for ( size_t i
= 0; i
< ListSize
; ++i
)
94 ScInterpreterTableOpParams
* pTOp
= &pDok
->aTableOpList
[ i
];
95 if ( rPos
== pTOp
->aOld1
)
100 else if ( rPos
== pTOp
->aOld2
)
108 void ScInterpreter::ReplaceCell( SCCOL
& rCol
, SCROW
& rRow
, SCTAB
& rTab
)
110 ScAddress
aCellPos( rCol
, rRow
, rTab
);
111 size_t ListSize
= pDok
->aTableOpList
.size();
112 for ( size_t i
= 0; i
< ListSize
; ++i
)
114 ScInterpreterTableOpParams
* pTOp
= &pDok
->aTableOpList
[ i
];
115 if ( aCellPos
== pTOp
->aOld1
)
117 rCol
= pTOp
->aNew1
.Col();
118 rRow
= pTOp
->aNew1
.Row();
119 rTab
= pTOp
->aNew1
.Tab();
122 else if ( aCellPos
== pTOp
->aOld2
)
124 rCol
= pTOp
->aNew2
.Col();
125 rRow
= pTOp
->aNew2
.Row();
126 rTab
= pTOp
->aNew2
.Tab();
132 bool ScInterpreter::IsTableOpInRange( const ScRange
& rRange
)
134 if ( rRange
.aStart
== rRange
.aEnd
)
135 return false; // not considered to be a range in TableOp sense
137 // we can't replace a single cell in a range
138 size_t ListSize
= pDok
->aTableOpList
.size();
139 for ( size_t i
= 0; i
< ListSize
; ++i
)
141 ScInterpreterTableOpParams
* pTOp
= &pDok
->aTableOpList
[ i
];
142 if ( rRange
.In( pTOp
->aOld1
) )
144 if ( rRange
.In( pTOp
->aOld2
) )
150 sal_uLong
ScInterpreter::GetCellNumberFormat( const ScAddress
& rPos
, ScRefCellValue
& rCell
)
156 nFormat
= pDok
->GetNumberFormat( rPos
);
161 if (rCell
.meType
== CELLTYPE_FORMULA
)
162 nErr
= rCell
.mpFormula
->GetErrCode();
165 nFormat
= pDok
->GetNumberFormat( rPos
);
172 /// Only ValueCell, formula cells already store the result rounded.
173 double ScInterpreter::GetValueCellValue( const ScAddress
& rPos
, double fOrig
)
175 if ( bCalcAsShown
&& fOrig
!= 0.0 )
177 sal_uLong nFormat
= pDok
->GetNumberFormat( rPos
);
178 fOrig
= pDok
->RoundValueAsShown( fOrig
, nFormat
);
183 sal_uInt16
ScInterpreter::GetCellErrCode( const ScRefCellValue
& rCell
)
185 return rCell
.meType
== CELLTYPE_FORMULA
? rCell
.mpFormula
->GetErrCode() : 0;
188 double ScInterpreter::ConvertStringToValue( const OUString
& rStr
)
190 double fValue
= ScGlobal::ConvertStringToValue( rStr
, maCalcConfig
, nGlobalError
, mnStringNoValueError
,
191 pFormatter
, nCurFmtType
);
193 SetError(nGlobalError
);
197 double ScInterpreter::ConvertStringToValue( const OUString
& rStr
, sal_uInt16
& rError
, short& rCurFmtType
)
199 return ScGlobal::ConvertStringToValue( rStr
, maCalcConfig
, rError
, mnStringNoValueError
, pFormatter
, rCurFmtType
);
202 double ScInterpreter::GetCellValue( const ScAddress
& rPos
, ScRefCellValue
& rCell
)
204 sal_uInt16 nErr
= nGlobalError
;
206 double nVal
= GetCellValueOrZero(rPos
, rCell
);
207 if ( !nGlobalError
|| nGlobalError
== errCellNoValue
)
212 double ScInterpreter::GetCellValueOrZero( const ScAddress
& rPos
, ScRefCellValue
& rCell
)
216 CellType eType
= rCell
.meType
;
219 case CELLTYPE_FORMULA
:
221 ScFormulaCell
* pFCell
= rCell
.mpFormula
;
222 sal_uInt16 nErr
= pFCell
->GetErrCode();
225 if (pFCell
->IsValue())
227 fValue
= pFCell
->GetValue();
228 pDok
->GetNumberFormatInfo( nCurFmtType
, nCurFmtIndex
,
233 fValue
= ConvertStringToValue(pFCell
->GetString().getString());
245 fValue
= rCell
.mfValue
;
246 nCurFmtIndex
= pDok
->GetNumberFormat( rPos
);
247 nCurFmtType
= pFormatter
->GetType( nCurFmtIndex
);
248 if ( bCalcAsShown
&& fValue
!= 0.0 )
249 fValue
= pDok
->RoundValueAsShown( fValue
, nCurFmtIndex
);
252 case CELLTYPE_STRING
:
255 // SUM(A1:A2) differs from A1+A2. No good. But people insist on
257 OUString aStr
= rCell
.getString(pDok
);
258 fValue
= ConvertStringToValue( aStr
);
262 fValue
= 0.0; // empty or broadcaster cell
269 void ScInterpreter::GetCellString( svl::SharedString
& rStr
, ScRefCellValue
& rCell
)
273 switch (rCell
.meType
)
275 case CELLTYPE_STRING
:
277 rStr
= mrStrPool
.intern(rCell
.getString(pDok
));
279 case CELLTYPE_FORMULA
:
281 ScFormulaCell
* pFCell
= rCell
.mpFormula
;
282 nErr
= pFCell
->GetErrCode();
283 if (pFCell
->IsValue())
285 double fVal
= pFCell
->GetValue();
286 sal_uLong nIndex
= pFormatter
->GetStandardFormat(
287 css::util::NumberFormat::NUMBER
,
290 pFormatter
->GetInputLineString(fVal
, nIndex
, aStr
);
291 rStr
= mrStrPool
.intern(aStr
);
294 rStr
= pFCell
->GetString();
299 double fVal
= rCell
.mfValue
;
300 sal_uLong nIndex
= pFormatter
->GetStandardFormat(
301 css::util::NumberFormat::NUMBER
,
304 pFormatter
->GetInputLineString(fVal
, nIndex
, aStr
);
305 rStr
= mrStrPool
.intern(aStr
);
309 rStr
= svl::SharedString::getEmptyString();
316 bool ScInterpreter::CreateDoubleArr(SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
317 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
, sal_uInt8
* pCellArr
)
320 // Old Add-Ins are hard limited to sal_uInt16 values.
321 #if MAXCOLCOUNT_DEFINE > USHRT_MAX
322 #error Add check for columns > USHRT_MAX!
324 if (nRow1
> USHRT_MAX
|| nRow2
> USHRT_MAX
)
327 sal_uInt16 nCount
= 0;
328 sal_uInt16
* p
= reinterpret_cast<sal_uInt16
*>(pCellArr
);
329 *p
++ = static_cast<sal_uInt16
>(nCol1
);
330 *p
++ = static_cast<sal_uInt16
>(nRow1
);
331 *p
++ = static_cast<sal_uInt16
>(nTab1
);
332 *p
++ = static_cast<sal_uInt16
>(nCol2
);
333 *p
++ = static_cast<sal_uInt16
>(nRow2
);
334 *p
++ = static_cast<sal_uInt16
>(nTab2
);
335 sal_uInt16
* pCount
= p
;
337 sal_uInt16 nPos
= 14;
340 while (nTab
<= nTab2
)
344 while (nRow
<= nRow2
)
348 while (nCol
<= nCol2
)
352 ScRefCellValue aCell
;
353 aCell
.assign(*pDok
, aAdr
);
354 if (!aCell
.isEmpty())
359 switch (aCell
.meType
)
361 case CELLTYPE_VALUE
:
362 nVal
= GetValueCellValue(aAdr
, aCell
.mfValue
);
364 case CELLTYPE_FORMULA
:
365 if (aCell
.mpFormula
->IsValue())
367 nErr
= aCell
.mpFormula
->GetErrCode();
368 nVal
= aCell
.mpFormula
->GetValue();
379 if ((nPos
+ (4 * sizeof(sal_uInt16
)) + sizeof(double)) > MAXARRSIZE
)
381 *p
++ = static_cast<sal_uInt16
>(nCol
);
382 *p
++ = static_cast<sal_uInt16
>(nRow
);
383 *p
++ = static_cast<sal_uInt16
>(nTab
);
385 memcpy( p
, &nVal
, sizeof(double));
386 nPos
+= 8 + sizeof(double);
387 p
= reinterpret_cast<sal_uInt16
*>( pCellArr
+ nPos
);
401 bool ScInterpreter::CreateStringArr(SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
402 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
,
406 // Old Add-Ins are hard limited to sal_uInt16 values.
407 #if MAXCOLCOUNT_DEFINE > USHRT_MAX
408 #error Add check for columns > USHRT_MAX!
410 if (nRow1
> USHRT_MAX
|| nRow2
> USHRT_MAX
)
413 sal_uInt16 nCount
= 0;
414 sal_uInt16
* p
= reinterpret_cast<sal_uInt16
*>(pCellArr
);
415 *p
++ = static_cast<sal_uInt16
>(nCol1
);
416 *p
++ = static_cast<sal_uInt16
>(nRow1
);
417 *p
++ = static_cast<sal_uInt16
>(nTab1
);
418 *p
++ = static_cast<sal_uInt16
>(nCol2
);
419 *p
++ = static_cast<sal_uInt16
>(nRow2
);
420 *p
++ = static_cast<sal_uInt16
>(nTab2
);
421 sal_uInt16
* pCount
= p
;
423 sal_uInt16 nPos
= 14;
425 while (nTab
<= nTab2
)
428 while (nRow
<= nRow2
)
431 while (nCol
<= nCol2
)
433 ScRefCellValue aCell
;
434 aCell
.assign(*pDok
, ScAddress(nCol
, nRow
, nTab
));
435 if (!aCell
.isEmpty())
440 switch (aCell
.meType
)
442 case CELLTYPE_STRING
:
444 aStr
= aCell
.getString(pDok
);
446 case CELLTYPE_FORMULA
:
447 if (!aCell
.mpFormula
->IsValue())
449 nErr
= aCell
.mpFormula
->GetErrCode();
450 aStr
= aCell
.mpFormula
->GetString().getString();
461 OString
aTmp(OUStringToOString(aStr
,
462 osl_getThreadTextEncoding()));
463 // Old Add-Ins are limited to sal_uInt16 string
464 // lengths, and room for pad byte check.
465 if ( aTmp
.getLength() > SAL_MAX_UINT16
- 2 )
467 // Append a 0-pad-byte if string length is odd
468 // MUST be sal_uInt16
469 sal_uInt16 nStrLen
= (sal_uInt16
) aTmp
.getLength();
470 sal_uInt16 nLen
= ( nStrLen
+ 2 ) & ~1;
472 if (((sal_uLong
)nPos
+ (5 * sizeof(sal_uInt16
)) + nLen
) > MAXARRSIZE
)
474 *p
++ = static_cast<sal_uInt16
>(nCol
);
475 *p
++ = static_cast<sal_uInt16
>(nRow
);
476 *p
++ = static_cast<sal_uInt16
>(nTab
);
479 memcpy( p
, aTmp
.getStr(), nStrLen
+ 1);
480 nPos
+= 10 + nStrLen
+ 1;
481 sal_uInt8
* q
= ( pCellArr
+ nPos
);
482 if( (nStrLen
& 1) == 0 )
484 p
= reinterpret_cast<sal_uInt16
*>( pCellArr
+ nPos
);
498 bool ScInterpreter::CreateCellArr(SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
499 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
,
503 // Old Add-Ins are hard limited to sal_uInt16 values.
504 #if MAXCOLCOUNT_DEFINE > USHRT_MAX
505 #error Add check for columns > USHRT_MAX!
507 if (nRow1
> USHRT_MAX
|| nRow2
> USHRT_MAX
)
510 sal_uInt16 nCount
= 0;
511 sal_uInt16
* p
= reinterpret_cast<sal_uInt16
*>(pCellArr
);
512 *p
++ = static_cast<sal_uInt16
>(nCol1
);
513 *p
++ = static_cast<sal_uInt16
>(nRow1
);
514 *p
++ = static_cast<sal_uInt16
>(nTab1
);
515 *p
++ = static_cast<sal_uInt16
>(nCol2
);
516 *p
++ = static_cast<sal_uInt16
>(nRow2
);
517 *p
++ = static_cast<sal_uInt16
>(nTab2
);
518 sal_uInt16
* pCount
= p
;
520 sal_uInt16 nPos
= 14;
523 while (nTab
<= nTab2
)
527 while (nRow
<= nRow2
)
531 while (nCol
<= nCol2
)
534 ScRefCellValue aCell
;
535 aCell
.assign(*pDok
, aAdr
);
536 if (!aCell
.isEmpty())
539 sal_uInt16 nType
= 0; // 0 = Zahl; 1 = String
543 switch (aCell
.meType
)
545 case CELLTYPE_STRING
:
547 aStr
= aCell
.getString(pDok
);
550 case CELLTYPE_VALUE
:
551 nVal
= GetValueCellValue(aAdr
, aCell
.mfValue
);
553 case CELLTYPE_FORMULA
:
554 nErr
= aCell
.mpFormula
->GetErrCode();
555 if (aCell
.mpFormula
->IsValue())
556 nVal
= aCell
.mpFormula
->GetValue();
558 aStr
= aCell
.mpFormula
->GetString().getString();
566 if ((nPos
+ (5 * sizeof(sal_uInt16
))) > MAXARRSIZE
)
568 *p
++ = static_cast<sal_uInt16
>(nCol
);
569 *p
++ = static_cast<sal_uInt16
>(nRow
);
570 *p
++ = static_cast<sal_uInt16
>(nTab
);
576 if ((nPos
+ sizeof(double)) > MAXARRSIZE
)
578 memcpy( p
, &nVal
, sizeof(double));
579 nPos
+= sizeof(double);
583 OString
aTmp(OUStringToOString(aStr
,
584 osl_getThreadTextEncoding()));
585 // Old Add-Ins are limited to sal_uInt16 string
586 // lengths, and room for pad byte check.
587 if ( aTmp
.getLength() > SAL_MAX_UINT16
- 2 )
589 // Append a 0-pad-byte if string length is odd
590 // MUST be sal_uInt16
591 sal_uInt16 nStrLen
= (sal_uInt16
) aTmp
.getLength();
592 sal_uInt16 nLen
= ( nStrLen
+ 2 ) & ~1;
593 if ( ((sal_uLong
)nPos
+ 2 + nLen
) > MAXARRSIZE
)
596 memcpy( p
, aTmp
.getStr(), nStrLen
+ 1);
597 nPos
+= 2 + nStrLen
+ 1;
598 sal_uInt8
* q
= ( pCellArr
+ nPos
);
599 if( (nStrLen
& 1) == 0 )
603 p
= reinterpret_cast<sal_uInt16
*>( pCellArr
+ nPos
);
618 // Also releases a TempToken if appropriate.
620 void ScInterpreter::PushWithoutError( FormulaToken
& r
)
622 if ( sp
>= MAXSTACK
)
623 SetError( errStackOverflow
);
626 nCurFmtType
= css::util::NumberFormat::UNDEFINED
;
631 pStack
[ sp
]->DecRef();
637 void ScInterpreter::Push( FormulaToken
& r
)
639 if ( sp
>= MAXSTACK
)
640 SetError( errStackOverflow
);
645 if (r
.GetType() == svError
)
647 r
.SetError( nGlobalError
);
648 PushWithoutError( r
);
651 PushWithoutError( *(new FormulaErrorToken( nGlobalError
)));
654 PushWithoutError( r
);
658 void ScInterpreter::PushTempToken( FormulaToken
* p
)
660 if ( sp
>= MAXSTACK
)
662 SetError( errStackOverflow
);
664 // p is a dangling pointer hereafter!
671 if (p
->GetType() == svError
)
673 p
->SetError( nGlobalError
);
674 PushTempTokenWithoutError( p
);
679 // p is a dangling pointer hereafter!
681 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError
));
685 PushTempTokenWithoutError( p
);
689 void ScInterpreter::PushTempTokenWithoutError( FormulaToken
* p
)
692 if ( sp
>= MAXSTACK
)
694 SetError( errStackOverflow
);
695 // p may be a dangling pointer hereafter!
703 pStack
[ sp
]->DecRef();
709 void ScInterpreter::PushTempToken( const FormulaToken
& r
)
711 if (!IfErrorPushError())
712 PushTempTokenWithoutError( r
.Clone());
715 void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString
,
716 const ScAddress
& rAddress
, short * pRetTypeExpr
, sal_uLong
* pRetIndexExpr
)
718 ScRefCellValue aCell
;
719 aCell
.assign(*pDok
, rAddress
);
720 if (aCell
.hasEmptyValue())
722 bool bInherited
= (aCell
.meType
== CELLTYPE_FORMULA
);
723 if (pRetTypeExpr
&& pRetIndexExpr
)
724 pDok
->GetNumberFormatInfo(*pRetTypeExpr
, *pRetIndexExpr
, rAddress
);
725 PushTempToken( new ScEmptyCellToken( bInherited
, bDisplayEmptyAsString
));
730 if (aCell
.meType
== CELLTYPE_FORMULA
)
731 nErr
= aCell
.mpFormula
->GetErrCode();
737 *pRetTypeExpr
= css::util::NumberFormat::UNDEFINED
;
741 else if (aCell
.hasString())
743 svl::SharedString aRes
;
744 GetCellString( aRes
, aCell
);
747 *pRetTypeExpr
= css::util::NumberFormat::TEXT
;
753 double fVal
= GetCellValue(rAddress
, aCell
);
756 *pRetTypeExpr
= nCurFmtType
;
758 *pRetIndexExpr
= nCurFmtIndex
;
762 // Simply throw away TOS.
764 void ScInterpreter::Pop()
769 SetError(errUnknownStackVariable
);
772 // Simply throw away TOS and set error code, used with ocIsError et al.
774 void ScInterpreter::PopError()
779 if (pStack
[sp
]->GetType() == svError
)
780 nGlobalError
= pStack
[sp
]->GetError();
783 SetError(errUnknownStackVariable
);
786 FormulaTokenRef
ScInterpreter::PopToken()
791 FormulaToken
* p
= pStack
[ sp
];
792 if (p
->GetType() == svError
)
793 nGlobalError
= p
->GetError();
797 SetError(errUnknownStackVariable
);
801 double ScInterpreter::PopDouble()
803 nCurFmtType
= css::util::NumberFormat::NUMBER
;
808 FormulaToken
* p
= pStack
[ sp
];
809 switch (p
->GetType())
812 nGlobalError
= p
->GetError();
815 return p
->GetDouble();
820 SetError( errIllegalArgument
);
824 SetError( errUnknownStackVariable
);
828 svl::SharedString
ScInterpreter::PopString()
830 nCurFmtType
= css::util::NumberFormat::TEXT
;
835 FormulaToken
* p
= pStack
[ sp
];
836 switch (p
->GetType())
839 nGlobalError
= p
->GetError();
842 return p
->GetString();
845 return svl::SharedString::getEmptyString();
847 SetError( errIllegalArgument
);
851 SetError( errUnknownStackVariable
);
853 return svl::SharedString::getEmptyString();
856 void ScInterpreter::ValidateRef( const ScSingleRefData
& rRef
)
861 SingleRefToVars( rRef
, nCol
, nRow
, nTab
);
864 void ScInterpreter::ValidateRef( const ScComplexRefData
& rRef
)
866 ValidateRef( rRef
.Ref1
);
867 ValidateRef( rRef
.Ref2
);
870 void ScInterpreter::ValidateRef( const ScRefList
& rRefList
)
872 ScRefList::const_iterator
it( rRefList
.begin());
873 ScRefList::const_iterator
end( rRefList
.end());
874 for ( ; it
!= end
; ++it
)
880 void ScInterpreter::SingleRefToVars( const ScSingleRefData
& rRef
,
881 SCCOL
& rCol
, SCROW
& rRow
, SCTAB
& rTab
)
883 if ( rRef
.IsColRel() )
884 rCol
= aPos
.Col() + rRef
.Col();
888 if ( rRef
.IsRowRel() )
889 rRow
= aPos
.Row() + rRef
.Row();
893 if ( rRef
.IsTabRel() )
894 rTab
= aPos
.Tab() + rRef
.Tab();
898 if( !ValidCol( rCol
) || rRef
.IsColDeleted() )
899 SetError( errNoRef
), rCol
= 0;
900 if( !ValidRow( rRow
) || rRef
.IsRowDeleted() )
901 SetError( errNoRef
), rRow
= 0;
902 if( !ValidTab( rTab
, pDok
->GetTableCount() - 1) || rRef
.IsTabDeleted() )
903 SetError( errNoRef
), rTab
= 0;
906 void ScInterpreter::PopSingleRef(SCCOL
& rCol
, SCROW
&rRow
, SCTAB
& rTab
)
911 FormulaToken
* p
= pStack
[ sp
];
912 switch (p
->GetType())
915 nGlobalError
= p
->GetError();
918 SingleRefToVars( *p
->GetSingleRef(), rCol
, rRow
, rTab
);
919 if ( !pDok
->aTableOpList
.empty() )
920 ReplaceCell( rCol
, rRow
, rTab
);
923 SetError( errIllegalParameter
);
927 SetError( errUnknownStackVariable
);
930 void ScInterpreter::PopSingleRef( ScAddress
& rAdr
)
935 FormulaToken
* p
= pStack
[ sp
];
936 switch (p
->GetType())
939 nGlobalError
= p
->GetError();
946 SingleRefToVars( *p
->GetSingleRef(), nCol
, nRow
, nTab
);
947 rAdr
.Set( nCol
, nRow
, nTab
);
948 if ( !pDok
->aTableOpList
.empty() )
953 SetError( errIllegalParameter
);
957 SetError( errUnknownStackVariable
);
960 void ScInterpreter::DoubleRefToVars( const formula::FormulaToken
* p
,
961 SCCOL
& rCol1
, SCROW
&rRow1
, SCTAB
& rTab1
,
962 SCCOL
& rCol2
, SCROW
&rRow2
, SCTAB
& rTab2
,
963 bool bDontCheckForTableOp
)
965 const ScComplexRefData
& rCRef
= *p
->GetDoubleRef();
966 SingleRefToVars( rCRef
.Ref1
, rCol1
, rRow1
, rTab1
);
967 SingleRefToVars( rCRef
.Ref2
, rCol2
, rRow2
, rTab2
);
968 if ( !pDok
->aTableOpList
.empty() && !bDontCheckForTableOp
)
970 ScRange
aRange( rCol1
, rRow1
, rTab1
, rCol2
, rRow2
, rTab2
);
971 if ( IsTableOpInRange( aRange
) )
972 SetError( errIllegalParameter
);
976 ScDBRangeBase
* ScInterpreter::PopDBDoubleRef()
978 StackVar eType
= GetStackType();
982 SetError(errUnknownStackVariable
);
992 PopDoubleRef(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
, false);
995 return new ScDBInternalRange(pDok
,
996 ScRange(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
));
999 case svExternalDoubleRef
:
1002 if (eType
== svMatrix
)
1005 PopExternalDoubleRef(pMat
);
1008 return new ScDBExternalRange(pDok
, pMat
);
1011 SetError( errIllegalParameter
);
1017 void ScInterpreter::PopDoubleRef(SCCOL
& rCol1
, SCROW
&rRow1
, SCTAB
& rTab1
,
1018 SCCOL
& rCol2
, SCROW
&rRow2
, SCTAB
& rTab2
,
1019 bool bDontCheckForTableOp
)
1024 FormulaToken
* p
= pStack
[ sp
];
1025 switch (p
->GetType())
1028 nGlobalError
= p
->GetError();
1031 DoubleRefToVars( p
, rCol1
, rRow1
, rTab1
, rCol2
, rRow2
, rTab2
,
1032 bDontCheckForTableOp
);
1035 SetError( errIllegalParameter
);
1039 SetError( errUnknownStackVariable
);
1042 void ScInterpreter::DoubleRefToRange( const ScComplexRefData
& rCRef
,
1043 ScRange
& rRange
, bool bDontCheckForTableOp
)
1048 SingleRefToVars( rCRef
.Ref1
, nCol
, nRow
, nTab
);
1049 rRange
.aStart
.Set( nCol
, nRow
, nTab
);
1050 SingleRefToVars( rCRef
.Ref2
, nCol
, nRow
, nTab
);
1051 rRange
.aEnd
.Set( nCol
, nRow
, nTab
);
1053 if (! pDok
->aTableOpList
.empty() && !bDontCheckForTableOp
)
1055 if ( IsTableOpInRange( rRange
) )
1056 SetError( errIllegalParameter
);
1060 void ScInterpreter::PopDoubleRef( ScRange
& rRange
, short & rParam
, size_t & rRefInList
)
1064 formula::FormulaToken
* pToken
= pStack
[ sp
-1 ];
1065 switch (pToken
->GetType())
1068 nGlobalError
= pToken
->GetError();
1072 DoubleRefToRange( *pToken
->GetDoubleRef(), rRange
);
1076 const ScRefList
* pList
= pToken
->GetRefList();
1077 if (rRefInList
< pList
->size())
1079 DoubleRefToRange( (*pList
)[rRefInList
], rRange
);
1080 if (++rRefInList
< pList
->size())
1092 SetError( errIllegalParameter
);
1097 SetError( errIllegalParameter
);
1101 SetError( errUnknownStackVariable
);
1104 void ScInterpreter::PopDoubleRef( ScRange
& rRange
, bool bDontCheckForTableOp
)
1109 FormulaToken
* p
= pStack
[ sp
];
1110 switch (p
->GetType())
1113 nGlobalError
= p
->GetError();
1116 DoubleRefToRange( *p
->GetDoubleRef(), rRange
, bDontCheckForTableOp
);
1119 SetError( errIllegalParameter
);
1123 SetError( errUnknownStackVariable
);
1126 void ScInterpreter::PopExternalSingleRef(sal_uInt16
& rFileId
, OUString
& rTabName
, ScSingleRefData
& rRef
)
1130 SetError(errUnknownStackVariable
);
1135 FormulaToken
* p
= pStack
[sp
];
1136 StackVar eType
= p
->GetType();
1138 if (eType
== svError
)
1140 nGlobalError
= p
->GetError();
1144 if (eType
!= svExternalSingleRef
)
1146 SetError( errIllegalParameter
);
1150 rFileId
= p
->GetIndex();
1151 rTabName
= p
->GetString().getString();
1152 rRef
= *p
->GetSingleRef();
1155 void ScInterpreter::PopExternalSingleRef(ScExternalRefCache::TokenRef
& rToken
, ScExternalRefCache::CellFormat
* pFmt
)
1159 ScSingleRefData aData
;
1160 PopExternalSingleRef(nFileId
, aTabName
, aData
, rToken
, pFmt
);
1163 void ScInterpreter::PopExternalSingleRef(
1164 sal_uInt16
& rFileId
, OUString
& rTabName
, ScSingleRefData
& rRef
,
1165 ScExternalRefCache::TokenRef
& rToken
, ScExternalRefCache::CellFormat
* pFmt
)
1167 PopExternalSingleRef(rFileId
, rTabName
, rRef
);
1171 ScExternalRefManager
* pRefMgr
= pDok
->GetExternalRefManager();
1172 const OUString
* pFile
= pRefMgr
->getExternalFileName(rFileId
);
1175 SetError(errNoName
);
1179 if (rRef
.IsTabRel())
1181 OSL_FAIL("ScCompiler::GetToken: external single reference must have an absolute table reference!");
1186 ScAddress aAddr
= rRef
.toAbs(aPos
);
1187 ScExternalRefCache::CellFormat aFmt
;
1188 ScExternalRefCache::TokenRef xNew
= pRefMgr
->getSingleRefToken(
1189 rFileId
, rTabName
, aAddr
, &aPos
, NULL
, &aFmt
);
1202 void ScInterpreter::PopExternalDoubleRef(sal_uInt16
& rFileId
, OUString
& rTabName
, ScComplexRefData
& rRef
)
1206 SetError(errUnknownStackVariable
);
1211 FormulaToken
* p
= pStack
[sp
];
1212 StackVar eType
= p
->GetType();
1214 if (eType
== svError
)
1216 nGlobalError
= p
->GetError();
1220 if (eType
!= svExternalDoubleRef
)
1222 SetError( errIllegalParameter
);
1226 rFileId
= p
->GetIndex();
1227 rTabName
= p
->GetString().getString();
1228 rRef
= *p
->GetDoubleRef();
1231 void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef
& rArray
)
1235 ScComplexRefData aData
;
1236 PopExternalDoubleRef(nFileId
, aTabName
, aData
);
1240 GetExternalDoubleRef(nFileId
, aTabName
, aData
, rArray
);
1245 void ScInterpreter::PopExternalDoubleRef(ScMatrixRef
& rMat
)
1247 ScExternalRefCache::TokenArrayRef pArray
;
1248 PopExternalDoubleRef(pArray
);
1252 // For now, we only support single range data for external
1253 // references, which means the array should only contain a
1254 // single matrix token.
1255 formula::FormulaToken
* p
= pArray
->First();
1256 if (!p
|| p
->GetType() != svMatrix
)
1257 SetError( errIllegalParameter
);
1260 rMat
= p
->GetMatrix();
1262 SetError( errUnknownVariable
);
1266 void ScInterpreter::GetExternalDoubleRef(
1267 sal_uInt16 nFileId
, const OUString
& rTabName
, const ScComplexRefData
& rData
, ScExternalRefCache::TokenArrayRef
& rArray
)
1269 ScExternalRefManager
* pRefMgr
= pDok
->GetExternalRefManager();
1270 const OUString
* pFile
= pRefMgr
->getExternalFileName(nFileId
);
1273 SetError(errNoName
);
1276 if (rData
.Ref1
.IsTabRel() || rData
.Ref2
.IsTabRel())
1278 OSL_FAIL("ScCompiler::GetToken: external double reference must have an absolute table reference!");
1283 ScComplexRefData
aData(rData
);
1284 ScRange aRange
= aData
.toAbs(aPos
);
1285 ScExternalRefCache::TokenArrayRef pArray
= pRefMgr
->getDoubleRefTokens(
1286 nFileId
, rTabName
, aRange
, &aPos
);
1290 SetError(errIllegalArgument
);
1294 formula::FormulaToken
* pToken
= pArray
->First();
1295 if (pToken
->GetType() != svMatrix
)
1297 SetError(errIllegalArgument
);
1303 // Can't handle more than one matrix per parameter.
1304 SetError( errIllegalArgument
);
1311 bool ScInterpreter::PopDoubleRefOrSingleRef( ScAddress
& rAdr
)
1313 switch ( GetStackType() )
1318 PopDoubleRef( aRange
, true );
1319 return DoubleRefToPosSingleRef( aRange
, rAdr
);
1323 PopSingleRef( rAdr
);
1328 SetError( errNoRef
);
1333 void ScInterpreter::PopDoubleRefPushMatrix()
1335 if ( GetStackType() == svDoubleRef
)
1337 ScMatrixRef pMat
= GetMatrix();
1341 PushIllegalParameter();
1344 SetError( errNoRef
);
1347 ScTokenMatrixMap
* ScInterpreter::CreateTokenMatrixMap()
1349 return new ScTokenMatrixMap
;
1352 bool ScInterpreter::ConvertMatrixParameters()
1354 sal_uInt16 nParams
= pCur
->GetParamCount();
1355 OSL_ENSURE( nParams
<= sp
, "ConvertMatrixParameters: stack/param count mismatch");
1356 SCSIZE nJumpCols
= 0, nJumpRows
= 0;
1357 for ( sal_uInt16 i
=1; i
<= nParams
&& i
<= sp
; ++i
)
1359 FormulaToken
* p
= pStack
[ sp
- i
];
1360 if ( p
->GetOpCode() != ocPush
&& p
->GetOpCode() != ocMissing
)
1362 OSL_FAIL( "ConvertMatrixParameters: not a push");
1366 switch ( p
->GetType() )
1371 case svExternalSingleRef
:
1379 if ( ScParameterClassification::GetParameterType( pCur
, nParams
- i
)
1380 == ScParameterClassification::Value
)
1381 { // only if single value expected
1382 ScMatrixRef pMat
= p
->GetMatrix();
1384 SetError( errUnknownVariable
);
1387 SCSIZE nCols
, nRows
;
1388 pMat
->GetDimensions( nCols
, nRows
);
1389 if ( nJumpCols
< nCols
)
1391 if ( nJumpRows
< nRows
)
1399 ScParameterClassification::Type eType
=
1400 ScParameterClassification::GetParameterType( pCur
, nParams
- i
);
1401 if ( eType
!= ScParameterClassification::Reference
&&
1402 eType
!= ScParameterClassification::ReferenceOrForceArray
&&
1403 // For scalar Value: convert to Array/JumpMatrix
1404 // only if in array formula context, else (function
1405 // has ForceArray or ReferenceOrForceArray
1406 // parameter *somewhere else*) pick a normal
1407 // position dependent implicit intersection later.
1408 (eType
!= ScParameterClassification::Value
|| bMatrixFormula
|| pCur
->HasForceArray()))
1413 DoubleRefToVars( p
, nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
1414 // Make sure the map exists, created if not.
1415 GetTokenMatrixMap();
1416 ScMatrixRef pMat
= CreateMatrixFromDoubleRef( p
,
1417 nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
1420 if ( eType
== ScParameterClassification::Value
)
1421 { // only if single value expected
1422 if ( nJumpCols
< static_cast<SCSIZE
>(nCol2
- nCol1
+ 1) )
1423 nJumpCols
= static_cast<SCSIZE
>(nCol2
- nCol1
+ 1);
1424 if ( nJumpRows
< static_cast<SCSIZE
>(nRow2
- nRow1
+ 1) )
1425 nJumpRows
= static_cast<SCSIZE
>(nRow2
- nRow1
+ 1);
1427 formula::FormulaToken
* pNew
= new ScMatrixToken( pMat
);
1429 pStack
[ sp
- i
] = pNew
;
1430 p
->DecRef(); // p may be dead now!
1435 case svExternalDoubleRef
:
1437 ScParameterClassification::Type eType
=
1438 ScParameterClassification::GetParameterType( pCur
, nParams
- i
);
1439 if (eType
== ScParameterClassification::Array
)
1441 sal_uInt16 nFileId
= p
->GetIndex();
1442 OUString aTabName
= p
->GetString().getString();
1443 const ScComplexRefData
& rRef
= *p
->GetDoubleRef();
1444 ScExternalRefCache::TokenArrayRef pArray
;
1445 GetExternalDoubleRef(nFileId
, aTabName
, rRef
, pArray
);
1446 if (nGlobalError
|| !pArray
)
1448 formula::FormulaToken
* pTemp
= pArray
->First();
1452 ScMatrixRef pMat
= pTemp
->GetMatrix();
1455 formula::FormulaToken
* pNew
= new ScMatrixToken( pMat
);
1457 pStack
[ sp
- i
] = pNew
;
1458 p
->DecRef(); // p may be dead now!
1465 ScParameterClassification::Type eType
=
1466 ScParameterClassification::GetParameterType( pCur
, nParams
- i
);
1467 if ( eType
!= ScParameterClassification::Reference
&&
1468 eType
!= ScParameterClassification::ReferenceOrForceArray
)
1470 // can't convert to matrix
1471 SetError( errNoValue
);
1476 OSL_FAIL( "ConvertMatrixParameters: unknown parameter type");
1480 if( nJumpCols
&& nJumpRows
)
1482 short nPC
= aCode
.GetPC();
1483 short nStart
= nPC
- 1; // restart on current code (-1)
1484 short nNext
= nPC
; // next instruction after subroutine
1485 short nStop
= nPC
+ 1; // stop subroutine before reaching that
1486 FormulaTokenRef xNew
;
1487 ScTokenMatrixMap::const_iterator aMapIter
;
1488 if (pTokenMatrixMap
&& ((aMapIter
= pTokenMatrixMap
->find( pCur
)) !=
1489 pTokenMatrixMap
->end()))
1490 xNew
= (*aMapIter
).second
;
1493 ScJumpMatrix
* pJumpMat
= new ScJumpMatrix( nJumpCols
, nJumpRows
);
1494 pJumpMat
->SetAllJumps( 1.0, nStart
, nNext
, nStop
);
1495 // pop parameters and store in ScJumpMatrix, push in JumpMatrix()
1496 ScTokenVec
* pParams
= new ScTokenVec( nParams
);
1497 for ( sal_uInt16 i
=1; i
<= nParams
&& sp
> 0; ++i
)
1499 FormulaToken
* p
= pStack
[ --sp
];
1501 // store in reverse order such that a push may simply iterate
1502 (*pParams
)[ nParams
- i
] = p
;
1504 pJumpMat
->SetJumpParameters( pParams
);
1505 xNew
= new ScJumpMatrixToken( pJumpMat
);
1506 GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type( pCur
,
1509 PushTempToken( xNew
.get());
1510 // set continuation point of path for main code line
1511 aCode
.Jump( nNext
, nNext
);
1517 ScMatrixRef
ScInterpreter::PopMatrix()
1522 FormulaToken
* p
= pStack
[ sp
];
1523 switch (p
->GetType())
1526 nGlobalError
= p
->GetError();
1530 ScMatrix
* pMat
= p
->GetMatrix();
1532 pMat
->SetErrorInterpreter( this);
1534 SetError( errUnknownVariable
);
1538 SetError( errIllegalParameter
);
1542 SetError( errUnknownStackVariable
);
1546 sc::RangeMatrix
ScInterpreter::PopRangeMatrix()
1548 sc::RangeMatrix aRet
;
1551 switch (pStack
[sp
-1]->GetType())
1556 FormulaToken
* p
= pStack
[sp
];
1557 aRet
.mpMat
= p
->GetMatrix();
1560 aRet
.mpMat
->SetErrorInterpreter(this);
1561 if (p
->GetByte() == MATRIX_TOKEN_HAS_RANGE
)
1563 const ScComplexRefData
& rRef
= *p
->GetDoubleRef();
1564 if (!rRef
.Ref1
.IsColRel() && !rRef
.Ref1
.IsRowRel() && !rRef
.Ref2
.IsColRel() && !rRef
.Ref2
.IsRowRel())
1566 aRet
.mnCol1
= rRef
.Ref1
.Col();
1567 aRet
.mnRow1
= rRef
.Ref1
.Row();
1568 aRet
.mnTab1
= rRef
.Ref1
.Tab();
1569 aRet
.mnCol2
= rRef
.Ref2
.Col();
1570 aRet
.mnRow2
= rRef
.Ref2
.Row();
1571 aRet
.mnTab2
= rRef
.Ref2
.Tab();
1576 SetError( errUnknownVariable
);
1580 aRet
.mpMat
= PopMatrix();
1586 void ScInterpreter::QueryMatrixType(ScMatrixRef
& xMat
, short& rRetTypeExpr
, sal_uLong
& rRetIndexExpr
)
1590 SCSIZE nCols
, nRows
;
1591 xMat
->GetDimensions(nCols
, nRows
);
1592 ScMatrixValue nMatVal
= xMat
->Get(0, 0);
1593 ScMatValType nMatValType
= nMatVal
.nType
;
1594 if (ScMatrix::IsNonValueType( nMatValType
))
1596 if ( xMat
->IsEmptyPath( 0, 0))
1597 { // result of empty FALSE jump path
1598 FormulaTokenRef xRes
= new FormulaDoubleToken( 0.0);
1599 PushTempToken( new ScMatrixFormulaCellToken(nCols
, nRows
, xMat
, xRes
.get()));
1600 rRetTypeExpr
= css::util::NumberFormat::LOGICAL
;
1602 else if ( xMat
->IsEmptyResult( 0, 0))
1603 { // empty formula result
1604 FormulaTokenRef xRes
= new ScEmptyCellToken( true, true); // inherited, display empty
1605 PushTempToken( new ScMatrixFormulaCellToken(nCols
, nRows
, xMat
, xRes
.get()));
1607 else if ( xMat
->IsEmpty( 0, 0))
1608 { // empty or empty cell
1609 FormulaTokenRef xRes
= new ScEmptyCellToken( false, true); // not inherited, display empty
1610 PushTempToken( new ScMatrixFormulaCellToken(nCols
, nRows
, xMat
, xRes
.get()));
1614 svl::SharedString
aStr( nMatVal
.GetString());
1615 FormulaTokenRef xRes
= new FormulaStringToken( aStr
);
1616 PushTempToken( new ScMatrixFormulaCellToken(nCols
, nRows
, xMat
, xRes
.get()));
1617 rRetTypeExpr
= css::util::NumberFormat::TEXT
;
1622 sal_uInt16 nErr
= GetDoubleErrorValue( nMatVal
.fVal
);
1623 FormulaTokenRef xRes
;
1625 xRes
= new FormulaErrorToken( nErr
);
1627 xRes
= new FormulaDoubleToken( nMatVal
.fVal
);
1628 PushTempToken( new ScMatrixFormulaCellToken(nCols
, nRows
, xMat
, xRes
.get()));
1629 if ( rRetTypeExpr
!= css::util::NumberFormat::LOGICAL
)
1630 rRetTypeExpr
= css::util::NumberFormat::NUMBER
;
1633 xMat
->SetErrorInterpreter( NULL
);
1636 SetError( errUnknownStackVariable
);
1639 void ScInterpreter::PushDouble(double nVal
)
1641 TreatDoubleError( nVal
);
1642 if (!IfErrorPushError())
1643 PushTempTokenWithoutError( new FormulaDoubleToken( nVal
) );
1646 void ScInterpreter::PushInt(int nVal
)
1648 if (!IfErrorPushError())
1649 PushTempTokenWithoutError( new FormulaDoubleToken( nVal
) );
1652 void ScInterpreter::PushStringBuffer( const sal_Unicode
* pString
)
1656 svl::SharedString aSS
= pDok
->GetSharedStringPool().intern(OUString(pString
));
1660 PushString(svl::SharedString::getEmptyString());
1663 void ScInterpreter::PushString( const OUString
& rStr
)
1665 PushString(pDok
->GetSharedStringPool().intern(rStr
));
1668 void ScInterpreter::PushString( const svl::SharedString
& rString
)
1670 if (!IfErrorPushError())
1671 PushTempTokenWithoutError( new FormulaStringToken( rString
) );
1674 void ScInterpreter::PushSingleRef(SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
1676 if (!IfErrorPushError())
1678 ScSingleRefData aRef
;
1679 aRef
.InitAddress(ScAddress(nCol
,nRow
,nTab
));
1680 PushTempTokenWithoutError( new ScSingleRefToken( aRef
) );
1684 void ScInterpreter::PushDoubleRef(SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
1685 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
)
1687 if (!IfErrorPushError())
1689 ScComplexRefData aRef
;
1690 aRef
.InitRange(ScRange(nCol1
,nRow1
,nTab1
,nCol2
,nRow2
,nTab2
));
1691 PushTempTokenWithoutError( new ScDoubleRefToken( aRef
) );
1695 void ScInterpreter::PushExternalSingleRef(
1696 sal_uInt16 nFileId
, const OUString
& rTabName
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
1698 if (!IfErrorPushError())
1700 ScSingleRefData aRef
;
1701 aRef
.InitAddress(ScAddress(nCol
,nRow
,nTab
));
1702 PushTempTokenWithoutError( new ScExternalSingleRefToken(nFileId
, rTabName
, aRef
)) ;
1706 void ScInterpreter::PushExternalDoubleRef(
1707 sal_uInt16 nFileId
, const OUString
& rTabName
,
1708 SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
, SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
)
1710 if (!IfErrorPushError())
1712 ScComplexRefData aRef
;
1713 aRef
.InitRange(ScRange(nCol1
,nRow1
,nTab1
,nCol2
,nRow2
,nTab2
));
1714 PushTempTokenWithoutError( new ScExternalDoubleRefToken(nFileId
, rTabName
, aRef
) );
1718 void ScInterpreter::PushSingleRef( const ScRefAddress
& rRef
)
1720 if (!IfErrorPushError())
1722 ScSingleRefData aRef
;
1723 aRef
.InitFromRefAddress( rRef
, aPos
);
1724 PushTempTokenWithoutError( new ScSingleRefToken( aRef
) );
1728 void ScInterpreter::PushDoubleRef( const ScRefAddress
& rRef1
, const ScRefAddress
& rRef2
)
1730 if (!IfErrorPushError())
1732 ScComplexRefData aRef
;
1733 aRef
.InitFromRefAddresses( rRef1
, rRef2
, aPos
);
1734 PushTempTokenWithoutError( new ScDoubleRefToken( aRef
) );
1738 void ScInterpreter::PushMatrix( const sc::RangeMatrix
& rMat
)
1740 if (!rMat
.isRangeValid())
1742 // Just push the matrix part only.
1743 PushMatrix(rMat
.mpMat
);
1747 rMat
.mpMat
->SetErrorInterpreter(NULL
);
1749 PushTempTokenWithoutError(new ScMatrixRangeToken(rMat
));
1752 void ScInterpreter::PushMatrix(const ScMatrixRef
& pMat
)
1754 pMat
->SetErrorInterpreter( NULL
);
1755 // No if (!IfErrorPushError()) because ScMatrix stores errors itself,
1756 // but with notifying ScInterpreter via nGlobalError, substituting it would
1757 // mean to inherit the error on all array elements in all following
1760 PushTempTokenWithoutError( new ScMatrixToken( pMat
) );
1763 void ScInterpreter::PushError( sal_uInt16 nError
)
1765 SetError( nError
); // only sets error if not already set
1766 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError
));
1769 void ScInterpreter::PushParameterExpected()
1771 PushError( errParameterExpected
);
1774 void ScInterpreter::PushIllegalParameter()
1776 PushError( errIllegalParameter
);
1779 void ScInterpreter::PushIllegalArgument()
1781 PushError( errIllegalArgument
);
1784 void ScInterpreter::PushNA()
1786 PushError( NOTAVAILABLE
);
1789 void ScInterpreter::PushNoValue()
1791 PushError( errNoValue
);
1794 bool ScInterpreter::IsMissing()
1796 return sp
&& pStack
[sp
- 1]->GetType() == svMissing
;
1799 StackVar
ScInterpreter::GetRawStackType()
1804 eRes
= pStack
[sp
- 1]->GetType();
1808 SetError(errUnknownStackVariable
);
1814 StackVar
ScInterpreter::GetStackType()
1819 eRes
= pStack
[sp
- 1]->GetType();
1820 if( eRes
== svMissing
|| eRes
== svEmptyCell
)
1821 eRes
= svDouble
; // default!
1825 SetError(errUnknownStackVariable
);
1831 StackVar
ScInterpreter::GetStackType( sal_uInt8 nParam
)
1836 eRes
= pStack
[sp
- nParam
]->GetType();
1837 if( eRes
== svMissing
|| eRes
== svEmptyCell
)
1838 eRes
= svDouble
; // default!
1845 bool ScInterpreter::DoubleRefToPosSingleRef( const ScRange
& rRange
, ScAddress
& rAdr
)
1847 // Check for a singleton first - no implicit intersection for them.
1848 if( rRange
.aStart
== rRange
.aEnd
)
1850 rAdr
= rRange
.aStart
;
1858 bOk
= rRange
.aStart
.Tab() == rRange
.aEnd
.Tab();
1860 SetError( errIllegalArgument
);
1864 pJumpMatrix
->GetPos( nC
, nR
);
1865 rAdr
.SetCol( sal::static_int_cast
<SCCOL
>( rRange
.aStart
.Col() + nC
) );
1866 rAdr
.SetRow( sal::static_int_cast
<SCROW
>( rRange
.aStart
.Row() + nR
) );
1867 rAdr
.SetTab( rRange
.aStart
.Tab());
1868 bOk
= rRange
.aStart
.Col() <= rAdr
.Col() && rAdr
.Col() <=
1869 rRange
.aEnd
.Col() && rRange
.aStart
.Row() <= rAdr
.Row() &&
1870 rAdr
.Row() <= rRange
.aEnd
.Row();
1872 SetError( errNoValue
);
1877 SCCOL nMyCol
= aPos
.Col();
1878 SCROW nMyRow
= aPos
.Row();
1879 SCTAB nMyTab
= aPos
.Tab();
1883 nTab
= rRange
.aStart
.Tab();
1884 if ( rRange
.aStart
.Col() <= nMyCol
&& nMyCol
<= rRange
.aEnd
.Col() )
1886 nRow
= rRange
.aStart
.Row();
1887 if ( nRow
== rRange
.aEnd
.Row() )
1892 else if ( nTab
!= nMyTab
&& nTab
== rRange
.aEnd
.Tab()
1893 && rRange
.aStart
.Row() <= nMyRow
&& nMyRow
<= rRange
.aEnd
.Row() )
1900 else if ( rRange
.aStart
.Row() <= nMyRow
&& nMyRow
<= rRange
.aEnd
.Row() )
1902 nCol
= rRange
.aStart
.Col();
1903 if ( nCol
== rRange
.aEnd
.Col() )
1908 else if ( nTab
!= nMyTab
&& nTab
== rRange
.aEnd
.Tab()
1909 && rRange
.aStart
.Col() <= nMyCol
&& nMyCol
<= rRange
.aEnd
.Col() )
1918 if ( nTab
== rRange
.aEnd
.Tab() )
1920 else if ( nTab
<= nMyTab
&& nMyTab
<= rRange
.aEnd
.Tab() )
1925 rAdr
.Set( nCol
, nRow
, nTab
);
1928 SetError( errNoValue
);
1932 double ScInterpreter::GetDoubleFromMatrix(const ScMatrixRef
& pMat
)
1938 return pMat
->GetDouble( 0 );
1940 SCSIZE nCols
, nRows
, nC
, nR
;
1941 pMat
->GetDimensions( nCols
, nRows
);
1942 pJumpMatrix
->GetPos( nC
, nR
);
1943 // Use vector replication for single row/column arrays.
1944 if ( (nC
< nCols
|| nCols
== 1) && (nR
< nRows
|| nRows
== 1) )
1945 return pMat
->GetDouble( nC
, nR
);
1947 SetError( errNoValue
);
1951 double ScInterpreter::GetDouble()
1954 switch( GetRawStackType() )
1960 nVal
= ConvertStringToValue( PopString().getString());
1965 PopSingleRef( aAdr
);
1966 ScRefCellValue aCell
;
1967 aCell
.assign(*pDok
, aAdr
);
1968 nVal
= GetCellValue(aAdr
, aCell
);
1972 { // generate position dependent SingleRef
1974 PopDoubleRef( aRange
);
1976 if ( !nGlobalError
&& DoubleRefToPosSingleRef( aRange
, aAdr
) )
1978 ScRefCellValue aCell
;
1979 aCell
.assign(*pDok
, aAdr
);
1980 nVal
= GetCellValue(aAdr
, aCell
);
1986 case svExternalSingleRef
:
1988 ScExternalRefCache::TokenRef pToken
;
1989 PopExternalSingleRef(pToken
);
1990 if (!nGlobalError
&& pToken
)
1991 nVal
= pToken
->GetDouble();
1994 case svExternalDoubleRef
:
1997 PopExternalDoubleRef(pMat
);
2001 nVal
= GetDoubleFromMatrix(pMat
);
2006 ScMatrixRef pMat
= PopMatrix();
2007 nVal
= GetDoubleFromMatrix(pMat
);
2021 SetError( errIllegalParameter
);
2024 if ( nFuncFmtType
== nCurFmtType
)
2025 nFuncFmtIndex
= nCurFmtIndex
;
2029 double ScInterpreter::GetDoubleWithDefault(double nDefault
)
2031 bool bMissing
= IsMissing();
2032 double nResultVal
= GetDouble();
2034 nResultVal
= nDefault
;
2038 svl::SharedString
ScInterpreter::GetString()
2040 switch (GetRawStackType())
2044 return svl::SharedString::getEmptyString();
2048 return svl::SharedString::getEmptyString();
2051 double fVal
= PopDouble();
2052 sal_uLong nIndex
= pFormatter
->GetStandardFormat(
2053 css::util::NumberFormat::NUMBER
,
2056 pFormatter
->GetInputLineString(fVal
, nIndex
, aStr
);
2057 return mrStrPool
.intern(aStr
);
2064 PopSingleRef( aAdr
);
2065 if (nGlobalError
== 0)
2067 ScRefCellValue aCell
;
2068 aCell
.assign(*pDok
, aAdr
);
2069 svl::SharedString aSS
;
2070 GetCellString(aSS
, aCell
);
2074 return svl::SharedString::getEmptyString();
2077 { // generate position dependent SingleRef
2079 PopDoubleRef( aRange
);
2081 if ( !nGlobalError
&& DoubleRefToPosSingleRef( aRange
, aAdr
) )
2083 ScRefCellValue aCell
;
2084 aCell
.assign(*pDok
, aAdr
);
2085 svl::SharedString aSS
;
2086 GetCellString(aSS
, aCell
);
2090 return svl::SharedString::getEmptyString();
2092 case svExternalSingleRef
:
2094 ScExternalRefCache::TokenRef pToken
;
2095 PopExternalSingleRef(pToken
);
2097 return svl::SharedString::getEmptyString();
2099 return pToken
->GetString();
2101 case svExternalDoubleRef
:
2104 PopExternalDoubleRef(pMat
);
2105 return GetStringFromMatrix(pMat
);
2109 ScMatrixRef pMat
= PopMatrix();
2110 return GetStringFromMatrix(pMat
);
2115 SetError( errIllegalArgument
);
2117 return svl::SharedString::getEmptyString();
2120 svl::SharedString
ScInterpreter::GetStringFromMatrix(const ScMatrixRef
& pMat
)
2124 else if ( !pJumpMatrix
)
2126 return pMat
->GetString( *pFormatter
, 0, 0);
2130 SCSIZE nCols
, nRows
, nC
, nR
;
2131 pMat
->GetDimensions( nCols
, nRows
);
2132 pJumpMatrix
->GetPos( nC
, nR
);
2133 if ( nC
< nCols
&& nR
< nRows
)
2135 return pMat
->GetString( *pFormatter
, nC
, nR
);
2138 SetError( errNoValue
);
2140 return svl::SharedString::getEmptyString();
2143 ScMatValType
ScInterpreter::GetDoubleOrStringFromMatrix(
2144 double& rDouble
, svl::SharedString
& rString
)
2148 rString
= svl::SharedString::getEmptyString();
2149 ScMatValType nMatValType
= SC_MATVAL_EMPTY
;
2152 StackVar eType
= GetStackType();
2153 if (eType
== svExternalDoubleRef
|| eType
== svExternalSingleRef
|| eType
== svMatrix
)
2160 SetError( errIllegalParameter
);
2164 ScMatrixValue nMatVal
;
2169 else if (!pJumpMatrix
)
2171 nMatVal
= pMat
->Get(0, 0);
2172 nMatValType
= nMatVal
.nType
;
2176 SCSIZE nCols
, nRows
, nC
, nR
;
2177 pMat
->GetDimensions( nCols
, nRows
);
2178 pJumpMatrix
->GetPos( nC
, nR
);
2179 if ( nC
< nCols
&& nR
< nRows
)
2181 nMatVal
= pMat
->Get( nC
, nR
);
2182 nMatValType
= nMatVal
.nType
;
2185 SetError( errNoValue
);
2188 if (nMatValType
== SC_MATVAL_VALUE
)
2189 rDouble
= nMatVal
.fVal
;
2190 else if (nMatValType
== SC_MATVAL_BOOLEAN
)
2192 rDouble
= nMatVal
.fVal
;
2193 nMatValType
= SC_MATVAL_VALUE
;
2196 rString
= nMatVal
.GetString();
2198 if (ScMatrix::IsValueType( nMatValType
))
2200 sal_uInt16 nError
= nMatVal
.GetError();
2208 void ScInterpreter::ScDBGet()
2210 bool bMissingField
= false;
2211 unique_ptr
<ScDBQueryParamBase
> pQueryParam( GetDBParams(bMissingField
) );
2212 if (!pQueryParam
.get())
2214 // Failed to create query param.
2215 PushIllegalParameter();
2219 pQueryParam
->mbSkipString
= false;
2220 ScDBQueryDataIterator
aValIter(pDok
, pQueryParam
.release());
2221 ScDBQueryDataIterator::Value aValue
;
2222 if (!aValIter
.GetFirst(aValue
) || aValue
.mnError
)
2229 ScDBQueryDataIterator::Value aValNext
;
2230 if (aValIter
.GetNext(aValNext
) && !aValNext
.mnError
)
2232 // There should be only one unique match.
2233 PushIllegalArgument();
2237 if (aValue
.mbIsNumber
)
2238 PushDouble(aValue
.mfValue
);
2240 PushString(aValue
.maString
);
2243 void ScInterpreter::ScExternal()
2245 sal_uInt8 nParamCount
= GetByte();
2247 OUString
aFuncName( ScGlobal::pCharClass
->uppercase( pCur
->GetExternal() ) );
2248 FuncData
* pFuncData
= ScGlobal::GetFuncCollection()->findByName(aFuncName
);
2251 // Old binary non-UNO add-in function.
2252 // NOTE: parameter count is 1-based with the 0th "parameter" being the
2253 // return value, included in pFuncDatat->GetParamCount()
2254 if (nParamCount
< MAXFUNCPARAM
&& nParamCount
== pFuncData
->GetParamCount() - 1)
2256 ParamType eParamType
[MAXFUNCPARAM
];
2257 void* ppParam
[MAXFUNCPARAM
];
2258 double nVal
[MAXFUNCPARAM
];
2259 sal_Char
* pStr
[MAXFUNCPARAM
];
2260 sal_uInt8
* pCellArr
[MAXFUNCPARAM
];
2263 for (i
= 0; i
< MAXFUNCPARAM
; i
++)
2265 eParamType
[i
] = pFuncData
->GetParamType(i
);
2272 for (i
= nParamCount
; (i
> 0) && (nGlobalError
== 0); i
--)
2274 switch (eParamType
[i
])
2276 case ParamType::PTR_DOUBLE
:
2278 nVal
[i
-1] = GetDouble();
2279 ppParam
[i
] = &nVal
[i
-1];
2282 case ParamType::PTR_STRING
:
2284 OString
aStr(OUStringToOString(GetString().getString(),
2285 osl_getThreadTextEncoding()));
2286 if ( aStr
.getLength() >= ADDIN_MAXSTRLEN
)
2287 SetError( errStringOverflow
);
2290 pStr
[i
-1] = new sal_Char
[ADDIN_MAXSTRLEN
];
2291 strncpy( pStr
[i
-1], aStr
.getStr(), ADDIN_MAXSTRLEN
);
2292 pStr
[i
-1][ADDIN_MAXSTRLEN
-1] = 0;
2293 ppParam
[i
] = pStr
[i
-1];
2297 case ParamType::PTR_DOUBLE_ARR
:
2305 PopDoubleRef(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
2306 pCellArr
[i
-1] = new sal_uInt8
[MAXARRSIZE
];
2307 if (!CreateDoubleArr(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
, pCellArr
[i
-1]))
2308 SetError(errCodeOverflow
);
2310 ppParam
[i
] = pCellArr
[i
-1];
2313 case ParamType::PTR_STRING_ARR
:
2321 PopDoubleRef(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
2322 pCellArr
[i
-1] = new sal_uInt8
[MAXARRSIZE
];
2323 if (!CreateStringArr(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
, pCellArr
[i
-1]))
2324 SetError(errCodeOverflow
);
2326 ppParam
[i
] = pCellArr
[i
-1];
2329 case ParamType::PTR_CELL_ARR
:
2337 PopDoubleRef(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
2338 pCellArr
[i
-1] = new sal_uInt8
[MAXARRSIZE
];
2339 if (!CreateCellArr(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
, pCellArr
[i
-1]))
2340 SetError(errCodeOverflow
);
2342 ppParam
[i
] = pCellArr
[i
-1];
2346 SetError(errIllegalParameter
);
2351 Pop(); // im Fehlerfall (sonst ist i==0) Parameter wegpoppen
2353 if (nGlobalError
== 0)
2355 if ( pFuncData
->GetAsyncType() == ParamType::NONE
)
2357 switch ( eParamType
[0] )
2359 case ParamType::PTR_DOUBLE
:
2363 pFuncData
->Call(ppParam
);
2367 case ParamType::PTR_STRING
:
2369 boost::scoped_array
<sal_Char
> pcErg(new sal_Char
[ADDIN_MAXSTRLEN
]);
2370 ppParam
[0] = pcErg
.get();
2371 pFuncData
->Call(ppParam
);
2372 OUString
aUni( pcErg
.get(), strlen(pcErg
.get()), osl_getThreadTextEncoding() );
2377 PushError( errUnknownState
);
2382 // enable asyncs after loading
2383 if ( rArr
.IsRecalcModeNormal() )
2384 rArr
.SetExclusiveRecalcModeOnLoad();
2385 // assure identical handler with identical call?
2388 pFuncData
->Call(ppParam
);
2389 sal_uLong nHandle
= sal_uLong( nErg
);
2390 if ( nHandle
>= 65536 )
2392 ScAddInAsync
* pAs
= ScAddInAsync::Get( nHandle
);
2395 pAs
= new ScAddInAsync(nHandle
, pFuncData
, pDok
);
2396 pMyFormulaCell
->StartListening( *pAs
);
2400 pMyFormulaCell
->StartListening( *pAs
);
2401 if ( !pAs
->HasDocument( pDok
) )
2402 pAs
->AddDocument( pDok
);
2404 if ( pAs
->IsValid() )
2406 switch ( pAs
->GetType() )
2408 case ParamType::PTR_DOUBLE
:
2409 PushDouble( pAs
->GetValue() );
2411 case ParamType::PTR_STRING
:
2412 PushString( pAs
->GetString() );
2415 PushError( errUnknownState
);
2426 for (i
= 0; i
< MAXFUNCPARAM
; i
++)
2429 delete[] pCellArr
[i
];
2434 while( nParamCount
-- > 0)
2436 PushIllegalParameter();
2439 else if ( !( aUnoName
= ScGlobal::GetAddInCollection()->FindFunction(aFuncName
, false) ).isEmpty() )
2441 // bLocalFirst=false in FindFunction, cFunc should be the stored
2444 ScUnoAddInCall
aCall( *ScGlobal::GetAddInCollection(), aUnoName
, nParamCount
);
2446 if ( !aCall
.ValidParamCount() )
2447 SetError( errIllegalParameter
);
2449 if ( aCall
.NeedsCaller() && !GetError() )
2451 SfxObjectShell
* pShell
= pDok
->GetDocumentShell();
2453 aCall
.SetCallerFromObjectShell( pShell
);
2456 // use temporary model object (without document) to supply options
2457 aCall
.SetCaller( static_cast<beans::XPropertySet
*>(
2458 new ScDocOptionsObj( pDok
->GetDocOptions() ) ) );
2462 short nPar
= nParamCount
;
2463 while ( nPar
> 0 && !GetError() )
2465 --nPar
; // 0 .. (nParamCount-1)
2467 ScAddInArgumentType eType
= aCall
.GetArgType( nPar
);
2468 sal_uInt8 nStackType
= sal::static_int_cast
<sal_uInt8
>( GetStackType() );
2473 case SC_ADDINARG_INTEGER
:
2475 double fVal
= GetDouble();
2476 double fInt
= (fVal
>= 0.0) ? ::rtl::math::approxFloor( fVal
) :
2477 ::rtl::math::approxCeil( fVal
);
2478 if ( fInt
>= LONG_MIN
&& fInt
<= LONG_MAX
)
2479 aParam
<<= (sal_Int32
)fInt
;
2481 SetError(errIllegalArgument
);
2485 case SC_ADDINARG_DOUBLE
:
2486 aParam
<<= (double) GetDouble();
2489 case SC_ADDINARG_STRING
:
2490 aParam
<<= GetString().getString();
2493 case SC_ADDINARG_INTEGER_ARRAY
:
2494 switch( nStackType
)
2500 double fVal
= GetDouble();
2501 double fInt
= (fVal
>= 0.0) ? ::rtl::math::approxFloor( fVal
) :
2502 ::rtl::math::approxCeil( fVal
);
2503 if ( fInt
>= LONG_MIN
&& fInt
<= LONG_MAX
)
2505 sal_Int32 nIntVal
= (long)fInt
;
2506 uno::Sequence
<sal_Int32
> aInner( &nIntVal
, 1 );
2507 uno::Sequence
< uno::Sequence
<sal_Int32
> > aOuter( &aInner
, 1 );
2511 SetError(errIllegalArgument
);
2517 PopDoubleRef( aRange
);
2518 if (!ScRangeToSequence::FillLongArray( aParam
, pDok
, aRange
))
2519 SetError(errIllegalParameter
);
2523 if (!ScRangeToSequence::FillLongArray( aParam
, PopMatrix().get() ))
2524 SetError(errIllegalParameter
);
2528 SetError(errIllegalParameter
);
2532 case SC_ADDINARG_DOUBLE_ARRAY
:
2533 switch( nStackType
)
2539 double fVal
= GetDouble();
2540 uno::Sequence
<double> aInner( &fVal
, 1 );
2541 uno::Sequence
< uno::Sequence
<double> > aOuter( &aInner
, 1 );
2548 PopDoubleRef( aRange
);
2549 if (!ScRangeToSequence::FillDoubleArray( aParam
, pDok
, aRange
))
2550 SetError(errIllegalParameter
);
2554 if (!ScRangeToSequence::FillDoubleArray( aParam
, PopMatrix().get() ))
2555 SetError(errIllegalParameter
);
2559 SetError(errIllegalParameter
);
2563 case SC_ADDINARG_STRING_ARRAY
:
2564 switch( nStackType
)
2570 OUString aString
= GetString().getString();
2571 uno::Sequence
<OUString
> aInner( &aString
, 1 );
2572 uno::Sequence
< uno::Sequence
<OUString
> > aOuter( &aInner
, 1 );
2579 PopDoubleRef( aRange
);
2580 if (!ScRangeToSequence::FillStringArray( aParam
, pDok
, aRange
))
2581 SetError(errIllegalParameter
);
2585 if (!ScRangeToSequence::FillStringArray( aParam
, PopMatrix().get(), pFormatter
))
2586 SetError(errIllegalParameter
);
2590 SetError(errIllegalParameter
);
2594 case SC_ADDINARG_MIXED_ARRAY
:
2595 switch( nStackType
)
2602 if ( nStackType
== svDouble
)
2603 aElem
<<= (double) GetDouble();
2604 else if ( nStackType
== svString
)
2605 aElem
<<= GetString().getString();
2609 if ( PopDoubleRefOrSingleRef( aAdr
) )
2611 ScRefCellValue aCell
;
2612 aCell
.assign(*pDok
, aAdr
);
2613 if (aCell
.hasString())
2615 svl::SharedString aStr
;
2616 GetCellString(aStr
, aCell
);
2617 aElem
<<= aStr
.getString();
2620 aElem
<<= GetCellValue(aAdr
, aCell
);
2623 uno::Sequence
<uno::Any
> aInner( &aElem
, 1 );
2624 uno::Sequence
< uno::Sequence
<uno::Any
> > aOuter( &aInner
, 1 );
2631 PopDoubleRef( aRange
);
2632 if (!ScRangeToSequence::FillMixedArray( aParam
, pDok
, aRange
))
2633 SetError(errIllegalParameter
);
2637 if (!ScRangeToSequence::FillMixedArray( aParam
, PopMatrix().get() ))
2638 SetError(errIllegalParameter
);
2642 SetError(errIllegalParameter
);
2646 case SC_ADDINARG_VALUE_OR_ARRAY
:
2648 nStackType
= svMissing
;
2649 switch( nStackType
)
2652 aParam
<<= (double) GetDouble();
2655 aParam
<<= GetString().getString();
2660 if ( PopDoubleRefOrSingleRef( aAdr
) )
2662 ScRefCellValue aCell
;
2663 aCell
.assign(*pDok
, aAdr
);
2664 if (aCell
.hasString())
2666 svl::SharedString aStr
;
2667 GetCellString(aStr
, aCell
);
2668 aParam
<<= aStr
.getString();
2671 aParam
<<= GetCellValue(aAdr
, aCell
);
2678 PopDoubleRef( aRange
);
2679 if (!ScRangeToSequence::FillMixedArray( aParam
, pDok
, aRange
))
2680 SetError(errIllegalParameter
);
2684 if (!ScRangeToSequence::FillMixedArray( aParam
, PopMatrix().get() ))
2685 SetError(errIllegalParameter
);
2693 SetError(errIllegalParameter
);
2697 case SC_ADDINARG_CELLRANGE
:
2698 switch( nStackType
)
2703 PopSingleRef( aAdr
);
2704 ScRange
aRange( aAdr
);
2705 uno::Reference
<table::XCellRange
> xObj
=
2706 ScCellRangeObj::CreateRangeFromDoc( pDok
, aRange
);
2710 SetError(errIllegalParameter
);
2716 PopDoubleRef( aRange
);
2717 uno::Reference
<table::XCellRange
> xObj
=
2718 ScCellRangeObj::CreateRangeFromDoc( pDok
, aRange
);
2725 SetError(errIllegalParameter
);
2731 SetError(errIllegalParameter
);
2737 SetError(errIllegalParameter
);
2739 aCall
.SetParam( nPar
, aParam
);
2744 Pop(); // in case of error, remove remaining args
2748 aCall
.ExecuteCall();
2750 if ( aCall
.HasVarRes() ) // handle async functions
2752 if ( rArr
.IsRecalcModeNormal() )
2754 rArr
.SetExclusiveRecalcModeOnLoad();
2756 uno::Reference
<sheet::XVolatileResult
> xRes
= aCall
.GetVarRes();
2757 ScAddInListener
* pLis
= ScAddInListener::Get( xRes
);
2760 pLis
= ScAddInListener::CreateListener( xRes
, pDok
);
2761 pMyFormulaCell
->StartListening( *pLis
);
2765 pMyFormulaCell
->StartListening( *pLis
);
2766 if ( !pLis
->HasDocument( pDok
) )
2768 pLis
->AddDocument( pDok
);
2772 aCall
.SetResult( pLis
->GetResult() ); // use result from async
2775 if ( aCall
.GetErrCode() )
2777 PushError( aCall
.GetErrCode() );
2779 else if ( aCall
.HasMatrix() )
2781 ScMatrixRef xMat
= aCall
.GetMatrix();
2784 else if ( aCall
.HasString() )
2786 PushString( aCall
.GetString() );
2790 PushDouble( aCall
.GetValue() );
2794 PushError( GetError());
2798 while( nParamCount
-- > 0)
2802 PushError( errNoAddin
);
2806 void ScInterpreter::ScMissing()
2808 if ( aCode
.IsEndOfPath() )
2809 PushTempToken( new ScEmptyCellToken( false, false ) );
2811 PushTempToken( new FormulaMissingToken
);
2814 #if HAVE_FEATURE_SCRIPTING
2816 static uno::Any
lcl_getSheetModule( const uno::Reference
<table::XCellRange
>& xCellRange
, ScDocument
* pDok
)
2818 uno::Reference
< sheet::XSheetCellRange
> xSheetRange( xCellRange
, uno::UNO_QUERY_THROW
);
2819 uno::Reference
< beans::XPropertySet
> xProps( xSheetRange
->getSpreadsheet(), uno::UNO_QUERY_THROW
);
2821 xProps
->getPropertyValue("CodeName") >>= sCodeName
;
2822 // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible
2823 // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there
2824 // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at
2825 // the document in the future could fix this, especially IF the switching of the vba mode takes care to
2826 // create the special document module objects if they don't exist.
2827 BasicManager
* pBasMgr
= pDok
->GetDocumentShell()->GetBasicManager();
2829 uno::Reference
< uno::XInterface
> xIf
;
2830 if ( pBasMgr
&& !pBasMgr
->GetName().isEmpty() )
2832 OUString
sProj( "Standard" );
2833 if ( !pDok
->GetDocumentShell()->GetBasicManager()->GetName().isEmpty() )
2835 sProj
= pDok
->GetDocumentShell()->GetBasicManager()->GetName();
2837 StarBASIC
* pBasic
= pDok
->GetDocumentShell()->GetBasicManager()->GetLib( sProj
);
2840 SbModule
* pMod
= pBasic
->FindModule( sCodeName
);
2843 xIf
= pMod
->GetUnoModule();
2847 return uno::makeAny( xIf
);
2850 static bool lcl_setVBARange( ScRange
& aRange
, ScDocument
* pDok
, SbxVariable
* pPar
)
2855 uno::Reference
< uno::XInterface
> xVBARange
;
2856 uno::Reference
<table::XCellRange
> xCellRange
= ScCellRangeObj::CreateRangeFromDoc( pDok
, aRange
);
2857 uno::Sequence
< uno::Any
> aArgs(2);
2858 aArgs
[0] = lcl_getSheetModule( xCellRange
, pDok
);
2859 aArgs
[1] = uno::Any( xCellRange
);
2860 xVBARange
= ooo::vba::createVBAUnoAPIServiceWithArgs( pDok
->GetDocumentShell(), "ooo.vba.excel.Range", aArgs
);
2861 if ( xVBARange
.is() )
2863 OUString
sDummy("A-Range");
2864 SbxObjectRef aObj
= GetSbUnoObject( sDummy
, uno::Any( xVBARange
) );
2865 SetSbUnoObjectDfltPropName( aObj
);
2866 bOk
= pPar
->PutObject( aObj
);
2869 catch( uno::Exception
& )
2877 void ScInterpreter::ScMacro()
2880 #if !HAVE_FEATURE_SCRIPTING
2881 PushNoValue(); // without DocShell no CallBasic
2884 SbxBase::ResetError();
2886 sal_uInt8 nParamCount
= GetByte();
2887 OUString
aMacro( pCur
->GetExternal() );
2889 SfxObjectShell
* pDocSh
= pDok
->GetDocumentShell();
2890 if ( !pDocSh
|| !ScDocument::CheckMacroWarn() )
2892 PushNoValue(); // without DocShell no CallBasic
2896 // no security queue beforehand (just CheckMacroWarn), moved to CallBasic
2898 // If the Dok was loaded during a Basic-Calls,
2899 // is the Sbx-Objekt created(?)
2900 // pDocSh->GetSbxObject();
2902 // search function with the name,
2903 // then assemble SfxObjectShell::CallBasic from aBasicStr, aMacroStr
2909 pRoot
= pDocSh
->GetBasic();
2916 SbxVariable
* pVar
= pRoot
? pRoot
->Find(aMacro
, SbxCLASS_METHOD
) : NULL
;
2917 if( !pVar
|| pVar
->GetType() == SbxVOID
|| !pVar
->ISA(SbMethod
) )
2919 PushError( errNoMacro
);
2923 bool bVolatileMacro
= false;
2924 SbMethod
* pMethod
= static_cast<SbMethod
*>(pVar
);
2926 SbModule
* pModule
= pMethod
->GetModule();
2927 bool bUseVBAObjects
= pModule
->IsVBACompat();
2928 SbxObject
* pObject
= pModule
->GetParent();
2929 OSL_ENSURE(pObject
->IsA(TYPE(StarBASIC
)), "No Basic found!");
2930 OUString aMacroStr
= pObject
->GetName() + "." + pModule
->GetName() + "." + pMethod
->GetName();
2932 if (pObject
->GetParent())
2934 aBasicStr
= pObject
->GetParent()->GetName(); // Dokumentenbasic
2938 aBasicStr
= SfxGetpApp()->GetName(); // Applikationsbasic
2940 // Parameter-Array zusammenbauen
2942 SbxArrayRef refPar
= new SbxArray
;
2944 for( short i
= nParamCount
; i
&& bOk
; i
-- )
2946 SbxVariable
* pPar
= refPar
->Get( (sal_uInt16
) i
);
2947 sal_uInt8 nStackType
= sal::static_int_cast
<sal_uInt8
>( GetStackType() );
2948 switch( nStackType
)
2951 pPar
->PutDouble( GetDouble() );
2954 pPar
->PutString( GetString().getString() );
2956 case svExternalSingleRef
:
2958 ScExternalRefCache::TokenRef pToken
;
2959 PopExternalSingleRef(pToken
);
2960 if ( pToken
->GetType() == svString
)
2961 pPar
->PutString( pToken
->GetString().getString() );
2962 else if ( pToken
->GetType() == svDouble
)
2963 pPar
->PutDouble( pToken
->GetDouble() );
2966 SetError( errIllegalArgument
);
2974 PopSingleRef( aAdr
);
2975 if ( bUseVBAObjects
)
2977 ScRange
aRange( aAdr
);
2978 bOk
= lcl_setVBARange( aRange
, pDok
, pPar
);
2982 bOk
= SetSbxVariable( pPar
, aAdr
);
2994 PopDoubleRef( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
2995 if( nTab1
!= nTab2
)
2997 SetError( errIllegalParameter
);
3002 if ( bUseVBAObjects
)
3004 ScRange
aRange( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
3005 bOk
= lcl_setVBARange( aRange
, pDok
, pPar
);
3009 SbxDimArrayRef refArray
= new SbxDimArray
;
3010 refArray
->AddDim32( 1, nRow2
- nRow1
+ 1 );
3011 refArray
->AddDim32( 1, nCol2
- nCol1
+ 1 );
3012 ScAddress
aAdr( nCol1
, nRow1
, nTab1
);
3013 for( SCROW nRow
= nRow1
; bOk
&& nRow
<= nRow2
; nRow
++ )
3015 aAdr
.SetRow( nRow
);
3016 sal_Int32 nIdx
[ 2 ];
3017 nIdx
[ 0 ] = nRow
-nRow1
+1;
3018 for( SCCOL nCol
= nCol1
; bOk
&& nCol
<= nCol2
; nCol
++ )
3020 aAdr
.SetCol( nCol
);
3021 nIdx
[ 1 ] = nCol
-nCol1
+1;
3022 SbxVariable
* p
= refArray
->Get32( nIdx
);
3023 bOk
= SetSbxVariable( p
, aAdr
);
3026 pPar
->PutObject( refArray
);
3031 case svExternalDoubleRef
:
3034 ScMatrixRef pMat
= GetMatrix();
3036 if (pMat
&& !nGlobalError
)
3038 pMat
->GetDimensions(nC
, nR
);
3039 SbxDimArrayRef refArray
= new SbxDimArray
;
3040 refArray
->AddDim32( 1, static_cast<sal_Int32
>(nR
) );
3041 refArray
->AddDim32( 1, static_cast<sal_Int32
>(nC
) );
3042 for( SCSIZE nMatRow
= 0; nMatRow
< nR
; nMatRow
++ )
3044 sal_Int32 nIdx
[ 2 ];
3045 nIdx
[ 0 ] = static_cast<sal_Int32
>(nMatRow
+1);
3046 for( SCSIZE nMatCol
= 0; nMatCol
< nC
; nMatCol
++ )
3048 nIdx
[ 1 ] = static_cast<sal_Int32
>(nMatCol
+1);
3049 SbxVariable
* p
= refArray
->Get32( nIdx
);
3050 if (pMat
->IsString(nMatCol
, nMatRow
))
3052 p
->PutString( pMat
->GetString(nMatCol
, nMatRow
).getString() );
3056 p
->PutDouble( pMat
->GetDouble(nMatCol
, nMatRow
));
3060 pPar
->PutObject( refArray
);
3064 SetError( errIllegalParameter
);
3069 SetError( errIllegalParameter
);
3075 pDok
->LockTable( aPos
.Tab() );
3076 SbxVariableRef refRes
= new SbxVariable
;
3077 pDok
->IncMacroInterpretLevel();
3078 ErrCode eRet
= pDocSh
->CallBasic( aMacroStr
, aBasicStr
, refPar
, refRes
);
3079 pDok
->DecMacroInterpretLevel();
3080 pDok
->UnlockTable( aPos
.Tab() );
3082 ScMacroManager
* pMacroMgr
= pDok
->GetMacroManager();
3085 bVolatileMacro
= pMacroMgr
->GetUserFuncVolatile( pMethod
->GetName() );
3086 pMacroMgr
->AddDependentCell(pModule
->GetName(), pMyFormulaCell
);
3089 SbxDataType eResType
= refRes
->GetType();
3090 if( SbxBase::GetError() )
3092 SetError( errNoValue
);
3094 if ( eRet
!= ERRCODE_NONE
)
3098 else if( eResType
>= SbxINTEGER
&& eResType
<= SbxDOUBLE
)
3100 PushDouble( refRes
->GetDouble() );
3102 else if ( eResType
& SbxARRAY
)
3104 SbxBase
* pElemObj
= refRes
->GetObject();
3105 SbxDimArray
* pDimArray
= PTR_CAST(SbxDimArray
,pElemObj
);
3106 short nDim
= pDimArray
->GetDims();
3107 if ( 1 <= nDim
&& nDim
<= 2 )
3109 sal_Int32 nCs
, nCe
, nRs
, nRe
;
3114 { // array( cols ) one line, several columns
3115 pDimArray
->GetDim32( 1, nCs
, nCe
);
3116 nC
= static_cast<SCSIZE
>(nCe
- nCs
+ 1);
3123 { // array( rows, cols )
3124 pDimArray
->GetDim32( 1, nRs
, nRe
);
3125 nR
= static_cast<SCSIZE
>(nRe
- nRs
+ 1);
3126 pDimArray
->GetDim32( 2, nCs
, nCe
);
3127 nC
= static_cast<SCSIZE
>(nCe
- nCs
+ 1);
3131 ScMatrixRef pMat
= GetNewMat( nC
, nR
);
3136 for ( SCSIZE j
=0; j
< nR
; j
++ )
3138 sal_Int32 nIdx
[ 2 ];
3139 // in one-dimensional array( cols ) nIdx[1]
3140 // from SbxDimArray::Get is ignored
3141 nIdx
[ nRowIdx
] = nRs
+ static_cast<sal_Int32
>(j
);
3142 for ( SCSIZE i
=0; i
< nC
; i
++ )
3144 nIdx
[ nColIdx
] = nCs
+ static_cast<sal_Int32
>(i
);
3145 pV
= pDimArray
->Get32( nIdx
);
3146 eType
= pV
->GetType();
3147 if ( eType
>= SbxINTEGER
&& eType
<= SbxDOUBLE
)
3149 pMat
->PutDouble( pV
->GetDouble(), i
, j
);
3153 pMat
->PutString(mrStrPool
.intern(pV
->GetOUString()), i
, j
);
3161 PushIllegalArgument();
3171 PushString( refRes
->GetOUString() );
3175 if (bVolatileMacro
&& meVolatileType
== NOT_VOLATILE
)
3176 meVolatileType
= VOLATILE_MACRO
;
3180 #if HAVE_FEATURE_SCRIPTING
3182 bool ScInterpreter::SetSbxVariable( SbxVariable
* pVar
, const ScAddress
& rPos
)
3185 ScRefCellValue aCell
;
3186 aCell
.assign(*pDok
, rPos
);
3187 if (!aCell
.isEmpty())
3191 switch (aCell
.meType
)
3193 case CELLTYPE_VALUE
:
3194 nVal
= GetValueCellValue(rPos
, aCell
.mfValue
);
3195 pVar
->PutDouble( nVal
);
3197 case CELLTYPE_STRING
:
3198 case CELLTYPE_EDIT
:
3199 pVar
->PutString(aCell
.getString(pDok
));
3201 case CELLTYPE_FORMULA
:
3202 nErr
= aCell
.mpFormula
->GetErrCode();
3205 if (aCell
.mpFormula
->IsValue())
3207 nVal
= aCell
.mpFormula
->GetValue();
3208 pVar
->PutDouble(aCell
.mpFormula
->GetValue());
3211 pVar
->PutString(aCell
.mpFormula
->GetString().getString());
3214 SetError( nErr
), bOk
= false;
3217 pVar
->PutDouble( 0.0 );
3221 pVar
->PutDouble( 0.0 );
3229 class FindByPointer
: ::std::unary_function
<ScInterpreterTableOpParams
, bool>
3231 const ScInterpreterTableOpParams
* mpTableOp
;
3233 FindByPointer(const ScInterpreterTableOpParams
* p
) : mpTableOp(p
) {}
3234 bool operator() (const ScInterpreterTableOpParams
& val
) const
3236 return &val
== mpTableOp
;
3242 void ScInterpreter::ScTableOp()
3244 sal_uInt8 nParamCount
= GetByte();
3245 if (nParamCount
!= 3 && nParamCount
!= 5)
3247 PushIllegalParameter();
3250 ScInterpreterTableOpParams
* pTableOp
= new ScInterpreterTableOpParams
;
3251 if (nParamCount
== 5)
3253 PopSingleRef( pTableOp
->aNew2
);
3254 PopSingleRef( pTableOp
->aOld2
);
3256 PopSingleRef( pTableOp
->aNew1
);
3257 PopSingleRef( pTableOp
->aOld1
);
3258 PopSingleRef( pTableOp
->aFormulaPos
);
3260 pTableOp
->bValid
= true;
3261 pDok
->aTableOpList
.push_back( pTableOp
);
3262 pDok
->IncInterpreterTableOpLevel();
3264 bool bReuseLastParams
= (pDok
->aLastTableOpParams
== *pTableOp
);
3265 if ( bReuseLastParams
)
3267 pTableOp
->aNotifiedFormulaPos
= pDok
->aLastTableOpParams
.aNotifiedFormulaPos
;
3268 pTableOp
->bRefresh
= true;
3269 for ( ::std::vector
< ScAddress
>::const_iterator
iBroadcast(
3270 pTableOp
->aNotifiedFormulaPos
.begin() );
3271 iBroadcast
!= pTableOp
->aNotifiedFormulaPos
.end();
3273 { // emulate broadcast and indirectly collect cell pointers
3274 ScRefCellValue aCell
;
3275 aCell
.assign(*pDok
, *iBroadcast
);
3276 if (aCell
.meType
== CELLTYPE_FORMULA
)
3277 aCell
.mpFormula
->SetTableOpDirty();
3281 { // broadcast and indirectly collect cell pointers and positions
3282 pDok
->SetTableOpDirty( pTableOp
->aOld1
);
3283 if ( nParamCount
== 5 )
3284 pDok
->SetTableOpDirty( pTableOp
->aOld2
);
3286 pTableOp
->bCollectNotifications
= false;
3288 ScRefCellValue aCell
;
3289 aCell
.assign(*pDok
, pTableOp
->aFormulaPos
);
3290 if (aCell
.meType
== CELLTYPE_FORMULA
)
3291 aCell
.mpFormula
->SetDirtyVar();
3292 if (aCell
.hasNumeric())
3294 PushDouble(GetCellValue(pTableOp
->aFormulaPos
, aCell
));
3298 svl::SharedString aCellString
;
3299 GetCellString(aCellString
, aCell
);
3300 PushString( aCellString
);
3303 boost::ptr_vector
< ScInterpreterTableOpParams
>::iterator itr
=
3304 ::std::find_if(pDok
->aTableOpList
.begin(), pDok
->aTableOpList
.end(), FindByPointer(pTableOp
));
3305 if (itr
!= pDok
->aTableOpList
.end())
3306 pTableOp
= pDok
->aTableOpList
.release(itr
).release();
3308 // set dirty again once more to be able to recalculate original
3309 for ( ::std::vector
< ScFormulaCell
* >::const_iterator
iBroadcast(
3310 pTableOp
->aNotifiedFormulaCells
.begin() );
3311 iBroadcast
!= pTableOp
->aNotifiedFormulaCells
.end();
3314 (*iBroadcast
)->SetTableOpDirty();
3317 // save these params for next incarnation
3318 if ( !bReuseLastParams
)
3319 pDok
->aLastTableOpParams
= *pTableOp
;
3321 if (aCell
.meType
== CELLTYPE_FORMULA
)
3323 aCell
.mpFormula
->SetDirtyVar();
3324 aCell
.mpFormula
->GetErrCode(); // recalculate original
3327 // Reset all dirty flags so next incarnation does really collect all cell
3328 // pointers during notifications and not just non-dirty ones, which may
3329 // happen if a formula cell is used by more than one TableOp block.
3330 for ( ::std::vector
< ScFormulaCell
* >::const_iterator
iBroadcast2(
3331 pTableOp
->aNotifiedFormulaCells
.begin() );
3332 iBroadcast2
!= pTableOp
->aNotifiedFormulaCells
.end();
3335 (*iBroadcast2
)->ResetTableOpDirtyVar();
3339 pDok
->DecInterpreterTableOpLevel();
3342 void ScInterpreter::ScDBArea()
3344 ScDBData
* pDBData
= pDok
->GetDBCollection()->getNamedDBs().findByIndex(pCur
->GetIndex());
3347 ScComplexRefData aRefData
;
3348 aRefData
.InitFlags();
3350 pDBData
->GetArea(aRange
);
3351 aRange
.aEnd
.SetTab(aRange
.aStart
.Tab());
3352 aRefData
.SetRange(aRange
, aPos
);
3353 PushTempToken( new ScDoubleRefToken( aRefData
) );
3356 PushError( errNoName
);
3359 void ScInterpreter::ScColRowNameAuto()
3361 ScComplexRefData
aRefData( *pCur
->GetDoubleRef() );
3362 ScRange aAbs
= aRefData
.toAbs(aPos
);
3363 if (!ValidRange(aAbs
))
3365 PushError( errNoRef
);
3372 // maybe remember limit by using defined ColRowNameRange
3373 SCsCOL nCol2
= aAbs
.aEnd
.Col();
3374 SCsROW nRow2
= aAbs
.aEnd
.Row();
3375 // DataArea of the first cell
3376 nStartCol
= aAbs
.aStart
.Col();
3377 nStartRow
= aAbs
.aStart
.Row();
3378 aAbs
.aEnd
= aAbs
.aStart
; // Shrink to the top-left cell.
3381 // Expand to the data area. Only modify the end position.
3382 SCCOL nDACol1
= aAbs
.aStart
.Col(), nDACol2
= aAbs
.aEnd
.Col();
3383 SCROW nDARow1
= aAbs
.aStart
.Row(), nDARow2
= aAbs
.aEnd
.Row();
3384 pDok
->GetDataArea(aAbs
.aStart
.Tab(), nDACol1
, nDARow1
, nDACol2
, nDARow2
, true, false);
3385 aAbs
.aEnd
.SetCol(nDACol2
);
3386 aAbs
.aEnd
.SetRow(nDARow2
);
3389 // corresponds with ScCompiler::GetToken
3390 if ( aRefData
.Ref1
.IsColRel() )
3392 aAbs
.aEnd
.SetCol(nStartCol
);
3393 // maybe get previous limit by using defined ColRowNameRange
3394 if (aAbs
.aEnd
.Row() > nRow2
)
3395 aAbs
.aEnd
.SetRow(nRow2
);
3397 if ( aPos
.Col() == nStartCol
3398 && nStartRow
<= (nMyRow
= aPos
.Row()) && nMyRow
<= aAbs
.aEnd
.Row())
3399 { //Formula in the same column and within the range
3400 if ( nMyRow
== nStartRow
)
3401 { // take the rest under the name
3403 if ( nStartRow
> MAXROW
)
3405 aAbs
.aStart
.SetRow(nStartRow
);
3408 { // below the name to the formula cell
3409 aAbs
.aEnd
.SetRow(nMyRow
- 1);
3415 aAbs
.aEnd
.SetRow(nStartRow
);
3416 // maybe get previous limit by using defined ColRowNameRange
3417 if (aAbs
.aEnd
.Col() > nCol2
)
3418 aAbs
.aEnd
.SetCol(nCol2
);
3420 if ( aPos
.Row() == nStartRow
3421 && nStartCol
<= (nMyCol
= aPos
.Col()) && nMyCol
<= aAbs
.aEnd
.Col())
3422 { //Formula in the same column and within the range
3423 if ( nMyCol
== nStartCol
)
3424 { // take the rest under the name
3426 if ( nStartCol
> MAXCOL
)
3428 aAbs
.aStart
.SetCol(nStartCol
);
3431 { // below the name to the formula cell
3432 aAbs
.aEnd
.SetCol(nMyCol
- 1);
3436 aRefData
.SetRange(aAbs
, aPos
);
3437 PushTempToken( new ScDoubleRefToken( aRefData
) );
3440 // --- internals ------------------------------------------------------------
3442 void ScInterpreter::ScTTT()
3443 { // temporary test, testing functions etc.
3444 sal_uInt8 nParamCount
= GetByte();
3445 // do something, count down nParamCount with Pops!
3448 while ( nParamCount
-- > 0)
3450 PushError(errNoValue
);
3453 ScInterpreter::ScInterpreter( ScFormulaCell
* pCell
, ScDocument
* pDoc
,
3454 const ScAddress
& rPos
, ScTokenArray
& r
)
3459 , mrStrPool(pDoc
->GetSharedStringPool())
3461 , pTokenMatrixMap(NULL
)
3462 , pMyFormulaCell(pCell
)
3463 , pFormatter(pDoc
->GetFormatTable())
3474 , mnStringNoValueError(errNoValue
)
3475 , mnSubTotalFlags(0)
3477 , bCalcAsShown(pDoc
->GetDocOptions().IsCalcAsShown())
3478 , meVolatileType(r
.IsRecalcModeAlways() ? VOLATILE
: NOT_VOLATILE
)
3484 sal_uInt8 cMatFlag
= pMyFormulaCell
->GetMatrixFlag();
3485 bMatrixFormula
= ( cMatFlag
== MM_FORMULA
|| cMatFlag
== MM_FAKE
);
3488 bMatrixFormula
= false;
3490 if (!bGlobalStackInUse
)
3492 bGlobalStackInUse
= true;
3494 pGlobalStack
= new ScTokenStack
;
3495 pStackObj
= pGlobalStack
;
3499 pStackObj
= new ScTokenStack
;
3501 pStack
= pStackObj
->pPointer
;
3504 ScInterpreter::~ScInterpreter()
3508 if ( pStackObj
== pGlobalStack
)
3509 bGlobalStackInUse
= false;
3512 if (pTokenMatrixMap
)
3513 delete pTokenMatrixMap
;
3516 void ScInterpreter::SetGlobalConfig(const ScCalcConfig
& rConfig
)
3518 maGlobalConfig
= rConfig
;
3521 const ScCalcConfig
& ScInterpreter::GetGlobalConfig()
3523 return maGlobalConfig
;
3526 void ScInterpreter::MergeCalcConfig()
3528 maCalcConfig
= maGlobalConfig
;
3529 maCalcConfig
.MergeDocumentSpecific( pDok
->GetCalcConfig());
3532 void ScInterpreter::GlobalExit()
3534 OSL_ENSURE(!bGlobalStackInUse
, "who is still using the TokenStack?");
3535 DELETEZ(pGlobalStack
);
3540 double applyImplicitIntersection(const sc::RangeMatrix
& rMat
, const ScAddress
& rPos
)
3542 if (rMat
.mnRow1
<= rPos
.Row() && rPos
.Row() <= rMat
.mnRow2
&& rMat
.mnCol1
== rMat
.mnCol2
)
3544 SCROW nOffset
= rPos
.Row() - rMat
.mnRow1
;
3545 return rMat
.mpMat
->GetDouble(0, nOffset
);
3548 if (rMat
.mnCol1
<= rPos
.Col() && rPos
.Col() <= rMat
.mnCol2
&& rMat
.mnRow1
== rMat
.mnRow2
)
3550 SCROW nOffset
= rPos
.Col() - rMat
.mnCol1
;
3551 return rMat
.mpMat
->GetDouble(nOffset
, 0);
3555 rtl::math::setNan(&fVal
);
3561 StackVar
ScInterpreter::Interpret()
3563 short nRetTypeExpr
= css::util::NumberFormat::UNDEFINED
;
3564 sal_uLong nRetIndexExpr
= 0;
3565 sal_uInt16 nErrorFunction
= 0;
3566 sal_uInt16 nErrorFunctionCount
= 0;
3567 sal_uInt16 nStackBase
;
3570 nStackBase
= sp
= maxsp
= 0;
3571 nRetFmtType
= css::util::NumberFormat::UNDEFINED
;
3572 nFuncFmtType
= css::util::NumberFormat::UNDEFINED
;
3573 nFuncFmtIndex
= nCurFmtIndex
= nRetFmtIndex
= 0;
3576 mnSubTotalFlags
= 0x00;
3577 ScTokenMatrixMap::const_iterator aTokenMatrixMapIter
;
3579 // Once upon a time we used to have FP exceptions on, and there was a
3580 // Windows printer driver that kept switching off exceptions, so we had to
3581 // switch them back on again every time. Who knows if there isn't a driver
3582 // that keeps switching exceptions on, now that we run with exceptions off,
3583 // so reassure exceptions are really off.
3584 SAL_MATH_FPEXCEPTIONS_OFF();
3587 while( ( pCur
= aCode
.Next() ) != NULL
3588 && (!nGlobalError
|| nErrorFunction
<= nErrorFunctionCount
) )
3590 OpCode eOp
= pCur
->GetOpCode();
3591 cPar
= pCur
->GetByte();
3592 if ( eOp
== ocPush
)
3594 // RPN code push without error
3595 PushWithoutError( (FormulaToken
&) *pCur
);
3597 else if (pTokenMatrixMap
&&
3598 !(eOp
== ocIf
|| eOp
== ocIfError
|| eOp
== ocIfNA
|| eOp
== ocChoose
) &&
3599 ((aTokenMatrixMapIter
= pTokenMatrixMap
->find( pCur
)) !=
3600 pTokenMatrixMap
->end()) &&
3601 (*aTokenMatrixMapIter
).second
->GetType() != svJumpMatrix
)
3603 // Path already calculated, reuse result.
3604 nStackBase
= sp
- pCur
->GetParamCount();
3605 if ( nStackBase
> sp
)
3606 nStackBase
= sp
; // underflow?!?
3608 PushTempToken( (*aTokenMatrixMapIter
).second
.get());
3612 // previous expression determines the current number format
3613 nCurFmtType
= nRetTypeExpr
;
3614 nCurFmtIndex
= nRetIndexExpr
;
3615 // default function's format, others are set if needed
3616 nFuncFmtType
= css::util::NumberFormat::NUMBER
;
3619 if ( eOp
== ocIf
|| eOp
== ocChoose
|| eOp
== ocIfError
|| eOp
== ocIfNA
)
3620 nStackBase
= sp
; // don't mess around with the jumps
3623 // Convert parameters to matrix if in array/matrix formula and
3624 // parameters of function indicate doing so. Create JumpMatrix
3626 if ( MatrixParameterConversion() )
3628 eOp
= ocNone
; // JumpMatrix created
3632 nStackBase
= sp
- pCur
->GetParamCount();
3634 if ( nStackBase
> sp
)
3635 nStackBase
= sp
; // underflow?!?
3640 case ocClose
: // pushed by the compiler
3641 case ocMissing
: ScMissing(); break;
3642 case ocMacro
: ScMacro(); break;
3643 case ocDBArea
: ScDBArea(); break;
3644 case ocColRowNameAuto
: ScColRowNameAuto(); break;
3645 case ocIf
: ScIfJump(); break;
3646 case ocIfError
: ScIfError( false ); break;
3647 case ocIfNA
: ScIfError( true ); break;
3648 case ocChoose
: ScChooseJump(); break;
3649 case ocAdd
: ScAdd(); break;
3650 case ocSub
: ScSub(); break;
3651 case ocMul
: ScMul(); break;
3652 case ocDiv
: ScDiv(); break;
3653 case ocAmpersand
: ScAmpersand(); break;
3654 case ocPow
: ScPow(); break;
3655 case ocEqual
: ScEqual(); break;
3656 case ocNotEqual
: ScNotEqual(); break;
3657 case ocLess
: ScLess(); break;
3658 case ocGreater
: ScGreater(); break;
3659 case ocLessEqual
: ScLessEqual(); break;
3660 case ocGreaterEqual
: ScGreaterEqual(); break;
3661 case ocAnd
: ScAnd(); break;
3662 case ocOr
: ScOr(); break;
3663 case ocXor
: ScXor(); break;
3664 case ocIntersect
: ScIntersect(); break;
3665 case ocRange
: ScRangeFunc(); break;
3666 case ocUnion
: ScUnionFunc(); break;
3667 case ocNot
: ScNot(); break;
3669 case ocNeg
: ScNeg(); break;
3670 case ocPercentSign
: ScPercentSign(); break;
3671 case ocPi
: ScPi(); break;
3672 case ocRandom
: ScRandom(); break;
3673 case ocTrue
: ScTrue(); break;
3674 case ocFalse
: ScFalse(); break;
3675 case ocGetActDate
: ScGetActDate(); break;
3676 case ocGetActTime
: ScGetActTime(); break;
3677 case ocNotAvail
: PushError( NOTAVAILABLE
); break;
3678 case ocDeg
: ScDeg(); break;
3679 case ocRad
: ScRad(); break;
3680 case ocSin
: ScSin(); break;
3681 case ocCos
: ScCos(); break;
3682 case ocTan
: ScTan(); break;
3683 case ocCot
: ScCot(); break;
3684 case ocArcSin
: ScArcSin(); break;
3685 case ocArcCos
: ScArcCos(); break;
3686 case ocArcTan
: ScArcTan(); break;
3687 case ocArcCot
: ScArcCot(); break;
3688 case ocSinHyp
: ScSinHyp(); break;
3689 case ocCosHyp
: ScCosHyp(); break;
3690 case ocTanHyp
: ScTanHyp(); break;
3691 case ocCotHyp
: ScCotHyp(); break;
3692 case ocArcSinHyp
: ScArcSinHyp(); break;
3693 case ocArcCosHyp
: ScArcCosHyp(); break;
3694 case ocArcTanHyp
: ScArcTanHyp(); break;
3695 case ocArcCotHyp
: ScArcCotHyp(); break;
3696 case ocCosecant
: ScCosecant(); break;
3697 case ocSecant
: ScSecant(); break;
3698 case ocCosecantHyp
: ScCosecantHyp(); break;
3699 case ocSecantHyp
: ScSecantHyp(); break;
3700 case ocExp
: ScExp(); break;
3701 case ocLn
: ScLn(); break;
3702 case ocLog10
: ScLog10(); break;
3703 case ocSqrt
: ScSqrt(); break;
3704 case ocFact
: ScFact(); break;
3705 case ocGetYear
: ScGetYear(); break;
3706 case ocGetMonth
: ScGetMonth(); break;
3707 case ocGetDay
: ScGetDay(); break;
3708 case ocGetDayOfWeek
: ScGetDayOfWeek(); break;
3709 case ocWeek
: ScGetWeekOfYear(); break;
3710 case ocEasterSunday
: ScEasterSunday(); break;
3711 case ocNetWorkdays
: ScNetWorkdays( false); break;
3712 case ocNetWorkdays_MS
: ScNetWorkdays( true ); break;
3713 case ocWorkday_MS
: ScWorkday_MS(); break;
3714 case ocGetHour
: ScGetHour(); break;
3715 case ocGetMin
: ScGetMin(); break;
3716 case ocGetSec
: ScGetSec(); break;
3717 case ocPlusMinus
: ScPlusMinus(); break;
3718 case ocAbs
: ScAbs(); break;
3719 case ocInt
: ScInt(); break;
3720 case ocEven
: ScEven(); break;
3721 case ocOdd
: ScOdd(); break;
3722 case ocPhi
: ScPhi(); break;
3723 case ocGauss
: ScGauss(); break;
3724 case ocStdNormDist
: ScStdNormDist(); break;
3725 case ocStdNormDist_MS
: ScStdNormDist_MS(); break;
3726 case ocFisher
: ScFisher(); break;
3727 case ocFisherInv
: ScFisherInv(); break;
3728 case ocIsEmpty
: ScIsEmpty(); break;
3729 case ocIsString
: ScIsString(); break;
3730 case ocIsNonString
: ScIsNonString(); break;
3731 case ocIsLogical
: ScIsLogical(); break;
3732 case ocType
: ScType(); break;
3733 case ocCell
: ScCell(); break;
3734 case ocIsRef
: ScIsRef(); break;
3735 case ocIsValue
: ScIsValue(); break;
3736 case ocIsFormula
: ScIsFormula(); break;
3737 case ocFormula
: ScFormula(); break;
3738 case ocIsNA
: ScIsNV(); break;
3739 case ocIsErr
: ScIsErr(); break;
3740 case ocIsError
: ScIsError(); break;
3741 case ocIsEven
: ScIsEven(); break;
3742 case ocIsOdd
: ScIsOdd(); break;
3743 case ocN
: ScN(); break;
3744 case ocGetDateValue
: ScGetDateValue(); break;
3745 case ocGetTimeValue
: ScGetTimeValue(); break;
3746 case ocCode
: ScCode(); break;
3747 case ocTrim
: ScTrim(); break;
3748 case ocUpper
: ScUpper(); break;
3749 case ocProper
: ScProper(); break;
3750 case ocLower
: ScLower(); break;
3751 case ocLen
: ScLen(); break;
3752 case ocT
: ScT(); break;
3753 case ocClean
: ScClean(); break;
3754 case ocValue
: ScValue(); break;
3755 case ocNumberValue
: ScNumberValue(); break;
3756 case ocChar
: ScChar(); break;
3757 case ocArcTan2
: ScArcTan2(); break;
3758 case ocMod
: ScMod(); break;
3759 case ocPower
: ScPower(); break;
3760 case ocRound
: ScRound(); break;
3761 case ocRoundUp
: ScRoundUp(); break;
3763 case ocRoundDown
: ScRoundDown(); break;
3764 case ocCeil
: ScCeil( true ); break;
3765 case ocCeil_MS
: ScCeil_MS(); break;
3766 case ocCeil_Precise
:
3767 case ocCeil_ISO
: ScCeil_Precise(); break;
3768 case ocCeil_Math
: ScCeil( false ); break;
3769 case ocFloor
: ScFloor( true ); break;
3770 case ocFloor_MS
: ScFloor_MS(); break;
3771 case ocFloor_Precise
: ScFloor_Precise(); break;
3772 case ocFloor_Math
: ScFloor( false ); break;
3773 case ocSumProduct
: ScSumProduct(); break;
3774 case ocSumSQ
: ScSumSQ(); break;
3775 case ocSumX2MY2
: ScSumX2MY2(); break;
3776 case ocSumX2DY2
: ScSumX2DY2(); break;
3777 case ocSumXMY2
: ScSumXMY2(); break;
3778 case ocLog
: ScLog(); break;
3779 case ocGCD
: ScGCD(); break;
3780 case ocLCM
: ScLCM(); break;
3781 case ocGetDate
: ScGetDate(); break;
3782 case ocGetTime
: ScGetTime(); break;
3783 case ocGetDiffDate
: ScGetDiffDate(); break;
3784 case ocGetDiffDate360
: ScGetDiffDate360(); break;
3785 case ocGetDateDif
: ScGetDateDif(); break;
3786 case ocMin
: ScMin( false ); break;
3787 case ocMinA
: ScMin( true ); break;
3788 case ocMax
: ScMax( false ); break;
3789 case ocMaxA
: ScMax( true ); break;
3790 case ocSum
: ScSum(); break;
3791 case ocProduct
: ScProduct(); break;
3792 case ocNPV
: ScNPV(); break;
3793 case ocIRR
: ScIRR(); break;
3794 case ocMIRR
: ScMIRR(); break;
3795 case ocISPMT
: ScISPMT(); break;
3796 case ocAverage
: ScAverage( false ); break;
3797 case ocAverageA
: ScAverage( true ); break;
3798 case ocCount
: ScCount(); break;
3799 case ocCount2
: ScCount2(); break;
3801 case ocVarS
: ScVar( false ); break;
3802 case ocVarA
: ScVar( true ); break;
3804 case ocVarP_MS
: ScVarP( false ); break;
3805 case ocVarPA
: ScVarP( true ); break;
3807 case ocStDevS
: ScStDev( false ); break;
3808 case ocStDevA
: ScStDev( true ); break;
3810 case ocStDevP_MS
: ScStDevP( false ); break;
3811 case ocStDevPA
: ScStDevP( true ); break;
3812 case ocPV
: ScPV(); break;
3813 case ocSYD
: ScSYD(); break;
3814 case ocDDB
: ScDDB(); break;
3815 case ocDB
: ScDB(); break;
3816 case ocVBD
: ScVDB(); break;
3817 case ocDuration
: ScDuration(); break;
3818 case ocSLN
: ScSLN(); break;
3819 case ocPMT
: ScPMT(); break;
3820 case ocColumns
: ScColumns(); break;
3821 case ocRows
: ScRows(); break;
3822 case ocSheets
: ScSheets(); break;
3823 case ocColumn
: ScColumn(); break;
3824 case ocRow
: ScRow(); break;
3825 case ocSheet
: ScSheet(); break;
3826 case ocRRI
: ScRRI(); break;
3827 case ocFV
: ScFV(); break;
3828 case ocNper
: ScNper(); break;
3829 case ocRate
: ScRate(); break;
3830 case ocFilterXML
: ScFilterXML(); break;
3831 case ocWebservice
: ScWebservice(); break;
3832 case ocEncodeURL
: ScEncodeURL(); break;
3833 case ocColor
: ScColor(); break;
3834 case ocErf_MS
: ScErf(); break;
3835 case ocErfc_MS
: ScErfc(); break;
3836 case ocIpmt
: ScIpmt(); break;
3837 case ocPpmt
: ScPpmt(); break;
3838 case ocCumIpmt
: ScCumIpmt(); break;
3839 case ocCumPrinc
: ScCumPrinc(); break;
3840 case ocEffective
: ScEffective(); break;
3841 case ocNominal
: ScNominal(); break;
3842 case ocSubTotal
: ScSubTotal(); break;
3843 case ocAggregate
: ScAggregate(); break;
3844 case ocDBSum
: ScDBSum(); break;
3845 case ocDBCount
: ScDBCount(); break;
3846 case ocDBCount2
: ScDBCount2(); break;
3847 case ocDBAverage
: ScDBAverage(); break;
3848 case ocDBGet
: ScDBGet(); break;
3849 case ocDBMax
: ScDBMax(); break;
3850 case ocDBMin
: ScDBMin(); break;
3851 case ocDBProduct
: ScDBProduct(); break;
3852 case ocDBStdDev
: ScDBStdDev(); break;
3853 case ocDBStdDevP
: ScDBStdDevP(); break;
3854 case ocDBVar
: ScDBVar(); break;
3855 case ocDBVarP
: ScDBVarP(); break;
3856 case ocIndirect
: ScIndirect(); break;
3857 case ocAddress
: ScAddressFunc(); break;
3858 case ocMatch
: ScMatch(); break;
3859 case ocCountEmptyCells
: ScCountEmptyCells(); break;
3860 case ocCountIf
: ScCountIf(); break;
3861 case ocSumIf
: ScSumIf(); break;
3862 case ocAverageIf
: ScAverageIf(); break;
3863 case ocSumIfs
: ScSumIfs(); break;
3864 case ocAverageIfs
: ScAverageIfs(); break;
3865 case ocCountIfs
: ScCountIfs(); break;
3866 case ocLookup
: ScLookup(); break;
3867 case ocVLookup
: ScVLookup(); break;
3868 case ocHLookup
: ScHLookup(); break;
3869 case ocIndex
: ScIndex(); break;
3870 case ocMultiArea
: ScMultiArea(); break;
3871 case ocOffset
: ScOffset(); break;
3872 case ocAreas
: ScAreas(); break;
3873 case ocCurrency
: ScCurrency(); break;
3874 case ocReplace
: ScReplace(); break;
3875 case ocFixed
: ScFixed(); break;
3876 case ocFind
: ScFind(); break;
3877 case ocExact
: ScExact(); break;
3878 case ocLeft
: ScLeft(); break;
3879 case ocRight
: ScRight(); break;
3880 case ocSearch
: ScSearch(); break;
3881 case ocMid
: ScMid(); break;
3882 case ocText
: ScText(); break;
3883 case ocSubstitute
: ScSubstitute(); break;
3884 case ocRept
: ScRept(); break;
3885 case ocConcat
: ScConcat(); break;
3886 case ocMatValue
: ScMatValue(); break;
3887 case ocMatrixUnit
: ScEMat(); break;
3888 case ocMatDet
: ScMatDet(); break;
3889 case ocMatInv
: ScMatInv(); break;
3890 case ocMatMult
: ScMatMult(); break;
3891 case ocMatTrans
: ScMatTrans(); break;
3892 case ocMatRef
: ScMatRef(); break;
3893 case ocB
: ScB(); break;
3894 case ocNormDist
: ScNormDist( 3 ); break;
3895 case ocNormDist_MS
: ScNormDist( 4 ); break;
3897 case ocExpDist_MS
: ScExpDist(); break;
3899 case ocBinomDist_MS
: ScBinomDist(); break;
3900 case ocPoissonDist
:
3901 case ocPoissonDist_MS
: ScPoissonDist(); break;
3902 case ocCombin
: ScCombin(); break;
3903 case ocCombinA
: ScCombinA(); break;
3904 case ocPermut
: ScPermut(); break;
3905 case ocPermutationA
: ScPermutationA(); break;
3906 case ocHypGeomDist
: ScHypGeomDist(); break;
3907 case ocHypGeomDist_MS
: ScHypGeomDist_MS(); break;
3908 case ocLogNormDist
: ScLogNormDist( 1 ); break;
3909 case ocLogNormDist_MS
: ScLogNormDist( 4 ); break;
3910 case ocTDist
: ScTDist(); break;
3911 case ocTDist_MS
: ScTDist_MS(); break;
3912 case ocTDist_RT
: ScTDist_T( 1 ); break;
3913 case ocTDist_2T
: ScTDist_T( 2 ); break;
3915 case ocFDist_RT
: ScFDist(); break;
3916 case ocFDist_LT
: ScFDist_LT(); break;
3918 case ocChiDist_MS
: ScChiDist(); break;
3919 case ocChiSqDist
: ScChiSqDist(); break;
3920 case ocChiSqDist_MS
: ScChiSqDist_MS(); break;
3921 case ocStandard
: ScStandard(); break;
3922 case ocAveDev
: ScAveDev(); break;
3923 case ocDevSq
: ScDevSq(); break;
3924 case ocKurt
: ScKurt(); break;
3925 case ocSkew
: ScSkew(); break;
3926 case ocSkewp
: ScSkewp(); break;
3927 case ocModalValue
: ScModalValue(); break;
3928 case ocModalValue_MS
: ScModalValue(); break;
3929 case ocModalValue_Multi
: ScModalValue_Multi(); break;
3930 case ocMedian
: ScMedian(); break;
3931 case ocGeoMean
: ScGeoMean(); break;
3932 case ocHarMean
: ScHarMean(); break;
3934 case ocWeibull_MS
: ScWeibull(); break;
3936 case ocCritBinom
: ScCritBinom(); break;
3937 case ocNegBinomVert
: ScNegBinomDist(); break;
3938 case ocNegBinomDist_MS
: ScNegBinomDist_MS(); break;
3939 case ocNoName
: ScNoName(); break;
3940 case ocBad
: ScBadName(); break;
3942 case ocZTest_MS
: ScZTest(); break;
3944 case ocTTest_MS
: ScTTest(); break;
3946 case ocFTest_MS
: ScFTest(); break;
3948 case ocRank_Eq
: ScRank( false ); break;
3949 case ocRank_Avg
: ScRank( true ); break;
3951 case ocPercentile_Inc
: ScPercentile( true ); break;
3952 case ocPercentile_Exc
: ScPercentile( false ); break;
3953 case ocPercentrank
:
3954 case ocPercentrank_Inc
: ScPercentrank( true ); break;
3955 case ocPercentrank_Exc
: ScPercentrank( false ); break;
3956 case ocLarge
: ScLarge(); break;
3957 case ocSmall
: ScSmall(); break;
3958 case ocFrequency
: ScFrequency(); break;
3960 case ocQuartile_Inc
: ScQuartile( true ); break;
3961 case ocQuartile_Exc
: ScQuartile( false ); break;
3963 case ocNormInv_MS
: ScNormInv(); break;
3965 case ocSNormInv_MS
: ScSNormInv(); break;
3967 case ocConfidence_N
: ScConfidence(); break;
3968 case ocConfidence_T
: ScConfidenceT(); break;
3969 case ocTrimMean
: ScTrimMean(); break;
3970 case ocProb
: ScProbability(); break;
3971 case ocCorrel
: ScCorrel(); break;
3973 case ocCovarianceP
: ScCovarianceP(); break;
3974 case ocCovarianceS
: ScCovarianceS(); break;
3975 case ocPearson
: ScPearson(); break;
3976 case ocRSQ
: ScRSQ(); break;
3977 case ocSTEYX
: ScSTEYX(); break;
3978 case ocSlope
: ScSlope(); break;
3979 case ocIntercept
: ScIntercept(); break;
3980 case ocTrend
: ScTrend(); break;
3981 case ocGrowth
: ScGrowth(); break;
3982 case ocLinest
: ScLinest(); break;
3983 case ocLogest
: ScLogest(); break;
3984 case ocForecast
: ScForecast(); break;
3986 case ocGammaLn_MS
: ScLogGamma(); break;
3987 case ocGamma
: ScGamma(); break;
3988 case ocGammaDist
: ScGammaDist( 3 ); break;
3989 case ocGammaDist_MS
: ScGammaDist( 4 ); break;
3991 case ocGammaInv_MS
: ScGammaInv(); break;
3993 case ocChiTest_MS
: ScChiTest(); break;
3995 case ocChiInv_MS
: ScChiInv(); break;
3997 case ocChiSqInv_MS
: ScChiSqInv(); break;
3999 case ocTInv_2T
: ScTInv( 2 ); break;
4000 case ocTInv_MS
: ScTInv( 4 ); break;
4002 case ocFInv_RT
: ScFInv(); break;
4003 case ocFInv_LT
: ScFInv_LT(); break;
4005 case ocLogInv_MS
: ScLogNormInv(); break;
4006 case ocBetaDist
: ScBetaDist(); break;
4007 case ocBetaDist_MS
: ScBetaDist_MS(); break;
4009 case ocBetaInv_MS
: ScBetaInv(); break;
4010 case ocExternal
: ScExternal(); break;
4011 case ocTableOp
: ScTableOp(); break;
4012 case ocStop
: break;
4013 case ocErrorType
: ScErrorType(); break;
4014 case ocErrorType_ODF
: ScErrorType_ODF(); break;
4015 case ocCurrent
: ScCurrent(); break;
4016 case ocStyle
: ScStyle(); break;
4017 case ocDde
: ScDde(); break;
4018 case ocBase
: ScBase(); break;
4019 case ocDecimal
: ScDecimal(); break;
4020 case ocConvert
: ScConvert(); break;
4021 case ocEuroConvert
: ScEuroConvert(); break;
4022 case ocRoman
: ScRoman(); break;
4023 case ocArabic
: ScArabic(); break;
4024 case ocInfo
: ScInfo(); break;
4025 case ocHyperLink
: ScHyperLink(); break;
4026 case ocBahtText
: ScBahtText(); break;
4027 case ocGetPivotData
: ScGetPivotData(); break;
4028 case ocJis
: ScJis(); break;
4029 case ocAsc
: ScAsc(); break;
4030 case ocLenB
: ScLenB(); break;
4031 case ocRightB
: ScRightB(); break;
4032 case ocLeftB
: ScLeftB(); break;
4033 case ocMidB
: ScMidB(); break;
4034 case ocUnicode
: ScUnicode(); break;
4035 case ocUnichar
: ScUnichar(); break;
4036 case ocBitAnd
: ScBitAnd(); break;
4037 case ocBitOr
: ScBitOr(); break;
4038 case ocBitXor
: ScBitXor(); break;
4039 case ocBitRshift
: ScBitRshift(); break;
4040 case ocBitLshift
: ScBitLshift(); break;
4041 case ocTTT
: ScTTT(); break;
4042 case ocDebugVar
: ScDebugVar(); break;
4043 case ocNone
: nFuncFmtType
= css::util::NumberFormat::UNDEFINED
; break;
4044 default : PushError( errUnknownOpCode
); break;
4047 // If the function pushed a subroutine as result, continue with
4048 // execution of the subroutine.
4049 if (sp
> nStackBase
&& pStack
[sp
-1]->GetOpCode() == ocCall
4050 /* && pStack[sp-1]->GetType() == svSubroutine */)
4055 if (FormulaCompiler::IsOpCodeVolatile(eOp
))
4056 meVolatileType
= VOLATILE
;
4058 // Remember result matrix in case it could be reused.
4059 if (pTokenMatrixMap
&& sp
&& GetStackType() == svMatrix
)
4060 pTokenMatrixMap
->insert( ScTokenMatrixMap::value_type( pCur
,
4063 // outer function determines format of an expression
4064 if ( nFuncFmtType
!= css::util::NumberFormat::UNDEFINED
)
4066 nRetTypeExpr
= nFuncFmtType
;
4067 // inherit the format index only for currency formats
4068 nRetIndexExpr
= ( nFuncFmtType
== css::util::NumberFormat::CURRENCY
?
4069 nFuncFmtIndex
: 0 );
4073 // Need a clean stack environment for the JumpMatrix to work.
4074 if (nGlobalError
&& eOp
!= ocPush
&& sp
> nStackBase
+ 1)
4076 // Not all functions pop all parameters in case an error is
4077 // generated. Clean up stack. Assumes that every function pushes a
4078 // result, may be arbitrary in case of error.
4079 const FormulaToken
* pLocalResult
= pStack
[ sp
- 1 ];
4080 while (sp
> nStackBase
)
4082 PushTempToken( *pLocalResult
);
4089 sal_uInt8 nLevel
= 0;
4090 if ( GetStackType( ++nLevel
) == svJumpMatrix
)
4092 else if ( GetStackType( ++nLevel
) == svJumpMatrix
)
4096 if ( nLevel
== 1 || (nLevel
== 2 && aCode
.IsEndOfPath()) )
4097 bGotResult
= JumpMatrix( nLevel
);
4100 } while ( bGotResult
);
4102 // Functions that evaluate an error code and directly set nGlobalError to 0,
4103 // usage: switch( OpCode ) { CASE_OCERRFUNC statements; }
4104 #define CASE_OCERRFUNC \
4107 case ocErrorType : \
4111 case ocIsFormula : \
4112 case ocIsLogical : \
4114 case ocIsNonString : \
4122 case ocErrorType_ODF :
4133 if ( !nErrorFunctionCount
)
4134 { // count of errorcode functions in formula
4135 for ( FormulaToken
* t
= rArr
.FirstRPN(); t
; t
= rArr
.NextRPN() )
4137 switch ( t
->GetOpCode() )
4140 ++nErrorFunctionCount
;
4146 if ( nErrorFunction
>= nErrorFunctionCount
)
4147 ++nErrorFunction
; // that's it, error => terminate
4151 // End: obtain result
4155 pCur
= pStack
[ sp
-1 ];
4156 if( pCur
->GetOpCode() == ocPush
)
4158 switch( pCur
->GetType() )
4164 nGlobalError
= pCur
->GetError();
4167 if ( nFuncFmtType
== css::util::NumberFormat::UNDEFINED
)
4169 nRetTypeExpr
= css::util::NumberFormat::NUMBER
;
4174 nRetTypeExpr
= css::util::NumberFormat::TEXT
;
4180 PopSingleRef( aAdr
);
4182 PushCellResultToken( false, aAdr
,
4183 &nRetTypeExpr
, &nRetIndexExpr
);
4187 PopError(); // maybe #REF! takes precedence over #VALUE!
4188 PushError( errNoValue
);
4192 if ( bMatrixFormula
)
4193 { // create matrix for {=A1:A5}
4194 PopDoubleRefPushMatrix();
4195 ScMatrixRef xMat
= PopMatrix();
4196 QueryMatrixType(xMat
, nRetTypeExpr
, nRetIndexExpr
);
4201 PopDoubleRef( aRange
);
4203 if ( !nGlobalError
&& DoubleRefToPosSingleRef( aRange
, aAdr
))
4204 PushCellResultToken( false, aAdr
,
4205 &nRetTypeExpr
, &nRetIndexExpr
);
4209 case svExternalDoubleRef
:
4212 PopExternalDoubleRef(xMat
);
4213 QueryMatrixType(xMat
, nRetTypeExpr
, nRetIndexExpr
);
4218 sc::RangeMatrix aMat
= PopRangeMatrix();
4219 if (aMat
.isRangeValid())
4221 // This matrix represents a range reference. Apply implicit intersection.
4222 double fVal
= applyImplicitIntersection(aMat
, aPos
);
4223 if (rtl::math::isNan(fVal
))
4229 // This is a normal matrix.
4230 QueryMatrixType(aMat
.mpMat
, nRetTypeExpr
, nRetIndexExpr
);
4233 case svExternalSingleRef
:
4235 ScExternalRefCache::TokenRef pToken
;
4236 ScExternalRefCache::CellFormat aFmt
;
4237 PopExternalSingleRef(pToken
, &aFmt
);
4241 PushTempToken(*pToken
);
4245 nFuncFmtType
= aFmt
.mnType
;
4246 nFuncFmtIndex
= aFmt
.mnIndex
;
4251 SetError( errUnknownStackVariable
);
4255 SetError( errUnknownStackVariable
);
4258 SetError( errNoCode
);
4260 if( nRetTypeExpr
!= css::util::NumberFormat::UNDEFINED
)
4262 nRetFmtType
= nRetTypeExpr
;
4263 nRetFmtIndex
= nRetIndexExpr
;
4265 else if( nFuncFmtType
!= css::util::NumberFormat::UNDEFINED
)
4267 nRetFmtType
= nFuncFmtType
;
4268 nRetFmtIndex
= nFuncFmtIndex
;
4271 nRetFmtType
= css::util::NumberFormat::NUMBER
;
4273 if (nGlobalError
&& GetStackType() != svError
)
4274 PushError( nGlobalError
);
4276 // THE final result.
4277 xResult
= PopToken();
4279 xResult
= new FormulaErrorToken( errUnknownStackVariable
);
4281 // release tokens in expression stack
4282 FormulaToken
** p
= pStack
;
4286 StackVar eType
= xResult
->GetType();
4287 if (eType
== svMatrix
)
4288 // Results are immutable in case they would be reused as input for new
4290 xResult
.get()->GetMatrix()->SetImmutable( true);
4294 svl::SharedString
ScInterpreter::GetStringResult() const
4296 return xResult
->GetString();
4299 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */