summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--formula/source/core/api/FormulaCompiler.cxx64
-rw-r--r--sc/qa/unit/ucalc.hxx2
-rw-r--r--sc/qa/unit/ucalc_formula.cxx36
-rw-r--r--sc/source/core/tool/compiler.cxx36
4 files changed, 137 insertions, 1 deletions
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index 964c38cdb69d..8e79e5ca68dd 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -1873,6 +1873,11 @@ void FormulaCompiler::UnaryLine()
FormulaTokenRef p = mpToken;
NextToken();
UnaryLine();
+ if (mbComputeII && IsIIOpCode(p->GetOpCode()))
+ {
+ FormulaToken** pArg = pCode - 1;
+ HandleIIOpCode(p->GetOpCode(), p->GetInForceArray(), &pArg, 1);
+ }
PutCode( p );
}
else
@@ -1884,6 +1889,11 @@ void FormulaCompiler::PostOpLine()
UnaryLine();
while ( mpToken->GetOpCode() == ocPercentSign )
{ // this operator _follows_ its operand
+ if (mbComputeII && IsIIOpCode(mpToken->GetOpCode()))
+ {
+ FormulaToken** pArg = pCode - 1;
+ HandleIIOpCode(mpToken->GetOpCode(), mpToken->GetInForceArray(), &pArg, 1);
+ }
PutCode( mpToken );
NextToken();
}
@@ -1895,8 +1905,17 @@ void FormulaCompiler::PowLine()
while (mpToken->GetOpCode() == ocPow)
{
FormulaTokenRef p = mpToken;
+ bool bDoIICompute = mbComputeII && IsIIOpCode(p->GetOpCode());
+ FormulaToken** pArgArray[2];
+ if (bDoIICompute)
+ pArgArray[0] = pCode - 1; // Add first argument
NextToken();
PostOpLine();
+ if (bDoIICompute)
+ {
+ pArgArray[1] = pCode - 1; // Add second argument
+ HandleIIOpCode(p->GetOpCode(), p->GetInForceArray(), pArgArray, 2);
+ }
PutCode(p);
}
}
@@ -1907,8 +1926,17 @@ void FormulaCompiler::MulDivLine()
while (mpToken->GetOpCode() == ocMul || mpToken->GetOpCode() == ocDiv)
{
FormulaTokenRef p = mpToken;
+ bool bDoIICompute = mbComputeII && IsIIOpCode(p->GetOpCode());
+ FormulaToken** pArgArray[2];
+ if (bDoIICompute)
+ pArgArray[0] = pCode - 1; // Add first argument
NextToken();
PowLine();
+ if (bDoIICompute)
+ {
+ pArgArray[1] = pCode - 1; // Add second argument
+ HandleIIOpCode(p->GetOpCode(), p->GetInForceArray(), pArgArray, 2);
+ }
PutCode(p);
}
}
@@ -1919,8 +1947,17 @@ void FormulaCompiler::AddSubLine()
while (mpToken->GetOpCode() == ocAdd || mpToken->GetOpCode() == ocSub)
{
FormulaTokenRef p = mpToken;
+ bool bDoIICompute = mbComputeII && IsIIOpCode(p->GetOpCode());
+ FormulaToken** pArgArray[2];
+ if (bDoIICompute)
+ pArgArray[0] = pCode - 1; // Add first argument
NextToken();
MulDivLine();
+ if (bDoIICompute)
+ {
+ pArgArray[1] = pCode - 1; // Add second argument
+ HandleIIOpCode(p->GetOpCode(), p->GetInForceArray(), pArgArray, 2);
+ }
PutCode(p);
}
}
@@ -1931,8 +1968,17 @@ void FormulaCompiler::ConcatLine()
while (mpToken->GetOpCode() == ocAmpersand)
{
FormulaTokenRef p = mpToken;
+ bool bDoIICompute = mbComputeII && IsIIOpCode(p->GetOpCode());
+ FormulaToken** pArgArray[2];
+ if (bDoIICompute)
+ pArgArray[0] = pCode - 1; // Add first argument
NextToken();
AddSubLine();
+ if (bDoIICompute)
+ {
+ pArgArray[1] = pCode - 1; // Add second argument
+ HandleIIOpCode(p->GetOpCode(), p->GetInForceArray(), pArgArray, 2);
+ }
PutCode(p);
}
}
@@ -1943,8 +1989,17 @@ void FormulaCompiler::CompareLine()
while (mpToken->GetOpCode() >= ocEqual && mpToken->GetOpCode() <= ocGreaterEqual)
{
FormulaTokenRef p = mpToken;
+ bool bDoIICompute = mbComputeII && IsIIOpCode(p->GetOpCode());
+ FormulaToken** pArgArray[2];
+ if (bDoIICompute)
+ pArgArray[0] = pCode - 1; // Add first argument
NextToken();
ConcatLine();
+ if (bDoIICompute)
+ {
+ pArgArray[1] = pCode - 1; // Add second argument
+ HandleIIOpCode(p->GetOpCode(), p->GetInForceArray(), pArgArray, 2);
+ }
PutCode(p);
}
}
@@ -1963,8 +2018,17 @@ OpCode FormulaCompiler::Expression()
{
FormulaTokenRef p = mpToken;
mpToken->SetByte( 2 ); // 2 parameters!
+ bool bDoIICompute = mbComputeII && IsIIOpCode(p->GetOpCode());
+ FormulaToken** pArgArray[2];
+ if (bDoIICompute)
+ pArgArray[0] = pCode - 1; // Add first argument
NextToken();
CompareLine();
+ if (bDoIICompute)
+ {
+ pArgArray[1] = pCode - 1; // Add second argument
+ HandleIIOpCode(p->GetOpCode(), p->GetInForceArray(), pArgArray, 2);
+ }
PutCode(p);
}
return mpToken->GetOpCode();
diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx
index e2c778a01dda..1d46b3d50800 100644
--- a/sc/qa/unit/ucalc.hxx
+++ b/sc/qa/unit/ucalc.hxx
@@ -148,6 +148,7 @@ public:
void testFormulaCompilerImplicitIntersection1ParamNoChange();
void testFormulaCompilerImplicitIntersection1ParamWithChange();
void testFormulaCompilerImplicitIntersection1NoGroup();
+ void testFormulaCompilerImplicitIntersectionOperators();
void testFormulaRefUpdate();
void testFormulaRefUpdateRange();
void testFormulaRefUpdateSheets();
@@ -579,6 +580,7 @@ public:
CPPUNIT_TEST(testFormulaCompilerImplicitIntersection1ParamNoChange);
CPPUNIT_TEST(testFormulaCompilerImplicitIntersection1ParamWithChange);
CPPUNIT_TEST(testFormulaCompilerImplicitIntersection1NoGroup);
+ CPPUNIT_TEST(testFormulaCompilerImplicitIntersectionOperators);
CPPUNIT_TEST(testFormulaRefUpdate);
CPPUNIT_TEST(testFormulaRefUpdateRange);
CPPUNIT_TEST(testFormulaRefUpdateSheets);
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index a3b0125c9beb..3b69bce3049f 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -1426,6 +1426,42 @@ void Test::testFormulaCompilerImplicitIntersection1NoGroup()
m_pDoc->DeleteTab(0);
}
+void Test::testFormulaCompilerImplicitIntersectionOperators()
+{
+ struct TestCase
+ {
+ OUString formula[3];
+ double result[3];
+ };
+
+ m_pDoc->InsertTab(0, "Test");
+ sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on.
+
+ m_pDoc->SetValue(2, 0, 0, 5); // C1
+ m_pDoc->SetValue(2, 1, 0, 4); // C2
+ m_pDoc->SetValue(2, 2, 0, 3); // C3
+ m_pDoc->SetValue(3, 0, 0, 1); // D1
+ m_pDoc->SetValue(3, 1, 0, 2); // D2
+ m_pDoc->SetValue(3, 2, 0, 3); // D3
+
+ TestCase tests[] =
+ {
+ { OUString("=C:C/D:D"), OUString("=C:C/D:D"), OUString("=C:C/D:D"), 5, 2, 1 },
+ { OUString("=C1:C2/D1:D2"), OUString("=C2:C3/D2:D3"), OUString("=C3:C4/D3:D4"), 5, 2, 1 }
+ };
+
+ for (const TestCase& test : tests)
+ {
+ for(int i = 0; i < 2; ++i )
+ m_pDoc->SetString(ScAddress(4,i,0), test.formula[i]); // E1-3
+ for(int i = 0; i < 2; ++i )
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(OUString( test.formula[i] + " result incorrect in row " + OUString::number(i+1)).toUtf8().getStr(),
+ test.result[i], m_pDoc->GetValue(ScAddress(4,i,0)));
+ }
+
+ m_pDoc->DeleteTab(0);
+}
+
void Test::testFormulaRefUpdate()
{
m_pDoc->InsertTab(0, "Formula");
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 5a9de437077e..ab5920a61aed 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -5800,8 +5800,14 @@ formula::ParamClass ScCompiler::GetForceArrayParameter( const formula::FormulaTo
bool ScCompiler::IsIIOpCode(OpCode nOpCode) const
{
- if (nOpCode == ocSumIf || nOpCode == ocAverageIf || (nOpCode >= SC_OPCODE_START_1_PAR && nOpCode < SC_OPCODE_STOP_1_PAR))
+ if (nOpCode == ocSumIf || nOpCode == ocAverageIf || (nOpCode >= SC_OPCODE_START_1_PAR && nOpCode < SC_OPCODE_STOP_1_PAR)
+ || (nOpCode >= SC_OPCODE_START_BIN_OP && nOpCode < SC_OPCODE_STOP_UN_OP
+ && nOpCode != ocIntersect && nOpCode != ocUnion && nOpCode != ocRange
+ && nOpCode != ocAnd && nOpCode != ocOr && nOpCode != ocXor )
+ || nOpCode == ocPercentSign)
+ {
return true;
+ }
return false;
}
@@ -5862,6 +5868,34 @@ void ScCompiler::HandleIIOpCode(OpCode nOpCode, formula::ParamClass eClass, Form
ReplaceDoubleRefII(pppToken[0]);
}
+ else if (nOpCode >= SC_OPCODE_START_BIN_OP && nOpCode < SC_OPCODE_STOP_BIN_OP)
+ {
+ assert(nOpCode != ocIntersect && nOpCode != ocUnion && nOpCode != ocRange);
+
+ if (nNumParams != 2)
+ return;
+
+ if (eClass == formula::ForceArray || mbMatrixFlag)
+ return;
+
+ // Convert only if the other parameter is not a matrix nor an array (which would force the result to be a matrix).
+ if ((*pppToken[0])->GetType() == svDoubleRef && (*pppToken[1])->GetType() != svMatrix && (*pppToken[1])->IsInForceArray())
+ ReplaceDoubleRefII(pppToken[0]);
+ if ((*pppToken[1])->GetType() == svDoubleRef && (*pppToken[0])->GetType() != svMatrix && (*pppToken[0])->IsInForceArray())
+ ReplaceDoubleRefII(pppToken[1]);
+ }
+ else if ((nOpCode >= SC_OPCODE_START_UN_OP && nOpCode < SC_OPCODE_STOP_UN_OP)
+ || nOpCode == ocPercentSign)
+ {
+ if (nNumParams != 1)
+ return;
+
+ if (eClass == formula::ForceArray || mbMatrixFlag)
+ return;
+
+ if ((*pppToken[0])->GetType() == svDoubleRef)
+ ReplaceDoubleRefII(pppToken[0]);
+ }
}
void ScCompiler::ReplaceDoubleRefII(FormulaToken** ppDoubleRefTok)