summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2016-12-01 07:38:32 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2016-12-02 08:35:34 +0000
commit438bb23d7225cb32c273950845e71c0d74486e5a (patch)
treeeee5869fa224179b9ea24cc19e56c4820543dbdc
parent1a567a548bc369551abdfcb4016dcd8d1ae0b85e (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.cxx76
-rw-r--r--sc/qa/unit/data/xlsx/tdf104310.xlsxbin0 -> 4668 bytes
-rw-r--r--sc/source/filter/inc/worksheetfragment.hxx36
-rw-r--r--sc/source/filter/oox/extlstcontext.cxx8
-rw-r--r--sc/source/filter/oox/worksheetfragment.cxx203
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
new file mode 100644
index 000000000000..95570d39ff9f
--- /dev/null
+++ b/sc/qa/unit/data/xlsx/tdf104310.xlsx
Binary files differ
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 ) :