diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2009-01-06 13:57:48 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2009-01-06 13:57:48 +0000 |
commit | 4453678f4d07a65e548a04b6fa2655b66274514d (patch) | |
tree | 0f9787ba9adaea1aa46b3354481b2e4e6e8d42c7 /sc/source | |
parent | 6c0208067b950fec47d8a2679e0daa79fc78a2c0 (diff) |
CWS-TOOLING: integrate CWS odff05
2008-12-11 04:17:37 +0100 er r265237 : #i94555# AppendIntToken for GAMMADIST, Excel needs 4 parameters; also use AppendIntToken instead of AppendNumToken for POISSON
2008-12-11 04:04:27 +0100 er r265236 : #i96837# make cumulative parameter of POISSON optional; patch from <lvyue> with slight modifications
2008-12-11 03:35:03 +0100 er r265235 : #i96835# make base parameter of LOG() optional also in UI; patch from <lvyue>
2008-12-11 03:15:30 +0100 er r265234 : #i94555# patch from <regina>, ODFF:
Add GAMMA, CHISQDIST, CHISQINV.
Make the 'cumulative' parameter of GAMMADIST optional.
Adapt the domain of CHIDIST to allow negative x.
Remove the constraint "degrees of freedom < 1.0E5" from CHIDIST and CHIINV.
Plus a mechanism to write the now optional parameter of GAMMADIST to PODF and
ODFF if omitted, for backwards compatibility.
2008-12-10 18:14:16 +0100 er r265214 : DBG_... need semicolon
2008-12-05 00:49:55 +0100 er r264881 : WaE unxlngi6: declaration of 'pFuncInfo' shadows a previous local
2008-12-05 00:26:05 +0100 er r264879 : #i91547# BETADIST with optional density/cumulative parameter and much better precision; patch from <regina>
2008-12-04 22:51:40 +0100 er r264877 : #i91602# add expm1() and log1p() replacements; based on a patch from <regina>
2008-12-01 16:07:35 +0100 dr r264614 : #i93789# import of EUROCONVERT from XLSX/XLSB
2008-11-28 13:15:01 +0100 dr r264543 : #i93789# new sheet function EUROCONVERT + XLS import/export, patch contributed by lvyue
2008-11-26 14:54:23 +0100 er r264397 : CWS-TOOLING: rebase CWS odff05 to trunk@264325 (milestone: DEV300:m36)
2008-11-20 14:23:33 +0100 er r264053 : CWS-TOOLING: rebase CWS odff05 to trunk@263288 (milestone: DEV300:m35)
2008-11-19 18:07:43 +0100 er r264012 : merged from trunk
2008-11-19 17:51:36 +0100 er r264011 : migrate CWS odff05 to SVN
Diffstat (limited to 'sc/source')
25 files changed, 1235 insertions, 345 deletions
diff --git a/sc/source/core/data/validat.cxx b/sc/source/core/data/validat.cxx index 8aa84645d8c8..b3e88a05239b 100644 --- a/sc/source/core/data/validat.cxx +++ b/sc/source/core/data/validat.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: validat.cxx,v $ - * $Revision: 1.25 $ + * $Revision: 1.24.110.2 $ * * This file is part of OpenOffice.org. * @@ -711,7 +711,7 @@ bool ScValidationData::GetSelectionFromFormula( TypedScStrCollection* pStrings, const ScMatrixValue* pMatVal = pValues->Get( nCol, nRow, nMatValType); // strings and empties - if( NULL == pMatVal || ScMatrix::IsStringType( nMatValType ) ) + if( NULL == pMatVal || ScMatrix::IsNonValueType( nMatValType ) ) { if( NULL != pMatVal ) aValStr = pMatVal->GetString(); diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index c1bd2c29bc48..3cce11685e54 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -106,6 +106,7 @@ class ScInterpreter friend class ScTDistFunction; friend class ScFDistFunction; friend class ScChiDistFunction; + friend class ScChiSqDistFunction; public: DECL_FIXEDMEMPOOL_NEWDEL( ScInterpreter ) @@ -560,6 +561,7 @@ void ScDde(); void ScBase(); void ScDecimal(); void ScConvert(); +void ScEuroConvert(); //----------------------- Finanzfunktionen ------------------------------------ void ScNPV(); @@ -642,17 +644,21 @@ double phi(double x); double taylor(double* pPolynom, USHORT nMax, double x); double gauss(double x); double gaussinv(double x); -double GetBetaDist(double x, double alpha, double beta); +double GetBetaDist(double x, double alpha, double beta); //cumulative distribution function +double GetBetaDistPDF(double fX, double fA, double fB); //probability density function) double GetChiDist(double fChi, double fDF); // for LEGACY.CHIDIST, returns right tail double GetChiSqDistCDF(double fX, double fDF); // for CHISQDIST, returns left tail +double GetChiSqDistPDF(double fX, double fDF); // probability density function double GetFDist(double x, double fF1, double fF2); double GetTDist(double T, double fDF); double Fakultaet(double x); double BinomKoeff(double n, double k); double GetGamma(double x); double GetLogGamma(double x); +double GetBeta(double fAlpha, double fBeta); +double GetLogBeta(double fAlpha, double fBeta); void ScLogGamma(); -void ScGamma(); // ready for ODF 1.2 GAMMA +void ScGamma(); void ScPhi(); void ScGauss(); void ScStdNormDist(); @@ -676,7 +682,8 @@ void ScLogNormInv(); void ScTDist(); void ScFDist(); void ScChiDist(); // for LEGACY.CHIDIST, returns right tail -// TODO: void ScChiSqDist; +void ScChiSqDist(); // returns left tail or density +void ScChiSqInv(); //invers to CHISQDIST void ScWeibull(); void ScBetaDist(); void ScFInv(); diff --git a/sc/source/core/inc/jumpmatrix.hxx b/sc/source/core/inc/jumpmatrix.hxx index bce78c6500e2..34893187009c 100644 --- a/sc/source/core/inc/jumpmatrix.hxx +++ b/sc/source/core/inc/jumpmatrix.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: jumpmatrix.hxx,v $ - * $Revision: 1.6 $ + * $Revision: 1.6.148.1 $ * * This file is part of OpenOffice.org. * @@ -73,6 +73,8 @@ class ScJumpMatrix SCSIZE nRows; SCSIZE nCurCol; SCSIZE nCurRow; + SCSIZE nResMatCols; + SCSIZE nResMatRows; bool bStarted; // not implemented, prevent usage @@ -88,6 +90,8 @@ public: , nRows( nRowsP ) , nCurCol( 0 ) , nCurRow( 0 ) + , nResMatCols( nColsP ) + , nResMatRows( nRowsP ) , bStarted( false ) { // Initialize result matrix in case of @@ -128,6 +132,21 @@ public: short& rStart, short& rNext, short& rStop ) const { + if (nCols == 1 && nRows == 1) + { + nCol = 0; + nRow = 0; + } + else if (nCols == 1 && nRow < nRows) + nCol = 0; + else if (nRows == 1 && nCol < nCols) + nRow = 0; + else if (nCols <= nCol || nRows <= nRow) + { + DBG_ERROR("ScJumpMatrix::GetJump: dimension error"); + nCol = 0; + nRow = 0; + } pJump[ (ULONG)nCol * nRows + nRow ]. GetJump( rBool, rStart, rNext, rStop); } @@ -160,14 +179,45 @@ public: } else { - if ( ++nCurRow >= nRows ) + if ( ++nCurRow >= nResMatRows ) { nCurRow = 0; ++nCurCol; } } GetPos( rCol, rRow ); - return nCurCol < nCols; + return nCurCol < nResMatCols; + } + void GetResMatDimensions( SCSIZE& rCols, SCSIZE& rRows ) + { + rCols = nResMatCols; + rRows = nResMatRows; + } + void SetNewResMat( SCSIZE nNewCols, SCSIZE nNewRows ) + { + if ( nNewCols > nResMatCols || nNewRows > nResMatRows ) + { + pMat = pMat->CloneAndExtend( nNewCols, nNewRows ); + if ( nResMatCols < nNewCols ) + { + pMat->FillDouble( CreateDoubleError( + NOTAVAILABLE), nResMatCols, 0, nNewCols-1, + nResMatRows-1); + } + if ( nResMatRows < nNewRows ) + { + pMat->FillDouble( CreateDoubleError( + NOTAVAILABLE), 0, nResMatRows, nNewCols-1, + nNewRows-1); + } + if ( nRows == 1 && nCurCol != 0 ) + { + nCurCol = 0; + nCurRow = nResMatRows - 1; + } + nResMatCols = nNewCols; + nResMatRows = nNewRows; + } } }; diff --git a/sc/source/core/src/compiler.src b/sc/source/core/src/compiler.src index e72a63a52506..1c953ec8f981 100644 --- a/sc/source/core/src/compiler.src +++ b/sc/source/core/src/compiler.src @@ -1179,6 +1179,19 @@ Resource RID_SC_FUNCTION_NAMES { Text [ en-US ] = "NUMBERVALUE" ; }; + String SC_OPCODE_GAMMA + { + Text [ en-US ] = "GAMMA" ; + }; + String SC_OPCODE_CHISQ_DIST + { + Text [ en-US ] = "CHISQDIST" ; + }; + String SC_OPCODE_CHISQ_INV + { + Text [ en-US ] = "CHISQINV" ; + }; + /* BEGIN defined ERROR.TYPE() values. */ /* ERROR.TYPE( #NULL! ) == 1 */ String SC_OPCODE_ERROR_NULL @@ -1529,6 +1542,9 @@ Resource RID_SC_FUNCTION_NAMES_ENGLISH String SC_OPCODE_GET_PIVOT_DATA { Text = "GETPIVOTDATA" ; }; String SC_OPCODE_EUROCONVERT { Text = "EUROCONVERT" ; }; String SC_OPCODE_NUMBERVALUE { Text = "NUMBERVALUE" ; }; + String SC_OPCODE_GAMMA { Text = "GAMMA" ; }; + String SC_OPCODE_CHISQ_DIST { Text = "CHISQDIST" ; }; + String SC_OPCODE_CHISQ_INV { Text = "CHISQINV" ;}; /* BEGIN defined ERROR.TYPE() values. */ String SC_OPCODE_ERROR_NULL { Text = "#NULL!" ; }; String SC_OPCODE_ERROR_DIVZERO { Text = "#DIV/0!" ; }; @@ -1850,6 +1866,9 @@ Resource RID_SC_FUNCTION_NAMES_ENGLISH_ODFF String SC_OPCODE_GET_PIVOT_DATA { Text = "GETPIVOTDATA" ; }; String SC_OPCODE_EUROCONVERT { Text = "EUROCONVERT" ; }; String SC_OPCODE_NUMBERVALUE { Text = "NUMBERVALUE" ; }; + String SC_OPCODE_GAMMA { Text = "GAMMA" ; }; + String SC_OPCODE_CHISQ_DIST { Text = "CHISQDIST" ;}; + String SC_OPCODE_CHISQ_INV { Text = "CHISQINV" ;}; /* BEGIN defined ERROR.TYPE() values. */ String SC_OPCODE_ERROR_NULL { Text = "#NULL!" ; }; String SC_OPCODE_ERROR_DIVZERO { Text = "#DIV/0!" ; }; diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 16f51a015667..e9b583ec7783 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -6725,11 +6725,13 @@ void ScCompiler::CreateStringFromTokenArray( rtl::OUStringBuffer& rBuffer ) return; ScTokenArray* pSaveArr = pArr; - if (ScGrammar::isPODF( meGrammar)) + bool bODFF = ScGrammar::isODFF( meGrammar); + if (bODFF || ScGrammar::isPODF( meGrammar)) { // Scan token array for missing args and re-write if present. - if (pArr->NeedsPofRewrite()) - pArr = pArr->RewriteMissingToPof(); + ScMissingConvention aConv( bODFF); + if (pArr->NeedsPofRewrite( aConv)) + pArr = pArr->RewriteMissingToPof( aConv); } // At least one character per token, plus some are references, some are diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 242dc0662d8e..f1ab1da94432 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: interpr1.cxx,v $ - * $Revision: 1.61 $ + * $Revision: 1.60.54.5 $ * * This file is part of OpenOffice.org. * @@ -129,8 +129,11 @@ void ScInterpreter::ScIfJump() } else { + // Treat empty and empty path as 0, but string + // as error. + bIsValue = !ScMatrix::IsRealStringType( nType); bTrue = false; - fVal = 0.0; + fVal = (bIsValue ? 0.0 : CreateDoubleError( errNoValue)); } if ( bTrue ) { // TRUE @@ -309,6 +312,37 @@ void ScInterpreter::ScChoseJump() } +void lcl_AdjustJumpMatrix( ScJumpMatrix* pJumpM, ScMatrixRef& pResMat, SCSIZE nParmCols, SCSIZE nParmRows ) +{ + SCSIZE nJumpCols, nJumpRows; + SCSIZE nResCols, nResRows; + SCSIZE nAdjustCols, nAdjustRows; + pJumpM->GetDimensions( nJumpCols, nJumpRows ); + pJumpM->GetResMatDimensions( nResCols, nResRows ); + if (( nJumpCols == 1 && nParmCols > nResCols ) || + ( nJumpRows == 1 && nParmRows > nResRows )) + { + if ( nJumpCols == 1 && nJumpRows == 1 ) + { + nAdjustCols = nParmCols > nResCols ? nParmCols : nResCols; + nAdjustRows = nParmRows > nResRows ? nParmRows : nResRows; + } + else if ( nJumpCols == 1 ) + { + nAdjustCols = nParmCols; + nAdjustRows = nResRows; + } + else + { + nAdjustCols = nResCols; + nAdjustRows = nParmRows; + } + pJumpM->SetNewResMat( nAdjustCols, nAdjustRows ); + pResMat = pJumpM->GetResultMatrix(); + } +} + + bool ScInterpreter::JumpMatrix( short nStackLevel ) { pJumpMatrix = pStack[sp-nStackLevel]->GetJumpMatrix(); @@ -404,52 +438,69 @@ bool ScInterpreter::JumpMatrix( short nStackLevel ) double fVal; ScRange aRange; PopDoubleRef( aRange ); - ScAddress& rAdr = aRange.aStart; - ULONG nCol = (ULONG)rAdr.Col() + nC; - ULONG nRow = (ULONG)rAdr.Row() + nR; if ( nGlobalError ) { fVal = CreateDoubleError( nGlobalError ); nGlobalError = 0; pResMat->PutDouble( fVal, nC, nR ); } - else if ( nCol > static_cast<ULONG>(aRange.aEnd.Col()) || - nRow > static_cast<ULONG>(aRange.aEnd.Row())) - { - fVal = CreateDoubleError( errNoValue ); - pResMat->PutDouble( fVal, nC, nR ); - } else { - rAdr.SetCol( static_cast<SCCOL>(nCol) ); - rAdr.SetRow( static_cast<SCROW>(nRow) ); - ScBaseCell* pCell = GetCell( rAdr ); - if (HasCellEmptyData( pCell)) - pResMat->PutEmpty( nC, nR ); - else if (HasCellValueData( pCell)) + // Do not modify the original range because we use it + // to adjust the size of the result matrix if necessary. + ScAddress aAdr( aRange.aStart); + ULONG nCol = (ULONG)aAdr.Col() + nC; + ULONG nRow = (ULONG)aAdr.Row() + nR; + if ((nCol > static_cast<ULONG>(aRange.aEnd.Col()) && + aRange.aEnd.Col() != aRange.aStart.Col()) + || (nRow > static_cast<ULONG>(aRange.aEnd.Row()) && + aRange.aEnd.Row() != aRange.aStart.Row())) { - double fCellVal = GetCellValue( rAdr, pCell); - if ( nGlobalError ) - { - fCellVal = CreateDoubleError( - nGlobalError); - nGlobalError = 0; - } - pResMat->PutDouble( fCellVal, nC, nR ); + fVal = CreateDoubleError( NOTAVAILABLE ); + pResMat->PutDouble( fVal, nC, nR ); } else { - String aStr; - GetCellString( aStr, pCell ); - if ( nGlobalError ) + // Replicate column and/or row of a vector if it is + // one. Note that this could be a range reference + // that in fact consists of only one cell, e.g. A1:A1 + if (aRange.aEnd.Col() == aRange.aStart.Col()) + nCol = aRange.aStart.Col(); + if (aRange.aEnd.Row() == aRange.aStart.Row()) + nRow = aRange.aStart.Row(); + aAdr.SetCol( static_cast<SCCOL>(nCol) ); + aAdr.SetRow( static_cast<SCROW>(nRow) ); + ScBaseCell* pCell = GetCell( aAdr ); + if (HasCellEmptyData( pCell)) + pResMat->PutEmpty( nC, nR ); + else if (HasCellValueData( pCell)) { - pResMat->PutDouble( CreateDoubleError( - nGlobalError), nC, nR); - nGlobalError = 0; + double fCellVal = GetCellValue( aAdr, pCell); + if ( nGlobalError ) + { + fCellVal = CreateDoubleError( + nGlobalError); + nGlobalError = 0; + } + pResMat->PutDouble( fCellVal, nC, nR ); } else - pResMat->PutString( aStr, nC, nR ); + { + String aStr; + GetCellString( aStr, pCell ); + if ( nGlobalError ) + { + pResMat->PutDouble( CreateDoubleError( + nGlobalError), nC, nR); + nGlobalError = 0; + } + else + pResMat->PutString( aStr, nC, nR ); + } } + SCSIZE nParmCols = aRange.aEnd.Col() - aRange.aStart.Col() + 1; + SCSIZE nParmRows = aRange.aEnd.Row() - aRange.aStart.Row() + 1; + lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nParmCols, nParmRows ); } } break; @@ -472,9 +523,10 @@ bool ScInterpreter::JumpMatrix( short nStackLevel ) { SCSIZE nCols, nRows; pMat->GetDimensions( nCols, nRows ); - if ( nCols <= nC || nRows <= nR ) + if ((nCols <= nC && nCols != 1) || + (nRows <= nR && nRows != 1)) { - fVal = CreateDoubleError( errNoValue ); + fVal = CreateDoubleError( NOTAVAILABLE ); pResMat->PutDouble( fVal, nC, nR ); } else @@ -492,6 +544,7 @@ bool ScInterpreter::JumpMatrix( short nStackLevel ) pResMat->PutString( rStr, nC, nR ); } } + lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nCols, nRows ); } } break; @@ -775,7 +828,9 @@ ScMatrixRef ScInterpreter::CompareMat() { for ( SCSIZE k=0; k<nR; k++ ) { - if ( j < nC0 && j < nC1 && k < nR0 && k < nR1 ) + SCSIZE nCol = j, nRow = k; + if ( pMat[0]->ValidColRowOrReplicated( nCol, nRow ) && + pMat[1]->ValidColRowOrReplicated( nCol, nRow )) { for ( short i=1; i>=0; i-- ) { @@ -3963,6 +4018,16 @@ static void lcl_GetLastMatch( SCSIZE& rIndex, const ScMatrix& rMat, nVal == rMat.GetDouble(rIndex+1)) ++rIndex; } + //! Order of IsEmptyPath, IsEmpty, IsString is significant! + else if (rMat.IsEmptyPath(rIndex)) + { + if (bReverse) + while (rIndex > 0 && rMat.IsEmptyPath(rIndex-1)) + --rIndex; + else + while (rIndex < nMatCount-1 && rMat.IsEmptyPath(rIndex+1)) + ++rIndex; + } else if (rMat.IsEmpty(rIndex)) { if (bReverse) @@ -3984,14 +4049,9 @@ static void lcl_GetLastMatch( SCSIZE& rIndex, const ScMatrix& rMat, aStr == rMat.GetString(rIndex+1)) ++rIndex; } - else if (rMat.IsEmptyPath(rIndex)) + else { - if (bReverse) - while (rIndex > 0 && rMat.IsEmptyPath(rIndex-1)) - --rIndex; - else - while (rIndex < nMatCount-1 && rMat.IsEmptyPath(rIndex+1)) - ++rIndex; + DBG_ERRORFILE("lcl_GetLastMatch: unhandled matrix type"); } } @@ -4097,7 +4157,7 @@ void ScInterpreter::ScMatch() { ScMatValType nType = GetDoubleOrStringFromMatrix( rEntry.nVal, *rEntry.pStr); - rEntry.bQueryByString = ScMatrix::IsStringType( nType); + rEntry.bQueryByString = ScMatrix::IsNonValueType( nType); } break; default: @@ -4353,7 +4413,7 @@ void ScInterpreter::ScCountIf() { ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, rString); - bIsString = ScMatrix::IsStringType( nType); + bIsString = ScMatrix::IsNonValueType( nType); } break; case svString: @@ -4540,7 +4600,7 @@ void ScInterpreter::ScSumIf() { ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, rString); - bIsString = ScMatrix::IsStringType( nType); + bIsString = ScMatrix::IsNonValueType( nType); } break; default: @@ -4848,7 +4908,7 @@ void ScInterpreter::ScLookup() { ScMatValType nType = GetDoubleOrStringFromMatrix( rEntry.nVal, *rEntry.pStr); - rEntry.bQueryByString = ScMatrix::IsStringType(nType); + rEntry.bQueryByString = ScMatrix::IsNonValueType(nType); } break; default: @@ -5237,7 +5297,7 @@ void ScInterpreter::ScHLookup() { ScMatValType nType = GetDoubleOrStringFromMatrix( rEntry.nVal, *rEntry.pStr); - rEntry.bQueryByString = ScMatrix::IsStringType( nType); + rEntry.bQueryByString = ScMatrix::IsNonValueType( nType); } break; default: @@ -5489,7 +5549,7 @@ void ScInterpreter::ScVLookup() { ScMatValType nType = GetDoubleOrStringFromMatrix( rEntry.nVal, *rEntry.pStr); - rEntry.bQueryByString = ScMatrix::IsStringType( nType); + rEntry.bQueryByString = ScMatrix::IsNonValueType( nType); } break; default: @@ -6064,18 +6124,27 @@ void ScInterpreter::ScIndirect() BYTE nParamCount = GetByte(); if ( MustHaveParamCount( nParamCount, 1, 2 ) ) { + bool bTryXlA1 = true; // whether to try XL_A1 style as well. ScAddress::Convention eConv = ScAddress::CONV_OOO; if (nParamCount == 2 && 0.0 == ::rtl::math::approxFloor( GetDouble())) + { eConv = ScAddress::CONV_XL_R1C1; + bTryXlA1 = false; + } const ScAddress::Details aDetails( eConv, aPos ); + const ScAddress::Details aDetailsXlA1( ScAddress::CONV_XL_A1, aPos ); SCTAB nTab = aPos.Tab(); String sRefStr( GetString() ); ScRefAddress aRefAd, aRefAd2; - if ( ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, aRefAd2, aDetails ) ) + if ( ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, aRefAd2, aDetails) || + (bTryXlA1 && ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, + aRefAd2, aDetailsXlA1))) PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(), - aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() ); - else if ( ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, aDetails ) ) + aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() ); + else if ( ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, aDetails) || + (bTryXlA1 && ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, + aDetailsXlA1))) PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() ); else { diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx index 20a7a6070071..26e41b0df46f 100644 --- a/sc/source/core/tool/interpr2.cxx +++ b/sc/source/core/tool/interpr2.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: interpr2.cxx,v $ - * $Revision: 1.38 $ + * $Revision: 1.37.100.3 $ * * This file is part of OpenOffice.org. * @@ -172,7 +172,7 @@ void ScInterpreter::ScGetDateValue() { short eType = pFormatter->GetType(nFIndex); if (eType == NUMBERFORMAT_DATE || eType == NUMBERFORMAT_DATETIME) - PushDouble(fVal); + PushDouble(::rtl::math::approxFloor(fVal)); else PushIllegalArgument(); } @@ -391,7 +391,11 @@ void ScInterpreter::ScGetTimeValue() { short eType = pFormatter->GetType(nFIndex); if (eType == NUMBERFORMAT_TIME || eType == NUMBERFORMAT_DATETIME) - PushDouble(fVal); + { + double fDateVal = rtl::math::approxFloor(fVal); + double fTimeVal = fVal - fDateVal; + PushDouble(fTimeVal); + } else PushIllegalArgument(); } @@ -1551,7 +1555,7 @@ void ScInterpreter::ScBackSolver() const USHORT nMaxIter = 100; const double fEps = 1E-10; - const double fDelta = 1E-3; + const double fDelta = 1E-6; double fBestX, fXPrev; double fBestF, fFPrev; @@ -1672,7 +1676,9 @@ void ScInterpreter::ScBackSolver() } } - double nX = ::rtl::math::approxFloor((fBestX / fDelta) + 0.5) * fDelta; + // Try a nice rounded input value if possible. + const double fNiceDelta = (bDoneIteration && fabs(fBestX) >= 1e-3 ? 1e-3 : fDelta); + double nX = ::rtl::math::approxFloor((fBestX / fNiceDelta) + 0.5) * fNiceDelta; if ( bDoneIteration ) { @@ -2328,6 +2334,103 @@ void ScInterpreter::ScConvert() } +BOOL lclConvertMoney( const String& aSearchUnit, double& rfRate, int& rnDec ) +{ + struct ConvertInfo + { + const sal_Char* pCurrText; + double fRate; + int nDec; + }; + ConvertInfo aConvertTable[] = { + { "EUR", 1.0, 2 }, + { "ATS", 13.7603, 2 }, + { "BEF", 40.3399, 0 }, + { "DEM", 1.95583, 2 }, + { "ESP", 166.386, 0 }, + { "FIM", 5.94573, 2 }, + { "FRF", 6.55957, 2 }, + { "IEP", 0.787564, 2 }, + { "ITL", 1936.27, 0 }, + { "LUF", 40.3399, 0 }, + { "NLG", 2.20371, 2 }, + { "PTE", 200.482, 2 }, + { "GRD", 340.750, 2 }, + { "SIT", 239.640, 2 }, + { "MTL", 0.429300, 2 }, + { "CYP", 0.585274, 2 } + }; + + const size_t nConversionCount = sizeof( aConvertTable ) / sizeof( aConvertTable[0] ); + for ( size_t i = 0; i < nConversionCount; i++ ) + if ( aSearchUnit.EqualsIgnoreCaseAscii( aConvertTable[i].pCurrText ) ) + { + rfRate = aConvertTable[i].fRate; + rnDec = aConvertTable[i].nDec; + return TRUE; + } + return FALSE; +} + +void ScInterpreter::ScEuroConvert() +{ //Value, FromUnit, ToUnit[, FullPrecision, [TriangulationPrecision]] + BYTE nParamCount = GetByte(); + if ( MustHaveParamCount( nParamCount, 3, 5 ) ) + { + double nPrecision = 0.0; + if ( nParamCount == 5 ) + { + nPrecision = ::rtl::math::approxFloor(GetDouble()); + if ( nPrecision < 3 ) + { + PushIllegalArgument(); + return; + } + } + BOOL bFullPrecision = FALSE; + if ( nParamCount >= 4 ) + bFullPrecision = GetBool(); + String aToUnit( GetString() ); + String aFromUnit( GetString() ); + double fVal = GetDouble(); + if ( nGlobalError ) + PushError( nGlobalError); + else + { + double fRes; + double fFromRate; + double fToRate; + int nFromDec; + int nToDec; + String aEur( RTL_CONSTASCII_USTRINGPARAM("EUR")); + if ( lclConvertMoney( aFromUnit, fFromRate, nFromDec ) + && lclConvertMoney( aToUnit, fToRate, nToDec ) ) + { + if ( aFromUnit.EqualsIgnoreCaseAscii( aToUnit ) ) + fRes = fVal; + else + { + if ( aFromUnit.EqualsIgnoreCaseAscii( aEur ) ) + fRes = fVal * fToRate; + else + { + double fIntermediate = fVal / fFromRate; + if ( nPrecision ) + fIntermediate = ::rtl::math::round( fIntermediate, + (int) nPrecision ); + fRes = fIntermediate * fToRate; + } + if ( !bFullPrecision ) + fRes = ::rtl::math::round( fRes, nToDec ); + } + PushDouble( fRes ); + } + else + PushIllegalArgument(); + } + } +} + void ScInterpreter::ScRoman() { // Value [Mode] BYTE nParamCount = GetByte(); diff --git a/sc/source/core/tool/interpr3.cxx b/sc/source/core/tool/interpr3.cxx index a50f39e25e88..246632a4c2e4 100644 --- a/sc/source/core/tool/interpr3.cxx +++ b/sc/source/core/tool/interpr3.cxx @@ -61,6 +61,7 @@ using ::std::vector; //#define PI 3.1415926535897932 const double ScInterpreter::fMaxGammaArgument = 171.624376956302; // found experimental +const double fMachEps = ::std::numeric_limits<double>::epsilon(); //----------------------------------------------------------------------------- @@ -649,85 +650,6 @@ double ScInterpreter::GetLogGamma(double fZ) return lcl_GetLogGammaHelper(fZ+2) - log(fZ+1) - log(fZ); } -double ScInterpreter::GetBetaDist(double x, double alpha, double beta) -{ - if (beta == 1.0) - return pow(x, alpha); - else if (alpha == 1.0) - return 1.0 - pow(1.0-x,beta); - double fEps = 1.0E-8; - BOOL bReflect; - double cf, fA, fB; - if (x < (alpha+1.0)/(alpha+beta+1.0)) - { - bReflect = FALSE; - fA = alpha; - fB = beta; - } - else - { - bReflect = TRUE; - fA = beta; - fB = alpha; - x = 1.0 - x; - } - if (x < fEps) - cf = 0.0; - else - { - double a1, b1, a2, b2, fnorm, rm, apl2m, d2m, d2m1, cfnew; - a1 = 1.0; b1 = 1.0; - b2 = 1.0 - (fA+fB)*x/(fA+1.0); - if (b2 == 0.0) - { - a2 = b2; - fnorm = 1.0; - cf = 1.0; - } - else - { - a2 = 1.0; - fnorm = 1.0/b2; - cf = a2*fnorm; - } - cfnew = 1.0; - for (USHORT j = 1; j <= 100; j++) - { - rm = (double) j; - apl2m = fA + 2.0*rm; - d2m = rm*(fB-rm)*x/((apl2m-1.0)*apl2m); - d2m1 = -(fA+rm)*(fA+fB+rm)*x/(apl2m*(apl2m+1.0)); - a1 = (a2+d2m*a1)*fnorm; - b1 = (b2+d2m*b1)*fnorm; - a2 = a1 + d2m1*a2*fnorm; - b2 = b1 + d2m1*b2*fnorm; - if (b2 != 0.0) - { - fnorm = 1.0/b2; - cfnew = a2*fnorm; - if (fabs(cf-cfnew)/cf < fEps) - j = 101; - else - cf = cfnew; - } - } - if (fB < fEps) - b1 = 69; // ln(1.0E30) - else - b1 = GetLogGamma(fA)+GetLogGamma(fB)-GetLogGamma(fA+fB); - - // cf *= pow(x, fA)*pow(1.0-x,fB)/(fA*exp(b1)); - // #108995# The formula above has 0 as results for the terms too easily, - // resulting in an error where the equivalent formula below still works: - // (x can't be 0 or 1, this is handled above) - cf *= exp( log(x)*fA + log(1.0-x)*fB - b1 ) / fA; - } - if (bReflect) - return 1.0-cf; - else - return cf; -} - double ScInterpreter::GetFDist(double x, double fF1, double fF2) { double arg = fF2/(fF2+fF1*x); @@ -799,7 +721,68 @@ double ScInterpreter::GetChiSqDistCDF(double fX, double fDF) return GetLowRegIGamma( fDF/2.0, fX/2.0); } -// for ODF 1.2 GAMMA +double ScInterpreter::GetChiSqDistPDF(double fX, double fDF) +{ + // you must ensure fDF is positive integer + double fValue; + double fCount; + if (fX <= 0.0) + return 0.0; // see ODFF + if (fDF*fX > 1391000.0) + { + // intermediate invalid values, use log + fValue = exp((0.5*fDF - 1) * log(fX*0.5) - 0.5 * fX - log(2.0) - GetLogGamma(0.5*fDF)); + } + else // fDF is small in most cases, we can iterate + { + if (fmod(fDF,2.0)<0.5) + { + // even + fValue = 0.5; + fCount = 2.0; + } + else + { + fValue = 1/sqrt(fX*2*F_PI); + fCount = 1.0; + } + while ( fCount < fDF) + { + fValue *= (fX / fCount); + fCount += 2.0; + } + if (fX>=1425.0) // underflow in e^(-x/2) + fValue = exp(log(fValue)-fX/2); + else + fValue *= exp(-fX/2); + } + return fValue; +} + +void ScInterpreter::ScChiSqDist() +{ + BYTE nParamCount = GetByte(); + if ( !MustHaveParamCount( nParamCount, 2, 3 ) ) + return; + double fX; + bool bCumulative; + if (nParamCount == 3) + bCumulative = GetBool(); + else + bCumulative = true; + double fDF = ::rtl::math::approxFloor(GetDouble()); + if (fDF < 1.0) + PushIllegalArgument(); + else + { + fX = GetDouble(); + if (bCumulative) + PushDouble(GetChiSqDistCDF(fX,fDF)); + else + PushDouble(GetChiSqDistPDF(fX,fDF)); + } +} + void ScInterpreter::ScGamma() { double x = GetDouble(); @@ -828,31 +811,296 @@ void ScInterpreter::ScLogGamma() PushIllegalArgument(); } +double ScInterpreter::GetBeta(double fAlpha, double fBeta) +{ + double fA; + double fB; + if (fAlpha > fBeta) + { + fA = fAlpha; fB = fBeta; + } + else + { + fA = fBeta; fB = fAlpha; + } + if (fA+fB < fMaxGammaArgument) // simple case + return GetGamma(fA)/GetGamma(fA+fB)*GetGamma(fB); + // need logarithm + // GetLogGamma is not accurate enough, back to Lanczos for all three + // GetGamma and arrange factors newly. + const double fg = 6.024680040776729583740234375; //see GetGamma + double fgm = fg - 0.5; + double fLanczos = lcl_getLanczosSum(fA); + fLanczos /= lcl_getLanczosSum(fA+fB); + fLanczos *= lcl_getLanczosSum(fB); + double fABgm = fA+fB+fgm; + fLanczos *= sqrt((fABgm/(fA+fgm))/(fB+fgm)); + double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm)) + double fTempB = fA/(fB+fgm); + double fResult = exp(-fA * ::rtl::math::log1p(fTempA) + -fB * ::rtl::math::log1p(fTempB)-fgm); + fResult *= fLanczos; + return fResult; +} + +// Same as GetBeta but with logarithm +double ScInterpreter::GetLogBeta(double fAlpha, double fBeta) +{ + double fA; + double fB; + if (fAlpha > fBeta) + { + fA = fAlpha; fB = fBeta; + } + else + { + fA = fBeta; fB = fAlpha; + } + const double fg = 6.024680040776729583740234375; //see GetGamma + double fgm = fg - 0.5; + double fLanczos = lcl_getLanczosSum(fA); + fLanczos /= lcl_getLanczosSum(fA+fB); + fLanczos *= lcl_getLanczosSum(fB); + double fLogLanczos = log(fLanczos); + double fABgm = fA+fB+fgm; + fLogLanczos += 0.5*(log(fABgm)-log(fA+fgm)-log(fB+fgm)); + double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm)) + double fTempB = fA/(fB+fgm); + double fResult = -fA * ::rtl::math::log1p(fTempA) + -fB * ::rtl::math::log1p(fTempB)-fgm; + fResult += fLogLanczos; + return fResult; +} + +// beta distribution probability density function +double ScInterpreter::GetBetaDistPDF(double fX, double fA, double fB) +{ + // special cases + if (fA == 1.0) // result b*(1-x)^(b-1) + { + if (fB == 1.0) + return 1.0; + if (fB == 2.0) + return -2.0*fX + 2.0; + if (fX == 1.0 && fB < 1.0) + { + SetError(errIllegalArgument); + return HUGE_VAL; + } + if (fX <= 0.01) + return fB + fB * ::rtl::math::expm1((fB-1.0) * ::rtl::math::log1p(-fX)); + else + return fB * pow(0.5-fX+0.5,fB-1.0); + } + if (fB == 1.0) // result a*x^(a-1) + { + if (fA == 2.0) + return fA * fX; + if (fX == 0.0 && fA < 1.0) + { + SetError(errIllegalArgument); + return HUGE_VAL; + } + return fA * pow(fX,fA-1); + } + if (fX <= 0.0) + { + if (fA < 1.0 && fX == 0.0) + { + SetError(errIllegalArgument); + return HUGE_VAL; + } + else + return 0.0; + } + if (fX >= 1.0) + if (fB < 1.0 && fX == 1.0) + { + SetError(errIllegalArgument); + return HUGE_VAL; + } + else + return 0.0; + + // normal cases; result x^(a-1)*(1-x)^(b-1)/Beta(a,b) + const double fLogDblMax = log( ::std::numeric_limits<double>::max()); + const double fLogDblMin = log( ::std::numeric_limits<double>::min()); + double fLogY = (fX < 0.1) ? ::rtl::math::log1p(-fX) : log(0.5-fX+0.5); + double fLogX = log(fX); + double fAm1 = fA-1.0; + double fBm1 = fB-1.0; + double fLogBeta = GetLogBeta(fA,fB); + // check whether parts over- or underflow + if ( fAm1 * fLogX < fLogDblMax && fAm1 * fLogX > fLogDblMin + && fBm1 * fLogY < fLogDblMax && fBm1* fLogY > fLogDblMin + && fLogBeta < fLogDblMax && fLogBeta > fLogDblMin ) + return pow(fX,fA-1.0) * pow(0.5-fX+0.5,fB-1.0) / GetBeta(fA,fB); + else // need logarithm; + // might overflow as a whole, but seldom, not worth to pre-detect it + return exp((fA-1.0)*fLogX + (fB-1.0)* fLogY - fLogBeta); +} + + +/* + x^a * (1-x)^b + I_x(a,b) = ---------------- * result of ContFrac + a * Beta(a,b) +*/ +double lcl_GetBetaHelperContFrac(double fX, double fA, double fB) +{ // like old version + double a1, b1, a2, b2, fnorm, apl2m, d2m, d2m1, cfnew, cf; + a1 = 1.0; b1 = 1.0; + b2 = 1.0 - (fA+fB)/(fA+1.0)*fX; + if (b2 == 0.0) + { + a2 = 0.0; + fnorm = 1.0; + cf = 1.0; + } + else + { + a2 = 1.0; + fnorm = 1.0/b2; + cf = a2*fnorm; + } + cfnew = 1.0; + double rm = 1.0; + + const double fMaxIter = 50000.0; + // loop security, normal cases converge in less than 100 iterations. + // FIXME: You will get so much iteratons for fX near mean, + // I do not know a better algorithm. + bool bfinished = false; + do + { + apl2m = fA + 2.0*rm; + d2m = rm*(fB-rm)*fX/((apl2m-1.0)*apl2m); + d2m1 = -(fA+rm)*(fA+fB+rm)*fX/(apl2m*(apl2m+1.0)); + a1 = (a2+d2m*a1)*fnorm; + b1 = (b2+d2m*b1)*fnorm; + a2 = a1 + d2m1*a2*fnorm; + b2 = b1 + d2m1*b2*fnorm; + if (b2 != 0.0) + { + fnorm = 1.0/b2; + cfnew = a2*fnorm; + bfinished = (fabs(cf-cfnew) < fabs(cf)*fMachEps); + } + cf = cfnew; + rm += 1.0; + } + while (rm < fMaxIter && !bfinished); + return cf; +} + +// cumulative distribution function, normalized +double ScInterpreter::GetBetaDist(double fXin, double fAlpha, double fBeta) +{ +// special cases + if (fXin <= 0.0) // values are valid, see spec + return 0.0; + if (fXin >= 1.0) // values are valid, see spec + return 1.0; + if (fBeta == 1.0) + return pow(fXin, fAlpha); + if (fAlpha == 1.0) + // 1.0 - pow(1.0-fX,fBeta) is not accurate enough + return -::rtl::math::expm1(fBeta * ::rtl::math::log1p(-fXin)); + //FIXME: need special algorithm for fX near fP for large fA,fB + double fResult; + // I use always continued fraction, power series are neither + // faster nor more accurate. + double fY = (0.5-fXin)+0.5; + double flnY = ::rtl::math::log1p(-fXin); + double fX = fXin; + double flnX = log(fXin); + double fA = fAlpha; + double fB = fBeta; + bool bReflect = fXin > fAlpha/(fAlpha+fBeta); + if (bReflect) + { + fA = fBeta; + fB = fAlpha; + fX = fY; + fY = fXin; + flnX = flnY; + flnY = log(fXin); + } + fResult = lcl_GetBetaHelperContFrac(fX,fA,fB); + fResult = fResult/fA; + double fP = fA/(fA+fB); + double fQ = fB/(fA+fB); + double fTemp; + if (fA > 1.0 && fB > 1.0 && fP < 0.97 && fQ < 0.97) //found experimental + fTemp = GetBetaDistPDF(fX,fA,fB)*fX*fY; + else + fTemp = exp(fA*flnX + fB*flnY - GetLogBeta(fA,fB)); + fResult *= fTemp; + if (bReflect) + fResult = 0.5 - fResult + 0.5; + if (fResult > 1.0) // ensure valid range + fResult = 1.0; + if (fResult < 0.0) + fResult = 0.0; + return fResult; +} void ScInterpreter::ScBetaDist() { BYTE nParamCount = GetByte(); - if ( !MustHaveParamCount( nParamCount, 3, 5 ) ) + if ( !MustHaveParamCount( nParamCount, 3, 6 ) ) // expanded, see #i91547# return; - double fA, fB, alpha, beta, x; - if (nParamCount == 5) - fB = GetDouble(); + double fLowerBound, fUpperBound; + double alpha, beta, x; + bool bIsCumulative; + if (nParamCount == 6) + bIsCumulative = GetBool(); else - fB = 1.0; + bIsCumulative = true; + if (nParamCount >= 5) + fUpperBound = GetDouble(); + else + fUpperBound = 1.0; if (nParamCount >= 4) - fA = GetDouble(); + fLowerBound = GetDouble(); else - fA = 0.0; + fLowerBound = 0.0; beta = GetDouble(); alpha = GetDouble(); x = GetDouble(); - if (x < fA || x > fB || fA == fB || alpha <= 0.0 || beta <= 0.0) + double fScale = fUpperBound - fLowerBound; + if (fScale <= 0.0 || alpha <= 0.0 || beta <= 0.0) { PushIllegalArgument(); return; } - x = (x-fA)/(fB-fA); // Skalierung auf (0,1) - PushDouble(GetBetaDist(x, alpha, beta)); + if (bIsCumulative) // cumulative distribution function + { + // special cases + if (x < fLowerBound) + { + PushDouble(0.0); return; //see spec + } + if (x > fUpperBound) + { + PushDouble(1.0); return; //see spec + } + // normal cases + x = (x-fLowerBound)/fScale; // convert to standard form + PushDouble(GetBetaDist(x, alpha, beta)); + return; + } + else // probability density function + { + if (x < fLowerBound || x > fUpperBound) + { + PushDouble(0.0); + return; + } + x = (x-fLowerBound)/fScale; + PushDouble(GetBetaDistPDF(x, alpha, beta)/fScale); + return; + } } void ScInterpreter::ScPhi() @@ -1325,7 +1573,7 @@ void ScInterpreter::ScChiDist() return; double fDF = ::rtl::math::approxFloor(GetDouble()); double fChi = GetDouble(); - if (fDF < 1.0 || fDF >= 1.0E5 || fChi < 0.0 ) + if (fDF < 1.0) // x<=0 returns 1, see ODFF 6.17.10 { PushIllegalArgument(); return; @@ -1359,9 +1607,10 @@ void ScInterpreter::ScWeibull() void ScInterpreter::ScPoissonDist() { - if ( MustHaveParamCount( GetByte(), 3 ) ) + BYTE nParamCount = GetByte(); + if ( MustHaveParamCount( nParamCount, 2, 3 ) ) { - double kum = GetDouble(); // 0 oder 1 + double kum = (nParamCount == 3 ? GetDouble() : 1); // 0 oder 1 double lambda = GetDouble(); // Mittelwert double x = ::rtl::math::approxFloor(GetDouble()); // x if (lambda < 0.0 || x < 0.0) @@ -1640,10 +1889,14 @@ void ScInterpreter::ScHypGeomDist() void ScInterpreter::ScGammaDist() { - if ( !MustHaveParamCount( GetByte(), 4 ) ) + BYTE nParamCount = GetByte(); + if ( !MustHaveParamCount( nParamCount, 3, 4 ) ) return; - double fCumulative = GetDouble(); // parameter type will change to bool - bool bCumulative = (fCumulative == 1.0); // see ODFF + double bCumulative; + if (nParamCount == 4) + bCumulative = GetBool(); + else + bCumulative = true; double fBeta = GetDouble(); // scale double fAlpha = GetDouble(); // shape double fX = GetDouble(); // x @@ -1873,7 +2126,7 @@ void ScInterpreter::ScChiInv() return; double fDF = ::rtl::math::approxFloor(GetDouble()); double fP = GetDouble(); - if (fDF < 1.0 || fDF >= 1.0E5 || fP <= 0.0 || fP > 1.0 ) + if (fDF < 1.0 || fP <= 0.0 || fP > 1.0 ) { PushIllegalArgument(); return; @@ -1887,6 +2140,39 @@ void ScInterpreter::ScChiInv() PushDouble(fVal); } +class ScChiSqDistFunction : public ScDistFunc +{ + ScInterpreter& rInt; + double fp, fDF; + +public: + ScChiSqDistFunction( ScInterpreter& rI, double fpVal, double fDFVal ) : + rInt(rI), fp(fpVal), fDF(fDFVal) {} + + double GetValue( double x ) const { return fp - rInt.GetChiSqDistCDF(x, fDF); } +}; + + +void ScInterpreter::ScChiSqInv() +{ + if ( !MustHaveParamCount( GetByte(), 2 ) ) + return; + double fDF = ::rtl::math::approxFloor(GetDouble()); + double fP = GetDouble(); + if (fDF < 1.0 || fP < 0.0 || fP >= 1.0 ) + { + PushIllegalArgument(); + return; + } + + bool bConvError; + ScChiSqDistFunction aFunc( *this, fP, fDF ); + double fVal = lcl_IterateInverse( aFunc, fDF*0.5, fDF, bConvError ); + if (bConvError) + SetError(errNoConvergence); + PushDouble(fVal); +} + /***********************************************/ void ScInterpreter::ScConfidence() diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 67eac357e302..4ef402815f9b 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -3650,6 +3650,7 @@ StackVar ScInterpreter::Interpret() case ocTDist : ScTDist(); break; case ocFDist : ScFDist(); break; case ocChiDist : ScChiDist(); break; + case ocChiSqDist : ScChiSqDist(); break; case ocStandard : ScStandard(); break; case ocAveDev : ScAveDev(); break; case ocDevSq : ScDevSq(); break; @@ -3692,10 +3693,12 @@ StackVar ScInterpreter::Interpret() case ocRKP : ScRKP(); break; case ocForecast : ScForecast(); break; case ocGammaLn : ScLogGamma(); break; + case ocGamma : ScGamma(); break; case ocGammaDist : ScGammaDist(); break; case ocGammaInv : ScGammaInv(); break; case ocChiTest : ScChiTest(); break; case ocChiInv : ScChiInv(); break; + case ocChiSqInv : ScChiSqInv(); break; case ocTInv : ScTInv(); break; case ocFInv : ScFInv(); break; case ocLogInv : ScLogNormInv(); break; @@ -3712,6 +3715,7 @@ StackVar ScInterpreter::Interpret() case ocBase : ScBase(); break; case ocDecimal : ScDecimal(); break; case ocConvert : ScConvert(); break; + case ocEuroConvert : ScEuroConvert(); break; case ocRoman : ScRoman(); break; case ocArabic : ScArabic(); break; case ocInfo : ScInfo(); break; @@ -3887,7 +3891,7 @@ StackVar ScInterpreter::Interpret() const ScMatrixValue* pMatVal = xMat->Get(0, 0, nMatValType); if ( pMatVal ) { - if (ScMatrix::IsStringType( nMatValType)) + if (ScMatrix::IsNonValueType( nMatValType)) { if ( xMat->IsEmptyPath( 0, 0)) { // result of empty FALSE jump path diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx index 72f1b070d02f..32be76431569 100644 --- a/sc/source/core/tool/interpr5.cxx +++ b/sc/source/core/tool/interpr5.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: interpr5.cxx,v $ - * $Revision: 1.34 $ + * $Revision: 1.33.36.3 $ * * This file is part of OpenOffice.org. * @@ -520,7 +520,7 @@ void ScInterpreter::ScMatValue() ScMatValType nMatValType; const ScMatrixValue* pMatVal = pMat->Get( nC, nR, nMatValType); - if (ScMatrix::IsStringType( nMatValType)) + if (ScMatrix::IsNonValueType( nMatValType)) PushString( pMatVal->GetString() ); else PushDouble(pMatVal->fVal); @@ -578,7 +578,7 @@ void ScInterpreter::ScMatValue() ScMatValType nMatValType; const ScMatrixValue* pMatVal = pMat->Get( nC, nR, nMatValType); - if (ScMatrix::IsStringType( nMatValType)) + if (ScMatrix::IsNonValueType( nMatValType)) PushString( pMatVal->GetString() ); else PushDouble(pMatVal->fVal); @@ -1018,6 +1018,23 @@ void ScInterpreter::ScMatTrans() } } + +/** Minimum extent of one result matrix dimension. + For a row or column vector to be replicated the larger matrix dimension is + returned, else the smaller dimension. + */ +inline SCSIZE lcl_GetMinExtent( SCSIZE n1, SCSIZE n2 ) +{ + if (n1 == 1) + return n2; + else if (n2 == 1) + return n1; + else if (n1 < n2) + return n1; + else + return n2; +} + ScMatrixRef ScInterpreter::MatAdd(ScMatrix* pMat1, ScMatrix* pMat2) { SCSIZE nC1, nC2, nMinC; @@ -1025,14 +1042,8 @@ ScMatrixRef ScInterpreter::MatAdd(ScMatrix* pMat1, ScMatrix* pMat2) SCSIZE i, j; pMat1->GetDimensions(nC1, nR1); pMat2->GetDimensions(nC2, nR2); - if (nC1 < nC2) - nMinC = nC1; - else - nMinC = nC2; - if (nR1 < nR2) - nMinR = nR1; - else - nMinR = nR2; + nMinC = lcl_GetMinExtent( nC1, nC2); + nMinR = lcl_GetMinExtent( nR1, nR2); ScMatrixRef xResMat = GetNewMat(nMinC, nMinR); if (xResMat) { @@ -1060,14 +1071,8 @@ ScMatrixRef ScInterpreter::MatSub(ScMatrix* pMat1, ScMatrix* pMat2) SCSIZE i, j; pMat1->GetDimensions(nC1, nR1); pMat2->GetDimensions(nC2, nR2); - if (nC1 < nC2) - nMinC = nC1; - else - nMinC = nC2; - if (nR1 < nR2) - nMinR = nR1; - else - nMinR = nR2; + nMinC = lcl_GetMinExtent( nC1, nC2); + nMinR = lcl_GetMinExtent( nR1, nR2); ScMatrixRef xResMat = GetNewMat(nMinC, nMinR); if (xResMat) { @@ -1095,14 +1100,8 @@ ScMatrixRef ScInterpreter::MatMul(ScMatrix* pMat1, ScMatrix* pMat2) SCSIZE i, j; pMat1->GetDimensions(nC1, nR1); pMat2->GetDimensions(nC2, nR2); - if (nC1 < nC2) - nMinC = nC1; - else - nMinC = nC2; - if (nR1 < nR2) - nMinR = nR1; - else - nMinR = nR2; + nMinC = lcl_GetMinExtent( nC1, nC2); + nMinR = lcl_GetMinExtent( nR1, nR2); ScMatrixRef xResMat = GetNewMat(nMinC, nMinR); if (xResMat) { @@ -1130,14 +1129,8 @@ ScMatrixRef ScInterpreter::MatDiv(ScMatrix* pMat1, ScMatrix* pMat2) SCSIZE i, j; pMat1->GetDimensions(nC1, nR1); pMat2->GetDimensions(nC2, nR2); - if (nC1 < nC2) - nMinC = nC1; - else - nMinC = nC2; - if (nR1 < nR2) - nMinR = nR1; - else - nMinR = nR2; + nMinC = lcl_GetMinExtent( nC1, nC2); + nMinR = lcl_GetMinExtent( nR1, nR2); ScMatrixRef xResMat = GetNewMat(nMinC, nMinR); if (xResMat) { @@ -1166,14 +1159,8 @@ ScMatrixRef ScInterpreter::MatPow(ScMatrix* pMat1, ScMatrix* pMat2) SCSIZE i, j; pMat1->GetDimensions(nC1, nR1); pMat2->GetDimensions(nC2, nR2); - if (nC1 < nC2) - nMinC = nC1; - else - nMinC = nC2; - if (nR1 < nR2) - nMinR = nR1; - else - nMinR = nR2; + nMinC = lcl_GetMinExtent( nC1, nC2); + nMinR = lcl_GetMinExtent( nR1, nR2); ScMatrixRef xResMat = GetNewMat(nMinC, nMinR); if (xResMat) { @@ -1201,14 +1188,8 @@ ScMatrixRef ScInterpreter::MatConcat(ScMatrix* pMat1, ScMatrix* pMat2) SCSIZE i, j; pMat1->GetDimensions(nC1, nR1); pMat2->GetDimensions(nC2, nR2); - if (nC1 < nC2) - nMinC = nC1; - else - nMinC = nC2; - if (nR1 < nR2) - nMinR = nR1; - else - nMinR = nR2; + nMinC = lcl_GetMinExtent( nC1, nC2); + nMinR = lcl_GetMinExtent( nR1, nR2); ScMatrixRef xResMat = GetNewMat(nMinC, nMinR); if (xResMat) { @@ -3679,26 +3660,28 @@ void ScInterpreter::ScMatRef() const ScMatrix* pMat = pCell->GetMatrix(); if( pMat ) { - SCSIZE nCl, nRw; - pMat->GetDimensions( nCl, nRw ); + SCSIZE nCols, nRows; + pMat->GetDimensions( nCols, nRows ); SCSIZE nC = static_cast<SCSIZE>(aPos.Col() - aAdr.Col()); SCSIZE nR = static_cast<SCSIZE>(aPos.Row() - aAdr.Row()); - if (nC < nCl && nR < nRw) + if ((nCols <= nC && nCols != 1) || (nRows <= nR && nRows != 1)) + PushNA(); + else { ScMatValType nMatValType; const ScMatrixValue* pMatVal = pMat->Get( nC, nR, nMatValType); - if (ScMatrix::IsStringType( nMatValType)) + if (ScMatrix::IsNonValueType( nMatValType)) { - if (ScMatrix::IsEmptyType( nMatValType)) - { - // Not inherited (really?) and display as empty string, not 0. - PushTempToken( new ScEmptyCellToken( false, true)); - } - else if (ScMatrix::IsEmptyPathType( nMatValType)) + if (ScMatrix::IsEmptyPathType( nMatValType)) { // result of empty FALSE jump path nFuncFmtType = NUMBERFORMAT_LOGICAL; PushInt(0); } + else if (ScMatrix::IsEmptyType( nMatValType)) + { + // Not inherited (really?) and display as empty string, not 0. + PushTempToken( new ScEmptyCellToken( false, true)); + } else PushString( pMatVal->GetString() ); } @@ -3710,8 +3693,6 @@ void ScInterpreter::ScMatRef() nFuncFmtIndex = nCurFmtIndex; } } - else - PushNA(); } else { diff --git a/sc/source/core/tool/parclass.cxx b/sc/source/core/tool/parclass.cxx index d31c4a8ce565..8e4d3e0b1272 100644 --- a/sc/source/core/tool/parclass.cxx +++ b/sc/source/core/tool/parclass.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: parclass.cxx,v $ - * $Revision: 1.12 $ + * $Revision: 1.12.148.1 $ * * This file is part of OpenOffice.org. * @@ -149,6 +149,7 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] = { ocN, {{ Reference }, false }}, { ocNPV, {{ Value, Reference }, true }}, { ocNeg, {{ Array }, false }}, + { ocNegSub, {{ Array }, false }}, { ocNot, {{ Array }, false }}, { ocNotEqual, {{ Array, Array }, false }}, { ocOffset, {{ Reference, Value, Value, Value, Value }, false }}, diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx index 014cbbb5c491..891ed6378022 100644 --- a/sc/source/core/tool/scmatrix.cxx +++ b/sc/source/core/tool/scmatrix.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: scmatrix.cxx,v $ - * $Revision: 1.18 $ + * $Revision: 1.17.136.3 $ * * This file is part of OpenOffice.org. * @@ -79,6 +79,14 @@ ScMatrix* ScMatrix::Clone() const return pScMat; } +ScMatrix* ScMatrix::CloneAndExtend( SCSIZE nNewCols, SCSIZE nNewRows ) const +{ + ScMatrix* pScMat = new ScMatrix( nNewCols, nNewRows); + MatCopy(*pScMat); + pScMat->SetErrorInterpreter( pErrorInterpreter); + return pScMat; +} + void ScMatrix::SetErrorAtInterpreter( USHORT nError ) const { if ( pErrorInterpreter ) @@ -180,7 +188,7 @@ void ScMatrix::Store(SvStream& /* rStream */) const for (SCSIZE i=0; i<nCount; i++) { BYTE nType = CELLTYPE_VALUE; - if ( mnValType && IsStringType( mnValType[i])) + if ( mnValType && IsNonValueType( mnValType[i])) { if ( pMat[i].pS ) aMatStr = *pMat[i].pS; @@ -208,7 +216,7 @@ void ScMatrix::ResetIsString() { for (SCSIZE i = 0; i < nCount; i++) { - if ( IsStringType( mnValType[i])) + if ( IsNonValueType( mnValType[i])) delete pMat[i].pS; } } @@ -225,7 +233,7 @@ void ScMatrix::DeleteIsString() SCSIZE nCount = nColCount * nRowCount; for ( SCSIZE i = 0; i < nCount; i++ ) { - if (IsStringType( mnValType[i])) + if (IsNonValueType( mnValType[i])) delete pMat[i].pS; } delete [] mnValType; @@ -258,7 +266,7 @@ void ScMatrix::PutString(const String& rStr, SCSIZE nIndex) { if (mnValType == NULL) ResetIsString(); - if ( IsStringType( mnValType[nIndex]) && pMat[nIndex].pS ) + if ( IsNonValueType( mnValType[nIndex]) && pMat[nIndex].pS ) *(pMat[nIndex].pS) = rStr; else { @@ -277,10 +285,10 @@ void ScMatrix::PutStringEntry( const String* pStr, BYTE bFlag, SCSIZE nIndex ) // the value with if (IsValueOrEmpty()) GetDouble(). Backup pS first. String* pS = pMat[nIndex].pS; pMat[nIndex].fVal = 0.0; - // An EMPTY entry must not have a string pointer therefor. + // An EMPTY or EMPTYPATH entry must not have a string pointer therefor. DBG_ASSERT( (((bFlag & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY) && !pStr) || TRUE, - "ScMatrix::PutStringEntry: pStr passed though EMPTY entry"); - if ( IsStringType( mnValType[nIndex]) && pS ) + "ScMatrix::PutStringEntry: pStr passed through EMPTY entry"); + if ( IsNonValueType( mnValType[nIndex]) && pS ) { if ((bFlag & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY) delete pS, pS = NULL; @@ -312,7 +320,7 @@ void ScMatrix::PutEmpty(SCSIZE nIndex) { if (mnValType == NULL) ResetIsString(); - if ( IsStringType( mnValType[nIndex]) && pMat[nIndex].pS ) + if ( IsNonValueType( mnValType[nIndex]) && pMat[nIndex].pS ) { delete pMat[nIndex].pS; } @@ -339,7 +347,7 @@ void ScMatrix::PutEmptyPath(SCSIZE nIndex) { if (mnValType == NULL) ResetIsString(); - if ( IsStringType( mnValType[nIndex]) && pMat[nIndex].pS ) + if ( IsNonValueType( mnValType[nIndex]) && pMat[nIndex].pS ) { delete pMat[nIndex].pS; } @@ -366,7 +374,7 @@ void ScMatrix::PutBoolean( bool bVal, SCSIZE nIndex) { if (mnValType == NULL) ResetIsString(); - if ( IsStringType( mnValType[nIndex]) && pMat[nIndex].pS ) + if ( IsNonValueType( mnValType[nIndex]) && pMat[nIndex].pS ) { delete pMat[nIndex].pS; mnNonValue--; @@ -379,29 +387,29 @@ void ScMatrix::PutBoolean( bool bVal, SCSIZE nIndex) USHORT ScMatrix::GetError( SCSIZE nC, SCSIZE nR) const { - if (ValidColRow( nC, nR)) + if (ValidColRowOrReplicated( nC, nR )) return GetError( CalcOffset( nC, nR) ); else { DBG_ERRORFILE("ScMatrix::GetError: dimension error"); - return 0; // TODO: do we want an error instead? + return errNoValue; } } double ScMatrix::GetDouble(SCSIZE nC, SCSIZE nR) const { - if (ValidColRow( nC, nR)) + if (ValidColRowOrReplicated( nC, nR )) return GetDouble( CalcOffset( nC, nR) ); else { DBG_ERRORFILE("ScMatrix::GetDouble: dimension error"); - return 0.0; + return CreateDoubleError( errNoValue); } } const String& ScMatrix::GetString(SCSIZE nC, SCSIZE nR) const { - if (ValidColRow( nC, nR)) + if (ValidColRowOrReplicated( nC, nR )) { SCSIZE nIndex = CalcOffset( nC, nR); if ( IsString( nIndex ) ) @@ -454,7 +462,7 @@ String ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nIndex) const String ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const { - if (ValidColRow( nC, nR)) + if (ValidColRowOrReplicated( nC, nR )) { SCSIZE nIndex = CalcOffset( nC, nR); return GetString( rFormatter, nIndex); @@ -469,7 +477,7 @@ String ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const ScMatrixValue* ScMatrix::Get(SCSIZE nC, SCSIZE nR, ScMatValType& nType) const { - if (ValidColRow( nC, nR)) + if (ValidColRowOrReplicated( nC, nR )) { SCSIZE nIndex = CalcOffset( nC, nR); if (mnValType) @@ -488,11 +496,11 @@ const ScMatrixValue* ScMatrix::Get(SCSIZE nC, SCSIZE nR, ScMatValType& nType) co void ScMatrix::MatCopy(ScMatrix& mRes) const { - if (nColCount != mRes.nColCount || nRowCount != mRes.nRowCount) + if (nColCount > mRes.nColCount || nRowCount > mRes.nRowCount) { DBG_ERRORFILE("ScMatrix::MatCopy: dimension error"); } - else + else if ( nColCount == mRes.nColCount && nRowCount == mRes.nRowCount ) { if (mnValType) { @@ -503,7 +511,7 @@ void ScMatrix::MatCopy(ScMatrix& mRes) const SCSIZE nStart = i * nRowCount; for (SCSIZE j = 0; j < nRowCount; j++) { - if (IsStringType( (nType = mnValType[nStart+j]))) + if (IsNonValueType( (nType = mnValType[nStart+j]))) mRes.PutStringEntry( pMat[nStart+j].pS, nType, nStart+j ); else { @@ -521,6 +529,41 @@ void ScMatrix::MatCopy(ScMatrix& mRes) const mRes.pMat[i].fVal = pMat[i].fVal; } } + else + { + // Copy this matrix to upper left rectangle of result matrix. + if (mnValType) + { + ScMatValType nType; + mRes.ResetIsString(); + for (SCSIZE i = 0; i < nColCount; i++) + { + SCSIZE nStart = i * nRowCount; + SCSIZE nResStart = i * mRes.nRowCount; + for (SCSIZE j = 0; j < nRowCount; j++) + { + if (IsNonValueType( (nType = mnValType[nStart+j]))) + mRes.PutStringEntry( pMat[nStart+j].pS, nType, nResStart+j ); + else + { + mRes.pMat[nResStart+j].fVal = pMat[nStart+j].fVal; + mRes.mnValType[nResStart+j] = nType; + } + } + } + } + else + { + mRes.DeleteIsString(); + for (SCSIZE i = 0; i < nColCount; i++) + { + SCSIZE nStart = i * nRowCount; + SCSIZE nResStart = i * mRes.nRowCount; + for (SCSIZE j = 0; j < nRowCount; j++) + mRes.pMat[nResStart+j].fVal = pMat[nStart+j].fVal; + } + } + } } void ScMatrix::MatTrans(ScMatrix& mRes) const @@ -540,7 +583,7 @@ void ScMatrix::MatTrans(ScMatrix& mRes) const SCSIZE nStart = i * nRowCount; for ( SCSIZE j = 0; j < nRowCount; j++ ) { - if (IsStringType( (nType = mnValType[nStart+j]))) + if (IsNonValueType( (nType = mnValType[nStart+j]))) mRes.PutStringEntry( pMat[nStart+j].pS, nType, j*mRes.nRowCount+i ); else { @@ -565,6 +608,49 @@ void ScMatrix::MatTrans(ScMatrix& mRes) const } } +void ScMatrix::MatCopyUpperLeft(ScMatrix& mRes) const +{ + if (nColCount < mRes.nColCount || nRowCount < mRes.nRowCount) + { + DBG_ERRORFILE("ScMatrix::MatCopyUpperLeft: dimension error"); + } + else + { + if (mnValType) + { + ScMatValType nType; + mRes.ResetIsString(); + for ( SCSIZE i = 0; i < mRes.nColCount; i++ ) + { + SCSIZE nStart = i * nRowCount; + for ( SCSIZE j = 0; j < mRes.nRowCount; j++ ) + { + if ( IsNonValueType( (nType = mnValType[nStart+j]) )) + mRes.PutStringEntry( pMat[nStart+j].pS, nType, + i*mRes.nRowCount+j ); + else + { + mRes.pMat[i*mRes.nRowCount+j].fVal = pMat[nStart+j].fVal; + mRes.mnValType[i*mRes.nRowCount+j] = nType; + } + } + } + } + else + { + mRes.DeleteIsString(); + for ( SCSIZE i = 0; i < mRes.nColCount; i++ ) + { + SCSIZE nStart = i * nRowCount; + for ( SCSIZE j = 0; j < mRes.nRowCount; j++ ) + { + mRes.pMat[i*mRes.nRowCount+j].fVal = pMat[nStart+j].fVal; + } + } + } + } +} + void ScMatrix::FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 ) { if (ValidColRow( nC1, nR1) && ValidColRow( nC2, nR2)) diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index 31fdcdedb7e9..776831726fe6 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -2486,11 +2486,6 @@ void ScTokenArray::ReadjustRelative3DReferences( const ScAddress& rOldPos, // --- POF (plain old formula) rewrite of a token array --------------------- -/* TODO: When both POF OOoXML and ODFF are to be supported differently, the - * ScMissingContext and ScTokenArray::*Pof* methods should go to a convention - * on its own. - */ - #if 0 // static function can't be compiled if not used (warning) //#if OSL_DEBUG_LEVEL > 0 @@ -2512,37 +2507,41 @@ class ScMissingContext void Clear() { mpFunc = NULL; mnCurArg = 0; } inline bool AddDefaultArg( ScTokenArray* pNewArr, int nArg, double f ) const; - static inline bool IsRewriteNeeded( OpCode eOp ); bool AddMissingExternal( ScTokenArray* pNewArr ) const; - bool AddMissing( ScTokenArray *pNewArr ) const; - void AddMoreArgs( ScTokenArray *pNewArr ) const; + bool AddMissing( ScTokenArray *pNewArr, const ScMissingConvention & rConv ) const; + void AddMoreArgs( ScTokenArray *pNewArr, const ScMissingConvention & rConv ) const; }; -inline bool ScMissingContext::AddDefaultArg( ScTokenArray* pNewArr, int nArg, double f ) const -{ - if (mnCurArg == nArg) - { - pNewArr->AddDouble( f ); - return true; - } - return false; -} - -inline bool ScMissingContext::IsRewriteNeeded( OpCode eOp ) +inline bool ScMissingConvention::isRewriteNeeded( OpCode eOp ) const { switch (eOp) { + case ocGammaDist: + case ocPoissonDist: + return true; case ocMissing: case ocLog: case ocAddress: - return true; + return !isODFF(); // rewrite only for PODF default: return false; } } +inline bool ScMissingContext::AddDefaultArg( ScTokenArray* pNewArr, int nArg, double f ) const +{ + if (mnCurArg == nArg) + { + pNewArr->AddDouble( f ); + return true; + } + return false; +} + bool ScMissingContext::AddMissingExternal( ScTokenArray *pNewArr ) const { + // Only called for PODF, not ODFF. No need to distinguish. + const String &rName = mpFunc->GetExternal(); // initial (fast) check: @@ -2563,79 +2562,105 @@ bool ScMissingContext::AddMissingExternal( ScTokenArray *pNewArr ) const return false; } -bool ScMissingContext::AddMissing( ScTokenArray *pNewArr ) const +bool ScMissingContext::AddMissing( ScTokenArray *pNewArr, const ScMissingConvention & rConv ) const { if ( !mpFunc ) return false; bool bRet = false; - switch ( mpFunc->GetOpCode() ) + if (rConv.isODFF()) { - case ocFixed: - return AddDefaultArg( pNewArr, 1, 2.0 ); - //break; - case ocBetaDist: - case ocBetaInv: - case ocRMZ: // PMT - return AddDefaultArg( pNewArr, 3, 0.0 ); - //break; - case ocZinsZ: // IPMT - case ocKapz: // PPMT - return AddDefaultArg( pNewArr, 4, 0.0 ); - //break; - case ocBW: // PV - case ocZW: // FV - bRet |= AddDefaultArg( pNewArr, 2, 0.0 ); // pmt - bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // [fp]v - break; - case ocZins: // RATE - bRet |= AddDefaultArg( pNewArr, 1, 0.0 ); // pmt - bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // fv - bRet |= AddDefaultArg( pNewArr, 4, 0.0 ); // type - break; - case ocExternal: - return AddMissingExternal( pNewArr ); - //break; + } + else + { + switch ( mpFunc->GetOpCode() ) + { + case ocFixed: + return AddDefaultArg( pNewArr, 1, 2.0 ); + //break; + case ocBetaDist: + case ocBetaInv: + case ocRMZ: // PMT + return AddDefaultArg( pNewArr, 3, 0.0 ); + //break; + case ocZinsZ: // IPMT + case ocKapz: // PPMT + return AddDefaultArg( pNewArr, 4, 0.0 ); + //break; + case ocBW: // PV + case ocZW: // FV + bRet |= AddDefaultArg( pNewArr, 2, 0.0 ); // pmt + bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // [fp]v + break; + case ocZins: // RATE + bRet |= AddDefaultArg( pNewArr, 1, 0.0 ); // pmt + bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // fv + bRet |= AddDefaultArg( pNewArr, 4, 0.0 ); // type + break; + case ocExternal: + return AddMissingExternal( pNewArr ); + //break; - // --- more complex cases --- + // --- more complex cases --- - case ocOffset: - // FIXME: rather tough. - // if arg 3 (height) ommitted, export arg1 (rows) - break; - default: - break; + case ocOffset: + // FIXME: rather tough. + // if arg 3 (height) ommitted, export arg1 (rows) + break; + default: + break; + } } return bRet; } -void ScMissingContext::AddMoreArgs( ScTokenArray *pNewArr ) const +void ScMissingContext::AddMoreArgs( ScTokenArray *pNewArr, const ScMissingConvention & rConv ) const { if ( !mpFunc ) return; - // Log - if ( mpFunc->GetOpCode() == ocLog && mnCurArg < 1 ) + switch (mpFunc->GetOpCode()) { - pNewArr->AddOpCode( ocSep ); - pNewArr->AddDouble( 10.0 ); + case ocGammaDist: + if (mnCurArg == 2) + { + pNewArr->AddOpCode( ocSep ); + pNewArr->AddDouble( 1.0 ); // 4th, Cumulative=TRUE() + } + break; + case ocPoissonDist: + if (mnCurArg == 1) + { + pNewArr->AddOpCode( ocSep ); + pNewArr->AddDouble( 1.0 ); // 3rd, Cumulative=TRUE() + } + break; + case ocLog: + if ( !rConv.isODFF() && mnCurArg == 0 ) + { + pNewArr->AddOpCode( ocSep ); + pNewArr->AddDouble( 10.0 ); // 2nd, basis 10 + } + break; + default: + break; } } -bool ScTokenArray::NeedsPofRewrite() +bool ScTokenArray::NeedsPofRewrite( const ScMissingConvention & rConv ) { for ( ScToken *pCur = First(); pCur; pCur = Next() ) { - if (ScMissingContext::IsRewriteNeeded( pCur->GetOpCode())) + if (rConv.isRewriteNeeded( pCur->GetOpCode())) return true; } return false; } -ScTokenArray * ScTokenArray::RewriteMissingToPof() +ScTokenArray * ScTokenArray::RewriteMissingToPof( const ScMissingConvention & rConv ) { const size_t nAlloc = 256; ScMissingContext aCtx[ nAlloc ]; @@ -2683,7 +2708,7 @@ ScTokenArray * ScTokenArray::RewriteMissingToPof() pOcas[ nOcas++ ] = nFn; // entering ADDRESS() break; case ocClose: - pCtx[ nFn ].AddMoreArgs( pNewArr ); + pCtx[ nFn ].AddMoreArgs( pNewArr, rConv ); DBG_ASSERT( nFn > 0, "ScTokenArray::RewriteMissingToPof: underflow"); if (nOcas > 0 && pOcas[ nOcas-1 ] == nFn) --nOcas; // leaving ADDRESS() @@ -2701,7 +2726,7 @@ ScTokenArray * ScTokenArray::RewriteMissingToPof() break; case ocMissing: if (bAdd) - bAdd = !pCtx[ nFn ].AddMissing( pNewArr ); + bAdd = !pCtx[ nFn ].AddMissing( pNewArr, rConv ); break; default: break; diff --git a/sc/source/filter/excel/excform8.cxx b/sc/source/filter/excel/excform8.cxx index d59618ef35ac..47fbd506099c 100644 --- a/sc/source/filter/excel/excform8.cxx +++ b/sc/source/filter/excel/excform8.cxx @@ -680,6 +680,12 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn, } break; + case xlExtEuroConvert: + { + aStack << aPool.Store( ocEuroConvert, String() ); + } + break; + default: // OLE link { aPool << ocBad; diff --git a/sc/source/filter/excel/tokstack.cxx b/sc/source/filter/excel/tokstack.cxx index 78c29e079354..c6cff9bbce78 100644 --- a/sc/source/filter/excel/tokstack.cxx +++ b/sc/source/filter/excel/tokstack.cxx @@ -374,8 +374,13 @@ void TokenPool::GetElement( const UINT16 nId ) EXTCONT* p = ( n < nP_Ext )? ppP_Ext[ n ] : NULL; if( p ) + { + if( p->eId == ocEuroConvert ) + pScToken->AddOpCode( p->eId ); + else pScToken->AddExternal( p->aText, p->eId ); } + } break; case T_Nlf: { diff --git a/sc/source/filter/excel/xeformula.cxx b/sc/source/filter/excel/xeformula.cxx index cc2e7c519cd0..6fc5f782df8e 100644 --- a/sc/source/filter/excel/xeformula.cxx +++ b/sc/source/filter/excel/xeformula.cxx @@ -399,6 +399,7 @@ private: void AppendNameXToken( sal_uInt16 nExtSheet, sal_uInt16 nExtName, sal_uInt8 nExpClass, sal_uInt8 nSpaces = 0 ); void AppendMacroCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nExpClass, sal_uInt8 nSpaces = 0 ); void AppendAddInFuncToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nExpClass, sal_uInt8 nSpaces = 0 ); + void AppendEuroToolFuncToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nExpClass, sal_uInt8 nSpaces = 0 ); void AppendParenToken( sal_uInt8 nOpenSpaces = 0, sal_uInt8 nCloseSpaces = 0 ); void AppendJumpToken( XclExpFuncData& rFuncData, sal_uInt8 nAttrType ); @@ -1723,6 +1724,9 @@ void XclExpFmlaCompImpl::AppendDefaultParam( XclExpFuncData& rFuncData ) case ocExternal: AppendAddInFuncToken( rFuncData.GetExtFuncData(), EXC_TOKCLASS_REF ); break; + case ocEuroConvert: + AppendEuroToolFuncToken( rFuncData.GetExtFuncData(), EXC_TOKCLASS_REF ); + break; case ocMacro: AppendMacroCallToken( rFuncData.GetExtFuncData(), EXC_TOKCLASS_REF ); break; @@ -1784,6 +1788,26 @@ void XclExpFmlaCompImpl::AppendTrailingParam( XclExpFuncData& rFuncData ) AppendDefaultParam( rFuncData ); break; + case ocGammaDist: + if( nParamCount == 3 ) + { + // GAMMADIST function needs 4 parameters in Excel + PrepareParam( rFuncData ); + AppendIntToken( 1 ); + FinishParam( rFuncData ); + } + break; + + case ocPoissonDist: + if( nParamCount == 2 ) + { + // POISSON function needs 3 parameters in Excel + PrepareParam( rFuncData ); + AppendIntToken( 1 ); + FinishParam( rFuncData ); + } + break; + default:; } } @@ -2323,6 +2347,15 @@ void XclExpFmlaCompImpl::AppendAddInFuncToken( const XclExpExtFuncData& rExtFunc AppendMacroCallToken( rExtFuncData, nExpClass, nSpaces ); } +void XclExpFmlaCompImpl::AppendEuroToolFuncToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nExpClass, sal_uInt8 nSpaces ) +{ + sal_uInt16 nExtSheet, nExtName; + if( mpLinkMgr && mpLinkMgr->InsertEuroTool( nExtSheet, nExtName, rExtFuncData.maFuncName ) ) + AppendNameXToken( nExtSheet, nExtName, nExpClass, nSpaces ); + else + AppendMacroCallToken( rExtFuncData, nExpClass, nSpaces ); +} + void XclExpFmlaCompImpl::AppendParenToken( sal_uInt8 nOpenSpaces, sal_uInt8 nCloseSpaces ) { AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP_OPEN, nOpenSpaces ); diff --git a/sc/source/filter/excel/xehelper.cxx b/sc/source/filter/excel/xehelper.cxx index 771c659cbed6..45a44b2c88d1 100644 --- a/sc/source/filter/excel/xehelper.cxx +++ b/sc/source/filter/excel/xehelper.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: xehelper.cxx,v $ - * $Revision: 1.31.32.2 $ + * $Revision: 1.31.148.1 $ * * This file is part of OpenOffice.org. * @@ -1114,7 +1114,7 @@ void XclExpCachedMatrix::Save( XclExpStream& rStrm ) const rStrm << EXC_CACHEDVAL_EMPTY; rStrm.WriteZeroBytes( 8 ); } - else if( ScMatrix::IsStringType( nMatValType ) ) + else if( ScMatrix::IsNonValueType( nMatValType ) ) { XclExpString aStr( pMatVal->GetString(), EXC_STR_DEFAULT ); rStrm.SetSliceSize( 6 ); diff --git a/sc/source/filter/excel/xelink.cxx b/sc/source/filter/excel/xelink.cxx index f6520d1af861..9d1b7df3e741 100644 --- a/sc/source/filter/excel/xelink.cxx +++ b/sc/source/filter/excel/xelink.cxx @@ -140,6 +140,8 @@ public: /** Inserts an add-in function name @return The 1-based (Excel-like) list index of the name. */ sal_uInt16 InsertAddIn( const String& rName ); + /** InsertEuroTool */ + sal_uInt16 InsertEuroTool( const String& rName ); /** Inserts a DDE link. @return The 1-based (Excel-like) list index of the DDE link. */ sal_uInt16 InsertDde( const String& rApplic, const String& rTopic, const String& rItem ); @@ -335,6 +337,8 @@ public: explicit XclExpSupbook( const XclExpRoot& rRoot, sal_uInt16 nXclTabCount ); /** Creates a SUPBOOK record for add-in functions. */ explicit XclExpSupbook( const XclExpRoot& rRoot ); + /** EUROTOOL SUPBOOK */ + explicit XclExpSupbook( const XclExpRoot& rRoot, const String& rUrl, XclSupbookType ); /** Creates a SUPBOOK record for an external document. */ explicit XclExpSupbook( const XclExpRoot& rRoot, const String& rUrl ); /** Creates a SUPBOOK record for a DDE link. */ @@ -362,6 +366,8 @@ public: /** Finds or inserts an EXTERNNAME record for add-ins. @return The 1-based EXTERNNAME record index; or 0, if the record list is full. */ sal_uInt16 InsertAddIn( const String& rName ); + /** InsertEuroTool */ + sal_uInt16 InsertEuroTool( const String& rName ); /** Finds or inserts an EXTERNNAME record for DDE links. @return The 1-based EXTERNNAME record index; or 0, if the record list is full. */ sal_uInt16 InsertDde( const String& rItem ); @@ -443,6 +449,10 @@ public: bool InsertAddIn( sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const String& rName ); + /** InsertEuroTool */ + bool InsertEuroTool( + sal_uInt16& rnSupbook, sal_uInt16& rnExtName, + const String& rName ); /** Finds or inserts an EXTERNNAME record for DDE links. @param rnSupbook Returns the index of the SUPBOOK record which contains the DDE link. @param rnExtName Returns the 1-based EXTERNNAME record index. */ @@ -526,6 +536,11 @@ public: virtual bool InsertAddIn( sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName ) = 0; + /** InsertEuroTool */ + virtual bool InsertEuroTool( + sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, + const String& rName ) = 0; + /** Derived classes find or insert an EXTERNNAME record for DDE links. */ virtual bool InsertDde( sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, @@ -569,6 +584,11 @@ public: sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName ); + /** InsertEuroTool */ + virtual bool InsertEuroTool( + sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, + const String& rName ); + virtual bool InsertDde( sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rApplic, const String& rTopic, const String& rItem ); @@ -633,6 +653,10 @@ public: virtual bool InsertAddIn( sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName ); + /** InsertEuroTool */ + virtual bool InsertEuroTool( + sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, + const String& rName ); virtual bool InsertDde( sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, @@ -1078,6 +1102,12 @@ sal_uInt16 XclExpExtNameBuffer::InsertAddIn( const String& rName ) return nIndex ? nIndex : AppendNew( new XclExpExtNameAddIn( GetRoot(), rName ) ); } +sal_uInt16 XclExpExtNameBuffer::InsertEuroTool( const String& rName ) +{ + sal_uInt16 nIndex = GetIndex( rName ); + return nIndex ? nIndex : AppendNew( new XclExpExtNameBase( GetRoot(), rName ) ); +} + sal_uInt16 XclExpExtNameBuffer::InsertDde( const String& rApplic, const String& rTopic, const String& rItem ) { @@ -1421,6 +1451,17 @@ XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot ) : { } +XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const String& rUrl, XclSupbookType ) : + XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ), + maUrl( rUrl ), + maUrlEncoded( rUrl ), + meType( EXC_SBTYPE_EUROTOOL ), + mnXclTabCount( 0 ) +{ + SetRecSize( 2 + maUrlEncoded.GetSize() ); +} + + XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const String& rUrl ) : XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ), maUrl( rUrl ), @@ -1456,7 +1497,7 @@ XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const String& rApplic, co bool XclExpSupbook::IsUrlLink( const String& rUrl ) const { - return (meType == EXC_SBTYPE_EXTERN) && (maUrl == rUrl); + return (meType == EXC_SBTYPE_EXTERN || meType == EXC_SBTYPE_EUROTOOL) && (maUrl == rUrl); } bool XclExpSupbook::IsDdeLink( const String& rApplic, const String& rTopic ) const @@ -1534,6 +1575,11 @@ sal_uInt16 XclExpSupbook::InsertAddIn( const String& rName ) return GetExtNameBuffer().InsertAddIn( rName ); } +sal_uInt16 XclExpSupbook::InsertEuroTool( const String& rName ) +{ + return GetExtNameBuffer().InsertEuroTool( rName ); +} + sal_uInt16 XclExpSupbook::InsertDde( const String& rItem ) { return GetExtNameBuffer().InsertDde( maUrl, maDdeTopic, rItem ); @@ -1569,6 +1615,7 @@ void XclExpSupbook::WriteBody( XclExpStream& rStrm ) break; case EXC_SBTYPE_EXTERN: case EXC_SBTYPE_SPECIAL: + case EXC_SBTYPE_EUROTOOL: { sal_uInt16 nCount = ulimit_cast< sal_uInt16 >( maXctList.GetSize() ); rStrm << nCount << maUrlEncoded; @@ -1806,6 +1853,20 @@ bool XclExpSupbookBuffer::InsertAddIn( return rnExtName > 0; } +bool XclExpSupbookBuffer::InsertEuroTool( + sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const String& rName ) +{ + XclExpSupbookRef xSupbook; + String aUrl( RTL_CONSTASCII_USTRINGPARAM("\001\010EUROTOOL.XLA")); + if( !GetSupbookUrl( xSupbook, rnSupbook, aUrl ) ) + { + xSupbook.reset( new XclExpSupbook( GetRoot(), aUrl, EXC_SBTYPE_EUROTOOL ) ); + rnSupbook = Append( xSupbook ); + } + rnExtName = xSupbook->InsertEuroTool( rName ); + return rnExtName > 0; +} + bool XclExpSupbookBuffer::InsertDde( sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const String& rApplic, const String& rTopic, const String& rItem ) @@ -2008,6 +2069,13 @@ bool XclExpLinkManagerImpl5::InsertAddIn( return false; } +bool XclExpLinkManagerImpl5::InsertEuroTool( + sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const String& /*rName*/ ) +{ + return false; +} + + bool XclExpLinkManagerImpl5::InsertDde( sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const String& /*rApplic*/, const String& /*rTopic*/, const String& /*rItem*/ ) @@ -2202,6 +2270,19 @@ bool XclExpLinkManagerImpl8::InsertAddIn( return false; } +bool XclExpLinkManagerImpl8::InsertEuroTool( + sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName ) +{ + sal_uInt16 nSupbook; + if( maSBBuffer.InsertEuroTool( nSupbook, rnExtName, rName ) ) + { + rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) ); + return true; + } + return false; +} + + bool XclExpLinkManagerImpl8::InsertDde( sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rApplic, const String& rTopic, const String& rItem ) @@ -2328,6 +2409,12 @@ bool XclExpLinkManager::InsertAddIn( return mxImpl->InsertAddIn( rnExtSheet, rnExtName, rName ); } +bool XclExpLinkManager::InsertEuroTool( + sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName ) +{ + return mxImpl->InsertEuroTool( rnExtSheet, rnExtName, rName ); +} + bool XclExpLinkManager::InsertDde( sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rApplic, const String& rTopic, const String& rItem ) diff --git a/sc/source/filter/excel/xilink.cxx b/sc/source/filter/excel/xilink.cxx index 5373be4ae726..07b4c8fa4ace 100644 --- a/sc/source/filter/excel/xilink.cxx +++ b/sc/source/filter/excel/xilink.cxx @@ -289,7 +289,7 @@ sal_uInt16 XclImpTabInfo::GetCurrentIndex( sal_uInt16 nCreatedId, sal_uInt16 nMa // External names ============================================================= -XclImpExtName::XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm, bool bAddIn, ExcelToSc* pFormulaConv ) +XclImpExtName::XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm, XclSupbookType eSubType, ExcelToSc* pFormulaConv ) { sal_uInt16 nFlags; sal_uInt8 nLen; @@ -298,11 +298,14 @@ XclImpExtName::XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm maName = rStrm.ReadUniString( nLen ); if( ::get_flag( nFlags, EXC_EXTN_BUILTIN ) || !::get_flag( nFlags, EXC_EXTN_OLE_OR_DDE ) ) { - if( bAddIn ) + if( eSubType == EXC_SBTYPE_ADDIN ) { meType = xlExtAddIn; maName = rStrm.GetRoot().GetScAddInName( maName ); } + else if ( (eSubType == EXC_SBTYPE_EUROTOOL) && + maName.EqualsIgnoreCaseAscii( "EUROCONVERT" ) ) + meType = xlExtEuroConvert; else { meType = xlExtName; @@ -459,7 +462,12 @@ XclImpSupbook::XclImpSupbook( XclImpStream& rStrm ) : bool bSelf = false; XclImpUrlHelper::DecodeUrl( maXclUrl, bSelf, GetRoot(), aEncUrl ); - if( nSBTabCnt ) + if( maXclUrl.EqualsIgnoreCaseAscii( "\010EUROTOOL.XLA" ) ) + { + meType = EXC_SBTYPE_EUROTOOL; + maSupbTabList.Append( new XclImpSupbookTab( maXclUrl ) ); + } + else if( nSBTabCnt ) { meType = EXC_SBTYPE_EXTERN; for( sal_uInt16 nSBTab = 0; nSBTab < nSBTabCnt; ++nSBTab ) @@ -497,7 +505,7 @@ void XclImpSupbook::ReadCrn( XclImpStream& rStrm ) void XclImpSupbook::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv ) { - maExtNameList.Append( new XclImpExtName( *this, rStrm, meType == EXC_SBTYPE_ADDIN, pFormulaConv ) ); + maExtNameList.Append( new XclImpExtName( *this, rStrm, meType, pFormulaConv ) ); } const XclImpExtName* XclImpSupbook::GetExternName( sal_uInt16 nXclIndex ) const diff --git a/sc/source/filter/excel/xlformula.cxx b/sc/source/filter/excel/xlformula.cxx index 8b09f7284716..85286469ba62 100644 --- a/sc/source/filter/excel/xlformula.cxx +++ b/sc/source/filter/excel/xlformula.cxx @@ -338,7 +338,8 @@ static const XclFunctionInfo saFuncTable_8[] = { ocStDevA, 366, 1, 30, V, { R }, 0, 0 }, { ocVarA, 367, 1, 30, V, { R }, 0, 0 }, { ocBahtText, 368, 1, 1, V, { V }, EXC_FUNCFLAG_IMPORTONLY, EXC_FUNCNAME_BAHTTEXT }, - { ocBahtText, 255, 2, 2, V, { E, V }, EXC_FUNCFLAG_EXPORTONLY, EXC_FUNCNAME_BAHTTEXT } + { ocBahtText, 255, 2, 2, V, { E, V }, EXC_FUNCFLAG_EXPORTONLY, EXC_FUNCNAME_BAHTTEXT }, + { ocEuroConvert, 255, 4, 6, V, { E, V }, EXC_FUNCFLAG_EXPORTONLY, "EUROCONVERT" } }; // ---------------------------------------------------------------------------- diff --git a/sc/source/filter/inc/xelink.hxx b/sc/source/filter/inc/xelink.hxx index dca9df2409f7..b478ad150877 100644 --- a/sc/source/filter/inc/xelink.hxx +++ b/sc/source/filter/inc/xelink.hxx @@ -194,6 +194,10 @@ public: bool InsertAddIn( sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName ); + /** InsertEuroTool */ + bool InsertEuroTool( + sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, + const String& rName ); /** Finds or inserts an EXTERNNAME record for DDE links. @param rnExtSheet (out-param) Returns the index of the EXTSHEET structure for the DDE link. @param rnExtName (out-param) Returns the 1-based EXTERNNAME record index. diff --git a/sc/source/filter/inc/xilink.hxx b/sc/source/filter/inc/xilink.hxx index c4f64700070f..bb64a84a900e 100644 --- a/sc/source/filter/inc/xilink.hxx +++ b/sc/source/filter/inc/xilink.hxx @@ -101,7 +101,8 @@ enum XclImpExtNameType xlExtName, /// An external defined name. xlExtAddIn, /// An add-in function name. xlExtDDE, /// A DDE link range. - xlExtOLE /// An OLE object link. + xlExtOLE, /// An OLE object link. + xlExtEuroConvert /// An external in Excel, but internal in OO function name. }; // ---------------------------------------------------------------------------- @@ -116,8 +117,8 @@ class XclImpExtName { public: /** Reads the external name from the stream. */ - explicit XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm, bool bAddIn = false, - ExcelToSc* pFormulaConv = NULL ); + explicit XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm, + XclSupbookType eSubType, ExcelToSc* pFormulaConv ); ~XclImpExtName(); /** Create and apply the cached list of this DDE Link to the document. */ diff --git a/sc/source/filter/inc/xllink.hxx b/sc/source/filter/inc/xllink.hxx index 423e364b6941..a291abb52d78 100644 --- a/sc/source/filter/inc/xllink.hxx +++ b/sc/source/filter/inc/xllink.hxx @@ -86,7 +86,8 @@ enum XclSupbookType EXC_SBTYPE_SELF, /// SUPBOOK is used for internal references. EXC_SBTYPE_EXTERN, /// SUPBOOK is used for external references. EXC_SBTYPE_ADDIN, /// SUPBOOK contains add-in functions. - EXC_SBTYPE_SPECIAL /// SUPBOOK is used for DDE or OLE links. + EXC_SBTYPE_SPECIAL, /// SUPBOOK is used for DDE or OLE links. + EXC_SBTYPE_EUROTOOL /// SUPBOOK is uesd for EUROCONVERT. }; // ============================================================================ diff --git a/sc/source/filter/xml/XMLExportDDELinks.cxx b/sc/source/filter/xml/XMLExportDDELinks.cxx index 7a719319efb4..ceb2391c0f94 100644 --- a/sc/source/filter/xml/XMLExportDDELinks.cxx +++ b/sc/source/filter/xml/XMLExportDDELinks.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: XMLExportDDELinks.cxx,v $ - * $Revision: 1.18 $ + * $Revision: 1.18.148.1 $ * * This file is part of OpenOffice.org. * @@ -135,7 +135,7 @@ void ScXMLExportDDELinks::WriteTable(const sal_Int32 nPos) { ScMatValType nType = SC_MATVAL_VALUE; const ScMatrixValue* pMatVal = pMatrix->Get( static_cast<SCSIZE>(nColumn), static_cast<SCSIZE>(nRow), nType ); - BOOL bIsString = ScMatrix::IsStringType( nType); + BOOL bIsString = ScMatrix::IsNonValueType( nType); if (nColumn == 0) { diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src index 66eb90984f17..bb73e6fd52d8 100644 --- a/sc/source/ui/src/scfuncs.src +++ b/sc/source/ui/src/scfuncs.src @@ -3554,7 +3554,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1 0; ID_FUNCTION_GRP_MATH; U2S( HID_FUNC_LOG ); - 2; 0; 0; + 2; 0; 1; 0; }; String 2 // Name of Parameter 1 @@ -3571,7 +3571,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1 }; String 5 // Description of Parameter 2 { - Text [ en-US ] = "The base of the logarithm." ; + Text [ en-US ] = "The base of the logarithm. If omitted, the base is regarded as 10." ; }; }; // -=*# Resource for function LN #*=- @@ -5678,7 +5678,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 0; ID_FUNCTION_GRP_STATISTIC; U2S( HID_FUNC_POISSON ); - 3; 0; 0; 0; + 3; 0; 0; 1; 0; }; String 2 // Name of Parameter 1 @@ -5699,11 +5699,11 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; String 6 // Name of Parameter 3 { - Text [ en-US ] = "C" ; + Text [ en-US ] = "Cumulative" ; }; String 7 // Description of Parameter 3 { - Text [ en-US ] = "Cumulated. C=0 calculates the density function, C=1 the distribution." ; + Text [ en-US ] = "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function." ; }; }; // -=*# Resource for function NORMVERT #*=- @@ -5967,14 +5967,14 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 { String 1 // Description { - Text [ en-US ] = "Values of the gamma distribution." ; + Text [ en-US ] = "Returns the value of the probability density function or the cumulative distribution function for the Gamma distribution." ; }; ExtraData = { 0; ID_FUNCTION_GRP_STATISTIC; U2S( HID_FUNC_GAMMAVERT ); - 4; 0; 0; 0; 0; + 4; 0; 0; 0; 1; 0; }; String 2 // Name of Parameter 1 @@ -6003,11 +6003,11 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; String 8 // Name of Parameter 4 { - Text [ en-US ] = "C" ; + Text [ en-US ] = "Cumulative" ; }; String 9 // Description of Parameter 4 { - Text [ en-US ] = "Cumulated. C=0 calculates the density function, C=1 the distribution." ; + Text [ en-US ] = "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function." ; }; }; // -=*# Resource for function GAMMAINV #*=- @@ -6027,7 +6027,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; String 2 // Name of Parameter 1 { - Text [ en-US ] = "number" ; + Text [ en-US ] = "Number" ; }; String 3 // Description of Parameter 1 { @@ -6039,7 +6039,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; String 5 // Description of Parameter 2 { - Text [ en-US ] = "The Alpha parameter of the Gamma distribution." ; + Text [ en-US ] = "The Alpha (shape) parameter of the Gamma distribution." ; }; String 6 // Name of Parameter 3 { @@ -6047,7 +6047,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; String 7 // Description of Parameter 3 { - Text [ en-US ] = "The Beta parameter of the Gamma distribution." ; + Text [ en-US ] = "The Beta (scale) parameter of the Gamma distribution." ; }; }; // -=*# Resource for function GAMMALN #*=- @@ -6074,6 +6074,32 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 Text [ en-US ] = "The value for which the natural logarithm of the gamma function is to be calculated." ; }; }; + + // -=*# Resource for function GAMMA #*=- + Resource SC_OPCODE_GAMMA + { + String 1 // Description + { + Text [ en-US ] = "Returns the value of the Gamma function." ; + }; + ExtraData = + { + 0; + ID_FUNCTION_GRP_STATISTIC; + U2S( HID_FUNC_GAMMA ); + 1; 0; + 0; + }; + String 2 // Name of Parameter 1 + { + Text [ en-US ] = "Number" ; + }; + String 3 // Description of Parameter 1 + { + Text [ en-US ] = "The value for which the Gamma function is to be calculated." ; + }; + }; + // -=*# Resource for function BETAVERT #*=- Resource SC_OPCODE_BETA_DIST { @@ -6086,7 +6112,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 0; ID_FUNCTION_GRP_STATISTIC; U2S( HID_FUNC_BETAVERT ); - 5; 0; 0; 0; 1; 1; + 6; 0; 0; 0; 1; 1; 1; 0; }; String 2 // Name of Parameter 1 @@ -6129,6 +6155,14 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 { Text [ en-US ] = "The final value for the value interval of the distribution." ; }; + String 12 // Name of Parameter 6 + { + Text [en-US ] = "Cumulative" ; + }; + String 13 // Description of Parameter 6 + { + Text [ en-US ] = "0 or FALSE for probability density function, any other value or TRUE or omitted for cumulative distribution function."; + }; }; // -=*# Resource for function BETAINV #*=- Resource SC_OPCODE_BETA_INV @@ -6439,7 +6473,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 { String 1 // Description { - Text [ en-US ] = "Values of the chi square distribution." ; + Text [ en-US ] = "Returns the right-tail probability of the chi-square distribution." ; }; ExtraData = { @@ -6466,12 +6500,55 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 Text [ en-US ] = "The degrees of freedom of the chi square distribution." ; }; }; + + // -=*# Resource for function CHISQDIST #*=- + Resource SC_OPCODE_CHISQ_DIST + { + String 1 // Description + { + Text [ en-US ] = "Returns left-tail probability of the cumulative distribution function or values of the probability density function of the chi-square distribution." ; + }; + ExtraData = + { + 0; + ID_FUNCTION_GRP_STATISTIC; + U2S( HID_FUNC_CHISQDIST ); + 3; 0; 0; 1; + 0; + }; + String 2 // Name of Parameter 1 + { + Text [ en-US ] = "Number" ; + }; + String 3 // Description of Parameter 1 + { + Text [ en-US ] = "The value for which the probability density function or cumulative distribution function is to be calculated." ; + }; + String 4 // Name of Parameter 2 + { + Text [ en-US ] = "Degrees of Freedom" ; + }; + String 5 // Description of Parameter 2 + { + Text [ en-US ] = "The degrees of freedom of the chi-square distribution." ; + }; + String 6 // Name of Parameter 3 + { + Text [ en-US ] = "Cumulative" ; + }; + String 7 // Description of Parameter 3 + { + Text [ en-US ] = "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function." ; + }; + }; + + // -=*# Resource for function CHIINV #*=- Resource SC_OPCODE_CHI_INV { String 1 // Description { - Text [ en-US ] = "Values of the inverse chi-squared distribution." ; + Text [ en-US ] = "Values of the inverse of CHIDIST(x; DegreesOfFreedom)." ; }; ExtraData = { @@ -6498,6 +6575,40 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 Text [ en-US ] = "The degrees of freedom of the chi square distribution." ; }; }; + + // -=*# Resource for function CHISQINV #*=- + Resource SC_OPCODE_CHISQ_INV + { + String 1 // Description + { + Text [ en-US ] = "Values of the inverse of CHISQDIST(x;DegreesOfFreedom;TRUE())." ; + }; + ExtraData = + { + 0; + ID_FUNCTION_GRP_STATISTIC; + U2S( HID_FUNC_CHISQINV ); + 2; 0; 0; + 0; + }; + String 2 // Name of Parameter 1 + { + Text [ en-US ] = "Probability" ; + }; + String 3 // Description of Parameter 1 + { + Text [ en-US ] = "The probability value for which the inverse of the chi square distribution is to be calculated." ; + }; + String 4 // Name of Parameter 2 + { + Text [ en-US ] = "Degrees of Freedom" ; + }; + String 5 // Description of Parameter 2 + { + Text [ en-US ] = "The degrees of freedom of the chi square distribution." ; + }; + }; + // -=*# Resource for function STANDARDISIERUNG #*=- Resource SC_OPCODE_STANDARD { @@ -8841,7 +8952,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; ExtraData = { - 1; // TODO: implementation and unsuppress + 0; // DOING ID_FUNCTION_GRP_MATH; U2S( HID_FUNC_EUROCONVERT ); 5; 0; 0; 0; 1; 1; |