diff options
| author | Mike Kaganski <mike.kaganski@collabora.com> | 2016-12-01 07:38:32 +0300 | 
|---|---|---|
| committer | Mike Kaganski <mike.kaganski@collabora.com> | 2016-12-02 08:35:34 +0000 | 
| commit | 438bb23d7225cb32c273950845e71c0d74486e5a (patch) | |
| tree | eee5869fa224179b9ea24cc19e56c4820543dbdc | |
| parent | 1a567a548bc369551abdfcb4016dcd8d1ae0b85e (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>
(cherry picked from commit 0afbe8d5ca17c4e24bb49272dc6711925f82f5d5)
Reviewed-on: https://gerrit.libreoffice.org/31506
Tested-by: Mike Kaganski <mike.kaganski@collabora.com>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
| -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.xlsxBinary files differ new 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 ) : | 
