diff options
author | Eike Rathke <erack@redhat.com> | 2015-12-18 23:22:24 +0100 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2015-12-18 23:28:14 +0100 |
commit | dc89367a5622748dd7c37b89ac300a663b8b98e9 (patch) | |
tree | 07cea3163e2e9a300afda171fa4a7aed793dd153 | |
parent | fe88326d35579f2c88efe96a45911affa9c9f174 (diff) |
Formula Wizard: evaluating expressions always in matrix context is wrong
Change-Id: I276f7bbf2bd6fa7c67d8691634ad9d79e4a08b1c
-rw-r--r-- | formula/source/ui/dlg/formula.cxx | 32 | ||||
-rw-r--r-- | include/formula/IFunctionDescription.hxx | 2 | ||||
-rw-r--r-- | reportdesign/source/ui/dlg/Formula.cxx | 2 | ||||
-rw-r--r-- | reportdesign/source/ui/inc/Formula.hxx | 2 | ||||
-rw-r--r-- | sc/inc/simpleformulacalc.hxx | 6 | ||||
-rw-r--r-- | sc/qa/unit/ucalc.cxx | 4 | ||||
-rw-r--r-- | sc/source/core/data/simpleformulacalc.cxx | 16 | ||||
-rw-r--r-- | sc/source/ui/app/inputhdl.cxx | 4 | ||||
-rw-r--r-- | sc/source/ui/formdlg/formula.cxx | 8 | ||||
-rw-r--r-- | sc/source/ui/inc/formula.hxx | 2 |
10 files changed, 46 insertions, 32 deletions
diff --git a/formula/source/ui/dlg/formula.cxx b/formula/source/ui/dlg/formula.cxx index bb4f46d26f31..0d0a6462ea0c 100644 --- a/formula/source/ui/dlg/formula.cxx +++ b/formula/source/ui/dlg/formula.cxx @@ -77,9 +77,9 @@ public: RefInputStartBefore( RefEdit* pEdit, RefButton* pButton ); void RefInputStartAfter( RefEdit* pEdit, RefButton* pButton ); void RefInputDoneAfter( bool bForced ); - bool CalcValue( const OUString& rStrExp, OUString& rStrResult ); - bool CalcStruct( const OUString& rStrExp); - void UpdateValues(); + bool CalcValue( const OUString& rStrExp, OUString& rStrResult, bool bForceMatrixFormula = false ); + bool CalcStruct( const OUString& rStrExp, bool bForceRecalcStruct = false ); + void UpdateValues( bool bForceRecalcStruct = false ); void DeleteArgs(); sal_Int32 GetFunctionPos(sal_Int32 nPos); void ClearAllParas(); @@ -568,7 +568,7 @@ sal_Int32 FormulaDlg_Impl::GetFunctionPos(sal_Int32 nPos) return nFuncPos; } -bool FormulaDlg_Impl::CalcValue( const OUString& rStrExp, OUString& rStrResult ) +bool FormulaDlg_Impl::CalcValue( const OUString& rStrExp, OUString& rStrResult, bool bForceMatrixFormula ) { bool bResult = true; @@ -578,7 +578,7 @@ bool FormulaDlg_Impl::CalcValue( const OUString& rStrExp, OUString& rStrResult ) if ( !Application::AnyInput( VclInputFlags::KEYBOARD ) ) { - bResult = m_pHelper->calculateValue(rStrExp,rStrResult); + bResult = m_pHelper->calculateValue( rStrExp, rStrResult, bForceMatrixFormula || m_pBtnMatrix->IsChecked()); } else bResult = false; @@ -587,7 +587,7 @@ bool FormulaDlg_Impl::CalcValue( const OUString& rStrExp, OUString& rStrResult ) return bResult; } -void FormulaDlg_Impl::UpdateValues() +void FormulaDlg_Impl::UpdateValues( bool bForceRecalcStruct ) { OUString aStrResult; if ( CalcValue( pFuncDesc->getFormula( m_aArguments ), aStrResult ) ) @@ -603,15 +603,15 @@ void FormulaDlg_Impl::UpdateValues() aStrResult.clear(); m_pWndFormResult->SetText( aStrResult ); } - CalcStruct(pMEdit->GetText()); + CalcStruct( pMEdit->GetText(), bForceRecalcStruct); } -bool FormulaDlg_Impl::CalcStruct( const OUString& rStrExp) +bool FormulaDlg_Impl::CalcStruct( const OUString& rStrExp, bool bForceRecalcStruct ) { bool bResult = true; sal_Int32 nLength = rStrExp.getLength(); - if ( !rStrExp.isEmpty() && aOldFormula!=rStrExp && bStructUpdate) + if ( !rStrExp.isEmpty() && (bForceRecalcStruct || aOldFormula != rStrExp) && bStructUpdate) { // Only calculate the value when there isn't any more keyboard input: @@ -733,10 +733,17 @@ void FormulaDlg_Impl::MakeTree(StructPage* _pTree,SvTreeListEntry* pParent,Formu } else if (eOp==ocPush) { + // Interpret range reference in matrix context to resolve + // as array elements. + /* TODO: this should depend on parameter classification, if + * a scalar value is expected matrix should not be forced. + * */ + bool bForceMatrix = (!m_pBtnMatrix->IsChecked() && + (_pToken->GetType() == svDoubleRef || _pToken->GetType() == svExternalDoubleRef)); OUString aCellResult; - OUString aEquals(" = "); - if (CalcValue( "=" + aResult, aCellResult) && aCellResult != aResult) // cell is a formula, print subformula - _pTree->InsertEntry(aResult + aEquals + aCellResult,pParent,STRUCT_END,0,_pToken); + if (CalcValue( "=" + aResult, aCellResult, bForceMatrix) && aCellResult != aResult) + // Cell is a formula, print subformula. + _pTree->InsertEntry(aResult + " = " + aCellResult, pParent,STRUCT_END,0,_pToken); else _pTree->InsertEntry(aResult,pParent,STRUCT_END,0,_pToken); } @@ -1607,6 +1614,7 @@ IMPL_LINK_NOARG_TYPED(FormulaDlg_Impl, StructSelHdl, StructPage&, void) IMPL_LINK_NOARG_TYPED(FormulaDlg_Impl, MatrixHdl, Button*, void) { bUserMatrixFlag=true; + UpdateValues(true); } IMPL_LINK_NOARG_TYPED(FormulaDlg_Impl, FuncSelHdl, FuncPage&, void) diff --git a/include/formula/IFunctionDescription.hxx b/include/formula/IFunctionDescription.hxx index 1c7ccb96753f..bed71cd06302 100644 --- a/include/formula/IFunctionDescription.hxx +++ b/include/formula/IFunctionDescription.hxx @@ -124,7 +124,7 @@ namespace formula virtual void setSelection(sal_Int32 _nStart, sal_Int32 _nEnd) = 0; virtual FormEditData* getFormEditData() const = 0; - virtual bool calculateValue(const OUString& _sExpression, OUString& _rResult) = 0; + virtual bool calculateValue(const OUString& _sExpression, OUString& _rResult, bool bMatrixFormula) = 0; virtual void switchBack() = 0; diff --git a/reportdesign/source/ui/dlg/Formula.cxx b/reportdesign/source/ui/dlg/Formula.cxx index dd1b33f68be5..03f4a7a04a17 100644 --- a/reportdesign/source/ui/dlg/Formula.cxx +++ b/reportdesign/source/ui/dlg/Formula.cxx @@ -107,7 +107,7 @@ void FormulaDialog::dispose() // Funktionen fuer rechte Seite -bool FormulaDialog::calculateValue( const OUString& rStrExp, OUString& rStrResult ) +bool FormulaDialog::calculateValue( const OUString& rStrExp, OUString& rStrResult, bool /*bMatrixFormula*/ ) { rStrResult = rStrExp; return false; diff --git a/reportdesign/source/ui/inc/Formula.hxx b/reportdesign/source/ui/inc/Formula.hxx index 227df6b477e6..60b1d5683433 100644 --- a/reportdesign/source/ui/inc/Formula.hxx +++ b/reportdesign/source/ui/inc/Formula.hxx @@ -73,7 +73,7 @@ public: // IFormulaEditorHelper virtual void notifyChange() override; virtual void fill() override; - virtual bool calculateValue(const OUString& _sExpression, OUString& _rResult) override; + virtual bool calculateValue(const OUString& _sExpression, OUString& _rResult, bool bMatrixFormula) override; virtual void doClose(bool _bOk) override; virtual void insertEntryToLRUList(const formula::IFunctionDescription* pDesc) override; virtual void showReference(const OUString& _sFormula) override; diff --git a/sc/inc/simpleformulacalc.hxx b/sc/inc/simpleformulacalc.hxx index 081823de12ce..fef4fe9400a7 100644 --- a/sc/inc/simpleformulacalc.hxx +++ b/sc/inc/simpleformulacalc.hxx @@ -31,13 +31,15 @@ private: ScDocument* mpDoc; ScFormulaResult maResult; formula::FormulaGrammar::Grammar maGram; - bool bIsMatrix; + bool mbMatrixResult; OUString maMatrixFormulaResult; bool mbLimitString; + bool mbMatrixFormula; public: ScSimpleFormulaCalculator(ScDocument* pDoc, const ScAddress& rAddr, - const OUString& rFormula, formula::FormulaGrammar::Grammar eGram = formula::FormulaGrammar::GRAM_DEFAULT); + const OUString& rFormula, bool bMatrixFormula, + formula::FormulaGrammar::Grammar eGram = formula::FormulaGrammar::GRAM_DEFAULT); ~ScSimpleFormulaCalculator(); void Calculate(); diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 8de363a75dd7..ccb361942419 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -6585,7 +6585,7 @@ void Test::testFormulaWizardSubformula() m_pDoc->SetString(ScAddress(1,1,0), "=1/0"); // B2 m_pDoc->SetString(ScAddress(1,2,0), "=gibberish"); // B3 - ScSimpleFormulaCalculator pFCell1( m_pDoc, ScAddress(0,0,0), "=B1:B3" ); + ScSimpleFormulaCalculator pFCell1( m_pDoc, ScAddress(0,0,0), "=B1:B3", true ); sal_uInt16 nErrCode = pFCell1.GetErrCode(); CPPUNIT_ASSERT( nErrCode == 0 || pFCell1.IsMatrix() ); CPPUNIT_ASSERT_EQUAL( OUString("{1;#DIV/0!;#NAME?}"), pFCell1.GetString().getString() ); @@ -6593,7 +6593,7 @@ void Test::testFormulaWizardSubformula() m_pDoc->SetString(ScAddress(1,0,0), "=NA()"); // B1 m_pDoc->SetString(ScAddress(1,1,0), "2"); // B2 m_pDoc->SetString(ScAddress(1,2,0), "=1+2"); // B3 - ScSimpleFormulaCalculator pFCell2( m_pDoc, ScAddress(0,0,0), "=B1:B3" ); + ScSimpleFormulaCalculator pFCell2( m_pDoc, ScAddress(0,0,0), "=B1:B3", true ); nErrCode = pFCell2.GetErrCode(); CPPUNIT_ASSERT( nErrCode == 0 || pFCell2.IsMatrix() ); CPPUNIT_ASSERT_EQUAL( OUString("{#N/A;2;3}"), pFCell2.GetString().getString() ); diff --git a/sc/source/core/data/simpleformulacalc.cxx b/sc/source/core/data/simpleformulacalc.cxx index 7d2efe2fddc6..49b3459f06c0 100644 --- a/sc/source/core/data/simpleformulacalc.cxx +++ b/sc/source/core/data/simpleformulacalc.cxx @@ -16,15 +16,16 @@ #define DISPLAY_LEN 15 ScSimpleFormulaCalculator::ScSimpleFormulaCalculator( ScDocument* pDoc, const ScAddress& rAddr, - const OUString& rFormula, formula::FormulaGrammar::Grammar eGram ) + const OUString& rFormula, bool bMatrixFormula, formula::FormulaGrammar::Grammar eGram ) : mnFormatType(0) , mnFormatIndex(0) , mbCalculated(false) , maAddr(rAddr) , mpDoc(pDoc) , maGram(eGram) - , bIsMatrix(false) + , mbMatrixResult(false) , mbLimitString(false) + , mbMatrixFormula(bMatrixFormula) { // compile already here ScCompiler aComp(mpDoc, maAddr); @@ -45,7 +46,8 @@ void ScSimpleFormulaCalculator::Calculate() mbCalculated = true; ScInterpreter aInt(nullptr, mpDoc, maAddr, *mpCode.get()); - aInt.AssertFormulaMatrix(); + if (mbMatrixFormula) + aInt.AssertFormulaMatrix(); formula::StackVar aIntType = aInt.Interpret(); if ( aIntType == formula::svMatrixCell ) @@ -55,7 +57,7 @@ void ScSimpleFormulaCalculator::Calculate() OUStringBuffer aStr; aComp.CreateStringFromToken(aStr, aInt.GetResultToken().get()); - bIsMatrix = true; + mbMatrixResult = true; if (mbLimitString) { @@ -82,7 +84,7 @@ bool ScSimpleFormulaCalculator::IsValue() { Calculate(); - if (bIsMatrix) + if (mbMatrixResult) return false; return maResult.IsValue(); @@ -90,7 +92,7 @@ bool ScSimpleFormulaCalculator::IsValue() bool ScSimpleFormulaCalculator::IsMatrix() { - return bIsMatrix; + return mbMatrixResult; } sal_uInt16 ScSimpleFormulaCalculator::GetErrCode() @@ -118,7 +120,7 @@ svl::SharedString ScSimpleFormulaCalculator::GetString() { Calculate(); - if (bIsMatrix) + if (mbMatrixResult) return maMatrixFormulaResult; if ((!mpCode->GetCodeError() || mpCode->GetCodeError() == errDoubleRef) && diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx index 643aa3da2cee..82a8185ce0fd 100644 --- a/sc/source/ui/app/inputhdl.cxx +++ b/sc/source/ui/app/inputhdl.cxx @@ -1244,7 +1244,7 @@ static OUString lcl_Calculate( const OUString& rFormula, ScDocument* pDoc, const if(rFormula.isEmpty()) return OUString(); - std::unique_ptr<ScSimpleFormulaCalculator> pCalc( new ScSimpleFormulaCalculator( pDoc, rPos, rFormula ) ); + std::unique_ptr<ScSimpleFormulaCalculator> pCalc( new ScSimpleFormulaCalculator( pDoc, rPos, rFormula, false ) ); // FIXME: HACK! In order to not get a #REF! for ColRowNames, if a name is actually inserted as a Range // into the whole Formula, but is interpreted as a single cell reference when displaying it on its own @@ -1259,7 +1259,7 @@ static OUString lcl_Calculate( const OUString& rFormula, ScDocument* pDoc, const aBraced.append('('); aBraced.append(rFormula); aBraced.append(')'); - pCalc.reset( new ScSimpleFormulaCalculator( pDoc, rPos, aBraced.makeStringAndClear() ) ); + pCalc.reset( new ScSimpleFormulaCalculator( pDoc, rPos, aBraced.makeStringAndClear(), false ) ); } else bColRowName = false; diff --git a/sc/source/ui/formdlg/formula.cxx b/sc/source/ui/formdlg/formula.cxx index e6327ca8af03..28d3e4e10a6c 100644 --- a/sc/source/ui/formdlg/formula.cxx +++ b/sc/source/ui/formdlg/formula.cxx @@ -301,9 +301,10 @@ bool ScFormulaDlg::Close() // functions for right side -bool ScFormulaDlg::calculateValue( const OUString& rStrExp, OUString& rStrResult ) +bool ScFormulaDlg::calculateValue( const OUString& rStrExp, OUString& rStrResult, bool bMatrixFormula ) { - std::unique_ptr<ScSimpleFormulaCalculator> pFCell(new ScSimpleFormulaCalculator(m_pDoc, m_CursorPos, rStrExp)); + std::unique_ptr<ScSimpleFormulaCalculator> pFCell( new ScSimpleFormulaCalculator( + m_pDoc, m_CursorPos, rStrExp, bMatrixFormula)); pFCell->SetLimitString(true); // HACK! to avoid neither #REF! from ColRowNames @@ -320,7 +321,8 @@ bool ScFormulaDlg::calculateValue( const OUString& rStrExp, OUString& rStrResult aBraced.append('('); aBraced.append(rStrExp); aBraced.append(')'); - pFCell.reset(new ScSimpleFormulaCalculator(m_pDoc, m_CursorPos, aBraced.makeStringAndClear())); + pFCell.reset( new ScSimpleFormulaCalculator( + m_pDoc, m_CursorPos, aBraced.makeStringAndClear(), bMatrixFormula)); pFCell->SetLimitString(true); } else diff --git a/sc/source/ui/inc/formula.hxx b/sc/source/ui/inc/formula.hxx index 3ebdb61da57a..60613b70d7c7 100644 --- a/sc/source/ui/inc/formula.hxx +++ b/sc/source/ui/inc/formula.hxx @@ -59,7 +59,7 @@ public: // IFormulaEditorHelper virtual void notifyChange() override; virtual void fill() override; - virtual bool calculateValue(const OUString& _sExpression, OUString& _rResult) override; + virtual bool calculateValue(const OUString& _sExpression, OUString& _rResult, bool bMatrixFormula) override; virtual void doClose(bool _bOk) override; virtual void insertEntryToLRUList(const formula::IFunctionDescription* pDesc) override; virtual void showReference(const OUString& _sFormula) override; |