sc/inc/formulacell.hxx | 3 + sc/inc/sharedformula.hxx | 14 +++++ sc/inc/tokenarray.hxx | 3 + sc/qa/unit/ucalc.cxx | 6 +- sc/source/core/data/column.cxx | 62 +++++++++++++++++++++++-- sc/source/core/data/formulacell.cxx | 58 +++++++++++++++++++----- sc/source/core/tool/sharedformula.cxx | 65 +++++++++++++++++++++----- sc/source/core/tool/token.cxx | 82 ++++++++++++++++++++++++++++++++++ sc/source/filter/excel/xetable.cxx | 39 ++++++++-------- sc/source/filter/excel/xlformula.cxx | 7 -- sc/source/filter/inc/xetable.hxx | 3 - sc/source/filter/inc/xlformula.hxx | 8 --- 12 files changed, 281 insertions(+), 69 deletions(-)
New commits: commit 05effa857e3b03ac894c8a44cd8129374da8c9a7 Author: Kohei Yoshida <[email protected]> Date: Mon Aug 12 17:46:45 2013 -0400 Re-enable these tests. They pass now. Change-Id: I408f42a849e7635ef53d4b8c142a0d90ac37bb05 diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index d65be47..675e0dba 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -297,7 +297,7 @@ public: CPPUNIT_TEST(testHorizontalIterator); CPPUNIT_TEST(testFormulaDepTracking); CPPUNIT_TEST(testFormulaDepTracking2); -// CPPUNIT_TEST(testCellBroadcaster); + CPPUNIT_TEST(testCellBroadcaster); CPPUNIT_TEST(testFuncParam); CPPUNIT_TEST(testNamedRange); CPPUNIT_TEST(testCSV); @@ -341,8 +341,8 @@ public: CPPUNIT_TEST(testSetBackgroundColor); CPPUNIT_TEST(testRenameTable); CPPUNIT_TEST(testAutoFill); -// CPPUNIT_TEST(testCopyPasteFormulas); -// CPPUNIT_TEST(testCopyPasteFormulasExternalDoc); + CPPUNIT_TEST(testCopyPasteFormulas); + CPPUNIT_TEST(testCopyPasteFormulasExternalDoc); CPPUNIT_TEST(testFindAreaPosVertical); CPPUNIT_TEST(testFindAreaPosColRight); CPPUNIT_TEST(testSort); commit 56f048dbee4603adce5af80d2896a2d10cd2524b Author: Kohei Yoshida <[email protected]> Date: Mon Aug 12 17:23:30 2013 -0400 This is clearly a bug. Let's fix it. Change-Id: I83aa2c108e7d8561d28d76b69a8763a15a20a2bd diff --git a/sc/inc/sharedformula.hxx b/sc/inc/sharedformula.hxx index 0b49751..11493e646 100644 --- a/sc/inc/sharedformula.hxx +++ b/sc/inc/sharedformula.hxx @@ -34,7 +34,7 @@ public: for (++it; it != itEnd; ++it, pPrev = pCur) { pCur = *it; - ScFormulaCell::CompareState eState = pPrev->CompareByTokenArray(*pPrev); + ScFormulaCell::CompareState eState = pCur->CompareByTokenArray(*pPrev); if (eState == ScFormulaCell::NotEqual) continue; commit 05271f9a742e6c40540ae6db1211d9ceb95a57e6 Author: Kohei Yoshida <[email protected]> Date: Mon Aug 12 16:42:53 2013 -0400 Ungroup a cell when the group length becomes 1. Change-Id: Ic656d4837ab1fc5feb4b19765ae427371dfdfe10 diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx index 07d9029..6583ac9 100644 --- a/sc/source/core/tool/sharedformula.cxx +++ b/sc/source/core/tool/sharedformula.cxx @@ -38,13 +38,25 @@ void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type ScFormulaCellGroupRef xGroup = rTop.GetCellGroup(); - ScFormulaCellGroupRef xGroup2(new ScFormulaCellGroup); - xGroup2->mbInvariant = xGroup->mbInvariant; - xGroup2->mnStart = nRow; - xGroup2->mnLength = xGroup->mnStart + xGroup->mnLength - nRow; - xGroup2->mpCode = xGroup->mpCode->Clone(); + SCROW nLength2 = xGroup->mnStart + xGroup->mnLength - nRow; + ScFormulaCellGroupRef xGroup2; + if (nLength2 > 1) + { + xGroup2.reset(new ScFormulaCellGroup); + xGroup2->mbInvariant = xGroup->mbInvariant; + xGroup2->mnStart = nRow; + xGroup2->mnLength = nLength2; + xGroup2->mpCode = xGroup->mpCode->Clone(); + } xGroup->mnLength = nRow - xGroup->mnStart; + if (xGroup->mnLength == 1) + { + // The top group consists of only one cell. Ungroup this. + ScFormulaCellGroupRef xNone; + ScFormulaCell& rPrev = *sc::formula_block::at(*aPos.first->data, aPos.second-1); + rPrev.SetCellGroup(xNone); + } // Apply the lower group object to the lower cells. #if DEBUG_COLUMN_STORAGE @@ -56,7 +68,7 @@ void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type } #endif sc::formula_block::iterator itEnd = it; - std::advance(itEnd, xGroup2->mnLength); + std::advance(itEnd, nLength2); for (; it != itEnd; ++it) { ScFormulaCell& rCell = **it; commit 7ad68e3e8d97de37ca347deb50db379c252236e1 Author: Kohei Yoshida <[email protected]> Date: Mon Aug 12 16:28:29 2013 -0400 Fix indentation. Change-Id: I2caebb42d92bf81e3ba8809a47f833a9379e769d diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx index 9299e33..07d9029 100644 --- a/sc/source/core/tool/sharedformula.cxx +++ b/sc/source/core/tool/sharedformula.cxx @@ -48,12 +48,12 @@ void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type // Apply the lower group object to the lower cells. #if DEBUG_COLUMN_STORAGE - if (xGroup2->mnStart + xGroup2->mnLength > aPos.first->position + aPos.first->size) - { - cerr << "ScColumn::SplitFormulaCellGroup: Shared formula region goes beyond the formula block. Not good." << endl; - cerr.flush(); - abort(); - } + if (xGroup2->mnStart + xGroup2->mnLength > aPos.first->position + aPos.first->size) + { + cerr << "ScColumn::SplitFormulaCellGroup: Shared formula region goes beyond the formula block. Not good." << endl; + cerr.flush(); + abort(); + } #endif sc::formula_block::iterator itEnd = it; std::advance(itEnd, xGroup2->mnLength); commit 3f06d624d8505b86a88a96b7eaa9910604aab9a7 Author: Kohei Yoshida <[email protected]> Date: Mon Aug 12 15:48:50 2013 -0400 We still need to update cell positions for non-top cells. Change-Id: If967247ed5d916535e7b52af14b00090b7c9d0d2 diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index 6a1bbb0..c8e7f35 100644 --- a/sc/inc/formulacell.hxx +++ b/sc/inc/formulacell.hxx @@ -112,6 +112,8 @@ private: }; void InterpretTail( ScInterpretTailParameter ); + bool UpdatePosOnShift( const sc::RefUpdateContext& rCxt ); + /** * Update reference in response to cell insertion or deletion. */ diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 102de63..76582a0 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2128,6 +2128,29 @@ bool ScFormulaCell::HasColRowName() const return (pCode->GetNextColRowName() != NULL); } +bool ScFormulaCell::UpdatePosOnShift( const sc::RefUpdateContext& rCxt ) +{ + if (rCxt.meMode != URM_INSDEL) + // Just in case... + return false; + + if (!rCxt.mnColDelta && !rCxt.mnRowDelta && !rCxt.mnTabDelta) + // No movement. + return false; + + if (!rCxt.maRange.In(aPos)) + return false; + + // This formula cell itself is being shifted during cell range + // insertion or deletion. Update its position. + if (mxGroup && mxGroup->mnStart == aPos.Row()) + mxGroup->mnStart += rCxt.mnRowDelta; + + aPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta); + + return true; +} + namespace { /** @@ -2245,17 +2268,7 @@ bool ScFormulaCell::UpdateReferenceOnShift( if ( pUndoCellPos ) aUndoPos = *pUndoCellPos; ScAddress aOldPos( aPos ); - - if (rCxt.maRange.In(aPos)) - { - // 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 (mxGroup && mxGroup->mnStart == aOldPos.Row()) - mxGroup->mnStart += rCxt.mnRowDelta; - - bCellStateChanged = aPos != aOldPos; - } + bCellStateChanged = UpdatePosOnShift(rCxt); // Check presence of any references or column row names. pCode->Reset(); @@ -2554,8 +2567,19 @@ bool ScFormulaCell::UpdateReference( return false; if (mxGroup && mxGroup->mnStart != aPos.Row()) - // Update only the top cell in case the cell is part of a formula group. + { + // This is not a top cell of a formula group. Don't update references. + + switch (rCxt.meMode) + { + case URM_INSDEL: + return UpdatePosOnShift(rCxt); + break; + default: + ; + } return false; + } switch (rCxt.meMode) { commit 4625f6f699dfcc41b8e7ce2b86aedc1429eb4cf1 Author: Kohei Yoshida <[email protected]> Date: Mon Aug 12 15:23:28 2013 -0400 Do the splitting of formula groups. Change-Id: I5a8661895b558b67abc19cdc39de9eb027bc1c34 diff --git a/sc/inc/sharedformula.hxx b/sc/inc/sharedformula.hxx index 9423384..0b49751 100644 --- a/sc/inc/sharedformula.hxx +++ b/sc/inc/sharedformula.hxx @@ -63,7 +63,15 @@ public: */ static void splitFormulaCellGroup(const CellStoreType::position_type& aPos); - static void splitFormulaCellGroups(CellStoreType& rCells, const std::vector<SCROW>& rBounds); + /** + * Split existing shared formula ranges at specified row positions. + * + * @param rCells cell storage container + * @param rBounds row positions at which to split existing shared formula + * ranges. Note that this method will directly modify this + * parameter to sort and remove duplicates. + */ + static void splitFormulaCellGroups(CellStoreType& rCells, std::vector<SCROW>& rBounds); /** * See if two specified adjacent formula cells can be merged, and if they diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 3cacf7c..25e2f84 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -2364,6 +2364,10 @@ bool ScColumn::UpdateReference( const sc::RefUpdateContext& rCxt, ScDocument* pU if (rCxt.meMode == URM_COPY) return UpdateReferenceOnCopy(rCxt, pUndoDoc); + if (IsEmptyData()) + // Cells in this column are all empty. + return false; + std::vector<SCROW> aBounds; bool bThisColShifted = (rCxt.maRange.aStart.Tab() <= nTab && nTab <= rCxt.maRange.aEnd.Tab() && @@ -2387,11 +2391,6 @@ bool ScColumn::UpdateReference( const sc::RefUpdateContext& rCxt, ScDocument* pU UpdateRefGroupBoundChecker aBoundChecker(rCxt, aBounds); std::for_each(maCells.begin(), maCells.end(), aBoundChecker); - // Sort and remove duplicates. - std::sort(aBounds.begin(), aBounds.end()); - std::vector<SCROW>::iterator it = std::unique(aBounds.begin(), aBounds.end()); - aBounds.erase(it, aBounds.end()); - // Do the actual splitting. sc::SharedFormulaUtil::splitFormulaCellGroups(maCells, aBounds); diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx index d9f3a25..9299e33 100644 --- a/sc/source/core/tool/sharedformula.cxx +++ b/sc/source/core/tool/sharedformula.cxx @@ -64,9 +64,33 @@ void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type } } -void SharedFormulaUtil::splitFormulaCellGroups(CellStoreType& rCells, const std::vector<SCROW>& rBounds) +void SharedFormulaUtil::splitFormulaCellGroups(CellStoreType& rCells, std::vector<SCROW>& rBounds) { - // TODO: Implement this. + if (rBounds.empty()) + return; + + // Sort and remove duplicates. + std::sort(rBounds.begin(), rBounds.end()); + std::vector<SCROW>::iterator it = std::unique(rBounds.begin(), rBounds.end()); + rBounds.erase(it, rBounds.end()); + + it = rBounds.begin(); + SCROW nRow = *it; + CellStoreType::position_type aPos = rCells.position(nRow); + if (aPos.first == rCells.end()) + return; + + splitFormulaCellGroup(aPos); + std::vector<SCROW>::iterator itEnd = rBounds.end(); + for (++it; it != itEnd; ++it) + { + nRow = *it; + aPos = rCells.position(aPos.first, nRow); + if (aPos.first == rCells.end()) + return; + + splitFormulaCellGroup(aPos); + } } void SharedFormulaUtil::joinFormulaCells(const CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2) diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index 6cd491c..701e235 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -2981,7 +2981,7 @@ void checkBounds( SCROW nOffset = rCxt.maRange.aStart.Row() - aAbs.aStart.Row(); rBounds.push_back(rPos.Row()+nOffset); // Ditto. - nOffset = rCxt.maRange.aEnd.Row() - aAbs.aStart.Row(); + nOffset = rCxt.maRange.aEnd.Row() + 1 - aAbs.aStart.Row(); rBounds.push_back(rPos.Row()+nOffset); } commit 9d27add20779382192d3530178c9d0ca365c56c9 Author: Kohei Yoshida <[email protected]> Date: Sat Aug 10 23:31:38 2013 -0400 Collect all boundaries at which to split the formula group. Change-Id: Ic78d7a06991b983e625b161f11fbbabce02334f3 diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index 2a2b61c..6a1bbb0 100644 --- a/sc/inc/formulacell.hxx +++ b/sc/inc/formulacell.hxx @@ -352,6 +352,7 @@ public: bool IsShared() const; bool IsSharedInvariant() const; + bool IsSharedTop() const; SCROW GetSharedTopRow() const; SCROW GetSharedLength() const; ScTokenArray* GetSharedCode(); diff --git a/sc/inc/sharedformula.hxx b/sc/inc/sharedformula.hxx index 232c4bc..9423384 100644 --- a/sc/inc/sharedformula.hxx +++ b/sc/inc/sharedformula.hxx @@ -13,6 +13,8 @@ #include "formulacell.hxx" #include "mtvelements.hxx" +#include <vector> + namespace sc { class SharedFormulaUtil @@ -61,6 +63,8 @@ public: */ static void splitFormulaCellGroup(const CellStoreType::position_type& aPos); + static void splitFormulaCellGroups(CellStoreType& rCells, const std::vector<SCROW>& rBounds); + /** * See if two specified adjacent formula cells can be merged, and if they * can, merge them into the same group. diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx index 09a9798..00f192d 100644 --- a/sc/inc/tokenarray.hxx +++ b/sc/inc/tokenarray.hxx @@ -166,6 +166,9 @@ public: sc::RefUpdateResult AdjustReferenceOnMovedTab( sc::RefUpdateMoveTabContext& rCxt, const ScAddress& rOldPos ); + void CheckRelativeReferenceBounds( + const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, std::vector<SCROW>& rBounds ) const; + #if DEBUG_FORMULA_COMPILER void Dump() const; #endif diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index ba9b35e..3cacf7c 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -2295,6 +2295,46 @@ public: bool isUpdated() const { return mbUpdated; } }; +class UpdateRefGroupBoundChecker : std::unary_function<sc::CellStoreType::value_type, void> +{ + const sc::RefUpdateContext& mrCxt; + std::vector<SCROW>& mrBounds; +public: + UpdateRefGroupBoundChecker(const sc::RefUpdateContext& rCxt, std::vector<SCROW>& rBounds) : + mrCxt(rCxt), mrBounds(rBounds) {} + + void operator() (const sc::CellStoreType::value_type& node) + { + if (node.type != sc::element_type_formula) + return; + + sc::formula_block::const_iterator it = sc::formula_block::begin(*node.data); + sc::formula_block::const_iterator itEnd = sc::formula_block::end(*node.data); + + // Only pick shared formula cells that are the top cells of their + // respective shared ranges. + for (; it != itEnd; ++it) + { + const ScFormulaCell& rCell = **it; + if (!rCell.IsShared()) + continue; + + if (rCell.IsSharedTop()) + { + // Check its tokens and record its reference boundaries. + const ScTokenArray& rCode = *rCell.GetCode(); + rCode.CheckRelativeReferenceBounds( + mrCxt, rCell.aPos, rCell.GetSharedLength(), mrBounds); + + // Move to the last cell in the group, to get incremented to + // the next cell in the next iteration. + size_t nOffsetToLast = rCell.GetSharedLength() - 1; + std::advance(it, nOffsetToLast); + } + } + } +}; + } bool ScColumn::UpdateReferenceOnCopy( const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc ) @@ -2324,6 +2364,8 @@ bool ScColumn::UpdateReference( const sc::RefUpdateContext& rCxt, ScDocument* pU if (rCxt.meMode == URM_COPY) return UpdateReferenceOnCopy(rCxt, pUndoDoc); + std::vector<SCROW> aBounds; + bool bThisColShifted = (rCxt.maRange.aStart.Tab() <= nTab && nTab <= rCxt.maRange.aEnd.Tab() && rCxt.maRange.aStart.Col() <= nCol && nCol <= rCxt.maRange.aEnd.Col()); if (bThisColShifted) @@ -2333,17 +2375,26 @@ bool ScColumn::UpdateReference( const sc::RefUpdateContext& rCxt, ScDocument* pU SCROW nSplitPos = rCxt.maRange.aStart.Row(); if (ValidRow(nSplitPos)) { - sc::CellStoreType::position_type aPos = maCells.position(nSplitPos); - sc::SharedFormulaUtil::splitFormulaCellGroup(aPos); + aBounds.push_back(nSplitPos); nSplitPos = rCxt.maRange.aEnd.Row() + 1; if (ValidRow(nSplitPos)) - { - aPos = maCells.position(aPos.first, nSplitPos); - sc::SharedFormulaUtil::splitFormulaCellGroup(aPos); - } + aBounds.push_back(nSplitPos); } } + // Check the row positions at which the group must be split per relative + // references. + UpdateRefGroupBoundChecker aBoundChecker(rCxt, aBounds); + std::for_each(maCells.begin(), maCells.end(), aBoundChecker); + + // Sort and remove duplicates. + std::sort(aBounds.begin(), aBounds.end()); + std::vector<SCROW>::iterator it = std::unique(aBounds.begin(), aBounds.end()); + aBounds.erase(it, aBounds.end()); + + // Do the actual splitting. + sc::SharedFormulaUtil::splitFormulaCellGroups(maCells, aBounds); + UpdateRefOnNonCopy aHandler(nCol, nTab, rCxt, pUndoDoc); sc::ProcessFormula(maCells, aHandler); return aHandler.isUpdated(); diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 962b2dc..102de63 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -3774,6 +3774,14 @@ bool ScFormulaCell::IsSharedInvariant() const return mxGroup ? mxGroup->mbInvariant : false; } +bool ScFormulaCell::IsSharedTop() const +{ + if (!mxGroup) + return false; + + return mxGroup->mnStart == aPos.Row(); +} + SCROW ScFormulaCell::GetSharedTopRow() const { return mxGroup ? mxGroup->mnStart : -1; diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx index 3e77934..d9f3a25 100644 --- a/sc/source/core/tool/sharedformula.cxx +++ b/sc/source/core/tool/sharedformula.cxx @@ -64,6 +64,11 @@ void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type } } +void SharedFormulaUtil::splitFormulaCellGroups(CellStoreType& rCells, const std::vector<SCROW>& rBounds) +{ + // TODO: Implement this. +} + void SharedFormulaUtil::joinFormulaCells(const CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2) { ScFormulaCell::CompareState eState = rCell1.CompareByTokenArray(rCell2); diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index d231007..6cd491c 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -2934,6 +2934,88 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMovedTab( sc::RefUpdateMoveTa return aRes; } +namespace { + +void checkBounds( + const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, + const ScSingleRefData& rRef, std::vector<SCROW>& rBounds) +{ + if (!rRef.IsRowRel()) + return; + + ScRange aAbs(rRef.toAbs(rPos)); + aAbs.aEnd.IncRow(nGroupLen-1); + if (!rCxt.maRange.Intersects(aAbs)) + return; + + // Get the boundary row positions. + if (aAbs.aEnd.Row() < rCxt.maRange.aStart.Row()) + // No intersections. + return; + + if (aAbs.aEnd.Row() <= rCxt.maRange.aEnd.Row()) + { + // +-+ <---- top + // | | + // +--+-+--+ <---- boundary row position + // | | | | + // | +-+ | + // +-------+ + + // Add offset from the reference top to the cell position. + SCROW nOffset = rCxt.maRange.aStart.Row() - aAbs.aStart.Row(); + rBounds.push_back(rPos.Row()+nOffset); + return; + } + + // +-+ <---- top + // | | + // +--+-+--+ <---- boundary row position + // | | | | + // | | | | + // +--+-+--+ <---- boundary row position + // | | + // +-+ + + // Add offset from the reference top to the cell position. + SCROW nOffset = rCxt.maRange.aStart.Row() - aAbs.aStart.Row(); + rBounds.push_back(rPos.Row()+nOffset); + // Ditto. + nOffset = rCxt.maRange.aEnd.Row() - aAbs.aStart.Row(); + rBounds.push_back(rPos.Row()+nOffset); +} + +} + +void ScTokenArray::CheckRelativeReferenceBounds( + const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, std::vector<SCROW>& rBounds ) const +{ + FormulaToken** p = pCode; + FormulaToken** pEnd = p + static_cast<size_t>(nLen); + for (; p != pEnd; ++p) + { + switch ((*p)->GetType()) + { + case svSingleRef: + { + ScToken* pToken = static_cast<ScToken*>(*p); + checkBounds(rCxt, rPos, nGroupLen, pToken->GetSingleRef(), rBounds); + } + break; + case svDoubleRef: + { + ScToken* pToken = static_cast<ScToken*>(*p); + const ScComplexRefData& rRef = pToken->GetDoubleRef(); + checkBounds(rCxt, rPos, nGroupLen, rRef.Ref1, rBounds); + checkBounds(rCxt, rPos, nGroupLen, rRef.Ref2, rBounds); + } + break; + default: + ; + } + } +} + #if DEBUG_FORMULA_COMPILER void ScTokenArray::Dump() const { commit 9531c75056cf24cd2c15408dccf5318cf44b4499 Author: Kohei Yoshida <[email protected]> Date: Fri Aug 9 16:41:22 2013 -0400 If the formula cell is grouped, update reference only on the top cell. Change-Id: I5e2e9db621a61deba39a46962e0ca877235d7c90 diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index f755c98..962b2dc 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2553,6 +2553,10 @@ bool ScFormulaCell::UpdateReference( if (pDocument->IsClipOrUndo()) return false; + if (mxGroup && mxGroup->mnStart != aPos.Row()) + // Update only the top cell in case the cell is part of a formula group. + return false; + switch (rCxt.meMode) { case URM_INSDEL: commit 2ce9380ad1cac8b3cb741dabcf11e91c4ff37d75 Author: Kohei Yoshida <[email protected]> Date: Fri Aug 9 12:09:44 2013 -0400 Export shared formulas to xls, from the new shared formula in the core. Turns out we don't export shared formulas to xlsx, so no work is needed there. Change-Id: I85604f3b80c95c5b6179bbdac41e758c5de7854a diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx index b436a3d..b13c5bb 100644 --- a/sc/source/filter/excel/xetable.cxx +++ b/sc/source/filter/excel/xetable.cxx @@ -207,28 +207,29 @@ XclExpShrfmlaBuffer::XclExpShrfmlaBuffer( const XclExpRoot& rRoot ) : } XclExpShrfmlaRef XclExpShrfmlaBuffer::CreateOrExtendShrfmla( - const ScTokenArray& rScTokArr, const ScAddress& rScPos ) + const ScFormulaCell& rScCell, const ScAddress& rScPos ) { XclExpShrfmlaRef xRec; - if( const ScTokenArray* pShrdScTokArr = XclTokenArrayHelper::GetSharedFormula( GetRoot(), rScTokArr ) ) + const ScTokenArray* pShrdScTokArr = rScCell.GetSharedCode(); + if (!pShrdScTokArr) + // This formula cell is not shared formula cell. + return xRec; + + XclExpShrfmlaMap::iterator aIt = maRecMap.find( pShrdScTokArr ); + if( aIt == maRecMap.end() ) { - XclExpShrfmlaMap::iterator aIt = maRecMap.find( pShrdScTokArr ); - if( aIt == maRecMap.end() ) - { - // create a new record - XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_SHARED, *pShrdScTokArr, &rScPos ); - xRec.reset( new XclExpShrfmla( xTokArr, rScPos ) ); - maRecMap[ pShrdScTokArr ] = xRec; - } - else - { - // extend existing record - OSL_ENSURE( aIt->second, "XclExpShrfmlaBuffer::CreateOrExtendShrfmla - missing record" ); - xRec = aIt->second; - xRec->ExtendRange( rScPos ); - } + // create a new record + XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_SHARED, *pShrdScTokArr, &rScPos ); + xRec.reset( new XclExpShrfmla( xTokArr, rScPos ) ); + maRecMap[ pShrdScTokArr ] = xRec; + } + else + { + // extend existing record + OSL_ENSURE( aIt->second, "XclExpShrfmlaBuffer::CreateOrExtendShrfmla - missing record" ); + xRec = aIt->second; + xRec->ExtendRange( rScPos ); } - return xRec; } // Multiple operations ======================================================== @@ -851,7 +852,7 @@ XclExpFormulaCell::XclExpFormulaCell( // no matrix found - try to create shared formula if( !mxAddRec ) - mxAddRec = rShrfmlaBfr.CreateOrExtendShrfmla( rScTokArr, aScPos ); + mxAddRec = rShrfmlaBfr.CreateOrExtendShrfmla(mrScFmlaCell, aScPos); // no shared formula found - create a simple cell formula if( !mxAddRec ) diff --git a/sc/source/filter/excel/xlformula.cxx b/sc/source/filter/excel/xlformula.cxx index 356a348..a04ebfd 100644 --- a/sc/source/filter/excel/xlformula.cxx +++ b/sc/source/filter/excel/xlformula.cxx @@ -759,13 +759,6 @@ void XclTokenArrayHelper::ConvertStringToList( ScTokenArray& rScTokArr, sal_Unic } } -// shared formulas ------------------------------------------------------------ - -const ScTokenArray* XclTokenArrayHelper::GetSharedFormula( const XclRoot& /*rRoot*/, const ScTokenArray& /*rScTokArr*/ ) -{ - return NULL; -} - // multiple operations -------------------------------------------------------- namespace { diff --git a/sc/source/filter/inc/xetable.hxx b/sc/source/filter/inc/xetable.hxx index 533d2ec..0e47052 100644 --- a/sc/source/filter/inc/xetable.hxx +++ b/sc/source/filter/inc/xetable.hxx @@ -189,8 +189,7 @@ public: function updates its cell range to include the passed cell position, if there is a SHRFMLA record for the passed token array; otherwise this function creates and returns a new SHRFMLA record. */ - XclExpShrfmlaRef CreateOrExtendShrfmla( - const ScTokenArray& rScTokArr, const ScAddress& rScPos ); + XclExpShrfmlaRef CreateOrExtendShrfmla( const ScFormulaCell& rScCell, const ScAddress& rScPos ); private: typedef ::std::map< const ScTokenArray*, XclExpShrfmlaRef > XclExpShrfmlaMap; diff --git a/sc/source/filter/inc/xlformula.hxx b/sc/source/filter/inc/xlformula.hxx index fdf395e..0a90e08 100644 --- a/sc/source/filter/inc/xlformula.hxx +++ b/sc/source/filter/inc/xlformula.hxx @@ -523,14 +523,6 @@ public: @param bTrimLeadingSpaces true = remove leading spaces from each token. */ static void ConvertStringToList( ScTokenArray& rScTokArr, sal_Unicode cStringSep, bool bTrimLeadingSpaces ); - // shared formulas -------------------------------------------------------- - - /** Tries to extract the definition of a shared formula from the passed token array. - @descr Shared formulas are stored as hidden defined names in Calc. This - function looks if the passed token array consists of the reference to - such a hidden defined name and returns its definition on success. */ - static const ScTokenArray* GetSharedFormula( const XclRoot& rRoot, const ScTokenArray& rScTokArr ); - // multiple operations ---------------------------------------------------- /** Parses the passed formula and tries to extract references of a multiple operation. _______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
