summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Francis <dennis.francis@collabora.co.uk>2018-01-23 19:53:19 +0530
committerChristian Lohmaier <lohmaier+LibreOffice@googlemail.com>2018-01-24 21:23:04 +0100
commitde93c097e729f70c63de02e3d6b1d596fac7c5f6 (patch)
treed646c3ed6e930e92110f2dea42401a12b703325f
parente5f952e6bc6b0d0944cb9125b5aa243de5c742d7 (diff)
tdf#115093 : Do not reuse singleref tokens...
...in formula group computation if the formula contains only a single reference besides any ocOpen/ocClose pairs wrapping it as the sole content. In such a case the "result" formula token returned by ScInterpreter::GetResultToken() is the same as the original singleref token, so for each row of the formulagroup, we need to use a separate singleref token. Also added a unit test in sc/qa/unit/parallelism.cxx Change-Id: I6032efc5be9b51ca1e9daf9bdd19997a949d2f43 Reviewed-on: https://gerrit.libreoffice.org/48449 Reviewed-by: Michael Meeks <michael.meeks@collabora.com> Tested-by: Jenkins <ci@libreoffice.org> (cherry picked from commit ff166845fa5ed178a97b54bb2deef4beb0cf3bdf) Reviewed-on: https://gerrit.libreoffice.org/48495 Reviewed-by: Eike Rathke <erack@redhat.com> Reviewed-by: Christian Lohmaier <lohmaier+LibreOffice@googlemail.com> Tested-by: Christian Lohmaier <lohmaier+LibreOffice@googlemail.com>
-rw-r--r--sc/qa/unit/parallelism.cxx23
-rw-r--r--sc/source/core/tool/formulagroup.cxx16
2 files changed, 36 insertions, 3 deletions
diff --git a/sc/qa/unit/parallelism.cxx b/sc/qa/unit/parallelism.cxx
index 428d65a20bec..896b7c1d8382 100644
--- a/sc/qa/unit/parallelism.cxx
+++ b/sc/qa/unit/parallelism.cxx
@@ -46,12 +46,14 @@ public:
void testDivision();
void testVLOOKUP();
void testVLOOKUPSUM();
+ void testSingleRef();
CPPUNIT_TEST_SUITE(ScParallelismTest);
CPPUNIT_TEST(testSUMIFS);
CPPUNIT_TEST(testDivision);
CPPUNIT_TEST(testVLOOKUP);
CPPUNIT_TEST(testVLOOKUPSUM);
+ CPPUNIT_TEST(testSingleRef);
CPPUNIT_TEST_SUITE_END();
private:
@@ -296,6 +298,27 @@ void ScParallelismTest::testVLOOKUPSUM()
m_pDoc->DeleteTab(0);
}
+void ScParallelismTest::testSingleRef()
+{
+ m_pDoc->InsertTab(0, "1");
+
+ const size_t nNumRows = 200;
+ for (size_t i = 0; i < nNumRows; ++i)
+ {
+ m_pDoc->SetValue(0, i, 0, static_cast<double>(i));
+ m_pDoc->SetFormula(ScAddress(1, i, 0), "=A" + OUString::number(i+1), formula::FormulaGrammar::GRAM_NATIVE_UI);
+ }
+
+ m_xDocShell->DoHardRecalc();
+
+ for (size_t i = 0; i < nNumRows; ++i)
+ {
+ OString aMsg = "At row " + OString::number(i);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), i, static_cast<size_t>(m_pDoc->GetValue(1, i, 0)));
+ }
+ m_pDoc->DeleteTab(0);
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(ScParallelismTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index d763d15d2f1c..38b9c2a327ee 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -177,6 +177,7 @@ public:
ScTokenArray aCode2;
ScInterpreterContext aContext(mrDoc, mpFormatter);
+ sal_uInt16 nNumNonOpenClose = mrCode.GetLen();
for (SCROW i = mnIdx; i <= mnLastIdx; ++i, maBatchTopPos.IncRow())
{
@@ -212,7 +213,7 @@ public:
aCode2.AddString(rPool.intern(OUString(pStr)));
else
{
- if ( pTargetTok->GetType() == formula::svString )
+ if ( ( pTargetTok->GetType() == formula::svString ) && ( nNumNonOpenClose > 1 ) )
pTargetTok->SetString(rPool.intern(OUString(pStr)));
else
{
@@ -226,7 +227,7 @@ public:
// Value of NaN represents an empty cell.
if ( !pTargetTok )
aCode2.AddToken(ScEmptyCellToken(false, false));
- else if ( pTargetTok->GetType() != formula::svEmptyCell )
+ else if ( ( pTargetTok->GetType() != formula::svEmptyCell ) || ( nNumNonOpenClose == 1 ) )
{
ScEmptyCellToken* pEmptyTok = new ScEmptyCellToken(false, false);
aCode2.ReplaceToken(nTokIdx, pEmptyTok, formula::FormulaTokenArray::CODE_ONLY);
@@ -239,7 +240,7 @@ public:
aCode2.AddDouble(fVal);
else
{
- if ( pTargetTok->GetType() == formula::svDouble )
+ if ( ( pTargetTok->GetType() == formula::svDouble ) && ( nNumNonOpenClose > 1 ) )
pTargetTok->GetDoubleAsReference() = fVal;
else
{
@@ -291,7 +292,16 @@ public:
break;
default:
if ( !pTargetTok )
+ {
+ if ( p->GetType() == formula::svSep )
+ {
+ OpCode eOp = p->GetOpCode();
+ if ( eOp == ocOpen || eOp == ocClose )
+ --nNumNonOpenClose;
+ }
+
aCode2.AddToken(*p);
+ }
} // end of switch statement
} // end of formula token for loop