sc/inc/column.hxx | 5 - sc/inc/document.hxx | 1 sc/inc/formulacell.hxx | 12 ++ sc/inc/table.hxx | 1 sc/inc/tokenarray.hxx | 6 + sc/qa/unit/data/xls/shared-formula.xls |binary sc/qa/unit/filters-test.cxx | 9 ++ sc/source/core/data/column3.cxx | 25 ++++- sc/source/core/data/documen2.cxx | 8 + sc/source/core/data/formulacell.cxx | 103 ++++++++++++++++++------ sc/source/core/data/table2.cxx | 8 + sc/source/core/tool/token.cxx | 36 ++++++++ sc/source/filter/excel/excform.cxx | 141 +++++++++++++++------------------ sc/source/filter/excel/impop.cxx | 2 sc/source/filter/excel/namebuff.cxx | 97 ++++++---------------- sc/source/filter/excel/read.cxx | 2 sc/source/filter/inc/excform.hxx | 2 sc/source/filter/inc/namebuff.hxx | 35 +++----- sc/source/filter/inc/root.hxx | 4 19 files changed, 294 insertions(+), 203 deletions(-)
New commits: commit c12146c1c0614b9ddd55ec5bed458e581369af16 Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Tue Aug 6 00:15:10 2013 -0400 Map shared formula from xls to formula groups, and share the tokens as well. No more mapping to range names. Change-Id: Ic43b6ef35a91fe4d6fff748ebc22969ba4e036db diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 045b76a..22bb9bd 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -275,6 +275,7 @@ public: */ ScFormulaCell* SetFormulaCell( SCROW nRow, ScFormulaCell* pCell ); ScFormulaCell* SetFormulaCell( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScFormulaCell* pCell ); + bool SetGroupFormulaCell( SCROW nRow, ScFormulaCell* pCell ); void SetRawString( SCROW nRow, const OUString& rStr, bool bBroadcast = true ); void SetRawString( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, const OUString& rStr, bool bBroadcast = true ); @@ -507,8 +508,8 @@ private: sc::CellStoreType::iterator GetPositionToInsert( SCROW nRow ); sc::CellStoreType::iterator GetPositionToInsert( const sc::CellStoreType::iterator& it, SCROW nRow ); - void ActivateNewFormulaCell( const sc::CellStoreType::iterator& itPos, SCROW nRow, ScFormulaCell& rCell ); - void ActivateNewFormulaCell( const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell ); + void ActivateNewFormulaCell( const sc::CellStoreType::iterator& itPos, SCROW nRow, ScFormulaCell& rCell, bool bJoin = true ); + void ActivateNewFormulaCell( const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell, bool bJoin = true ); void BroadcastNewCell( SCROW nRow ); bool UpdateScriptType( sc::CellTextAttr& rAttr, SCROW nRow ); diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 90e0148..8b82fb7 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -804,6 +804,7 @@ public: * is deleted automatically on failure to insert. */ SC_DLLPUBLIC ScFormulaCell* SetFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell ); + SC_DLLPUBLIC bool SetGroupFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell ); SC_DLLPUBLIC void InsertMatrixFormula(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index 6480056..f857aff 100644 --- a/sc/inc/formulacell.hxx +++ b/sc/inc/formulacell.hxx @@ -27,6 +27,7 @@ #include "types.hxx" #include <set> +#include <boost/noncopyable.hpp> namespace sc { @@ -43,7 +44,7 @@ class ScProgress; class ScTokenArray; struct ScSimilarFormulaDelta; -struct SC_DLLPUBLIC ScFormulaCellGroup +struct SC_DLLPUBLIC ScFormulaCellGroup : boost::noncopyable { mutable size_t mnRefCount; @@ -55,6 +56,8 @@ struct SC_DLLPUBLIC ScFormulaCellGroup ScFormulaCellGroup(); ~ScFormulaCellGroup(); + + void setCode( const ScTokenArray& rCode ); }; inline void intrusive_ptr_add_ref(const ScFormulaCellGroup *p) diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 37c1430..a95f2bc 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -340,6 +340,7 @@ public: * is deleted automatically on failure to insert. */ ScFormulaCell* SetFormulaCell( SCCOL nCol, SCROW nRow, ScFormulaCell* pCell ); + bool SetGroupFormulaCell( SCCOL nCol, SCROW nRow, ScFormulaCell* pCell ); void SetValue( SCCOL nCol, SCROW nRow, const double& rVal ); void SetError( SCCOL nCol, SCROW nRow, sal_uInt16 nError); diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx index f9a4ff1..09a9798 100644 --- a/sc/inc/tokenarray.hxx +++ b/sc/inc/tokenarray.hxx @@ -62,6 +62,12 @@ public: ScFormulaVectorState GetVectorState() const; + /** + * If the array contains at least one relative row reference or named + * expression, it's variant. Otherwise invariant. + */ + bool IsInvariant() const; + /// Exactly and only one range (valid or deleted) bool IsReference( ScRange& rRange, const ScAddress& rPos ) const; /// Exactly and only one valid range (no #REF!s) diff --git a/sc/qa/unit/data/xls/shared-formula.xls b/sc/qa/unit/data/xls/shared-formula.xls index a9be6b7..f27acb4 100644 Binary files a/sc/qa/unit/data/xls/shared-formula.xls and b/sc/qa/unit/data/xls/shared-formula.xls differ diff --git a/sc/qa/unit/filters-test.cxx b/sc/qa/unit/filters-test.cxx index 1d7eeca..957e0e0 100644 --- a/sc/qa/unit/filters-test.cxx +++ b/sc/qa/unit/filters-test.cxx @@ -32,6 +32,8 @@ #include "cellform.hxx" #include "drwlayer.hxx" #include "userdat.hxx" +#include "formulacell.hxx" + #include <svx/svdpage.hxx> using namespace ::com::sun::star; @@ -344,6 +346,13 @@ void ScFiltersTest::testSharedFormulaXLS() double fCheck = i*10.0; CPPUNIT_ASSERT_EQUAL(fCheck, fVal); } + + ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(1,18,0)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pCell); + ScFormulaCellGroupRef xGroup = pCell->GetCellGroup(); + CPPUNIT_ASSERT_MESSAGE("This cell should be a part of a cell group.", xGroup); + CPPUNIT_ASSERT_MESSAGE("Incorrect group geometry.", xGroup->mnStart == 2 && xGroup->mnLength == 17); + xDocSh->DoClose(); } diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index 4474aec..461193c 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -381,16 +381,17 @@ sc::CellStoreType::iterator ScColumn::GetPositionToInsert( const sc::CellStoreTy } void ScColumn::ActivateNewFormulaCell( - const sc::CellStoreType::iterator& itPos, SCROW nRow, ScFormulaCell& rCell ) + const sc::CellStoreType::iterator& itPos, SCROW nRow, ScFormulaCell& rCell, bool bJoin ) { - ActivateNewFormulaCell(maCells.position(itPos, nRow), rCell); + ActivateNewFormulaCell(maCells.position(itPos, nRow), rCell, bJoin); } void ScColumn::ActivateNewFormulaCell( - const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell ) + const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell, bool bJoin ) { - // See if this new formula cell can join an existing shared formula group. - JoinNewFormulaCell(aPos, rCell); + if (bJoin) + // See if this new formula cell can join an existing shared formula group. + JoinNewFormulaCell(aPos, rCell); // When we insert from the Clipboard we still have wrong (old) References! // First they are rewired in CopyBlockFromClip via UpdateReference and the @@ -1729,6 +1730,20 @@ ScFormulaCell* ScColumn::SetFormulaCell( sc::ColumnBlockPosition& rBlockPos, SCR return pCell; } +bool ScColumn::SetGroupFormulaCell( SCROW nRow, ScFormulaCell* pCell ) +{ + sc::CellStoreType::iterator it = GetPositionToInsert(nRow); + sal_uInt32 nCellFormat = GetNumberFormat(nRow); + if( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0) + pCell->SetNeedNumberFormat(true); + it = maCells.set(it, nRow, pCell); + maCellTextAttrs.set(nRow, sc::CellTextAttr()); + CellStorageModified(); + + ActivateNewFormulaCell(it, nRow, *pCell, false); + return true; +} + namespace { class FilterEntriesHandler diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index 7a9e9d6..720b504 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -1075,6 +1075,14 @@ ScFormulaCell* ScDocument::SetFormulaCell( const ScAddress& rPos, ScFormulaCell* return maTabs[rPos.Tab()]->SetFormulaCell(rPos.Col(), rPos.Row(), pCell); } +bool ScDocument::SetGroupFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell ) +{ + if (!TableExists(rPos.Tab())) + return false; + + return maTabs[rPos.Tab()]->SetGroupFormulaCell(rPos.Col(), rPos.Row(), pCell); +} + void ScDocument::SetConsolidateDlgData( const ScConsolidateParam* pData ) { delete pConsolidateDlgData; diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index cdedb66..b9db55a 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -397,6 +397,14 @@ ScFormulaCellGroup::~ScFormulaCellGroup() delete mpCode; } +void ScFormulaCellGroup::setCode( const ScTokenArray& rCode ) +{ + delete mpCode; + mpCode = rCode.Clone(); + mbInvariant = mpCode->IsInvariant(); + mpCode->GenHash(); +} + // ============================================================================ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, @@ -522,8 +530,6 @@ ScFormulaCell::ScFormulaCell( if (bSubTotal) pDocument->AddSubTotalCell(this); - - pCode->GenHash(); } ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, int nCloneFlags ) : @@ -3358,7 +3364,7 @@ bool ScFormulaCell::InterpretFormulaGroup() // Re-build formulae groups if necessary - ideally this is done at // import / insert / delete etc. and is integral to the data structures - pDocument->RebuildFormulaGroups(); +// pDocument->RebuildFormulaGroups(); if (!mxGroup || !pCode) return false; diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 278096e..537f856 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -1453,6 +1453,14 @@ ScFormulaCell* ScTable::SetFormulaCell( SCCOL nCol, SCROW nRow, ScFormulaCell* p return aCol[nCol].SetFormulaCell(nRow, pCell); } +bool ScTable::SetGroupFormulaCell( SCCOL nCol, SCROW nRow, ScFormulaCell* pCell ) +{ + if (!ValidColRow(nCol, nRow)) + return false; + + return aCol[nCol].SetGroupFormulaCell(nRow, pCell); +} + void ScTable::SetValue( SCCOL nCol, SCROW nRow, const double& rVal ) { if (ValidColRow(nCol, nRow)) diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index 4703cde..d74182d 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -1474,6 +1474,42 @@ ScFormulaVectorState ScTokenArray::GetVectorState() const return meVectorState; } +bool ScTokenArray::IsInvariant() const +{ + FormulaToken** p = pCode; + FormulaToken** pEnd = p + static_cast<size_t>(nLen); + for (; p != pEnd; ++p) + { + switch ((*p)->GetType()) + { + case svSingleRef: + case svExternalSingleRef: + { + const ScToken* pT = static_cast<const ScToken*>(*p); + const ScSingleRefData& rRef = pT->GetSingleRef(); + if (rRef.IsRowRel()) + return false; + } + break; + case svDoubleRef: + case svExternalDoubleRef: + { + const ScToken* pT = static_cast<const ScToken*>(*p); + const ScComplexRefData& rRef = pT->GetDoubleRef(); + if (rRef.Ref1.IsRowRel() || rRef.Ref2.IsRowRel()) + return false; + } + break; + case svIndex: + return false; + default: + ; + } + } + + return true; +} + bool ScTokenArray::IsReference( ScRange& rRange, const ScAddress& rPos ) const { return ImplGetReference(rRange, rPos, false); diff --git a/sc/source/filter/excel/excform.cxx b/sc/source/filter/excel/excform.cxx index 4f60d7e..e236dad 100644 --- a/sc/source/filter/excel/excform.cxx +++ b/sc/source/filter/excel/excform.cxx @@ -101,7 +101,6 @@ void ImportExcel::Formula4() void ImportExcel::Formula( const XclAddress& rXclPos, sal_uInt16 nXF, sal_uInt16 nFormLen, double fCurVal, bool bShrFmla) { - ScAddress aScPos( ScAddress::UNINITIALIZED ); if (!GetAddressConverter().ConvertAddress(aScPos, rXclPos, GetCurrScTab(), true)) // Conversion failed. @@ -115,13 +114,18 @@ void ImportExcel::Formula( if (bShrFmla) { // This is a shared formula. Get the token array from the shared formula pool. - pResult = pFormConv->GetShrFmla(maStrm, nFormLen); - if (!pResult) + ScFormulaCellGroupRef xGroup = pFormConv->GetSharedFormula(maStrm, aScPos.Col(), nFormLen); + if (!xGroup) return; - ScFormulaCell* pCell = new ScFormulaCell( pD, aScPos, pResult ); + ScFormulaCell* pCell = new ScFormulaCell(pD, aScPos, xGroup); pD->EnsureTable(aScPos.Tab()); - pCell = pD->SetFormulaCell(aScPos, pCell); + bool bInserted = pD->SetGroupFormulaCell(aScPos, pCell); + if (!bInserted) + { + delete pCell; + return; + } pCell->SetNeedNumberFormat(false); if (!rtl::math::isNan(fCurVal)) pCell->SetResultDouble(fCurVal); @@ -1673,38 +1677,33 @@ const ScTokenArray* ExcelToSc::GetBoolErr( XclBoolError eType ) return pErgebnis; } - -// if a shared formula was found, stream seeks to first byte after <nFormulaLen>, -// else stream pointer stays unchanged -const ScTokenArray* ExcelToSc::GetShrFmla( XclImpStream& aIn, sal_Size nFormulaLen ) +ScFormulaCellGroupRef ExcelToSc::GetSharedFormula( XclImpStream& aIn, SCCOL nCol, sal_Size nFormulaLen ) { if (!nFormulaLen) - return NULL; + return ScFormulaCellGroupRef(); aIn.PushPosition(); sal_uInt8 nOp; aIn >> nOp; - if (nOp != 0x01) // Shared Formula [ 277] + if (nOp != 0x01) // must be PtgExp token. { aIn.PopPosition(); - return NULL; + return ScFormulaCellGroupRef(); } - sal_uInt16 nCol, nRow; - aIn >> nRow >> nCol; + sal_uInt16 nLeftCol, nRow; + aIn >> nRow >> nLeftCol; - aStack << aPool.StoreName( GetOldRoot().pShrfmlaBuff->Find( - ScAddress(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), GetCurrScTab())), true); + ScAddress aRefPos(nCol, nRow, GetCurrScTab()); + ScFormulaCellGroupRef xGroup = GetOldRoot().pShrfmlaBuff->Find(aRefPos); aIn.PopPosition(); - aIn.Ignore(nFormulaLen); - return aPool[aStack.Get()]; + return xGroup; } - void ExcelToSc::SetError( ScFormulaCell &rCell, const ConvErr eErr ) { sal_uInt16 nInd; diff --git a/sc/source/filter/excel/namebuff.cxx b/sc/source/filter/excel/namebuff.cxx index 6279c87..ac609a4 100644 --- a/sc/source/filter/excel/namebuff.cxx +++ b/sc/source/filter/excel/namebuff.cxx @@ -20,9 +20,6 @@ #include "namebuff.hxx" -#include <string.h> - -#include "rangenam.hxx" #include "document.hxx" #include "compiler.hxx" #include "scextopt.hxx" @@ -32,6 +29,7 @@ #include "xltools.hxx" #include "xiroot.hxx" +#include <string.h> sal_uInt32 StringHashEntry::MakeHashCode( const String& r ) { @@ -70,84 +68,41 @@ void NameBuffer::operator <<( const String &rNewString ) maHashes.push_back( new StringHashEntry( rNewString ) ); } +SharedFormulaBuffer::SharedFormulaBuffer( RootData* pRD ) : ExcRoot(pRD) {} -#if OSL_DEBUG_LEVEL > 0 -sal_uInt16 nShrCnt; -#endif - - -size_t SharedFormulaBuffer::ScAddressHashFunc::operator() (const ScAddress &addr) const -{ - // Use something simple, it is just a hash. - return static_cast< sal_uInt16 >( addr.Row() ) | (static_cast< sal_uInt8 >( addr.Col() ) << 16); -} - -const size_t nBase = 16384; // Range~ und Shared~ Dingens mit jeweils der Haelfte Ids -SharedFormulaBuffer::SharedFormulaBuffer( RootData* pRD ) : - ExcRoot( pRD ), - mnCurrIdx (nBase) -{ -#if OSL_DEBUG_LEVEL > 0 - nShrCnt = 0; -#endif -} - -SharedFormulaBuffer::~SharedFormulaBuffer() -{ -} +SharedFormulaBuffer::~SharedFormulaBuffer() {} void SharedFormulaBuffer::Clear() { - index_hash.clear(); - // do not clear index_list, index calculation depends on complete list size... - // do not change mnCurrIdx + maFormulaGroups.clear(); } -void SharedFormulaBuffer::Store( const ScRange& rRange, const ScTokenArray& rToken ) +void SharedFormulaBuffer::Store( const ScRange& rRange, const ScTokenArray& rArray ) { - String aName( CreateName( rRange.aStart ) ); - - OSL_ENSURE( mnCurrIdx <= 0xFFFF, "*ShrfmlaBuffer::Store(): I'm getting sick...!" ); - - ScRangeData* pData = new ScRangeData( pExcRoot->pIR->GetDocPtr(), aName, rToken, rRange.aStart, RT_SHARED ); - const ScAddress& rMaxPos = pExcRoot->pIR->GetMaxPos(); - pData->SetMaxCol(rMaxPos.Col()); - pData->SetMaxRow(rMaxPos.Row()); - pData->SetIndex( static_cast< sal_uInt16 >( mnCurrIdx ) ); - pExcRoot->pIR->GetNamedRanges().insert( pData ); - index_hash[rRange.aStart] = static_cast< sal_uInt16 >( mnCurrIdx ); - index_list.push_front (rRange); - ++mnCurrIdx; + SCROW nGroupLen = rRange.aEnd.Row() - rRange.aStart.Row() + 1; + for (SCCOL i = rRange.aStart.Col(); i <= rRange.aEnd.Col(); ++i) + { + // Create one group per column. + ScAddress aPos = rRange.aStart; + aPos.SetCol(i); + + ScFormulaCellGroupRef xNewGroup(new ScFormulaCellGroup); + xNewGroup->mnStart = rRange.aStart.Row(); + xNewGroup->mnLength = nGroupLen; + xNewGroup->mpCode = rArray.Clone(); + xNewGroup->mbInvariant = rArray.IsInvariant(); + xNewGroup->setCode(rArray); + maFormulaGroups.insert(FormulaGroupsType::value_type(aPos, xNewGroup)); + } } - -sal_uInt16 SharedFormulaBuffer::Find( const ScAddress & aAddr ) const +ScFormulaCellGroupRef SharedFormulaBuffer::Find( const ScAddress& rRefPos ) const { - ShrfmlaHash::const_iterator hash = index_hash.find (aAddr); - if (hash != index_hash.end()) - return hash->second; - - // It was not hashed on the top left corner ? do a brute force search - unsigned int ind = nBase; - for (ShrfmlaList::const_iterator ptr = index_list.end(); ptr != index_list.begin() ; ind++) - if ((--ptr)->In (aAddr)) - return static_cast< sal_uInt16 >( ind ); - return static_cast< sal_uInt16 >( mnCurrIdx ); -} - + FormulaGroupsType::const_iterator it = maFormulaGroups.find(rRefPos); + if (it == maFormulaGroups.end()) + return ScFormulaCellGroupRef(); -#define SHRFMLA_BASENAME "SHARED_FORMULA_" - -String SharedFormulaBuffer::CreateName( const ScRange& r ) -{ - OUString aName = SHRFMLA_BASENAME + - OUString::number( r.aStart.Col() ) + "_" + - OUString::number( r.aStart.Row() ) + "_" + - OUString::number( r.aEnd.Col() ) + "_" + - OUString::number( r.aEnd.Row() ) + "_" + - OUString::number( r.aStart.Tab() ); - - return aName; + return it->second; } sal_Int16 ExtSheetBuffer::Add( const String& rFPAN, const String& rTN, const sal_Bool bSWB ) diff --git a/sc/source/filter/inc/excform.hxx b/sc/source/filter/inc/excform.hxx index fb866fe..0e2004c 100644 --- a/sc/source/filter/inc/excform.hxx +++ b/sc/source/filter/inc/excform.hxx @@ -63,7 +63,7 @@ public: void GetDummy( const ScTokenArray*& ); const ScTokenArray* GetBoolErr( XclBoolError ); - const ScTokenArray* GetShrFmla( XclImpStream& rStrm, sal_Size nFormulaLen ); + ScFormulaCellGroupRef GetSharedFormula( XclImpStream& rStrm, SCCOL nCol, sal_Size nFormulaLen ); static void SetError( ScFormulaCell& rCell, const ConvErr eErr ); diff --git a/sc/source/filter/inc/namebuff.hxx b/sc/source/filter/inc/namebuff.hxx index 6f5aa28..97aebc1 100644 --- a/sc/source/filter/inc/namebuff.hxx +++ b/sc/source/filter/inc/namebuff.hxx @@ -26,6 +26,8 @@ #include "xiroot.hxx" #include "rangenam.hxx" +#include "formulacell.hxx" + #include <boost/unordered_map.hpp> #include <list> @@ -146,30 +148,21 @@ inline void NameBuffer::SetBase( sal_uInt16 nNewBase ) nBase = nNewBase; } - - - +/** + * Store and manage shared formula tokens. + */ class SharedFormulaBuffer : public ExcRoot { - struct ScAddressHashFunc : public std::unary_function< const ScAddress &, size_t > - { - size_t operator() (const ScAddress &addr) const; - }; - typedef boost::unordered_map <ScAddress, sal_uInt16, ScAddressHashFunc> ShrfmlaHash; - typedef std::list <ScRange> ShrfmlaList; + typedef boost::unordered_map<ScAddress, ScFormulaCellGroupRef, ScAddressHashFunctor> FormulaGroupsType; - ShrfmlaHash index_hash; - ShrfmlaList index_list; - size_t mnCurrIdx; + FormulaGroupsType maFormulaGroups; public: SharedFormulaBuffer( RootData* pRD ); virtual ~SharedFormulaBuffer(); - void Clear(); - void Store( const ScRange& rRange, const ScTokenArray& ); - sal_uInt16 Find (const ScAddress & rAddress ) const; - - static String CreateName( const ScRange& ); + void Clear(); + void Store( const ScRange& rRange, const ScTokenArray& rArray ); + ScFormulaCellGroupRef Find( const ScAddress& rRefPos ) const; }; commit f9e9ba86e17ee758cfbb2061ffed1786f88573e8 Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Mon Aug 5 22:31:58 2013 -0400 Rename this to SharedFormulaBuffer, which is readable. ShrfmlaBuffer is not readable. Change-Id: Ic91f7c2fcc15d4210af4f97341199ce03593d223 diff --git a/sc/source/filter/excel/impop.cxx b/sc/source/filter/excel/impop.cxx index 2cf90d2..28ddd9f 100644 --- a/sc/source/filter/excel/impop.cxx +++ b/sc/source/filter/excel/impop.cxx @@ -125,7 +125,7 @@ ImportExcel::ImportExcel( XclImpRootData& rImpData, SvStream& rStrm ): pExcRoot->pIR = this; // ExcRoot -> XclImpRoot pExcRoot->eDateiTyp = BiffX; pExcRoot->pExtSheetBuff = new ExtSheetBuffer( pExcRoot ); //&aExtSheetBuff; - pExcRoot->pShrfmlaBuff = new ShrfmlaBuffer( pExcRoot ); //&aShrfrmlaBuff; + pExcRoot->pShrfmlaBuff = new SharedFormulaBuffer( pExcRoot ); //&aShrfrmlaBuff; pExcRoot->pExtNameBuff = new ExtNameBuff ( *this ); pExtNameBuff = new NameBuffer( pExcRoot ); //prevent empty rootdata diff --git a/sc/source/filter/excel/namebuff.cxx b/sc/source/filter/excel/namebuff.cxx index eb9e90cc..6279c87 100644 --- a/sc/source/filter/excel/namebuff.cxx +++ b/sc/source/filter/excel/namebuff.cxx @@ -76,14 +76,14 @@ sal_uInt16 nShrCnt; #endif -size_t ShrfmlaBuffer::ScAddressHashFunc::operator() (const ScAddress &addr) const +size_t SharedFormulaBuffer::ScAddressHashFunc::operator() (const ScAddress &addr) const { // Use something simple, it is just a hash. return static_cast< sal_uInt16 >( addr.Row() ) | (static_cast< sal_uInt8 >( addr.Col() ) << 16); } const size_t nBase = 16384; // Range~ und Shared~ Dingens mit jeweils der Haelfte Ids -ShrfmlaBuffer::ShrfmlaBuffer( RootData* pRD ) : +SharedFormulaBuffer::SharedFormulaBuffer( RootData* pRD ) : ExcRoot( pRD ), mnCurrIdx (nBase) { @@ -92,18 +92,18 @@ ShrfmlaBuffer::ShrfmlaBuffer( RootData* pRD ) : #endif } -ShrfmlaBuffer::~ShrfmlaBuffer() +SharedFormulaBuffer::~SharedFormulaBuffer() { } -void ShrfmlaBuffer::Clear() +void SharedFormulaBuffer::Clear() { index_hash.clear(); // do not clear index_list, index calculation depends on complete list size... // do not change mnCurrIdx } -void ShrfmlaBuffer::Store( const ScRange& rRange, const ScTokenArray& rToken ) +void SharedFormulaBuffer::Store( const ScRange& rRange, const ScTokenArray& rToken ) { String aName( CreateName( rRange.aStart ) ); @@ -121,7 +121,7 @@ void ShrfmlaBuffer::Store( const ScRange& rRange, const ScTokenArray& rToken ) } -sal_uInt16 ShrfmlaBuffer::Find( const ScAddress & aAddr ) const +sal_uInt16 SharedFormulaBuffer::Find( const ScAddress & aAddr ) const { ShrfmlaHash::const_iterator hash = index_hash.find (aAddr); if (hash != index_hash.end()) @@ -138,7 +138,7 @@ sal_uInt16 ShrfmlaBuffer::Find( const ScAddress & aAddr ) const #define SHRFMLA_BASENAME "SHARED_FORMULA_" -String ShrfmlaBuffer::CreateName( const ScRange& r ) +String SharedFormulaBuffer::CreateName( const ScRange& r ) { OUString aName = SHRFMLA_BASENAME + OUString::number( r.aStart.Col() ) + "_" + diff --git a/sc/source/filter/inc/namebuff.hxx b/sc/source/filter/inc/namebuff.hxx index 38ead51..6f5aa28 100644 --- a/sc/source/filter/inc/namebuff.hxx +++ b/sc/source/filter/inc/namebuff.hxx @@ -149,7 +149,7 @@ inline void NameBuffer::SetBase( sal_uInt16 nNewBase ) -class ShrfmlaBuffer : public ExcRoot +class SharedFormulaBuffer : public ExcRoot { struct ScAddressHashFunc : public std::unary_function< const ScAddress &, size_t > { @@ -163,14 +163,14 @@ class ShrfmlaBuffer : public ExcRoot size_t mnCurrIdx; public: - ShrfmlaBuffer( RootData* pRD ); - virtual ~ShrfmlaBuffer(); + SharedFormulaBuffer( RootData* pRD ); + virtual ~SharedFormulaBuffer(); void Clear(); void Store( const ScRange& rRange, const ScTokenArray& ); sal_uInt16 Find (const ScAddress & rAddress ) const; static String CreateName( const ScRange& ); - }; +}; diff --git a/sc/source/filter/inc/root.hxx b/sc/source/filter/inc/root.hxx index 1c9e075..492a463 100644 --- a/sc/source/filter/inc/root.hxx +++ b/sc/source/filter/inc/root.hxx @@ -30,7 +30,7 @@ class ScRangeName; class RangeNameBufferWK3; -class ShrfmlaBuffer; +class SharedFormulaBuffer; class ExtNameBuff; class ExtSheetBuffer; class ExcelToSc; @@ -51,7 +51,7 @@ struct RootData // -> Inkarnation jeweils im ImportExcel-Objekt! { BiffTyp eDateiTyp; // feine Differenzierung ExtSheetBuffer* pExtSheetBuff; - ShrfmlaBuffer* pShrfmlaBuff; + SharedFormulaBuffer* pShrfmlaBuff; ExtNameBuff* pExtNameBuff; ExcelToSc* pFmlaConverter; XclImpColRowSettings* pColRowBuff; // Col/Row-Einstellungen 1 Tabelle commit 0ea90c486493a10ec796f3420e7a23c72549d64c Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Mon Aug 5 22:26:11 2013 -0400 Prepare for importing shared formulas as formula groups from xls. Still the first step. Change-Id: I1897c9c2cd3a5b5245febbfba76e1b088054f578 diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index 1213959..6480056 100644 --- a/sc/inc/formulacell.hxx +++ b/sc/inc/formulacell.hxx @@ -47,6 +47,7 @@ struct SC_DLLPUBLIC ScFormulaCellGroup { mutable size_t mnRefCount; + ScTokenArray* mpCode; SCROW mnStart; // Start offset of that cell SCROW mnLength; // How many of these do we have ? bool mbInvariant; @@ -77,6 +78,7 @@ enum ScMatrixMode { class SC_DLLPUBLIC ScFormulaCell : public SvtListener { private: + ScFormulaCellGroupRef mxGroup; // re-factoring hack - group of formulae we're part of. ScFormulaResult aResult; formula::FormulaGrammar::Grammar eTempGrammar; // used between string (creation) and (re)compilation ScTokenArray* pCode; // The (new) token array @@ -85,7 +87,6 @@ private: ScFormulaCell* pNext; ScFormulaCell* pPreviousTrack; ScFormulaCell* pNextTrack; - ScFormulaCellGroupRef xGroup; // re-factoring hack - group of formulae we're part of. sal_uInt16 nSeenInIteration; // Iteration cycle in which the cell was last encountered sal_uInt8 cMatrixFlag; // One of ScMatrixMode short nFormatType; @@ -146,6 +147,10 @@ public: const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT, sal_uInt8 = MM_NONE ); + ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, const ScFormulaCellGroupRef& xGroup, + const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT, + sal_uInt8 = MM_NONE ); + /** With formula string and grammar to compile with. formula::FormulaGrammar::GRAM_DEFAULT effectively isformula::FormulaGrammar::GRAM_NATIVE_UI that also includes formula::FormulaGrammar::CONV_UNSPECIFIED, therefor uses the address diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 0ad7cb6..cdedb66 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -384,6 +384,7 @@ void adjustDBRange(ScToken* pToken, ScDocument& rNewDoc, const ScDocument* pOldD ScFormulaCellGroup::ScFormulaCellGroup() : mnRefCount(0), + mpCode(NULL), mnStart(0), mnLength(0), mbInvariant(false), @@ -393,6 +394,7 @@ ScFormulaCellGroup::ScFormulaCellGroup() : ScFormulaCellGroup::~ScFormulaCellGroup() { + delete mpCode; } // ============================================================================ @@ -477,6 +479,53 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, pCode->GenHash(); } +ScFormulaCell::ScFormulaCell( + ScDocument* pDoc, const ScAddress& rPos, const ScFormulaCellGroupRef& xGroup, + const FormulaGrammar::Grammar eGrammar, sal_uInt8 cInd ) : + mxGroup(xGroup), + eTempGrammar( eGrammar), + pCode(xGroup->mpCode ? xGroup->mpCode : new ScTokenArray), + pDocument( pDoc ), + pPrevious(0), + pNext(0), + pPreviousTrack(0), + pNextTrack(0), + nSeenInIteration(0), + cMatrixFlag ( cInd ), + nFormatType ( NUMBERFORMAT_NUMBER ), + bDirty(false), + bChanged( false ), + bRunning( false ), + bCompile( false ), + bSubTotal( false ), + bIsIterCell( false ), + bInChangeTrack( false ), + bTableOpDirty( false ), + bNeedListening( false ), + mbNeedsNumberFormat( false ), + aPos( rPos ) +{ + // UPN-Array generation + if( pCode->GetLen() && !pCode->GetCodeError() && !pCode->GetCodeLen() ) + { + ScCompiler aComp( pDocument, aPos, *pCode); + aComp.SetGrammar(eTempGrammar); + bSubTotal = aComp.CompileTokenArray(); + nFormatType = aComp.GetNumFormatType(); + } + else + { + pCode->Reset(); + if ( pCode->GetNextOpCodeRPN( ocSubTotal ) ) + bSubTotal = true; + } + + if (bSubTotal) + pDocument->AddSubTotalCell(this); + + pCode->GenHash(); +} + ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, int nCloneFlags ) : SvtListener(), aResult( rCell.aResult ), @@ -605,7 +654,9 @@ ScFormulaCell::~ScFormulaCell() if (pDocument->HasExternalRefManager()) pDocument->GetExternalRefManager()->removeRefCell(this); - delete pCode; + if (!mxGroup || !mxGroup->mpCode) + // Formula token is not shared. + delete pCode; } ScFormulaCell* ScFormulaCell::Clone() const @@ -1579,8 +1630,8 @@ void ScFormulaCell::SetDirty( bool bDirtyFlag ) void ScFormulaCell::SetDirtyVar() { bDirty = true; - if (xGroup) - xGroup->meCalcState = sc::GroupCalcEnabled; + if (mxGroup) + mxGroup->meCalcState = sc::GroupCalcEnabled; // mark the sheet of this cell to be calculated //#FIXME do we need to revert this remnant of old fake vba events? pDocument->AddCalculateTable( aPos.Tab() ); @@ -2239,8 +2290,8 @@ bool ScFormulaCell::UpdateReferenceOnShift( // This formula cell itself is being shifted during cell range // insertion or deletion. Update its position. aPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta); - if (xGroup && xGroup->mnStart == aOldPos.Row()) - xGroup->mnStart += rCxt.mnRowDelta; + if (mxGroup && mxGroup->mnStart == aOldPos.Row()) + mxGroup->mnStart += rCxt.mnRowDelta; bCellStateChanged = aPos != aOldPos; } @@ -3074,12 +3125,12 @@ void ScFormulaCell::SetNextTrack( ScFormulaCell* pF ) { pNextTr ScFormulaCellGroupRef ScFormulaCell::GetCellGroup() { - return xGroup; + return mxGroup; } void ScFormulaCell::SetCellGroup( const ScFormulaCellGroupRef &xRef ) { - xGroup = xRef; + mxGroup = xRef; } ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( ScFormulaCell& rOther ) const @@ -3309,10 +3360,10 @@ bool ScFormulaCell::InterpretFormulaGroup() // import / insert / delete etc. and is integral to the data structures pDocument->RebuildFormulaGroups(); - if (!xGroup || !pCode) + if (!mxGroup || !pCode) return false; - if (xGroup->meCalcState == sc::GroupCalcDisabled) + if (mxGroup->meCalcState == sc::GroupCalcDisabled) return false; switch (pCode->GetVectorState()) @@ -3328,28 +3379,28 @@ bool ScFormulaCell::InterpretFormulaGroup() return false; } - if (xGroup->mbInvariant) + if (mxGroup->mbInvariant) return InterpretInvariantFormulaGroup(); sc::FormulaGroupContext aCxt; ScTokenArray aCode; ScAddress aTopPos = aPos; - aTopPos.SetRow(xGroup->mnStart); + aTopPos.SetRow(mxGroup->mnStart); GroupTokenConverter aConverter(aCxt, aCode, *pDocument, *this, aTopPos); if (!aConverter.convert(*pCode)) { - xGroup->meCalcState = sc::GroupCalcDisabled; + mxGroup->meCalcState = sc::GroupCalcDisabled; return false; } - xGroup->meCalcState = sc::GroupCalcRunning; - if (!sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, aTopPos, xGroup, aCode)) + mxGroup->meCalcState = sc::GroupCalcRunning; + if (!sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, aTopPos, mxGroup, aCode)) { - xGroup->meCalcState = sc::GroupCalcDisabled; + mxGroup->meCalcState = sc::GroupCalcDisabled; return false; } - xGroup->meCalcState = sc::GroupCalcEnabled; + mxGroup->meCalcState = sc::GroupCalcEnabled; return true; } @@ -3409,10 +3460,10 @@ bool ScFormulaCell::InterpretInvariantFormulaGroup() aResult.SetToken(aInterpreter.GetResultToken().get()); } - for ( sal_Int32 i = 0; i < xGroup->mnLength; i++ ) + for ( sal_Int32 i = 0; i < mxGroup->mnLength; i++ ) { ScAddress aTmpPos = aPos; - aTmpPos.SetRow(xGroup->mnStart + i); + aTmpPos.SetRow(mxGroup->mnStart + i); ScFormulaCell* pCell = pDocument->GetFormulaCell(aTmpPos); assert( pCell != NULL ); @@ -3642,21 +3693,21 @@ void ScFormulaCell::EndListeningTo( sc::EndListeningContext& rCxt ) bool ScFormulaCell::IsShared() const { - return xGroup.get() != NULL; + return mxGroup.get() != NULL; } bool ScFormulaCell::IsSharedInvariant() const { - return xGroup ? xGroup->mbInvariant : false; + return mxGroup ? mxGroup->mbInvariant : false; } SCROW ScFormulaCell::GetSharedTopRow() const { - return xGroup ? xGroup->mnStart : -1; + return mxGroup ? mxGroup->mnStart : -1; } SCROW ScFormulaCell::GetSharedLength() const { - return xGroup ? xGroup->mnLength : 0; + return mxGroup ? mxGroup->mnLength : 0; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/excel/excform.cxx b/sc/source/filter/excel/excform.cxx index b2a1619..4f60d7e 100644 --- a/sc/source/filter/excel/excform.cxx +++ b/sc/source/filter/excel/excform.cxx @@ -101,56 +101,63 @@ void ImportExcel::Formula4() void ImportExcel::Formula( const XclAddress& rXclPos, sal_uInt16 nXF, sal_uInt16 nFormLen, double fCurVal, bool bShrFmla) { - ConvErr eErr = ConvOK; ScAddress aScPos( ScAddress::UNINITIALIZED ); - if( GetAddressConverter().ConvertAddress( aScPos, rXclPos, GetCurrScTab(), true ) ) - { - // Formula will be read next, length in nFormLen - const ScTokenArray* pResult = NULL; - bool bConvert = false; + if (!GetAddressConverter().ConvertAddress(aScPos, rXclPos, GetCurrScTab(), true)) + // Conversion failed. + return; - pFormConv->Reset( aScPos ); + // Formula will be read next, length in nFormLen + const ScTokenArray* pResult = NULL; - if( bShrFmla ) - bConvert = !pFormConv->GetShrFmla( pResult, maStrm, nFormLen ); - else - bConvert = true; + pFormConv->Reset( aScPos ); - if( bConvert ) - eErr = pFormConv->Convert( pResult, maStrm, nFormLen, true, FT_CellFormula); + if (bShrFmla) + { + // This is a shared formula. Get the token array from the shared formula pool. + pResult = pFormConv->GetShrFmla(maStrm, nFormLen); + if (!pResult) + return; + + ScFormulaCell* pCell = new ScFormulaCell( pD, aScPos, pResult ); + pD->EnsureTable(aScPos.Tab()); + pCell = pD->SetFormulaCell(aScPos, pCell); + pCell->SetNeedNumberFormat(false); + if (!rtl::math::isNan(fCurVal)) + pCell->SetResultDouble(fCurVal); + + GetXFRangeBuffer().SetXF(aScPos, nXF); + return; + } - ScFormulaCell* pCell = NULL; + ConvErr eErr = pFormConv->Convert( pResult, maStrm, nFormLen, true, FT_CellFormula); - if (pResult) - { - pCell = new ScFormulaCell( pD, aScPos, pResult ); - pD->EnsureTable(aScPos.Tab()); - pCell = pD->SetFormulaCell(aScPos, pCell); - } - else - { - CellType eCellType = pD->GetCellType(aScPos); - if( eCellType == CELLTYPE_FORMULA ) - { - pCell = pD->GetFormulaCell(aScPos); - if( pCell ) - pCell->AddRecalcMode( RECALCMODE_ONLOAD_ONCE ); - } - } + ScFormulaCell* pCell = NULL; + if (pResult) + { + pCell = new ScFormulaCell( pD, aScPos, pResult ); + pD->EnsureTable(aScPos.Tab()); + pCell = pD->SetFormulaCell(aScPos, pCell); + } + else + { + pCell = pD->GetFormulaCell(aScPos); if (pCell) - { - pCell->SetNeedNumberFormat(false); - if( eErr != ConvOK ) - ExcelToSc::SetError( *pCell, eErr ); + pCell->AddRecalcMode( RECALCMODE_ONLOAD_ONCE ); + } - if (!rtl::math::isNan(fCurVal)) - pCell->SetResultDouble(fCurVal); - } + if (pCell) + { + pCell->SetNeedNumberFormat(false); + if( eErr != ConvOK ) + ExcelToSc::SetError( *pCell, eErr ); - GetXFRangeBuffer().SetXF( aScPos, nXF ); + if (!rtl::math::isNan(fCurVal)) + pCell->SetResultDouble(fCurVal); } + + GetXFRangeBuffer().SetXF(aScPos, nXF); } @@ -1669,45 +1676,32 @@ const ScTokenArray* ExcelToSc::GetBoolErr( XclBoolError eType ) // if a shared formula was found, stream seeks to first byte after <nFormulaLen>, // else stream pointer stays unchanged -sal_Bool ExcelToSc::GetShrFmla( const ScTokenArray*& rpErgebnis, XclImpStream& aIn, sal_Size nFormulaLen ) +const ScTokenArray* ExcelToSc::GetShrFmla( XclImpStream& aIn, sal_Size nFormulaLen ) { - sal_uInt8 nOp; - sal_Bool bRet = sal_True; + if (!nFormulaLen) + return NULL; - if( nFormulaLen == 0 ) - bRet = false; - else - { - aIn.PushPosition(); - - aIn >> nOp; + aIn.PushPosition(); - if( nOp == 0x01 ) // Shared Formula [ 277] - { - sal_uInt16 nCol, nRow; - - aIn >> nRow >> nCol; - - aStack << aPool.StoreName( GetOldRoot().pShrfmlaBuff->Find( - ScAddress(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), GetCurrScTab())), true); - - bRet = sal_True; - } - else - bRet = false; + sal_uInt8 nOp; + aIn >> nOp; + if (nOp != 0x01) // Shared Formula [ 277] + { aIn.PopPosition(); + return NULL; } - if( bRet ) - { - aIn.Ignore( nFormulaLen ); - rpErgebnis = aPool[ aStack.Get() ]; - } - else - rpErgebnis = NULL; + sal_uInt16 nCol, nRow; + aIn >> nRow >> nCol; + + aStack << aPool.StoreName( GetOldRoot().pShrfmlaBuff->Find( + ScAddress(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), GetCurrScTab())), true); + + aIn.PopPosition(); - return bRet; + aIn.Ignore(nFormulaLen); + return aPool[aStack.Get()]; } diff --git a/sc/source/filter/excel/read.cxx b/sc/source/filter/excel/read.cxx index d1ec8ae..9c4c5e7 100644 --- a/sc/source/filter/excel/read.cxx +++ b/sc/source/filter/excel/read.cxx @@ -1140,7 +1140,7 @@ FltError ImportExcel8::Read( void ) case EXC_ID2_ARRAY: case EXC_ID3_ARRAY: Array34(); break; // ARRAY [ 34 ] case 0x0225: Defrowheight345();break;//DEFAULTROWHEI[ 345 ] - case 0x04BC: Shrfmla(); break; // SHRFMLA [ 5 ] + case EXC_ID_SHRFMLA: Shrfmla(); break; // SHRFMLA [ 5 ] case 0x0867: SheetProtection(); break; // SHEETPROTECTION } } diff --git a/sc/source/filter/inc/excform.hxx b/sc/source/filter/inc/excform.hxx index 1b7786f..fb866fe 100644 --- a/sc/source/filter/inc/excform.hxx +++ b/sc/source/filter/inc/excform.hxx @@ -63,7 +63,7 @@ public: void GetDummy( const ScTokenArray*& ); const ScTokenArray* GetBoolErr( XclBoolError ); - sal_Bool GetShrFmla( const ScTokenArray*&, XclImpStream& rStrm, sal_Size nFormulaLen ); + const ScTokenArray* GetShrFmla( XclImpStream& rStrm, sal_Size nFormulaLen ); static void SetError( ScFormulaCell& rCell, const ConvErr eErr ); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits