Date: prev next · Thread: first prev next last
2012 Archives by date, by thread · List index


Attached patch adds formula XOR to calc.
Possibly the function ought to be included in one or more arrays of functions that are or are 
not known in Excel, Lotus, Qpro.

[...] However, you attached a patch for DATEDIF instead of XOR ;-)

This time the patch is the one that covers XOR.

Winfried
From 45326af955b020cc861148c7c1c95449dab858f4 Mon Sep 17 00:00:00 2001
From: Winfried Donkers <osc@dci-electronics.nl>
Date: Wed, 6 Jun 2012 16:33:38 +0200
Subject: [PATCH] fdo#50488 added calc formula XOR as in ODFF1.2

Change-Id: I89c3267d479d5f034ad25ff879d1df8f90b84a55
---
 formula/inc/formula/compiler.hrc               |    3 +-
 formula/inc/formula/opcode.hxx                 |    1 +
 formula/source/core/api/FormulaCompiler.cxx    |   10 ++-
 formula/source/core/api/token.cxx              |    2 +-
 formula/source/core/resource/core_resource.src |    5 +
 sc/inc/helpids.h                               |    2 +-
 sc/qa/unit/ucalc.cxx                           |    1 +
 sc/source/core/inc/interpre.hxx                |    1 +
 sc/source/core/tool/interpr1.cxx               |  105 ++++++++++++++++++++++++
 sc/source/core/tool/interpr4.cxx               |    1 +
 sc/source/core/tool/parclass.cxx               |    2 +
 sc/source/filter/oox/formulabase.cxx           |    2 +-
 sc/source/ui/src/scfuncs.src                   |   24 ++++++
 sc/source/ui/vba/vbawsfunction.cxx             |    2 +-
 sc/util/hidother.src                           |    1 +
 15 files changed, 153 insertions(+), 9 deletions(-)

diff --git a/formula/inc/formula/compiler.hrc b/formula/inc/formula/compiler.hrc
index a2d4bb5..54ded84 100644
--- a/formula/inc/formula/compiler.hrc
+++ b/formula/inc/formula/compiler.hrc
@@ -89,7 +89,8 @@
 #define SC_OPCODE_INTERSECT          54
 #define SC_OPCODE_UNION              55
 #define SC_OPCODE_RANGE              56
-#define SC_OPCODE_STOP_BIN_OP        57
+#define SC_OPCODE_XOR                57
+#define SC_OPCODE_STOP_BIN_OP        58
 
 /* NOTE: binary and unary operators must be in sequence for compiler! */
 
diff --git a/formula/inc/formula/opcode.hxx b/formula/inc/formula/opcode.hxx
index a1543dd..16b12ec 100644
--- a/formula/inc/formula/opcode.hxx
+++ b/formula/inc/formula/opcode.hxx
@@ -89,6 +89,7 @@ enum OpCodeEnum
         ocGreaterEqual      = SC_OPCODE_GREATER_EQUAL,
         ocAnd               = SC_OPCODE_AND,
         ocOr                = SC_OPCODE_OR,
+        ocXor               = SC_OPCODE_XOR,
         ocIntersect         = SC_OPCODE_INTERSECT,
         ocUnion             = SC_OPCODE_UNION,
         ocRange             = SC_OPCODE_RANGE,
diff --git a/formula/source/core/api/FormulaCompiler.cxx 
b/formula/source/core/api/FormulaCompiler.cxx
index 9e82422..e2de107 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -76,6 +76,7 @@ short lcl_GetRetFormat( OpCode eOpCode )
         case ocGreaterEqual:
         case ocAnd:
         case ocOr:
+        case ocXor:
         case ocNot:
         case ocTrue:
         case ocFalse:
@@ -1128,6 +1129,7 @@ void FormulaCompiler::Factor()
                 || eOp == ocMacro
                 || eOp == ocAnd
                 || eOp == ocOr
+                || eOp == ocXor
                 || eOp == ocBad
                 || ( eOp >= ocInternalBegin && eOp <= ocInternalEnd )
                 || (bCompileForFAP && ((eOp == ocIf) || (eOp == ocChose)))
@@ -1440,7 +1442,7 @@ OpCode FormulaCompiler::Expression()
         return ocStop;      //! generate token instead?
     }
     NotLine();
-    while (pToken->GetOpCode() == ocAnd || pToken->GetOpCode() == ocOr)
+    while (pToken->GetOpCode() == ocAnd || pToken->GetOpCode() == ocOr || pToken->GetOpCode() == 
ocXor)
     {
         FormulaTokenRef p = pToken;
         pToken->SetByte( 2 );       // 2 parameters!
@@ -1617,7 +1619,7 @@ FormulaToken* FormulaCompiler::CreateStringFromToken( rtl::OUStringBuffer& 
rBuff
     bool bSpaces = false;
     FormulaToken* t = pTokenP;
     OpCode eOp = t->GetOpCode();
-    if( eOp >= ocAnd && eOp <= ocOr )
+    if( eOp >= ocAnd && eOp <= ocXor )
     {
         // AND, OR infix?
         if ( bAllowArrAdvance )
@@ -1822,8 +1824,8 @@ OpCode FormulaCompiler::NextToken()
     else
     {
         // Before an operator there must not be another operator, with the
-        // exception of AND and OR.
-        if ( eOp != ocAnd && eOp != ocOr &&
+        // exception of AND, OR and XOR.
+        if ( eOp != ocAnd && eOp != ocOr && eOp != ocXor &&
                 (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP )
                 && (eLastOp == ocOpen || eLastOp == ocSep ||
                     (SC_OPCODE_START_BIN_OP <= eLastOp && eLastOp < SC_OPCODE_STOP_UN_OP)))
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index f426a31..fac4cbd 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -90,7 +90,7 @@ bool FormulaToken::IsFunction() const
         || (SC_OPCODE_START_2_PAR <= eOp && eOp < SC_OPCODE_STOP_2_PAR)     // x parameters 
(cByte==0 in
                                                                             // FuncAutoPilot)
         || eOp == ocMacro || eOp == ocExternal                  // macros, AddIns
-        || eOp == ocAnd || eOp == ocOr                          // former binary, now x parameters
+        || eOp == ocAnd || eOp == ocOr || eOp == ocXor          // former binary, now x parameters
         || eOp == ocNot || eOp == ocNeg                         // unary but function
         || (eOp >= ocInternalBegin && eOp <= ocInternalEnd)     // internal
         ));
diff --git a/formula/source/core/resource/core_resource.src 
b/formula/source/core/resource/core_resource.src
index 1259231..b4ea345 100644
--- a/formula/source/core/resource/core_resource.src
+++ b/formula/source/core/resource/core_resource.src
@@ -56,6 +56,7 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF
     String SC_OPCODE_GREATER_EQUAL { Text = ">=" ; };
     String SC_OPCODE_AND { Text = "AND" ; };
     String SC_OPCODE_OR { Text = "OR" ; };
+    String SC_OPCODE_XOR { Text = "XOR" ; };
     String SC_OPCODE_INTERSECT { Text = "!" ; };
     String SC_OPCODE_UNION { Text = "~" ; };
     String SC_OPCODE_RANGE { Text = ":" ; };
@@ -731,6 +732,10 @@ Resource RID_STRLIST_FUNCTION_NAMES
     {
         Text [ en-US ] = "OR" ;
     };
+    String SC_OPCODE_XOR
+    {
+        Text [ en-US ] = "XOR" ;
+    };
     String SC_OPCODE_INTERSECT { Text = "!" ; };
     String SC_OPCODE_UNION { Text = "~" ; };
     String SC_OPCODE_RANGE { Text = ":" ; };
diff --git a/sc/inc/helpids.h b/sc/inc/helpids.h
index 7c5955c..e966bc3 100644
--- a/sc/inc/helpids.h
+++ b/sc/inc/helpids.h
@@ -88,7 +88,6 @@
 #define HID_SC_FORM_ARGS                                        "SC_HID_SC_FORM_ARGS"
 #define HID_SCPAGE_SORT_FIELDS                                  "SC_HID_SCPAGE_SORT_FIELDS"
 #define HID_SCPAGE_SORT_OPTIONS                                 "SC_HID_SCPAGE_SORT_OPTIONS"
-#define HID_SCPAGE_SORTKEY_FIELDS                               "SC_HID_SCPAGE_SORTKEY_FIELDS"
 #define HID_SCPAGE_SUBT_OPTIONS                                 "SC_HID_SCPAGE_SUBT_OPTIONS"
 #define HID_SCPAGE_SUBT_GROUP                                   "SC_HID_SCPAGE_SUBT_GROUP"
 #define HID_SCPAGE_PROTECTION                                   "SC_HID_SCPAGE_PROTECTION"
@@ -487,6 +486,7 @@
 #define HID_FUNC_WENN                                           "SC_HID_FUNC_WENN"
 #define HID_FUNC_ODER                                           "SC_HID_FUNC_ODER"
 #define HID_FUNC_UND                                            "SC_HID_FUNC_UND"
+#define HID_FUNC_XOR                                            "SC_HID_FUNC_XOR"
 
 #define HID_FUNC_ABS                                            "SC_HID_FUNC_ABS"
 #define HID_FUNC_POTENZ                                         "SC_HID_FUNC_POTENZ"
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index d37e3f1..1db6294 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -3276,6 +3276,7 @@ void Test::testFunctionLists()
         "NOT",
         "OR",
         "TRUE",
+        "XOR",
         0
     };
 
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index c92ad0c..de577ca 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -393,6 +393,7 @@ void ScLessEqual();
 void ScGreaterEqual();
 void ScAnd();
 void ScOr();
+void ScXor();
 void ScNot();
 void ScNeg();
 void ScPercentSign();
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 34675c9..400b73c 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -1385,6 +1385,111 @@ void ScInterpreter::ScOr()
 }
 
 
+void ScInterpreter::ScXor()
+{
+    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScXor" );
+
+    nFuncFmtType = NUMBERFORMAT_LOGICAL;
+    short nParamCount = GetByte();
+    if ( MustHaveParamCountMin( nParamCount, 1 ) )
+    {
+        bool bHaveValue = false;
+        short nRes = 0;
+        size_t nRefInList = 0;
+        while( nParamCount-- > 0)
+        {
+            if ( !nGlobalError )
+            {
+                switch ( GetStackType() )
+                {
+                    case svDouble :
+                        bHaveValue = true;
+                        if ( PopDouble() != 0.0 )
+                            nRes++;
+                    break;
+                    case svString :
+                        Pop();
+                        SetError( errNoValue );
+                    break;
+                    case svSingleRef :
+                    {
+                        ScAddress aAdr;
+                        PopSingleRef( aAdr );
+                        if ( !nGlobalError )
+                        {
+                            ScBaseCell* pCell = GetCell( aAdr );
+                            if ( HasCellValueData( pCell ) )
+                            {
+                                bHaveValue = true;
+                                if ( GetCellValue( aAdr, pCell ) != 0.0 )
+                                    nRes++;
+                            }
+                            // else: Xcl raises no error here
+                        }
+                    }
+                    break;
+                    case svDoubleRef:
+                    case svRefList:
+                    {
+                        ScRange aRange;
+                        PopDoubleRef( aRange, nParamCount, nRefInList);
+                        if ( !nGlobalError )
+                        {
+                            double fVal;
+                            sal_uInt16 nErr = 0;
+                            ScValueIterator aValIter( pDok, aRange );
+                            if ( aValIter.GetFirst( fVal, nErr ) )
+                            {
+                                bHaveValue = true;
+                                do
+                                {
+                                    if ( fVal != 0.0 )
+                                        nRes++;
+                                } while ( (nErr == 0) &&
+                                    aValIter.GetNext( fVal, nErr ) );
+                            }
+                            SetError( nErr );
+                        }
+                    }
+                    break;
+                    case svExternalSingleRef:
+                    case svExternalDoubleRef:
+                    case svMatrix:
+                    {
+                        bHaveValue = true;
+                        ScMatrixRef pMat = GetMatrix();
+                        if ( pMat )
+                        {
+                            bHaveValue = true;
+                            double fVal = pMat->Or();
+                            sal_uInt16 nErr = GetDoubleErrorValue( fVal );
+                            if ( nErr )
+                            {
+                                SetError( nErr );
+                            }
+                            else
+                                if (fVal != 0.0)
+                                    nRes++;
+                        }
+                        // else: GetMatrix did set errIllegalParameter
+                    }
+                    break;
+                    default:
+                        Pop();
+                        SetError( errIllegalParameter);
+                }
+            }
+            else
+                Pop();
+        }
+        if ( bHaveValue )
+            PushInt( nRes % 2 );
+        else
+            PushNoValue();
+    }
+}
+
+
 void ScInterpreter::ScNeg()
 {
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNeg" );
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 4a10201..aeadfe9 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -3810,6 +3810,7 @@ StackVar ScInterpreter::Interpret()
                 case ocGreaterEqual     : ScGreaterEqual();             break;
                 case ocAnd              : ScAnd();                      break;
                 case ocOr               : ScOr();                       break;
+                case ocXor              : ScXor();                      break;
                 case ocIntersect        : ScIntersect();                break;
                 case ocRange            : ScRangeFunc();                break;
                 case ocUnion            : ScUnionFunc();                break;
diff --git a/sc/source/core/tool/parclass.cxx b/sc/source/core/tool/parclass.cxx
index e8509a3..ee2cc4b 100644
--- a/sc/source/core/tool/parclass.cxx
+++ b/sc/source/core/tool/parclass.cxx
@@ -193,6 +193,7 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
     { ocVarP,            {{ Reference                                            }, true }},
     { ocVarPA,           {{ Reference                                            }, true }},
     { ocVLookup,         {{ Value, Reference, Value, Value                       }, false }},
+    { ocXor,             {{ Reference                                            }, true }},
     { ocZTest,           {{ Reference, Value, Value                              }, false }},
     // Excel doubts:
     // ocT: Excel says (and handles) Reference, error? This means no position
@@ -498,6 +499,7 @@ void ScParameterClassification::GenerateDocumentation()
                 {
                     case ocAnd:
                     case ocOr:
+                    case ocXor:
                         aToken.SetByte(1);  // (r1)AND(r2) --> AND( r1, ...)
                     break;
                     default:
diff --git a/sc/source/filter/oox/formulabase.cxx b/sc/source/filter/oox/formulabase.cxx
index b80dbfa..a5276eb 100644
--- a/sc/source/filter/oox/formulabase.cxx
+++ b/sc/source/filter/oox/formulabase.cxx
@@ -669,6 +669,7 @@ static const FunctionData saFuncTableBiff5[] =
     { 0,                        "DATESTRING",           352,    352,    1,  1,  V, { VR }, 
FUNCFLAG_IMPORTONLY },   // not supported in Calc, missing in OOXML spec
     { 0,                        "NUMBERSTRING",         353,    353,    2,  2,  V, { VR }, 
FUNCFLAG_IMPORTONLY },   // not supported in Calc, missing in OOXML spec
     { "ROMAN",                  "ROMAN",                354,    354,    1,  2,  V, { VR }, 0 },
+    { "XOR",                    "XOR",                  355,    355,    1,  MX, V, { RX }, 0 },
 
     // *** EuroTool add-in ***
 
@@ -762,7 +763,6 @@ static const FunctionData saFuncTableOdf[] =
     { "SKEWP",                  0,                      NOID,   NOID,   1,  MX, V, { RX }, 
FUNCFLAG_MACROCALLODF },
     { "UNICHAR",                0,                      NOID,   NOID,   1,  1,  V, { VR }, 
FUNCFLAG_MACROCALLODF },
     { "UNICODE",                0,                      NOID,   NOID,   1,  1,  V, { VR }, 
FUNCFLAG_MACROCALLODF },
-    { "XOR",                    0,                      NOID,   NOID,   1,  MX, V, { RX }, 
FUNCFLAG_MACROCALLODF }
 };
 
 // ----------------------------------------------------------------------------
diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src
index 53780de..60f8fca 100644
--- a/sc/source/ui/src/scfuncs.src
+++ b/sc/source/ui/src/scfuncs.src
@@ -2682,6 +2682,30 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
             Text [ en-US ] = "Logical value 1, logical value 2,... are 1 to 30 conditions to be 
tested and which return either TRUE or FALSE." ;
         };
     };
+     // -=*# Resource for function XOR (EXKLUSIV ODER) #*=-
+    Resource SC_OPCODE_XOR
+    {
+        String 1 // Description
+        {
+            Text [ en-US ] = "Returns TRUE if one argument is TRUE, but not both." ;
+        };
+        ExtraData =
+        {
+            0;
+            ID_FUNCTION_GRP_LOGIC;
+            U2S( HID_FUNC_XOR );
+            VAR_ARGS;  0;
+            0;
+        };
+        String 2 // Name of Parameter 1
+        {
+            Text [ en-US ] = "Logical value " ;
+        };
+        String 3 // Description of Parameter 1
+        {
+            Text [ en-US ] = "Logical value 1, logical value 2, ... are 1 to 30 conditions to be 
tested and which returns either TRUE or FALSE." ;
+        };
+    };
      // -=*# Resource for function UND #*=-
     Resource SC_OPCODE_AND
     {
diff --git a/sc/source/ui/vba/vbawsfunction.cxx b/sc/source/ui/vba/vbawsfunction.cxx
index 0692afb..3a236b3 100644
--- a/sc/source/ui/vba/vbawsfunction.cxx
+++ b/sc/source/ui/vba/vbawsfunction.cxx
@@ -201,7 +201,7 @@ ScVbaWSFunction::invoke(const rtl::OUString& FunctionName, const uno::Sequence<
     if( (eOpCode == ocIsEmpty) || (eOpCode == ocIsString) || (eOpCode == ocIsNonString) || 
(eOpCode == ocIsLogical) ||
         (eOpCode == ocIsRef) || (eOpCode == ocIsValue) || (eOpCode == ocIsFormula) || (eOpCode == 
ocIsNA) ||
         (eOpCode == ocIsErr) || (eOpCode == ocIsError) || (eOpCode == ocIsEven) || (eOpCode == 
ocIsOdd) ||
-        (eOpCode == ocAnd) || (eOpCode == ocOr) || (eOpCode == ocNot) || (eOpCode == ocTrue) || 
(eOpCode == ocFalse) )
+        (eOpCode == ocAnd) || (eOpCode == ocOr) || (eOpCode == ocXor) || (eOpCode == ocNot) || 
(eOpCode == ocTrue) || (eOpCode == ocFalse) )
     {
         if( aRet.has< AnySeqSeq >() )
         {
diff --git a/sc/util/hidother.src b/sc/util/hidother.src
index 85d36f9..6a56a81 100644
--- a/sc/util/hidother.src
+++ b/sc/util/hidother.src
@@ -160,6 +160,7 @@ hidspecial HID_FUNC_WAHR         { HelpID = HID_FUNC_WAHR; };
 hidspecial HID_FUNC_WENN         { HelpID = HID_FUNC_WENN; };
 hidspecial HID_FUNC_ODER         { HelpID = HID_FUNC_ODER; };
 hidspecial HID_FUNC_UND      { HelpID = HID_FUNC_UND; };
+hidspecial HID_FUNC_XOR      { HelpID = HID_FUNC_XOR; };
 hidspecial HID_FUNC_ABS      { HelpID = HID_FUNC_ABS; };
 hidspecial HID_FUNC_POTENZ       { HelpID = HID_FUNC_POTENZ; };
 hidspecial HID_FUNC_ANZAHLLEEREZELLEN        { HelpID = HID_FUNC_ANZAHLLEEREZELLEN; };
-- 
1.7.7


Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.