>> 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 <o...@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
_______________________________________________ LibreOffice mailing list LibreOffice@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice