summaryrefslogtreecommitdiff
path: root/sc/source/core/data
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2013-08-10 23:31:38 -0400
committerKohei Yoshida <kohei.yoshida@gmail.com>2013-08-12 19:46:29 -0400
commit30503611efc30ac7a3b09744913f048bf28ef70a (patch)
tree6ed4cbb0ae787d6fb807c8d5d559a70d25586fae /sc/source/core/data
parentbbb2d8c660b515c98624a41a39ffe94d3a7ecc00 (diff)
Collect all boundaries at which to split the formula group.
Change-Id: Ic78d7a06991b983e625b161f11fbbabce02334f3
Diffstat (limited to 'sc/source/core/data')
-rw-r--r--sc/source/core/data/column.cxx63
-rw-r--r--sc/source/core/data/formulacell.cxx8
2 files changed, 65 insertions, 6 deletions
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 0171fab7a1c7..a395c78b4753 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 06fb6dc9bae7..1753153ca3ad 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3824,6 +3824,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;