tdf#104310: Accept also x14-style dataValidations
See https://msdn.microsoft.com/en-us/library/dd921584 Change-Id: I66c9474cbf83cea10ab0e7c2b44592673c8b683f Reviewed-on: https://gerrit.libreoffice.org/31456 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Markus Mohrhard <markus.mohrhard@googlemail.com>
This commit is contained in:
committed by
Andras Timar
parent
83b7e1f424
commit
0afbe8d5ca
@@ -7,66 +7,10 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <sal/config.h>
|
||||
#include <unotest/filters-test.hxx>
|
||||
#include <test/bootstrapfixture.hxx>
|
||||
#include <rtl/strbuf.hxx>
|
||||
#include <osl/file.hxx>
|
||||
|
||||
#include <sfx2/app.hxx>
|
||||
#include <sfx2/docfilt.hxx>
|
||||
#include <sfx2/docfile.hxx>
|
||||
#include <sfx2/sfxmodelfactory.hxx>
|
||||
#include <svl/stritem.hxx>
|
||||
#include <svx/svdograf.hxx>
|
||||
|
||||
#include "drwlayer.hxx"
|
||||
#include <svx/svdpage.hxx>
|
||||
#include <svx/svdoole2.hxx>
|
||||
#include <editeng/wghtitem.hxx>
|
||||
#include <editeng/postitem.hxx>
|
||||
#include <editeng/udlnitem.hxx>
|
||||
#include <editeng/editobj.hxx>
|
||||
#include <editeng/borderline.hxx>
|
||||
#include <editeng/flditem.hxx>
|
||||
#include <dbdata.hxx>
|
||||
#include "validat.hxx"
|
||||
#include "formulacell.hxx"
|
||||
#include "userdat.hxx"
|
||||
#include "dpobject.hxx"
|
||||
#include "dpsave.hxx"
|
||||
#include "stlsheet.hxx"
|
||||
#include "docfunc.hxx"
|
||||
#include "markdata.hxx"
|
||||
#include "colorscale.hxx"
|
||||
#include "olinetab.hxx"
|
||||
#include "patattr.hxx"
|
||||
#include "scitems.hxx"
|
||||
#include "docsh.hxx"
|
||||
#include "editutil.hxx"
|
||||
#include "cellvalue.hxx"
|
||||
#include "attrib.hxx"
|
||||
#include "dpshttab.hxx"
|
||||
#include "tabvwsh.hxx"
|
||||
#include <scopetools.hxx>
|
||||
#include <columnspanset.hxx>
|
||||
#include <tokenstringcontext.hxx>
|
||||
|
||||
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
|
||||
#include <com/sun/star/drawing/XControlShape.hpp>
|
||||
#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
|
||||
#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
|
||||
#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
|
||||
#include <com/sun/star/sheet/GeneralFunction.hpp>
|
||||
#include <com/sun/star/container/XIndexAccess.hpp>
|
||||
#include <com/sun/star/frame/XModel.hpp>
|
||||
#include <com/sun/star/text/textfield/Type.hpp>
|
||||
#include <com/sun/star/chart2/XChartDocument.hpp>
|
||||
#include <com/sun/star/chart2/data/XDataReceiver.hpp>
|
||||
#include <com/sun/star/frame/Desktop.hpp>
|
||||
|
||||
#include "helper/qahelper.hxx"
|
||||
#include "helper/shared_test_impl.hxx"
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
using namespace ::com::sun::star::uno;
|
||||
@@ -91,6 +35,7 @@ public:
|
||||
void testTdf88821_2();
|
||||
void testTdf103960();
|
||||
void testRhbz1390776();
|
||||
void testTdf104310();
|
||||
|
||||
CPPUNIT_TEST_SUITE(ScFiltersTest);
|
||||
CPPUNIT_TEST(testTdf64229);
|
||||
@@ -104,6 +49,7 @@ public:
|
||||
CPPUNIT_TEST(testTdf88821_2);
|
||||
CPPUNIT_TEST(testTdf103960);
|
||||
CPPUNIT_TEST(testRhbz1390776);
|
||||
CPPUNIT_TEST(testTdf104310);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
private:
|
||||
uno::Reference<uno::XInterface> m_xCalcComponent;
|
||||
@@ -294,6 +240,24 @@ void ScFiltersTest::testRhbz1390776()
|
||||
xDocSh->DoClose();
|
||||
}
|
||||
|
||||
void ScFiltersTest::testTdf104310()
|
||||
{
|
||||
ScDocShellRef xDocSh = loadDoc("tdf104310.", FORMAT_XLSX);
|
||||
ScDocument& rDoc = xDocSh->GetDocument();
|
||||
|
||||
const ScValidationData* pData = rDoc.GetValidationEntry(1);
|
||||
CPPUNIT_ASSERT(pData);
|
||||
|
||||
// Make sure the list is correct.
|
||||
std::vector<ScTypedStrData> aList;
|
||||
pData->FillSelectionList(aList, ScAddress(0, 1, 0));
|
||||
CPPUNIT_ASSERT_EQUAL(size_t(5), aList.size());
|
||||
for (size_t i = 0; i < 5; ++i)
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(double(i+1), aList[i].GetValue(), 1e-8);
|
||||
|
||||
xDocSh->DoClose();
|
||||
}
|
||||
|
||||
ScFiltersTest::ScFiltersTest()
|
||||
: ScBootstrapFixture( "/sc/qa/unit/data" )
|
||||
{
|
||||
|
BIN
sc/qa/unit/data/xlsx/tdf104310.xlsx
Normal file
BIN
sc/qa/unit/data/xlsx/tdf104310.xlsx
Normal file
Binary file not shown.
@@ -25,7 +25,25 @@
|
||||
namespace oox {
|
||||
namespace xls {
|
||||
|
||||
class DataValidationsContext : public WorksheetContextBase
|
||||
class DataValidationsContext_Base {
|
||||
public:
|
||||
DataValidationsContext_Base() {}
|
||||
void SetSqref(const OUString& rChars) { mSqref = rChars; }
|
||||
void SetFormula1(const OUString& rChars) { mFormula1 = rChars; }
|
||||
void SetFormula2(const OUString& rChars) { mFormula2 = rChars; }
|
||||
void SetValidation(::oox::xls::WorksheetHelper& rTarget);
|
||||
/** Imports the dataValidation element containing data validation settings. */
|
||||
void importDataValidation(const AttributeList& rAttribs);
|
||||
/** Imports the DATAVALIDATION record containing data validation settings. */
|
||||
static void importDataValidation(SequenceInputStream& rStrm, ::oox::xls::WorksheetHelper& rTarget);
|
||||
private:
|
||||
::std::unique_ptr< ValidationModel > mxValModel;
|
||||
OUString mSqref;
|
||||
OUString mFormula1;
|
||||
OUString mFormula2;
|
||||
};
|
||||
|
||||
class DataValidationsContext : public WorksheetContextBase, private DataValidationsContext_Base
|
||||
{
|
||||
public:
|
||||
explicit DataValidationsContext( WorksheetFragmentBase& rFragment );
|
||||
@@ -36,15 +54,19 @@ protected:
|
||||
virtual void onEndElement() override;
|
||||
|
||||
virtual ::oox::core::ContextHandlerRef onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) override;
|
||||
};
|
||||
|
||||
private:
|
||||
/** Imports the dataValidation element containing data validation settings. */
|
||||
void importDataValidation( const AttributeList& rAttribs );
|
||||
/** Imports the DATAVALIDATION record containing data validation settings. */
|
||||
void importDataValidation( SequenceInputStream& rStrm );
|
||||
class ExtDataValidationsContext : public WorksheetContextBase, private DataValidationsContext_Base
|
||||
{
|
||||
public:
|
||||
explicit ExtDataValidationsContext( WorksheetContextBase& rFragment );
|
||||
|
||||
protected:
|
||||
virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) override;
|
||||
virtual void onCharacters( const OUString& rChars ) override;
|
||||
virtual void onEndElement() override;
|
||||
private:
|
||||
::std::unique_ptr< ValidationModel > mxValModel;
|
||||
sal_Int32 mCurrFormula;
|
||||
};
|
||||
|
||||
class WorksheetFragment : public WorksheetFragmentBase
|
||||
|
@@ -229,9 +229,11 @@ ExtGlobalContext::ExtGlobalContext( WorksheetContextBase& rFragment ):
|
||||
|
||||
ContextHandlerRef ExtGlobalContext::onCreateContext( sal_Int32 nElement, const AttributeList& /*rAttribs*/ )
|
||||
{
|
||||
if (nElement == XLS14_TOKEN(conditionalFormatting))
|
||||
return new ExtConditionalFormattingContext(*this);
|
||||
|
||||
switch (nElement)
|
||||
{
|
||||
case XLS14_TOKEN(conditionalFormatting): return new ExtConditionalFormattingContext(*this);
|
||||
case XLS14_TOKEN(dataValidations): return new ExtDataValidationsContext(*this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@@ -75,6 +75,84 @@ const sal_uInt16 BIFF12_OLEOBJECT_AUTOLOAD = 0x0002;
|
||||
|
||||
} // namespace
|
||||
|
||||
void DataValidationsContext_Base::SetValidation(::oox::xls::WorksheetHelper& rTarget)
|
||||
{
|
||||
if (!mxValModel.get())
|
||||
return;
|
||||
|
||||
rTarget.getAddressConverter().convertToCellRangeList(mxValModel->maRanges, mSqref, rTarget.getSheetIndex(), true);
|
||||
mxValModel->msRef = mSqref;
|
||||
|
||||
mxValModel->maTokens1 = rTarget.getFormulaParser().importFormula(mxValModel->maRanges.getBaseAddress(), mFormula1);
|
||||
// process string list of a list validation (convert to list of string tokens)
|
||||
if (mxValModel->mnType == XML_list)
|
||||
rTarget.getFormulaParser().convertStringToStringList(mxValModel->maTokens1, ',', true);
|
||||
|
||||
mxValModel->maTokens2 = rTarget.getFormulaParser().importFormula(mxValModel->maRanges.getBaseAddress(), mFormula2);
|
||||
|
||||
rTarget.setValidation(*mxValModel);
|
||||
mxValModel.reset();
|
||||
}
|
||||
|
||||
void DataValidationsContext_Base::importDataValidation(const AttributeList& rAttribs)
|
||||
{
|
||||
mxValModel.reset(new ValidationModel);
|
||||
OUString aSqref = rAttribs.getString(XML_sqref, OUString());
|
||||
// Only set mSqref if it is set in attributes, to avoid owerwriting already set using SetSqref
|
||||
if (!aSqref.isEmpty())
|
||||
{
|
||||
mSqref = aSqref;
|
||||
}
|
||||
mxValModel->maInputTitle = rAttribs.getXString(XML_promptTitle, OUString());
|
||||
mxValModel->maInputMessage = rAttribs.getXString(XML_prompt, OUString());
|
||||
mxValModel->maErrorTitle = rAttribs.getXString(XML_errorTitle, OUString());
|
||||
mxValModel->maErrorMessage = rAttribs.getXString(XML_error, OUString());
|
||||
mxValModel->mnType = rAttribs.getToken(XML_type, XML_none);
|
||||
mxValModel->mnOperator = rAttribs.getToken(XML_operator, XML_between);
|
||||
mxValModel->mnErrorStyle = rAttribs.getToken(XML_errorStyle, XML_stop);
|
||||
mxValModel->mbShowInputMsg = rAttribs.getBool(XML_showInputMessage, false);
|
||||
mxValModel->mbShowErrorMsg = rAttribs.getBool(XML_showErrorMessage, false);
|
||||
/* The attribute showDropDown@dataValidation is in fact a "suppress
|
||||
dropdown" flag, as it was in the BIFF format! ECMA specification
|
||||
and attribute name are plain wrong! */
|
||||
mxValModel->mbNoDropDown = rAttribs.getBool(XML_showDropDown, false);
|
||||
mxValModel->mbAllowBlank = rAttribs.getBool(XML_allowBlank, false);
|
||||
}
|
||||
|
||||
void DataValidationsContext_Base::importDataValidation(SequenceInputStream& rStrm, ::oox::xls::WorksheetHelper& rTarget)
|
||||
{
|
||||
ValidationModel aModel;
|
||||
|
||||
sal_uInt32 nFlags;
|
||||
BinRangeList aRanges;
|
||||
nFlags = rStrm.readuInt32();
|
||||
rStrm >> aRanges >> aModel.maErrorTitle >> aModel.maErrorMessage >> aModel.maInputTitle >> aModel.maInputMessage;
|
||||
|
||||
// equal flags in all BIFFs
|
||||
aModel.setBiffType(extractValue< sal_uInt8 >(nFlags, 0, 4));
|
||||
aModel.setBiffOperator(extractValue< sal_uInt8 >(nFlags, 20, 4));
|
||||
aModel.setBiffErrorStyle(extractValue< sal_uInt8 >(nFlags, 4, 3));
|
||||
aModel.mbAllowBlank = getFlag(nFlags, BIFF_DATAVAL_ALLOWBLANK);
|
||||
aModel.mbNoDropDown = getFlag(nFlags, BIFF_DATAVAL_NODROPDOWN);
|
||||
aModel.mbShowInputMsg = getFlag(nFlags, BIFF_DATAVAL_SHOWINPUT);
|
||||
aModel.mbShowErrorMsg = getFlag(nFlags, BIFF_DATAVAL_SHOWERROR);
|
||||
|
||||
// cell range list
|
||||
rTarget.getAddressConverter().convertToCellRangeList(aModel.maRanges, aRanges, rTarget.getSheetIndex(), true);
|
||||
|
||||
// condition formula(s)
|
||||
FormulaParser& rParser = rTarget.getFormulaParser();
|
||||
ScAddress aBaseAddr = aModel.maRanges.getBaseAddress();
|
||||
aModel.maTokens1 = rParser.importFormula(aBaseAddr, FORMULATYPE_VALIDATION, rStrm);
|
||||
aModel.maTokens2 = rParser.importFormula(aBaseAddr, FORMULATYPE_VALIDATION, rStrm);
|
||||
// process string list of a list validation (convert to list of string tokens)
|
||||
if ((aModel.mnType == XML_list) && getFlag(nFlags, BIFF_DATAVAL_STRINGLIST))
|
||||
rParser.convertStringToStringList(aModel.maTokens1, ',', true);
|
||||
|
||||
// set validation data
|
||||
rTarget.setValidation(aModel);
|
||||
}
|
||||
|
||||
DataValidationsContext::DataValidationsContext( WorksheetFragmentBase& rFragment ) :
|
||||
WorksheetContextBase( rFragment )
|
||||
{
|
||||
@@ -105,89 +183,98 @@ ContextHandlerRef DataValidationsContext::onCreateContext( sal_Int32 nElement, c
|
||||
|
||||
void DataValidationsContext::onCharacters( const OUString& rChars )
|
||||
{
|
||||
if( mxValModel.get() ) switch( getCurrentElement() )
|
||||
switch( getCurrentElement() )
|
||||
{
|
||||
case XLS_TOKEN( formula1 ):
|
||||
mxValModel->maTokens1 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars );
|
||||
// process string list of a list validation (convert to list of string tokens)
|
||||
if( mxValModel->mnType == XML_list )
|
||||
getFormulaParser().convertStringToStringList( mxValModel->maTokens1, ',', true );
|
||||
SetFormula1( rChars );
|
||||
break;
|
||||
case XLS_TOKEN( formula2 ):
|
||||
mxValModel->maTokens2 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars );
|
||||
SetFormula2( rChars );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DataValidationsContext::onEndElement()
|
||||
{
|
||||
if( isCurrentElement( XLS_TOKEN( dataValidation ) ) && mxValModel.get() )
|
||||
if( isCurrentElement( XLS_TOKEN( dataValidation ) ) )
|
||||
{
|
||||
setValidation( *mxValModel );
|
||||
mxValModel.reset();
|
||||
SetValidation( *this );
|
||||
}
|
||||
}
|
||||
|
||||
ContextHandlerRef DataValidationsContext::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
|
||||
{
|
||||
if( nRecId == BIFF12_ID_DATAVALIDATION )
|
||||
importDataValidation( rStrm );
|
||||
importDataValidation( rStrm, *this );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void DataValidationsContext::importDataValidation( const AttributeList& rAttribs )
|
||||
ExtDataValidationsContext::ExtDataValidationsContext( WorksheetContextBase& rFragment ) :
|
||||
WorksheetContextBase( rFragment ), mCurrFormula( 0 )
|
||||
{
|
||||
mxValModel.reset( new ValidationModel );
|
||||
getAddressConverter().convertToCellRangeList( mxValModel->maRanges, rAttribs.getString( XML_sqref, OUString() ), getSheetIndex(), true );
|
||||
mxValModel->msRef = rAttribs.getString( XML_sqref, OUString() );
|
||||
mxValModel->maInputTitle = rAttribs.getXString( XML_promptTitle, OUString() );
|
||||
mxValModel->maInputMessage = rAttribs.getXString( XML_prompt, OUString() );
|
||||
mxValModel->maErrorTitle = rAttribs.getXString( XML_errorTitle, OUString() );
|
||||
mxValModel->maErrorMessage = rAttribs.getXString( XML_error, OUString() );
|
||||
mxValModel->mnType = rAttribs.getToken( XML_type, XML_none );
|
||||
mxValModel->mnOperator = rAttribs.getToken( XML_operator, XML_between );
|
||||
mxValModel->mnErrorStyle = rAttribs.getToken( XML_errorStyle, XML_stop );
|
||||
mxValModel->mbShowInputMsg = rAttribs.getBool( XML_showInputMessage, false );
|
||||
mxValModel->mbShowErrorMsg = rAttribs.getBool( XML_showErrorMessage, false );
|
||||
/* The attribute showDropDown@dataValidation is in fact a "suppress
|
||||
dropdown" flag, as it was in the BIFF format! ECMA specification
|
||||
and attribute name are plain wrong! */
|
||||
mxValModel->mbNoDropDown = rAttribs.getBool( XML_showDropDown, false );
|
||||
mxValModel->mbAllowBlank = rAttribs.getBool( XML_allowBlank, false );
|
||||
}
|
||||
|
||||
void DataValidationsContext::importDataValidation( SequenceInputStream& rStrm )
|
||||
ContextHandlerRef ExtDataValidationsContext::onCreateContext(sal_Int32 nElement, const AttributeList& rAttribs)
|
||||
{
|
||||
ValidationModel aModel;
|
||||
switch( getCurrentElement() )
|
||||
{
|
||||
case XLS14_TOKEN( dataValidations ):
|
||||
if ( nElement == XLS14_TOKEN( dataValidation ) )
|
||||
{
|
||||
importDataValidation( rAttribs );
|
||||
return this;
|
||||
}
|
||||
break;
|
||||
case XLS14_TOKEN( dataValidation ):
|
||||
switch ( nElement )
|
||||
{
|
||||
case XLS14_TOKEN( formula1 ):
|
||||
case XLS14_TOKEN( formula2 ):
|
||||
mCurrFormula = nElement;
|
||||
return this;
|
||||
case XM_TOKEN( sqref ):
|
||||
return this; // collect sqref in onCharacters()
|
||||
}
|
||||
break;
|
||||
case XLS14_TOKEN( formula1 ):
|
||||
case XLS14_TOKEN( formula2 ):
|
||||
switch( nElement )
|
||||
{
|
||||
case XM_TOKEN( f ):
|
||||
return this; // collect formulas in onCharacters()
|
||||
}
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sal_uInt32 nFlags;
|
||||
BinRangeList aRanges;
|
||||
nFlags = rStrm.readuInt32();
|
||||
rStrm >> aRanges >> aModel.maErrorTitle >> aModel.maErrorMessage >> aModel.maInputTitle >> aModel.maInputMessage;
|
||||
void ExtDataValidationsContext::onCharacters( const OUString& rChars )
|
||||
{
|
||||
switch( getCurrentElement() )
|
||||
{
|
||||
case XM_TOKEN( f ):
|
||||
switch( mCurrFormula )
|
||||
{
|
||||
case XLS14_TOKEN( formula1 ):
|
||||
SetFormula1( rChars );
|
||||
break;
|
||||
case XLS14_TOKEN( formula2 ):
|
||||
SetFormula2( rChars );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case XM_TOKEN( sqref ):
|
||||
SetSqref( rChars );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// equal flags in all BIFFs
|
||||
aModel.setBiffType( extractValue< sal_uInt8 >( nFlags, 0, 4 ) );
|
||||
aModel.setBiffOperator( extractValue< sal_uInt8 >( nFlags, 20, 4 ) );
|
||||
aModel.setBiffErrorStyle( extractValue< sal_uInt8 >( nFlags, 4, 3 ) );
|
||||
aModel.mbAllowBlank = getFlag( nFlags, BIFF_DATAVAL_ALLOWBLANK );
|
||||
aModel.mbNoDropDown = getFlag( nFlags, BIFF_DATAVAL_NODROPDOWN );
|
||||
aModel.mbShowInputMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWINPUT );
|
||||
aModel.mbShowErrorMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWERROR );
|
||||
|
||||
// cell range list
|
||||
getAddressConverter().convertToCellRangeList( aModel.maRanges, aRanges, getSheetIndex(), true );
|
||||
|
||||
// condition formula(s)
|
||||
FormulaParser& rParser = getFormulaParser();
|
||||
ScAddress aBaseAddr = aModel.maRanges.getBaseAddress();
|
||||
aModel.maTokens1 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm );
|
||||
aModel.maTokens2 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm );
|
||||
// process string list of a list validation (convert to list of string tokens)
|
||||
if( (aModel.mnType == XML_list) && getFlag( nFlags, BIFF_DATAVAL_STRINGLIST ) )
|
||||
rParser.convertStringToStringList( aModel.maTokens1, ',', true );
|
||||
|
||||
// set validation data
|
||||
setValidation( aModel );
|
||||
void ExtDataValidationsContext::onEndElement()
|
||||
{
|
||||
if( isCurrentElement( XLS14_TOKEN( dataValidation ) ) )
|
||||
{
|
||||
SetValidation( *this );
|
||||
}
|
||||
}
|
||||
|
||||
WorksheetFragment::WorksheetFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) :
|
||||
|
Reference in New Issue
Block a user