diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2016-12-01 07:38:32 +0300 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2016-12-01 17:37:43 +0000 |
commit | 0afbe8d5ca17c4e24bb49272dc6711925f82f5d5 (patch) | |
tree | 3bb06976eb2967a0fcb685ee7e8070a23d347c5a /sc | |
parent | 83b7e1f424a3fb0963b064e77d973e5f655fac1a (diff) |
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>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/qa/unit/bugfix-test.cxx | 76 | ||||
-rw-r--r-- | sc/qa/unit/data/xlsx/tdf104310.xlsx | bin | 0 -> 4668 bytes | |||
-rw-r--r-- | sc/source/filter/inc/worksheetfragment.hxx | 36 | ||||
-rw-r--r-- | sc/source/filter/oox/extlstcontext.cxx | 8 | ||||
-rw-r--r-- | sc/source/filter/oox/worksheetfragment.cxx | 203 |
5 files changed, 199 insertions, 124 deletions
diff --git a/sc/qa/unit/bugfix-test.cxx b/sc/qa/unit/bugfix-test.cxx index 649eba95d9cb..9b7f2b772ded 100644 --- a/sc/qa/unit/bugfix-test.cxx +++ b/sc/qa/unit/bugfix-test.cxx @@ -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" ) { diff --git a/sc/qa/unit/data/xlsx/tdf104310.xlsx b/sc/qa/unit/data/xlsx/tdf104310.xlsx Binary files differnew file mode 100644 index 000000000000..95570d39ff9f --- /dev/null +++ b/sc/qa/unit/data/xlsx/tdf104310.xlsx diff --git a/sc/source/filter/inc/worksheetfragment.hxx b/sc/source/filter/inc/worksheetfragment.hxx index 0cd02b3f5d74..2fb52cbf42ee 100644 --- a/sc/source/filter/inc/worksheetfragment.hxx +++ b/sc/source/filter/inc/worksheetfragment.hxx @@ -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 diff --git a/sc/source/filter/oox/extlstcontext.cxx b/sc/source/filter/oox/extlstcontext.cxx index 023c27df29a9..54f332aa740a 100644 --- a/sc/source/filter/oox/extlstcontext.cxx +++ b/sc/source/filter/oox/extlstcontext.cxx @@ -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; } diff --git a/sc/source/filter/oox/worksheetfragment.cxx b/sc/source/filter/oox/worksheetfragment.cxx index c8aa6c6c58f4..30872d8f02b9 100644 --- a/sc/source/filter/oox/worksheetfragment.cxx +++ b/sc/source/filter/oox/worksheetfragment.cxx @@ -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 ) -{ - 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 ); +ExtDataValidationsContext::ExtDataValidationsContext( WorksheetContextBase& rFragment ) : + WorksheetContextBase( rFragment ), mCurrFormula( 0 ) +{ } -void DataValidationsContext::importDataValidation( SequenceInputStream& rStrm ) +ContextHandlerRef ExtDataValidationsContext::onCreateContext(sal_Int32 nElement, const AttributeList& rAttribs) { - 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 - getAddressConverter().convertToCellRangeList( aModel.maRanges, aRanges, getSheetIndex(), true ); + 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; +} - // 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 ); +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; + } +} - // set validation data - setValidation( aModel ); +void ExtDataValidationsContext::onEndElement() +{ + if( isCurrentElement( XLS14_TOKEN( dataValidation ) ) ) + { + SetValidation( *this ); + } } WorksheetFragment::WorksheetFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) : |