diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index c11fcea7efe5..76c4541c9d3f 100644 --- a/sc/inc/formulacell.hxx +++ b/sc/inc/formulacell.hxx @@ -265,7 +265,7 @@ public: bool MarkUsedExternalReferences(); // Returns true if the cell was interpreted as part of the formula group. // The parameters may limit which subset of the formula group should be interpreted, if possible. - bool Interpret(SCROW nStartOffset = -1, SCROW nEndOffset = -1); + SC_DLLPUBLIC bool Interpret(SCROW nStartOffset = -1, SCROW nEndOffset = -1); bool IsIterCell() const { return bIsIterCell; } sal_uInt16 GetSeenInIteration() const { return nSeenInIteration; } diff --git a/sc/qa/unit/subsequent_export_test2.cxx b/sc/qa/unit/subsequent_export_test2.cxx index 2cd025858d9a..73a2cf013be0 100644 --- a/sc/qa/unit/subsequent_export_test2.cxx +++ b/sc/qa/unit/subsequent_export_test2.cxx @@ -1227,7 +1227,7 @@ CPPUNIT_TEST_FIXTURE(ScExportTest2, testValidationCopyPaste) // Copy B1 from src doc to clip ScDocument aClipDoc(SCDOCMODE_CLIP); - ScRange aSrcRange(1, 0, 1); + ScRange aSrcRange(1, 0, 0); ScClipParam aClipParam(aSrcRange, false); ScMarkData aMark(pDoc->GetSheetLimits()); aMark.SetMarkArea(aSrcRange); @@ -1249,7 +1249,7 @@ CPPUNIT_TEST_FIXTURE(ScExportTest2, testValidationCopyPaste) xmlDocUniquePtr pDocXml = parseExport(u"xl/worksheets/sheet1.xml"_ustr); CPPUNIT_ASSERT(pDocXml); assertXPathContent(pDocXml, "/x:worksheet/x:dataValidations/x:dataValidation/x:formula1", - u"#REF!"); + u"Sheet1!$A$1:$A$3"); } CPPUNIT_TEST_FIXTURE(ScExportTest2, testTdf115159) diff --git a/sc/source/filter/excel/xecontent.cxx b/sc/source/filter/excel/xecontent.cxx index 0404740d1b0c..022a9b17721b 100644 --- a/sc/source/filter/excel/xecontent.cxx +++ b/sc/source/filter/excel/xecontent.cxx @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -1699,7 +1700,8 @@ XclExpDV::XclExpDV( const XclExpRoot& rRoot, sal_uInt32 nScHandle ) : XclExpRecord( EXC_ID_DV ), XclExpRoot( rRoot ), mnFlags( 0 ), - mnScHandle( nScHandle ) + mnScHandle( nScHandle ), + mbValidFormula( true ) { if( const ScValidationData* pValData = GetDoc().GetValidationEntry( mnScHandle ) ) { @@ -1762,6 +1764,20 @@ XclExpDV::XclExpDV( const XclExpRoot& rRoot, sal_uInt32 nScHandle ) : // formulas XclExpFormulaCompiler& rFmlaComp = GetFormulaCompiler(); + auto checkFormula = [&](std::unique_ptr pTokArr) + { + ScFormulaCell aCell(GetDoc(), pValData->GetSrcPos(), std::move(pTokArr)); + aCell.SetFreeFlying(true); + aCell.Interpret(); + sc::FormulaResultValue aResult = aCell.GetResult(); + if (aResult.meType == sc::FormulaResultValue::Error + && (aResult.mnError == FormulaError::NoValue + || aResult.mnError == FormulaError::NoRef)) + { + mbValidFormula = false; + } + }; + // first formula std::unique_ptr< ScTokenArray > xScTokArr = pValData->CreateFlatCopiedTokenArray( 0 ); if (xScTokArr) @@ -1839,19 +1855,24 @@ XclExpDV::XclExpDV( const XclExpRoot& rRoot, sal_uInt32 nScHandle ) : Formula compiler supports this by offering two different functions CreateDataValFormula() and CreateListValFormula(). */ mxTokArr1 = rFmlaComp.CreateFormula(EXC_FMLATYPE_LISTVAL, *xScTokArr); + checkFormula(std::move(xScTokArr)); } } else { // no list validation -> convert the formula mxTokArr1 = rFmlaComp.CreateFormula(EXC_FMLATYPE_DATAVAL, *xScTokArr); + checkFormula(std::move(xScTokArr)); } } // second formula xScTokArr = pValData->CreateFlatCopiedTokenArray( 1 ); if (xScTokArr) + { mxTokArr2 = rFmlaComp.CreateFormula(EXC_FMLATYPE_DATAVAL, *xScTokArr); + checkFormula(std::move(xScTokArr)); + } } else { @@ -1891,6 +1912,9 @@ void XclExpDV::WriteBody( XclExpStream& rStrm ) void XclExpDV::SaveXml( XclExpXmlStream& rStrm ) { + if (!mbValidFormula) + return; + sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream(); rWorksheet->startElement( XML_dataValidation, XML_allowBlank, ToPsz( ::get_flag( mnFlags, EXC_DV_IGNOREBLANK ) ), @@ -1964,7 +1988,8 @@ void XclExpDV::SaveXml( XclExpXmlStream& rStrm ) XclExpDval::XclExpDval( const XclExpRoot& rRoot ) : XclExpRecord( EXC_ID_DVAL, 18 ), - XclExpRoot( rRoot ) + XclExpRoot( rRoot ), + mnDVCount( 0 ) { } @@ -2003,12 +2028,12 @@ void XclExpDval::Save( XclExpStream& rStrm ) void XclExpDval::SaveXml( XclExpXmlStream& rStrm ) { - if( maDVList.IsEmpty() ) + if( !mnDVCount) return; sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream(); rWorksheet->startElement( XML_dataValidations, - XML_count, OString::number(maDVList.GetSize()) + XML_count, OString::number(mnDVCount) // OOXTODO: XML_disablePrompts, // OOXTODO: XML_xWindow, // OOXTODO: XML_yWindow @@ -2053,6 +2078,8 @@ XclExpDV& XclExpDval::SearchOrCreateDv( sal_uInt32 nScHandle ) // create new DV record mxLastFoundDV = new XclExpDV( *this, nScHandle ); + if (mxLastFoundDV->ContainsValidFormula()) + mnDVCount++; maDVList.InsertRecord( mxLastFoundDV, nCurrPos ); return *mxLastFoundDV; } diff --git a/sc/source/filter/inc/xecontent.hxx b/sc/source/filter/inc/xecontent.hxx index 07318a037ca4..3695dff7ffd2 100644 --- a/sc/source/filter/inc/xecontent.hxx +++ b/sc/source/filter/inc/xecontent.hxx @@ -328,6 +328,8 @@ public: virtual void SaveXml( XclExpXmlStream& rStrm ) override; + bool ContainsValidFormula() const { return mbValidFormula; } + private: /** Writes the body of the DV record. */ virtual void WriteBody( XclExpStream& rStrm ) override; @@ -347,6 +349,7 @@ private: OUString msFormula2; /// OOXML Formula for second condition. sal_uInt32 mnFlags; /// Miscellaneous flags. sal_uInt32 mnScHandle; /// The core handle for quick list search. + bool mbValidFormula; /// Formula valid for export }; /** This class contains the DV record list following the DVAL record. */ @@ -376,6 +379,7 @@ private: XclExpDVList maDVList; /// List of DV records XclExpDVRef mxLastFoundDV; /// For search optimization. + sal_uInt16 mnDVCount; /// Count of Valid DV }; // Web Queries ================================================================