diff options
author | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-01-09 11:17:09 -0500 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-01-09 11:29:50 -0500 |
commit | b6fbc8642928893ca608a35b802032cfe42e40bb (patch) | |
tree | d7b1c0185c1fcfcdee133e9375f65ea45665c2e8 | |
parent | b7d0dd5252bdec31fcc925037aa7916b9fffeca7 (diff) |
fdo#58539: Correctly set cached matrix formula result.
During the import, a cached matrix value only has an empty matrix
of correct geometry, plus the token type of the top-left cell. The
rest of the elements are imported as hybrid values. For now, this
seems to do the trick.
In the future we may want to change it to fully populate the matrix
cache value during the import, and skip setting the hybrid values for
the non-top-left elements.
This commit also make several other trivial changes:
* Mark pRawToken mutable so that we can mark those IsFoo() methods
const.
* Move the ScCompiler instance from static instance to member of
ScXMLImport. Since we don't need the instance to persist once the
import is over, this is more appropriate.
Change-Id: I1abde03c0fcd91b02ef4dbf8b5526f7965eaf19c
-rw-r--r-- | formula/inc/formula/FormulaCompiler.hxx | 3 | ||||
-rw-r--r-- | formula/source/core/api/FormulaCompiler.cxx | 2 | ||||
-rw-r--r-- | sc/inc/cell.hxx | 5 | ||||
-rw-r--r-- | sc/inc/compiler.hxx | 4 | ||||
-rw-r--r-- | sc/inc/formularesult.hxx | 2 | ||||
-rw-r--r-- | sc/inc/token.hxx | 4 | ||||
-rw-r--r-- | sc/source/core/tool/compiler.cxx | 2 | ||||
-rw-r--r-- | sc/source/core/tool/formularesult.cxx | 10 | ||||
-rw-r--r-- | sc/source/core/tool/interpr1.cxx | 3 | ||||
-rw-r--r-- | sc/source/filter/xml/xmlcelli.cxx | 30 | ||||
-rw-r--r-- | sc/source/filter/xml/xmlimprt.cxx | 11 | ||||
-rw-r--r-- | sc/source/filter/xml/xmlimprt.hxx | 8 |
12 files changed, 70 insertions, 14 deletions
diff --git a/formula/inc/formula/FormulaCompiler.hxx b/formula/inc/formula/FormulaCompiler.hxx index ce4157dae9c9..85295b244cb4 100644 --- a/formula/inc/formula/FormulaCompiler.hxx +++ b/formula/inc/formula/FormulaCompiler.hxx @@ -212,6 +212,8 @@ public: */ OpCode GetEnglishOpCode( const String& rName ) const; + sal_uInt16 GetErrorConstant( const String& rName ) const; + void SetCompileForFAP( bool bVal ) { bCompileForFAP = bVal; bIgnoreErrors = bVal; } @@ -265,7 +267,6 @@ protected: virtual void CreateStringFromIndex(rtl::OUStringBuffer& rBuffer,FormulaToken* pTokenP); virtual void LocalizeString( String& rName ); // modify rName - input: exact name - sal_uInt16 GetErrorConstant( const String& rName ); void AppendErrorConstant( rtl::OUStringBuffer& rBuffer, sal_uInt16 nError ); bool GetToken(); diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx index 29b66945c799..f79201b6c673 100644 --- a/formula/source/core/api/FormulaCompiler.cxx +++ b/formula/source/core/api/FormulaCompiler.cxx @@ -816,7 +816,7 @@ void FormulaCompiler::OpCodeMap::copyFrom( const OpCodeMap& r ) } // ----------------------------------------------------------------------------- -sal_uInt16 FormulaCompiler::GetErrorConstant( const String& rName ) +sal_uInt16 FormulaCompiler::GetErrorConstant( const String& rName ) const { sal_uInt16 nError = 0; OpCodeHashMap::const_iterator iLook( mxSymbols->getHashMap()->find( rName)); diff --git a/sc/inc/cell.hxx b/sc/inc/cell.hxx index ee040a280014..716b76f4113c 100644 --- a/sc/inc/cell.hxx +++ b/sc/inc/cell.hxx @@ -493,6 +493,11 @@ public: const formula::FormulaGrammar::Grammar eGrammar ) { aResult.SetHybridFormula( r); eTempGrammar = eGrammar; } + void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL ) + { + aResult.SetMatrix(nCols, nRows, pMat, pUL); + } + /** For import only: set a double result. Use this instead of SetHybridDouble() if there is no (temporary) formula string because the formula is present as a token array, as it diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx index 4aa393d82ea6..d40d26166deb 100644 --- a/sc/inc/compiler.hxx +++ b/sc/inc/compiler.hxx @@ -320,7 +320,7 @@ private: sal_Unicode cSymbol[MAXSTRLEN]; // current Symbol String aFormula; // formula source code xub_StrLen nSrcPos; // tokenizer position (source code) - ScRawTokenRef pRawToken; + mutable ScRawTokenRef pRawToken; const CharClass* pCharClass; // which character classification is used for parseAnyToken sal_uInt16 mnPredetectedReference; // reference when reading ODF, 0 (none), 1 (single) or 2 (double) @@ -386,7 +386,7 @@ public: // Check if it is a valid english function name bool IsEnglishSymbol( const String& rName ); - bool IsErrorConstant( const String& ); + bool IsErrorConstant( const String& ) const; //! _either_ CompileForFAP _or_ AutoCorrection, _not_ both // #i101512# SetCompileForFAP is in formula::FormulaCompiler diff --git a/sc/inc/formularesult.hxx b/sc/inc/formularesult.hxx index c4f281fabb0c..2128636816b6 100644 --- a/sc/inc/formularesult.hxx +++ b/sc/inc/formularesult.hxx @@ -179,6 +179,8 @@ public: SetHybridFormula() for formula string to be compiled later. */ SC_DLLPUBLIC void SetHybridFormula( const String & rFormula ); + SC_DLLPUBLIC void SetMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL ); + /** Get the const ScMatrixFormulaCellToken* if token is of that type, else NULL. */ const ScMatrixFormulaCellToken* GetMatrixFormulaCellToken() const; diff --git a/sc/inc/token.hxx b/sc/inc/token.hxx index c8c87829860a..e08db6cb440c 100644 --- a/sc/inc/token.hxx +++ b/sc/inc/token.hxx @@ -350,6 +350,10 @@ private: SCROW nRows; SCCOL nCols; public: + ScMatrixFormulaCellToken( SCCOL nC, SCROW nR, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL ) : + ScMatrixCellResultToken(pMat, pUL), + nRows(nR), nCols(nC) {} + ScMatrixFormulaCellToken( SCCOL nC, SCROW nR ) : ScMatrixCellResultToken( NULL, NULL ), nRows( nR ), nCols( nC ) {} diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 4656e2b2c1c0..6de041772e4e 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -3306,7 +3306,7 @@ bool ScCompiler::IsBoolean( const String& rName ) } -bool ScCompiler::IsErrorConstant( const String& rName ) +bool ScCompiler::IsErrorConstant( const String& rName ) const { sal_uInt16 nError = GetErrorConstant( rName); if (nError) diff --git a/sc/source/core/tool/formularesult.cxx b/sc/source/core/tool/formularesult.cxx index 3b94481c4041..9e1032ec9d44 100644 --- a/sc/source/core/tool/formularesult.cxx +++ b/sc/source/core/tool/formularesult.cxx @@ -443,6 +443,16 @@ void ScFormulaResult::SetHybridFormula( const String & rFormula ) mbToken = true; } +void ScFormulaResult::SetMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL ) +{ + ResetToDefaults(); + if (mbToken && mpToken) + mpToken->DecRef(); + mpToken = new ScMatrixFormulaCellToken(nCols, nRows, pMat, pUL); + mpToken->IncRef(); + mbToken = true; +} + const ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellToken() const { return (GetType() == formula::svMatrixCell ? diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 0b86108ada5b..ec85a01f7314 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -135,7 +135,10 @@ void ScInterpreter::ScIfJump() SCSIZE nCols, nRows; pMat->GetDimensions( nCols, nRows ); if ( nCols == 0 || nRows == 0 ) + { PushIllegalArgument(); + return; + } else if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find( pCur)) != pTokenMatrixMap->end())) xNew = (*aMapIter).second; diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx index e9375705e897..25579f2a5085 100644 --- a/sc/source/filter/xml/xmlcelli.cxx +++ b/sc/source/filter/xml/xmlcelli.cxx @@ -47,8 +47,6 @@ #include "scerrors.hxx" #include "editutil.hxx" #include "cell.hxx" -#include "compiler.hxx" - #include <xmloff/xmltkmap.hxx> #include <xmloff/xmltoken.hxx> @@ -727,9 +725,7 @@ void ScXMLTableRowCellContext::SetFormulaCell(ScFormulaCell* pFCell) const { if( bFormulaTextResult && pOUTextValue ) { - static ScCompiler aComp(NULL, ScAddress()); - aComp.SetGrammar(formula::FormulaGrammar::GRAM_ODFF); - if(!aComp.IsErrorConstant(*pOUTextValue)) + if (!GetScImport().IsFormulaErrorConstant(*pOUTextValue)) { pFCell->SetHybridString( *pOUTextValue ); pFCell->ResetDirty(); @@ -1086,11 +1082,29 @@ void ScXMLTableRowCellContext::AddFormulaCell( const ScAddress& rCellPos ) std::min<SCROW>(rCellPos.Row() + nMatrixRows - 1, MAXROW), pOUFormula->first, pOUFormula->second, eGrammar); - //set the value/text of the first matrix position (top-left). - //the value/text of the matrix reference cells will be set later. + // Set the value/text of the top-left matrix position in its + // cached result. For import, we only need to set the correct + // matrix geometry and the value type of the top-left element. + ScFormulaCell* pFCell = static_cast<ScFormulaCell*>( rXMLImport.GetDocument()->GetCell(rCellPos) ); - SetFormulaCell(pFCell); + + ScMatrixRef pMat(new ScMatrix(nMatrixCols, nMatrixRows)); + if (bFormulaTextResult && pOUTextValue) + { + if (!GetScImport().IsFormulaErrorConstant(*pOUTextValue)) + { + pFCell->SetResultMatrix( + nMatrixCols, nMatrixRows, pMat, new formula::FormulaStringToken(*pOUTextValue)); + pFCell->ResetDirty(); + } + } + else if (!rtl::math::isNan(fValue)) + { + pFCell->SetResultMatrix( + nMatrixCols, nMatrixRows, pMat, new formula::FormulaDoubleToken(fValue)); + pFCell->ResetDirty(); + } } } else diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx index 7aae79ca597b..b7f229c9e4b9 100644 --- a/sc/source/filter/xml/xmlimprt.cxx +++ b/sc/source/filter/xml/xmlimprt.cxx @@ -2809,6 +2809,9 @@ throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::R if (!pDoc) throw lang::IllegalArgumentException(); + mpComp.reset(new ScCompiler(pDoc, ScAddress())); + mpComp->SetGrammar(formula::FormulaGrammar::GRAM_ODFF); + bFromWrapper = pDoc->IsXMLFromWrapper(); // UnlockSolarMutex below still works normally uno::Reference<document::XActionLockable> xActionLockable(xDoc, uno::UNO_QUERY); @@ -3294,4 +3297,12 @@ void ScXMLImport::ExtractFormulaNamespaceGrammar( reGrammar = eDefaultGrammar; } +bool ScXMLImport::IsFormulaErrorConstant( const OUString& rStr ) const +{ + if (!mpComp) + return false; + + return mpComp->GetErrorConstant(rStr) > 0; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/xml/xmlimprt.hxx b/sc/source/filter/xml/xmlimprt.hxx index c202160f5d18..87f3f3e8d974 100644 --- a/sc/source/filter/xml/xmlimprt.hxx +++ b/sc/source/filter/xml/xmlimprt.hxx @@ -31,6 +31,7 @@ #include "xmlsubti.hxx" #include "global.hxx" #include "formula/grammar.hxx" +#include "compiler.hxx" #include "xmlstyle.hxx" #include "XMLDetectiveContext.hxx" @@ -46,6 +47,8 @@ #include <boost/unordered_map.hpp> #include <boost/ptr_container/ptr_list.hpp> #include <boost/ptr_container/ptr_map.hpp> +#include <boost/noncopyable.hpp> +#include <boost/scoped_ptr.hpp> class ScMyStyleNumberFormats; class XMLNumberFormatAttributesExportHelper; @@ -732,7 +735,7 @@ typedef std::vector<ScMyImportValidation> ScMyImportValidations; typedef std::list<SvXMLImportContext*> ScMyViewContextList; class ScMyStylesImportHelper; -class ScXMLImport: public SvXMLImport +class ScXMLImport: public SvXMLImport, boost::noncopyable { typedef ::boost::unordered_map< ::rtl::OUString, sal_Int16, ::rtl::OUStringHash > CellTypeMap; typedef ::boost::ptr_map<SCTAB, ScMyNamedExpressions> SheetNamedExpMap; @@ -740,6 +743,7 @@ class ScXMLImport: public SvXMLImport CellTypeMap aCellTypeMap; ScDocument* pDoc; + boost::scoped_ptr<ScCompiler> mpComp; // For error-checking of cached string cell values. ScXMLChangeTrackingImportHelper* pChangeTrackingImportHelper; ScMyViewContextList aViewContextList; ScMyStylesImportHelper* pStylesImportHelper; @@ -1141,6 +1145,8 @@ public: ::formula::FormulaGrammar::Grammar& reGrammar, const ::rtl::OUString& rAttrValue, bool bRestrictToExternalNmsp = false ) const; + + bool IsFormulaErrorConstant( const OUString& rStr ) const; }; #endif |