XLSX: Skip export of Data Validations with invalid formulas

bug-document: forum-mso-en4-83006.xls
Change-Id: I92f0f4c374bf86ef5a8b5897777f377282352a0e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/201130
Reviewed-by: Michael Stahl <michael.stahl@collabora.com>
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/204180
Tested-by: Jenkins
This commit is contained in:
Karthik Godha
2026-04-24 10:21:14 +02:00
committed by Xisco Fauli
parent e9f276ebd8
commit a70e3dbfc6
4 changed files with 38 additions and 7 deletions
+1 -1
View File
@@ -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; }
+2 -2
View File
@@ -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)
+31 -4
View File
@@ -37,6 +37,7 @@
#include <editeng/flditem.hxx>
#include <document.hxx>
#include <docsh.hxx>
#include <formulacell.hxx>
#include <validat.hxx>
#include <unonames.hxx>
#include <convuno.hxx>
@@ -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<ScTokenArray> 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;
}
+4
View File
@@ -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 ================================================================