tdf#170565 save empty SUM/MAX/MIN functions with parameters to XLSX
Excel won't allow them with no parameters. In Calc: - SUM() is 0, - MAX()/MIN() gives Err:511. Save them to XLSX as SUM(0), MAX(#VALUE!) and MIN(#VALUE!). Change-Id: I0f0d05290b67684df294611bd0612090abf1a672 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198543 Reviewed-by: Aron Budea <aron.budea@collabora.com> Tested-by: Jenkins
This commit is contained in:
@@ -937,6 +937,11 @@ FormulaToken* FormulaTokenArray::AddStringXML( const OUString& rStr )
|
||||
return Add( new FormulaStringOpToken( ocStringXML, svl::SharedString( rStr ) ) ); // string not interned
|
||||
}
|
||||
|
||||
FormulaToken* FormulaTokenArray::AddError( FormulaError nErr )
|
||||
{
|
||||
return Add( new FormulaErrorToken( nErr ) );
|
||||
}
|
||||
|
||||
FormulaToken* FormulaTokenArray::AddStringName( const OUString& rStr )
|
||||
{
|
||||
return Add( new FormulaStringOpToken( ocStringName, svl::SharedString( rStr ) ) ); // string not interned
|
||||
@@ -969,7 +974,6 @@ void FormulaTokenArray::AddRecalcMode( ScRecalcMode nBits )
|
||||
SetCombinedBitsRecalcMode( nBits );
|
||||
}
|
||||
|
||||
|
||||
bool FormulaTokenArray::HasMatrixDoubleRefOps() const
|
||||
{
|
||||
if ( !pRPN || !nRPN )
|
||||
@@ -1074,6 +1078,9 @@ inline bool MissingConventionOOXML::isRewriteNeeded( OpCode eOp )
|
||||
switch (eOp)
|
||||
{
|
||||
case ocIf:
|
||||
case ocMax:
|
||||
case ocMin:
|
||||
case ocSum:
|
||||
|
||||
case ocExternal:
|
||||
case ocEuroConvert:
|
||||
@@ -1112,8 +1119,9 @@ class FormulaMissingContext
|
||||
public:
|
||||
const FormulaToken* mpFunc;
|
||||
int mnCurArg;
|
||||
bool mbEmpty; // no parameters: ()
|
||||
|
||||
void Clear() { mpFunc = nullptr; mnCurArg = 0; }
|
||||
void Clear() { mpFunc = nullptr; mnCurArg = 0; mbEmpty = false; }
|
||||
inline bool AddDefaultArg( FormulaTokenArray* pNewArr, int nArg, double f ) const;
|
||||
bool AddMissingExternal( FormulaTokenArray* pNewArr ) const;
|
||||
bool AddMissing( FormulaTokenArray *pNewArr, const MissingConvention & rConv ) const;
|
||||
@@ -1195,6 +1203,24 @@ void FormulaMissingContext::AddMoreArgs( FormulaTokenArray *pNewArr, const Missi
|
||||
}
|
||||
break;
|
||||
|
||||
case ocMax:
|
||||
case ocMin:
|
||||
if ( mnCurArg == 0 && mbEmpty )
|
||||
{
|
||||
// Excel needs at least one parameter in MAX/MIN functions
|
||||
// In Calc empty MAX/MIN are Err:511
|
||||
pNewArr->AddError( FormulaError::NoValue );
|
||||
}
|
||||
break;
|
||||
|
||||
case ocSum:
|
||||
if ( mnCurArg == 0 && mbEmpty )
|
||||
{
|
||||
// Excel needs at least one parameter in SUM function
|
||||
pNewArr->AddDouble( 0.0 ); // SUM() = 0
|
||||
}
|
||||
break;
|
||||
|
||||
case ocEuroConvert:
|
||||
if ( mnCurArg == 2 )
|
||||
{
|
||||
@@ -1477,6 +1503,11 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissing( const MissingConvention &
|
||||
++nFn; // all following operations on _that_ function
|
||||
pCtx[ nFn ].mpFunc = aIter.PeekPrevNoSpaces();
|
||||
pCtx[ nFn ].mnCurArg = 0;
|
||||
FormulaToken* pNext = aIter.PeekNextNoSpaces();
|
||||
if (pNext != nullptr && pNext->GetOpCode() == ocClose)
|
||||
pCtx[ nFn ].mbEmpty = true;
|
||||
else
|
||||
pCtx[ nFn ].mbEmpty = false;
|
||||
if (rConv.isPODF() && pCtx[ nFn ].mpFunc && pCtx[ nFn ].mpFunc->GetOpCode() == ocAddress)
|
||||
pOcas[ nOcas++ ] = nFn; // entering ADDRESS() if PODF
|
||||
else if ((rConv.isODFF() || rConv.isOOXML()) && pCtx[ nFn ].mpFunc)
|
||||
|
||||
@@ -488,6 +488,7 @@ public:
|
||||
FormulaToken* AddBad( const OUString& rStr ); /// ocBad with OUString
|
||||
FormulaToken* AddStringXML( const OUString& rStr ); /// ocStringXML with OUString, temporary during import
|
||||
FormulaToken* AddStringName( const OUString& rStr ); /// ocStringName with OUString - Lambda functions
|
||||
FormulaToken* AddError( FormulaError nErr );
|
||||
|
||||
virtual FormulaToken* MergeArray( );
|
||||
|
||||
|
||||
Binary file not shown.
@@ -2476,6 +2476,30 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf165733_leap_day_BCE)
|
||||
}
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf170565_empty_functions)
|
||||
{
|
||||
createScDoc("ods/tdf170565_empty_functions.ods");
|
||||
|
||||
save(TestFilter::XLSX);
|
||||
xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr);
|
||||
CPPUNIT_ASSERT(pSheet);
|
||||
|
||||
// Without the fix these would've been exported as SUM(), MIN(), MAX(), which aren't valid in Excel
|
||||
assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[1]/x:f", u"SUM(0)");
|
||||
assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[2]/x:c[1]/x:f", u"MIN(#VALUE!)");
|
||||
assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[3]/x:c[1]/x:f", u"MAX(#VALUE!)");
|
||||
// Further checks to ensure there are no regressions
|
||||
assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[2]/x:f", u"SUM(,)");
|
||||
assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[3]/x:f", u"SUM(100)");
|
||||
assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[4]/x:f", u"SUM(C1:C3)");
|
||||
assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[2]/x:c[2]/x:f", u"MIN(,)");
|
||||
assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[2]/x:c[3]/x:f", u"MIN(200)");
|
||||
assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[2]/x:c[4]/x:f", u"MIN(C1:C3)");
|
||||
assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[3]/x:c[2]/x:f", u"MAX(,)");
|
||||
assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[3]/x:c[3]/x:f", u"MAX(-100)");
|
||||
assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[3]/x:c[4]/x:f", u"MAX(C1:C3)");
|
||||
}
|
||||
|
||||
CPPUNIT_PLUGIN_IMPLEMENT();
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
Reference in New Issue
Block a user