summaryrefslogtreecommitdiff
path: root/oox/source/xls
diff options
context:
space:
mode:
authorDaniel Rentz [dr] <daniel.rentz@oracle.com>2010-11-04 11:03:35 +0100
committerDaniel Rentz [dr] <daniel.rentz@oracle.com>2010-11-04 11:03:35 +0100
commit0b66e33ee50cd1c77bd9b1073ab298bac03bcfb7 (patch)
tree3debbe6b1d0f39ee0d2d6e8d813438b9abcde483 /oox/source/xls
parent65a1b13469cf7c2497f70a6a23363fe7cd643121 (diff)
dr77: #i102872# handle new filter operators from css.sheet.FilterOperator2, rewrite OOXML autofilter import, add BIFF5/8/12 support
Diffstat (limited to 'oox/source/xls')
-rwxr-xr-xoox/source/xls/autofilterbuffer.cxx856
-rw-r--r--oox/source/xls/autofiltercontext.cxx731
-rwxr-xr-xoox/source/xls/connectionsbuffer.cxx55
-rw-r--r--oox/source/xls/connectionsfragment.cxx51
-rw-r--r--oox/source/xls/defnamesbuffer.cxx158
-rw-r--r--oox/source/xls/makefile.mk3
-rw-r--r--oox/source/xls/pivotcachefragment.cxx5
-rw-r--r--oox/source/xls/pivottablefragment.cxx4
-rw-r--r--oox/source/xls/querytablebuffer.cxx20
-rw-r--r--oox/source/xls/querytablefragment.cxx4
-rw-r--r--oox/source/xls/sheetdatacontext.cxx7
-rw-r--r--oox/source/xls/tablebuffer.cxx50
-rw-r--r--oox/source/xls/tablefragment.cxx33
-rw-r--r--oox/source/xls/workbookhelper.cxx50
-rw-r--r--oox/source/xls/worksheetfragment.cxx19
-rw-r--r--oox/source/xls/worksheethelper.cxx11
16 files changed, 1204 insertions, 853 deletions
diff --git a/oox/source/xls/autofilterbuffer.cxx b/oox/source/xls/autofilterbuffer.cxx
new file mode 100755
index 000000000000..15cb2f726327
--- /dev/null
+++ b/oox/source/xls/autofilterbuffer.cxx
@@ -0,0 +1,856 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "oox/xls/autofilterbuffer.hxx"
+
+#include <com/sun/star/sheet/FilterConnection.hpp>
+#include <com/sun/star/sheet/FilterOperator2.hpp>
+#include <com/sun/star/sheet/TableFilterField2.hpp>
+#include <com/sun/star/sheet/XDatabaseRange.hpp>
+#include <com/sun/star/sheet/XSheetFilterDescriptor2.hpp>
+#include <com/sun/star/table/TableOrientation.hpp>
+#include <rtl/ustrbuf.hxx>
+#include "oox/core/namespaces.hxx"
+#include "oox/helper/attributelist.hxx"
+#include "oox/helper/propertyset.hxx"
+#include "oox/helper/recordinputstream.hxx"
+#include "oox/xls/addressconverter.hxx"
+#include "oox/xls/biffinputstream.hxx"
+#include "oox/xls/defnamesbuffer.hxx"
+#include "properties.hxx"
+#include "tokens.hxx"
+
+namespace oox {
+namespace xls {
+
+using namespace ::com::sun::star::sheet;
+using namespace ::com::sun::star::table;
+using namespace ::com::sun::star::uno;
+
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+
+// ============================================================================
+
+namespace {
+
+const sal_uInt8 BIFF12_TOP10FILTER_TOP = 0x01;
+const sal_uInt8 BIFF12_TOP10FILTER_PERCENT = 0x02;
+
+const sal_uInt16 BIFF12_FILTERCOLUMN_HIDDENBUTTON = 0x0001;
+const sal_uInt16 BIFF12_FILTERCOLUMN_SHOWBUTTON = 0x0002;
+
+const sal_uInt16 BIFF_FILTERCOLUMN_OR = 0x0001;
+const sal_uInt16 BIFF_FILTERCOLUMN_TOP10FILTER = 0x0010;
+const sal_uInt16 BIFF_FILTERCOLUMN_TOP = 0x0020;
+const sal_uInt16 BIFF_FILTERCOLUMN_PERCENT = 0x0040;
+
+const sal_uInt8 BIFF_FILTER_DATATYPE_NONE = 0;
+const sal_uInt8 BIFF_FILTER_DATATYPE_RK = 2;
+const sal_uInt8 BIFF_FILTER_DATATYPE_DOUBLE = 4;
+const sal_uInt8 BIFF_FILTER_DATATYPE_STRING = 6;
+const sal_uInt8 BIFF_FILTER_DATATYPE_BOOLEAN = 8;
+const sal_uInt8 BIFF_FILTER_DATATYPE_EMPTY = 12;
+const sal_uInt8 BIFF_FILTER_DATATYPE_NOTEMPTY = 14;
+
+// ----------------------------------------------------------------------------
+
+bool lclGetApiOperatorFromToken( sal_Int32& rnApiOperator, sal_Int32 nToken )
+{
+ switch( nToken )
+ {
+ case XML_lessThan: rnApiOperator = FilterOperator2::NOT_EQUAL; return true;
+ case XML_equal: rnApiOperator = FilterOperator2::EQUAL; return true;
+ case XML_lessThanOrEqual: rnApiOperator = FilterOperator2::LESS_EQUAL; return true;
+ case XML_greaterThan: rnApiOperator = FilterOperator2::GREATER; return true;
+ case XML_notEqual: rnApiOperator = FilterOperator2::NOT_EQUAL; return true;
+ case XML_greaterThanOrEqual: rnApiOperator = FilterOperator2::GREATER_EQUAL; return true;
+ }
+ return false;
+}
+
+/** Removes leading asterisk characters from the passed string.
+ @return True = at least one asterisk character has been removed. */
+bool lclTrimLeadingAsterisks( OUString& rValue )
+{
+ sal_Int32 nLength = rValue.getLength();
+ sal_Int32 nPos = 0;
+ while( (nPos < nLength) && (rValue[ nPos ] == '*') )
+ ++nPos;
+ if( nPos > 0 )
+ {
+ rValue = rValue.copy( nPos );
+ return true;
+ }
+ return false;
+}
+
+/** Removes trailing asterisk characters from the passed string.
+ @return True = at least one asterisk character has been removed. */
+bool lclTrimTrailingAsterisks( OUString& rValue )
+{
+ sal_Int32 nLength = rValue.getLength();
+ sal_Int32 nPos = nLength;
+ while( (nPos > 0) && (rValue[ nPos - 1 ] == '*') )
+ --nPos;
+ if( nPos < nLength )
+ {
+ rValue = rValue.copy( 0, nPos );
+ return true;
+ }
+ return false;
+}
+
+/** Converts wildcard characters '*' and '?' to regular expressions and quotes
+ RE meta characters.
+ @return True = passed string has been changed (RE needs to be enabled). */
+bool lclConvertWildcardsToRegExp( OUString& rValue )
+{
+ // check existence of the wildcard characters '*' and '?'
+ if( (rValue.getLength() > 0) && ((rValue.indexOf( '*' ) >= 0) || (rValue.indexOf( '?' ) >= 0)) )
+ {
+ OUStringBuffer aBuffer;
+ aBuffer.ensureCapacity( rValue.getLength() + 5 );
+ const sal_Unicode* pcChar = rValue.getStr();
+ const sal_Unicode* pcEnd = pcChar + rValue.getLength();
+ for( ; pcChar < pcEnd; ++pcChar )
+ {
+ switch( *pcChar )
+ {
+ case '?':
+ aBuffer.append( sal_Unicode( '.' ) );
+ break;
+ case '*':
+ aBuffer.append( sal_Unicode( '.' ) ).append( sal_Unicode( '*' ) );
+ break;
+ case '\\': case '.': case '|': case '(': case ')': case '^': case '$':
+ // quote RE meta characters
+ aBuffer.append( sal_Unicode( '\\' ) ).append( *pcChar );
+ break;
+ default:
+ aBuffer.append( *pcChar );
+ }
+ }
+ rValue = aBuffer.makeStringAndClear();
+ return true;
+ }
+ return false;
+}
+
+} // namespace
+
+// ============================================================================
+
+ApiFilterSettings::ApiFilterSettings()
+{
+}
+
+void ApiFilterSettings::appendField( bool bAnd, sal_Int32 nOperator, double fValue )
+{
+ maFilterFields.resize( maFilterFields.size() + 1 );
+ TableFilterField2& rFilterField = maFilterFields.back();
+ rFilterField.Connection = bAnd ? FilterConnection_AND : FilterConnection_OR;
+ rFilterField.Operator = nOperator;
+ rFilterField.IsNumeric = sal_True;
+ rFilterField.NumericValue = fValue;
+}
+
+void ApiFilterSettings::appendField( bool bAnd, sal_Int32 nOperator, const OUString& rValue )
+{
+ maFilterFields.resize( maFilterFields.size() + 1 );
+ TableFilterField2& rFilterField = maFilterFields.back();
+ rFilterField.Connection = bAnd ? FilterConnection_AND : FilterConnection_OR;
+ rFilterField.Operator = nOperator;
+ rFilterField.IsNumeric = sal_False;
+ rFilterField.StringValue = rValue;
+}
+
+// ============================================================================
+
+FilterSettingsBase::FilterSettingsBase( const WorkbookHelper& rHelper ) :
+ WorkbookHelper( rHelper )
+{
+}
+
+void FilterSettingsBase::importAttribs( sal_Int32 /*nElement*/, const AttributeList& /*rAttribs*/ )
+{
+}
+
+void FilterSettingsBase::importRecord( sal_Int32 /*nRecId*/, RecordInputStream& /*rStrm*/ )
+{
+}
+
+void FilterSettingsBase::importBiffRecord( BiffInputStream& /*rStrm*/, sal_uInt16 /*nFlags*/ )
+{
+}
+
+ApiFilterSettings FilterSettingsBase::finalizeImport( sal_Int32 /*nMaxCount*/ )
+{
+ return ApiFilterSettings();
+}
+
+// ============================================================================
+
+DiscreteFilter::DiscreteFilter( const WorkbookHelper& rHelper ) :
+ FilterSettingsBase( rHelper ),
+ mnCalendarType( XML_none ),
+ mbShowBlank( false )
+{
+}
+
+void DiscreteFilter::importAttribs( sal_Int32 nElement, const AttributeList& rAttribs )
+{
+ switch( nElement )
+ {
+ case XLS_TOKEN( filters ):
+ mnCalendarType = rAttribs.getToken( XML_calendarType, XML_none );
+ mbShowBlank = rAttribs.getBool( XML_blank, false );
+ break;
+
+ case XLS_TOKEN( filter ):
+ {
+ OUString aValue = rAttribs.getXString( XML_val, OUString() );
+ if( aValue.getLength() > 0 )
+ maValues.push_back( aValue );
+ }
+ break;
+ }
+}
+
+void DiscreteFilter::importRecord( sal_Int32 nRecId, RecordInputStream& rStrm )
+{
+ switch( nRecId )
+ {
+ case BIFF12_ID_DISCRETEFILTERS:
+ {
+ sal_Int32 nShowBlank, nCalendarType;
+ rStrm >> nShowBlank >> nCalendarType;
+
+ static const sal_Int32 spnCalendarTypes[] = {
+ XML_none, XML_gregorian, XML_gregorianUs, XML_japan, XML_taiwan, XML_korea, XML_hijri, XML_thai, XML_hebrew,
+ XML_gregorianMeFrench, XML_gregorianArabic, XML_gregorianXlitEnglish, XML_gregorianXlitFrench };
+ mnCalendarType = STATIC_ARRAY_SELECT( spnCalendarTypes, nCalendarType, XML_none );
+ mbShowBlank = nShowBlank != 0;
+ }
+ break;
+
+ case BIFF12_ID_DISCRETEFILTER:
+ {
+ OUString aValue = rStrm.readString();
+ if( aValue.getLength() > 0 )
+ maValues.push_back( aValue );
+ }
+ break;
+ }
+}
+
+ApiFilterSettings DiscreteFilter::finalizeImport( sal_Int32 nMaxCount )
+{
+ ApiFilterSettings aSettings;
+ if( static_cast< sal_Int32 >( maValues.size() ) <= nMaxCount )
+ {
+ aSettings.maFilterFields.reserve( maValues.size() );
+
+ // insert all filter values
+ for( FilterValueVector::iterator aIt = maValues.begin(), aEnd = maValues.end(); aIt != aEnd; ++aIt )
+ aSettings.appendField( false, FilterOperator2::EQUAL, *aIt );
+
+ // extra field for 'show empty'
+ if( mbShowBlank )
+ aSettings.appendField( false, FilterOperator2::EMPTY, OUString() );
+
+ /* Require disabled regular expressions, filter entries may contain
+ any RE meta characters. */
+ if( !maValues.empty() )
+ aSettings.mobNeedsRegExp = false;
+ }
+ return aSettings;
+}
+
+// ============================================================================
+
+Top10Filter::Top10Filter( const WorkbookHelper& rHelper ) :
+ FilterSettingsBase( rHelper ),
+ mfValue( 0.0 ),
+ mbTop( true ),
+ mbPercent( false )
+{
+}
+
+void Top10Filter::importAttribs( sal_Int32 nElement, const AttributeList& rAttribs )
+{
+ if( nElement == XLS_TOKEN( top10 ) )
+ {
+ mfValue = rAttribs.getDouble( XML_val, 0.0 );
+ mbTop = rAttribs.getBool( XML_top, true );
+ mbPercent = rAttribs.getBool( XML_percent, false );
+ }
+}
+
+void Top10Filter::importRecord( sal_Int32 nRecId, RecordInputStream& rStrm )
+{
+ if( nRecId == BIFF12_ID_TOP10FILTER )
+ {
+ sal_uInt8 nFlags;
+ rStrm >> nFlags >> mfValue;
+ mbTop = getFlag( nFlags, BIFF12_TOP10FILTER_TOP );
+ mbPercent = getFlag( nFlags, BIFF12_TOP10FILTER_PERCENT );
+ }
+}
+
+void Top10Filter::importBiffRecord( BiffInputStream& /*rStrm*/, sal_uInt16 nFlags )
+{
+ mfValue = extractValue< sal_uInt16 >( nFlags, 7, 9 );
+ mbTop = getFlag( nFlags, BIFF_FILTERCOLUMN_TOP );
+ mbPercent = getFlag( nFlags, BIFF_FILTERCOLUMN_PERCENT );
+}
+
+ApiFilterSettings Top10Filter::finalizeImport( sal_Int32 /*nMaxCount*/ )
+{
+ sal_Int32 nOperator = mbTop ?
+ (mbPercent ? FilterOperator2::TOP_PERCENT : FilterOperator2::TOP_VALUES) :
+ (mbPercent ? FilterOperator2::BOTTOM_PERCENT : FilterOperator2::BOTTOM_VALUES);
+ ApiFilterSettings aSettings;
+ aSettings.appendField( true, nOperator, mfValue );
+ return aSettings;
+}
+
+// ============================================================================
+
+FilterCriterionModel::FilterCriterionModel() :
+ mnOperator( XML_equal ),
+ mnDataType( BIFF_FILTER_DATATYPE_NONE ),
+ mnStrLen( 0 )
+{
+}
+
+void FilterCriterionModel::setBiffOperator( sal_uInt8 nOperator )
+{
+ static const sal_Int32 spnOperators[] = { XML_TOKEN_INVALID,
+ XML_lessThan, XML_equal, XML_lessThanOrEqual, XML_greaterThan, XML_notEqual, XML_greaterThanOrEqual };
+ mnOperator = STATIC_ARRAY_SELECT( spnOperators, nOperator, XML_TOKEN_INVALID );
+}
+
+void FilterCriterionModel::readBiffData( RecordInputStream& rStrm )
+{
+ sal_uInt8 nOperator;
+ rStrm >> mnDataType >> nOperator;
+ setBiffOperator( nOperator );
+
+ switch( mnDataType )
+ {
+ case BIFF_FILTER_DATATYPE_DOUBLE:
+ maValue <<= rStrm.readDouble();
+ break;
+ case BIFF_FILTER_DATATYPE_STRING:
+ {
+ rStrm.skip( 8 );
+ OUString aValue = rStrm.readString().trim();
+ if( aValue.getLength() > 0 )
+ maValue <<= aValue;
+ }
+ break;
+ case BIFF_FILTER_DATATYPE_BOOLEAN:
+ maValue <<= (rStrm.readuInt8() != 0);
+ rStrm.skip( 7 );
+ break;
+ case BIFF_FILTER_DATATYPE_EMPTY:
+ rStrm.skip( 8 );
+ if( mnOperator == XML_equal )
+ maValue <<= OUString();
+ break;
+ case BIFF_FILTER_DATATYPE_NOTEMPTY:
+ rStrm.skip( 8 );
+ if( mnOperator == XML_notEqual )
+ maValue <<= OUString();
+ break;
+ default:
+ OSL_ENSURE( false, "FilterCriterionModel::readBiffData - unexpected data type" );
+ rStrm.skip( 8 );
+ }
+}
+
+void FilterCriterionModel::readBiffData( BiffInputStream& rStrm )
+{
+ sal_uInt8 nOperator;
+ rStrm >> mnDataType >> nOperator;
+ setBiffOperator( nOperator );
+
+ switch( mnDataType )
+ {
+ case BIFF_FILTER_DATATYPE_NONE:
+ rStrm.skip( 8 );
+ break;
+ case BIFF_FILTER_DATATYPE_RK:
+ maValue <<= BiffHelper::calcDoubleFromRk( rStrm.readInt32() );
+ rStrm.skip( 4 );
+ break;
+ case BIFF_FILTER_DATATYPE_DOUBLE:
+ maValue <<= rStrm.readDouble();
+ break;
+ case BIFF_FILTER_DATATYPE_STRING:
+ rStrm.skip( 4 );
+ rStrm >> mnStrLen;
+ rStrm.skip( 3 );
+ break;
+ case BIFF_FILTER_DATATYPE_BOOLEAN:
+ {
+ sal_uInt8 nValue, nType;
+ rStrm >> nValue >> nType;
+ rStrm.skip( 6 );
+ switch( nType )
+ {
+ case BIFF_BOOLERR_BOOL: maValue <<= (nValue != 0); break;
+ case BIFF_BOOLERR_ERROR: maValue <<= BiffHelper::calcDoubleFromError( nValue ); break;
+ default: OSL_ENSURE( false, "FilterCriterionModel::readBiffData - unknown type" );
+ }
+ }
+ break;
+ case BIFF_FILTER_DATATYPE_EMPTY:
+ rStrm.skip( 8 );
+ if( mnOperator == XML_equal )
+ maValue <<= OUString();
+ break;
+ case BIFF_FILTER_DATATYPE_NOTEMPTY:
+ rStrm.skip( 8 );
+ if( mnOperator == XML_notEqual )
+ maValue <<= OUString();
+ break;
+ default:
+ OSL_ENSURE( false, "FilterCriterionModel::readBiffData - unexpected data type" );
+ rStrm.skip( 8 );
+ }
+}
+
+void FilterCriterionModel::readString( BiffInputStream& rStrm, BiffType eBiff, rtl_TextEncoding eTextEnc )
+{
+ if( (mnDataType == BIFF_FILTER_DATATYPE_STRING) && (mnStrLen > 0) )
+ {
+ OUString aValue = (eBiff == BIFF8) ?
+ rStrm.readUniStringBody( mnStrLen, true ) :
+ rStrm.readCharArrayUC( mnStrLen, eTextEnc, true );
+ aValue = aValue.trim();
+ if( aValue.getLength() > 0 )
+ maValue <<= aValue;
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+CustomFilter::CustomFilter( const WorkbookHelper& rHelper ) :
+ FilterSettingsBase( rHelper ),
+ mbAnd( false )
+{
+}
+
+void CustomFilter::importAttribs( sal_Int32 nElement, const AttributeList& rAttribs )
+{
+ switch( nElement )
+ {
+ case XLS_TOKEN( customFilters ):
+ mbAnd = rAttribs.getBool( XML_and, false );
+ break;
+
+ case XLS_TOKEN( customFilter ):
+ {
+ FilterCriterionModel aCriterion;
+ aCriterion.mnOperator = rAttribs.getToken( XML_operator, XML_equal );
+ OUString aValue = rAttribs.getXString( XML_val, OUString() ).trim();
+ if( (aCriterion.mnOperator == XML_equal) || (aCriterion.mnOperator == XML_notEqual) || (aValue.getLength() > 0) )
+ aCriterion.maValue <<= aValue;
+ appendCriterion( aCriterion );
+ }
+ break;
+ }
+}
+
+void CustomFilter::importRecord( sal_Int32 nRecId, RecordInputStream& rStrm )
+{
+ switch( nRecId )
+ {
+ case BIFF12_ID_CUSTOMFILTERS:
+ mbAnd = rStrm.readInt32() == 0;
+ break;
+
+ case BIFF12_ID_CUSTOMFILTER:
+ {
+ FilterCriterionModel aCriterion;
+ aCriterion.readBiffData( rStrm );
+ appendCriterion( aCriterion );
+ }
+ break;
+ }
+}
+
+void CustomFilter::importBiffRecord( BiffInputStream& rStrm, sal_uInt16 nFlags )
+{
+ mbAnd = !getFlag( nFlags, BIFF_FILTERCOLUMN_OR );
+
+ FilterCriterionModel aCriterion1, aCriterion2;
+ aCriterion1.readBiffData( rStrm );
+ aCriterion2.readBiffData( rStrm );
+ aCriterion1.readString( rStrm, getBiff(), getTextEncoding() );
+ aCriterion2.readString( rStrm, getBiff(), getTextEncoding() );
+ appendCriterion( aCriterion1 );
+ appendCriterion( aCriterion2 );
+}
+
+ApiFilterSettings CustomFilter::finalizeImport( sal_Int32 /*nMaxCount*/ )
+{
+ ApiFilterSettings aSettings;
+ OSL_ENSURE( maCriteria.size() <= 2, "CustomFilter::finalizeImport - too many filter criteria" );
+ for( FilterCriterionVector::iterator aIt = maCriteria.begin(), aEnd = maCriteria.end(); aIt != aEnd; ++aIt )
+ {
+ // first extract the filter operator
+ sal_Int32 nOperator = 0;
+ bool bValidOperator = lclGetApiOperatorFromToken( nOperator, aIt->mnOperator );
+ if( bValidOperator )
+ {
+ if( aIt->maValue.has< OUString >() )
+ {
+ // string argument
+ OUString aValue;
+ aIt->maValue >>= aValue;
+ // check for 'empty', 'contains', 'begins with', or 'ends with' text filters
+ bool bEqual = nOperator == FilterOperator2::EQUAL;
+ bool bNotEqual = nOperator == FilterOperator2::NOT_EQUAL;
+ if( bEqual || bNotEqual )
+ {
+ if( aValue.getLength() == 0 )
+ {
+ // empty comparison string: create empty/not empty filters
+ nOperator = bNotEqual ? FilterOperator2::NOT_EMPTY : FilterOperator2::EMPTY;
+ }
+ else
+ {
+ // compare to something: try to find begins/ends/contains
+ bool bHasLeadingAsterisk = lclTrimLeadingAsterisks( aValue );
+ bool bHasTrailingAsterisk = lclTrimTrailingAsterisks( aValue );
+ // just '***' matches everything, do not create a filter field
+ bValidOperator = aValue.getLength() > 0;
+ if( bValidOperator )
+ {
+ if( bHasLeadingAsterisk && bHasTrailingAsterisk )
+ nOperator = bNotEqual ? FilterOperator2::DOES_NOT_CONTAIN : FilterOperator2::CONTAINS;
+ else if( bHasLeadingAsterisk )
+ nOperator = bNotEqual ? FilterOperator2::DOES_NOT_END_WITH : FilterOperator2::ENDS_WITH;
+ else if( bHasTrailingAsterisk )
+ nOperator = bNotEqual ? FilterOperator2::DOES_NOT_BEGIN_WITH : FilterOperator2::BEGINS_WITH;
+ // else: no asterisks, stick to equal/not equal
+ }
+ }
+ }
+
+ if( bValidOperator )
+ {
+ // if wildcards are present, require RE mode, otherwise keep don't care state
+ if( lclConvertWildcardsToRegExp( aValue ) )
+ aSettings.mobNeedsRegExp = true;
+ // create a new UNO API filter field
+ aSettings.appendField( mbAnd, nOperator, aValue );
+ }
+ }
+ else if( aIt->maValue.has< double >() )
+ {
+ // floating-point argument
+ double fValue;
+ aIt->maValue >>= fValue;
+ aSettings.appendField( mbAnd, nOperator, fValue );
+ }
+ }
+ }
+ return aSettings;
+}
+
+void CustomFilter::appendCriterion( const FilterCriterionModel& rCriterion )
+{
+ if( (rCriterion.mnOperator != XML_TOKEN_INVALID) && rCriterion.maValue.hasValue() )
+ maCriteria.push_back( rCriterion );
+}
+
+// ============================================================================
+
+FilterColumn::FilterColumn( const WorkbookHelper& rHelper ) :
+ WorkbookHelper( rHelper ),
+ mnColId( -1 ),
+ mbHiddenButton( false ),
+ mbShowButton( true )
+{
+}
+
+void FilterColumn::importFilterColumn( const AttributeList& rAttribs )
+{
+ mnColId = rAttribs.getInteger( XML_colId, -1 );
+ mbHiddenButton = rAttribs.getBool( XML_hiddenButton, false );
+ mbShowButton = rAttribs.getBool( XML_showButton, true );
+}
+
+void FilterColumn::importFilterColumn( RecordInputStream& rStrm )
+{
+ sal_uInt16 nFlags;
+ rStrm >> mnColId >> nFlags;
+ mbHiddenButton = getFlag( nFlags, BIFF12_FILTERCOLUMN_HIDDENBUTTON );
+ mbShowButton = getFlag( nFlags, BIFF12_FILTERCOLUMN_SHOWBUTTON );
+}
+
+void FilterColumn::importFilterColumn( BiffInputStream& rStrm )
+{
+ sal_uInt16 nFlags;
+ mnColId = rStrm.readuInt16();
+ rStrm >> nFlags;
+
+ // BIFF5/BIFF8 support top-10 filters and custom filters
+ if( getFlag( nFlags, BIFF_FILTERCOLUMN_TOP10FILTER ) )
+ createFilterSettings< Top10Filter >().importBiffRecord( rStrm, nFlags );
+ else
+ createFilterSettings< CustomFilter >().importBiffRecord( rStrm, nFlags );
+}
+
+ApiFilterSettings FilterColumn::finalizeImport( sal_Int32 nMaxCount )
+{
+ ApiFilterSettings aSettings;
+ if( (0 <= mnColId) && mxSettings.get() )
+ {
+ // filter settings object creates a sequence of filter fields
+ aSettings = mxSettings->finalizeImport( nMaxCount );
+ // add column index to all filter fields
+ for( ApiFilterSettings::FilterFieldVector::iterator aIt = aSettings.maFilterFields.begin(), aEnd = aSettings.maFilterFields.end(); aIt != aEnd; ++aIt )
+ aIt->Field = mnColId;
+ }
+ return aSettings;
+}
+
+// ============================================================================
+
+AutoFilter::AutoFilter( const WorkbookHelper& rHelper ) :
+ WorkbookHelper( rHelper )
+{
+}
+
+void AutoFilter::importAutoFilter( const AttributeList& rAttribs, sal_Int16 nSheet )
+{
+ OUString aRangeStr = rAttribs.getString( XML_ref, OUString() );
+ getAddressConverter().convertToCellRangeUnchecked( maRange, aRangeStr, nSheet );
+}
+
+void AutoFilter::importAutoFilter( RecordInputStream& rStrm, sal_Int16 nSheet )
+{
+ BinRange aBinRange;
+ rStrm >> aBinRange;
+ getAddressConverter().convertToCellRangeUnchecked( maRange, aBinRange, nSheet );
+}
+
+FilterColumn& AutoFilter::createFilterColumn()
+{
+ FilterColumnVector::value_type xFilterColumn( new FilterColumn( *this ) );
+ maFilterColumns.push_back( xFilterColumn );
+ return *xFilterColumn;
+}
+
+void AutoFilter::finalizeImport( const Reference< XSheetFilterDescriptor2 >& rxFilterDesc )
+{
+ if( rxFilterDesc.is() )
+ {
+ // set some common properties for the auto filter range
+ PropertySet aDescProps( rxFilterDesc );
+ aDescProps.setProperty( PROP_IsCaseSensitive, false );
+ aDescProps.setProperty( PROP_SkipDuplicates, false );
+ aDescProps.setProperty( PROP_Orientation, TableOrientation_ROWS );
+ aDescProps.setProperty( PROP_ContainsHeader, true );
+ aDescProps.setProperty( PROP_CopyOutputData, false );
+
+ // maximum number of UNO API filter fields
+ sal_Int32 nMaxCount = 0;
+ aDescProps.getProperty( nMaxCount, PROP_MaxFieldCount );
+ OSL_ENSURE( nMaxCount > 0, "AutoFilter::finalizeImport - invalid maximum filter field count" );
+
+ // resulting list of all UNO API filter fields
+ ::std::vector< TableFilterField2 > aFilterFields;
+
+ // track if columns require to enable or disable regular expressions
+ OptValue< bool > obNeedsRegExp;
+
+ /* Track whether the filter fields of the first filter column are
+ connected with 'or'. In this case, other filter fields cannot be
+ inserted without altering the result of the entire filter, due to
+ Calc's precedence for the 'and' connection operator. Example:
+ Excel's filter conditions 'A1 and (B1 or B2) and C1' where B1 and
+ B2 belong to filter column B, will be evaluated by Calc as
+ '(A1 and B1) or (B2 and C1)'. */
+ bool bHasOrConnection = false;
+
+ // process all filter column objects, exit when 'or' connection exists
+ for( FilterColumnVector::iterator aIt = maFilterColumns.begin(), aEnd = maFilterColumns.end(); !bHasOrConnection && (aIt != aEnd); ++aIt )
+ {
+ // the filter settings object creates a list of filter fields
+ ApiFilterSettings aSettings = (*aIt)->finalizeImport( nMaxCount );
+ ApiFilterSettings::FilterFieldVector& rColumnFields = aSettings.maFilterFields;
+
+ // new total number of filter fields
+ sal_Int32 nNewCount = static_cast< sal_Int32 >( aFilterFields.size() + rColumnFields.size() );
+
+ /* Check whether mode for regular expressions is compatible with
+ the global mode in obNeedsRegExp. If either one is still in
+ don't-care state, all is fine. If both are set, they must be
+ equal. */
+ bool bRegExpCompatible = !obNeedsRegExp || !aSettings.mobNeedsRegExp || (obNeedsRegExp.get() == aSettings.mobNeedsRegExp.get());
+
+ // check whether fields are connected by 'or' (see comments above).
+ if( rColumnFields.size() >= 2 )
+ for( ApiFilterSettings::FilterFieldVector::iterator aSIt = rColumnFields.begin() + 1, aSEnd = rColumnFields.end(); !bHasOrConnection && (aSIt != aSEnd); ++aSIt )
+ bHasOrConnection = aSIt->Connection == FilterConnection_OR;
+
+ /* Skip the column filter, if no filter fields have been created,
+ if the number of new filter fields would exceed the total limit
+ of filter fields, or if the mode for regular expressions of the
+ filter column does not fit. */
+ if( !rColumnFields.empty() && (nNewCount <= nMaxCount) && bRegExpCompatible )
+ {
+ /* Add 'and' connection to the first filter field to connect
+ it to the existing filter fields of other columns. */
+ rColumnFields[ 0 ].Connection = FilterConnection_AND;
+
+ // insert the new filter fields
+ aFilterFields.insert( aFilterFields.end(), rColumnFields.begin(), rColumnFields.end() );
+
+ // update the regular expressions mode
+ obNeedsRegExp.assignIfUsed( aSettings.mobNeedsRegExp );
+ }
+ }
+
+ // insert all filter fields to the filter descriptor
+ if( !aFilterFields.empty() )
+ rxFilterDesc->setFilterFields2( ContainerHelper::vectorToSequence( aFilterFields ) );
+
+ // regular expressions
+ bool bUseRegExp = obNeedsRegExp.get( false );
+ aDescProps.setProperty( PROP_UseRegularExpressions, bUseRegExp );
+ }
+}
+
+// ============================================================================
+
+AutoFilterBuffer::AutoFilterBuffer( const WorkbookHelper& rHelper ) :
+ WorkbookHelper( rHelper )
+{
+}
+
+AutoFilter& AutoFilterBuffer::createAutoFilter()
+{
+ AutoFilterVector::value_type xAutoFilter( new AutoFilter( *this ) );
+ maAutoFilters.push_back( xAutoFilter );
+ return *xAutoFilter;
+}
+
+void AutoFilterBuffer::finalizeImport( sal_Int16 nSheet )
+{
+ // rely on existence of the defined name '_FilterDatabase' containing the range address of the filtered area
+ if( const DefinedName* pFilterDBName = getDefinedNames().getByBuiltinId( BIFF_DEFNAME_FILTERDATABASE, nSheet ).get() )
+ {
+ CellRangeAddress aFilterRange;
+ if( pFilterDBName->getAbsoluteRange( aFilterRange ) && (aFilterRange.Sheet == nSheet) )
+ {
+ // use the same name for the database range as used for the defined name '_FilterDatabase'
+ OUString aDBRangeName = pFilterDBName->getCalcName();
+ Reference< XDatabaseRange > xDatabaseRange = createDatabaseRangeObject( aDBRangeName, aFilterRange );
+ // first, try to create an auto filter
+ bool bHasAutoFilter = finalizeImport( xDatabaseRange );
+ // no success: try to create an advanced filter
+ if( !bHasAutoFilter && xDatabaseRange.is() )
+ {
+ // the built-in defined name 'Criteria' must exist
+ if( const DefinedName* pCriteriaName = getDefinedNames().getByBuiltinId( BIFF_DEFNAME_CRITERIA, nSheet ).get() )
+ {
+ CellRangeAddress aCriteriaRange;
+ if( pCriteriaName->getAbsoluteRange( aCriteriaRange ) )
+ {
+ // set some common properties for the filter descriptor
+ PropertySet aDescProps( xDatabaseRange->getFilterDescriptor() );
+ aDescProps.setProperty( PROP_IsCaseSensitive, false );
+ aDescProps.setProperty( PROP_SkipDuplicates, false );
+ aDescProps.setProperty( PROP_Orientation, TableOrientation_ROWS );
+ aDescProps.setProperty( PROP_ContainsHeader, true );
+ // criteria range may contain wildcards, but these are incompatible with REs
+ aDescProps.setProperty( PROP_UseRegularExpressions, false );
+
+ // position of output data (if built-in defined name 'Extract' exists)
+ DefinedNameRef xExtractName = getDefinedNames().getByBuiltinId( BIFF_DEFNAME_EXTRACT, nSheet );
+ CellRangeAddress aOutputRange;
+ bool bHasOutputRange = xExtractName.get() && xExtractName->getAbsoluteRange( aOutputRange );
+ aDescProps.setProperty( PROP_CopyOutputData, bHasOutputRange );
+ if( bHasOutputRange )
+ {
+ aDescProps.setProperty( PROP_SaveOutputPosition, true );
+ aDescProps.setProperty( PROP_OutputPosition, CellAddress( aOutputRange.Sheet, aOutputRange.StartColumn, aOutputRange.StartRow ) );
+ }
+
+ /* Properties of the database range (must be set after
+ modifying properties of the filter descriptor,
+ otherwise the 'FilterCriteriaSource' property gets
+ deleted). */
+ PropertySet aRangeProps( xDatabaseRange );
+ aRangeProps.setProperty( PROP_AutoFilter, false );
+ aRangeProps.setProperty( PROP_FilterCriteriaSource, aCriteriaRange );
+ }
+ }
+ }
+ }
+ }
+}
+
+bool AutoFilterBuffer::finalizeImport( const Reference< XDatabaseRange >& rxDatabaseRange )
+{
+ AutoFilter* pAutoFilter = getActiveAutoFilter();
+ if( pAutoFilter && rxDatabaseRange.is() ) try
+ {
+ // the property 'AutoFilter' enables the drop-down buttons
+ PropertySet aRangeProps( rxDatabaseRange );
+ aRangeProps.setProperty( PROP_AutoFilter, true );
+ // convert filter settings using the filter descriptor of the database range
+ Reference< XSheetFilterDescriptor2 > xFilterDesc( rxDatabaseRange->getFilterDescriptor(), UNO_QUERY_THROW );
+ pAutoFilter->finalizeImport( xFilterDesc );
+ // return true to indicate enabled autofilter
+ return true;
+ }
+ catch( Exception& )
+ {
+ }
+ return false;
+}
+
+AutoFilter* AutoFilterBuffer::getActiveAutoFilter()
+{
+ // Excel expects not more than one auto filter per sheet or table
+ OSL_ENSURE( maAutoFilters.size() == 1, "AutoFilterBuffer::getActiveAutoFilter - too many auto filters" );
+ // stick to the last imported auto filter
+ return maAutoFilters.empty() ? 0 : maAutoFilters.back().get();
+}
+
+// ============================================================================
+
+} // namespace xls
+} // namespace oox
diff --git a/oox/source/xls/autofiltercontext.cxx b/oox/source/xls/autofiltercontext.cxx
index 87514d7804c5..d88e7026b80f 100644
--- a/oox/source/xls/autofiltercontext.cxx
+++ b/oox/source/xls/autofiltercontext.cxx
@@ -27,745 +27,156 @@
#include "oox/xls/autofiltercontext.hxx"
-#include <com/sun/star/container/XNameAccess.hpp>
-#include <com/sun/star/container/XNamed.hpp>
-#include <com/sun/star/i18n/XLocaleData.hpp>
-#include <com/sun/star/sheet/FilterConnection.hpp>
-#include <com/sun/star/sheet/FilterOperator.hpp>
-#include <com/sun/star/sheet/XDatabaseRange.hpp>
-#include <com/sun/star/sheet/XDatabaseRanges.hpp>
-#include <com/sun/star/sheet/XSheetFilterDescriptor.hpp>
-#include <com/sun/star/table/XCellRange.hpp>
-#include <rtl/ustrbuf.hxx>
-#include "oox/core/filterbase.hxx"
-#include "oox/helper/attributelist.hxx"
-#include "oox/helper/propertyset.hxx"
-#include "oox/xls/addressconverter.hxx"
-#include "properties.hxx"
-
-#define DEBUG_OOX_AUTOFILTER 0
-
-#if USE_SC_MULTI_STRING_FILTER_PATCH
-#include <com/sun/star/sheet/XExtendedSheetFilterDescriptor.hpp>
-#include <com/sun/star/sheet/TableFilterFieldNormal.hpp>
-#include <com/sun/star/sheet/TableFilterFieldMultiString.hpp>
-using ::com::sun::star::sheet::TableFilterFieldNormal;
-using ::com::sun::star::sheet::TableFilterFieldMultiString;
-using ::com::sun::star::sheet::XExtendedSheetFilterDescriptor;
-#else
-#include <com/sun/star/sheet/TableFilterField.hpp>
-using ::com::sun::star::sheet::TableFilterField;
-#endif
-
-#if DEBUG_OOX_AUTOFILTER
-#include <stdio.h>
-#endif
-
-using ::rtl::OUString;
-using ::rtl::OUStringBuffer;
-using ::com::sun::star::uno::Reference;
-using ::com::sun::star::uno::Exception;
-using ::com::sun::star::uno::Sequence;
-using ::com::sun::star::uno::UNO_QUERY;
-using ::com::sun::star::uno::UNO_QUERY_THROW;
-using ::com::sun::star::container::XNameAccess;
-using ::com::sun::star::container::XNamed;
-using ::com::sun::star::table::CellRangeAddress;
-using ::com::sun::star::table::XCellRange;
-using ::com::sun::star::sheet::XDatabaseRange;
-using ::com::sun::star::sheet::XDatabaseRanges;
-using ::com::sun::star::sheet::XSheetFilterDescriptor;
-using ::com::sun::star::i18n::LocaleDataItem;
-using ::com::sun::star::i18n::XLocaleData;
-using ::com::sun::star::lang::Locale;
-using ::oox::core::ContextHandlerRef;
+#include "oox/xls/autofilterbuffer.hxx"
+#include "oox/xls/biffinputstream.hxx"
namespace oox {
namespace xls {
-// ============================================================================
-
-FilterFieldItem::FilterFieldItem() :
-#if USE_SC_MULTI_STRING_FILTER_PATCH
- mpField(new TableFilterFieldNormal),
-#else
- mpField(new TableFilterField),
-#endif
- meType(NORMAL)
-{
-}
-
-FilterFieldItem::FilterFieldItem(Type eType) :
- meType(eType)
-{
-#if USE_SC_MULTI_STRING_FILTER_PATCH
- switch ( eType )
- {
- case MULTI_STRING:
- mpField.reset(new TableFilterFieldMultiString);
- break;
- case NORMAL:
- mpField.reset(new TableFilterFieldNormal);
- break;
- default:
- mpField.reset(new TableFilterFieldNormal);
- }
-#else
- mpField.reset(new TableFilterField);
- meType = NORMAL;
-#endif
-}
+using ::oox::core::ContextHandlerRef;
+using ::rtl::OUString;
// ============================================================================
-AutoFilterContext::AutoFilterContext( WorksheetFragmentBase& rFragment ) :
- WorksheetContextBase( rFragment ),
- mbValidAddress( false ),
- mbUseRegex( false ),
- mbShowBlank( false ),
- mbConnectionAnd( false )
+FilterSettingsContext::FilterSettingsContext( WorksheetContextBase& rParent, FilterSettingsBase& rFilterSettings ) :
+ WorksheetContextBase( rParent ),
+ mrFilterSettings( rFilterSettings )
{
}
-ContextHandlerRef AutoFilterContext::onCreateContext( sal_Int32 nElement, const AttributeList& )
+ContextHandlerRef FilterSettingsContext::onCreateContext( sal_Int32 nElement, const AttributeList& /*rAttribs*/ )
{
switch( getCurrentElement() )
{
- case XLS_TOKEN( autoFilter ):
- switch( nElement )
- {
- case XLS_TOKEN( filterColumn ): return this;
- }
- break;
-
- case XLS_TOKEN( filterColumn ):
- switch( nElement )
- {
- case XLS_TOKEN( filters ):
- case XLS_TOKEN( customFilters ):
- case XLS_TOKEN( top10 ):
- case XLS_TOKEN( dynamicFilter ): return this;
- }
- break;
-
case XLS_TOKEN( filters ):
- switch( nElement )
- {
- case XLS_TOKEN( filter ): return this;
- }
+ if( nElement == XLS_TOKEN( filter ) ) return this;
break;
-
case XLS_TOKEN( customFilters ):
- switch( nElement )
- {
- case XLS_TOKEN( customFilter ): return this;
- }
+ if( nElement == XLS_TOKEN( customFilter ) ) return this;
break;
}
return 0;
}
-void AutoFilterContext::onStartElement( const AttributeList& rAttribs )
+void FilterSettingsContext::onStartElement( const AttributeList& rAttribs )
{
- switch( getCurrentElement() )
- {
- case XLS_TOKEN( autoFilter ):
- importAutoFilter( rAttribs );
- break;
- case XLS_TOKEN( filterColumn ):
- if ( mbValidAddress )
- importFilterColumn( rAttribs );
- break;
- case XLS_TOKEN( filters ):
- if ( mbValidAddress )
- importFilters( rAttribs );
- break;
- case XLS_TOKEN( filter ):
- if ( mbValidAddress )
- importFilter( rAttribs );
- break;
- case XLS_TOKEN( customFilters ):
- if ( mbValidAddress )
- importCustomFilters( rAttribs );
- break;
- case XLS_TOKEN( customFilter ):
- if ( mbValidAddress )
- importCustomFilter( rAttribs );
- break;
- case XLS_TOKEN( top10 ):
- if ( mbValidAddress )
- importTop10( rAttribs );
- break;
- case XLS_TOKEN( dynamicFilter ):
- if ( mbValidAddress )
- importDynamicFilter( rAttribs );
- break;
- }
+ mrFilterSettings.importAttribs( getCurrentElement(), rAttribs );
}
-void AutoFilterContext::onEndElement()
+ContextHandlerRef FilterSettingsContext::onCreateRecordContext( sal_Int32 nRecId, RecordInputStream& /*rStrm*/ )
{
switch( getCurrentElement() )
{
- case XLS_TOKEN( autoFilter ):
- maybeShowBlank();
- setAutoFilter();
+ case BIFF12_ID_DISCRETEFILTERS:
+ if( nRecId == BIFF12_ID_DISCRETEFILTER ) return this;
break;
- case XLS_TOKEN( filters ):
- setFilterNames();
+ case BIFF12_ID_CUSTOMFILTERS:
+ if( nRecId == BIFF12_ID_CUSTOMFILTER ) return this;
break;
}
+ return 0;
}
-#if DEBUG_OOX_AUTOFILTER
-static void lclPrintNormalField(
-#if USE_SC_MULTI_STRING_FILTER_PATCH
- TableFilterFieldNormal* pField
-#else
- TableFilterField* pField
-#endif
-)
+void FilterSettingsContext::onStartRecord( RecordInputStream& rStrm )
{
- using namespace ::com::sun::star::sheet;
-
- printf(" Operator: ");
- switch ( pField->Operator )
- {
- case FilterOperator_EQUAL:
- printf("EQUAL");
- break;
- case FilterOperator_NOT_EQUAL:
- printf("NOT_EQUAL");
- break;
- case com::sun::star::sheet::FilterOperator_GREATER:
- printf("GREATER");
- break;
- case com::sun::star::sheet::FilterOperator_GREATER_EQUAL:
- printf("GREATER_EQUAL");
- break;
- case FilterOperator_LESS:
- printf("LESS");
- break;
- case FilterOperator_LESS_EQUAL:
- printf("LESS_EQUAL");
- break;
- case FilterOperator_NOT_EMPTY:
- printf("NOT_EMPTY");
- break;
- case FilterOperator_EMPTY:
- printf("EMPTY");
- break;
- case FilterOperator_BOTTOM_PERCENT:
- printf("BOTTOM_PERCENT");
- break;
- case FilterOperator_BOTTOM_VALUES:
- printf("BOTTOM_VALUES");
- break;
- case FilterOperator_TOP_PERCENT:
- printf("TOP_PERCENT");
- break;
- case FilterOperator_TOP_VALUES:
- printf("TOP_VALUES");
- break;
- default:
- printf("other");
- }
- printf("\n");
-
- printf(" StringValue: %s\n",
- OUStringToOString(pField->StringValue, RTL_TEXTENCODING_UTF8).getStr());
-
- printf(" NumericValue: %g\n", pField->NumericValue);
-
- printf(" IsNumeric: ");
- if (pField->IsNumeric)
- printf("yes\n");
- else
- printf("no\n");
+ mrFilterSettings.importRecord( getCurrentElement(), rStrm );
}
-static void lclPrintFieldConnection( ::com::sun::star::sheet::FilterConnection eConn )
-{
- using namespace ::com::sun::star::sheet;
+// ============================================================================
- printf(" Connection: ");
- switch ( eConn )
- {
- case FilterConnection_AND:
- printf("AND");
- break;
- case FilterConnection_OR:
- printf("OR");
- break;
- case FilterConnection_MAKE_FIXED_SIZE:
- printf("MAKE_FIXED_SIZE");
- break;
- default:
- printf("other");
- }
- printf("\n");
+FilterColumnContext::FilterColumnContext( WorksheetContextBase& rParent, FilterColumn& rFilterColumn ) :
+ WorksheetContextBase( rParent ),
+ mrFilterColumn( rFilterColumn )
+{
}
-static void lclPrintFilterField( const FilterFieldItem& aItem )
+ContextHandlerRef FilterColumnContext::onCreateContext( sal_Int32 nElement, const AttributeList& /*rAttribs*/ )
{
- using namespace ::com::sun::star::sheet;
-
- printf("----------------------------------------\n");
-#if USE_SC_MULTI_STRING_FILTER_PATCH
- {
- // Print common fields first.
-
- TableFilterFieldBase* pField = aItem.mpField.get();
- printf(" Field: %ld\n", pField->Field);
- lclPrintFieldConnection(pField->Connection);
- }
- switch ( aItem.meType )
+ if( getCurrentElement() == XLS_TOKEN( filterColumn ) ) switch( nElement )
{
- case FilterFieldItem::NORMAL:
- {
- TableFilterFieldNormal* pField = static_cast<TableFilterFieldNormal*>(aItem.mpField.get());
- lclPrintNormalField(pField);
- }
- break;
- case FilterFieldItem::MULTI_STRING:
- {
- TableFilterFieldMultiString* pMultiStrField = static_cast<TableFilterFieldMultiString*>(aItem.mpField.get());
- sal_Int32 nSize = pMultiStrField->StringSet.getLength();
- printf(" StringSet:\n");
- for ( sal_Int32 i = 0; i < nSize; ++i )
- {
- printf(" * %s\n",
- OUStringToOString(pMultiStrField->StringSet[i], RTL_TEXTENCODING_UTF8).getStr());
- }
- }
- break;
+ case XLS_TOKEN( filters ):
+ return new FilterSettingsContext( *this, mrFilterColumn.createFilterSettings< DiscreteFilter >() );
+ case XLS_TOKEN( top10 ):
+ return new FilterSettingsContext( *this, mrFilterColumn.createFilterSettings< Top10Filter >() );
+ case XLS_TOKEN( customFilters ):
+ return new FilterSettingsContext( *this, mrFilterColumn.createFilterSettings< CustomFilter >() );
}
-#else
- TableFilterField* pField = aItem.mpField.get();
- printf(" Field: %ld\n", pField->Field);
- lclPrintFieldConnection(pField->Connection);
- lclPrintNormalField(pField);
-
-#endif
- fflush(stdout);
+ return 0;
}
-#endif
-void AutoFilterContext::initialize()
+void FilterColumnContext::onStartElement( const AttributeList& rAttribs )
{
- maFields.clear();
- maFilterNames.clear();
- mbValidAddress = mbShowBlank = mbUseRegex = mbConnectionAnd = false;
+ mrFilterColumn.importFilterColumn( rAttribs );
}
-void AutoFilterContext::setAutoFilter()
+ContextHandlerRef FilterColumnContext::onCreateRecordContext( sal_Int32 nRecId, RecordInputStream& /*rStrm*/ )
{
- using namespace ::com::sun::star::sheet;
-
- // Name this built-in database.
- OUStringBuffer sDataAreaNameBuf( CREATE_OUSTRING("Excel_BuiltIn__FilterDatabase_ ") );
- sDataAreaNameBuf.append( static_cast<sal_Int32>(getSheetIndex()+1) );
-
- OUString sDataAreaName = sDataAreaNameBuf.makeStringAndClear();
- Reference< XCellRange > xCellRange = getCellRange( maAutoFilterRange );
-
- // Create a new database range, add filters to it and refresh the database
- // for that to take effect.
-
- PropertySet aDocProps( getDocument() );
- Reference< XDatabaseRanges > xDBRanges( aDocProps.getAnyProperty( PROP_DatabaseRanges ), UNO_QUERY );
- OSL_ENSURE( xDBRanges.is(), "AutoFilterContext::setAutoFilter: DBRange empty" );
- if ( !xDBRanges.is() )
- return;
-
- Reference< XNameAccess > xNA( xDBRanges, UNO_QUERY_THROW );
- if ( !xNA->hasByName( sDataAreaName ) )
- xDBRanges->addNewByName( sDataAreaName, maAutoFilterRange );
-
- Reference< XDatabaseRange > xDB( xNA->getByName( sDataAreaName ), UNO_QUERY );
- if ( xDB.is() )
- {
- PropertySet aProp( xDB );
- aProp.setProperty( PROP_AutoFilter, true );
- }
-
- sal_Int32 nSize = maFields.size();
- sal_Int32 nMaxFieldCount = nSize;
- Reference< XSheetFilterDescriptor > xDescriptor = xDB->getFilterDescriptor();
- if ( xDescriptor.is() )
- {
- PropertySet aProp( xDescriptor );
- aProp.setProperty( PROP_ContainsHeader, true );
- aProp.setProperty( PROP_UseRegularExpressions, mbUseRegex );
- aProp.getProperty( nMaxFieldCount, PROP_MaxFieldCount );
- }
- else
- {
- OSL_ENSURE(false, "AutoFilterContext::setAutoFilter: descriptor is empty");
- return;
- }
-
- // Unpack all column field items into a sequence.
-#if USE_SC_MULTI_STRING_FILTER_PATCH
- Reference< XExtendedSheetFilterDescriptor > xExtDescriptor( xDescriptor, UNO_QUERY );
- if ( !xExtDescriptor.is() )
- {
- OSL_ENSURE(false, "AutoFilterContext::setAutoFilter: extended descriptor is empty");
- return;
- }
-
- xExtDescriptor->begin();
-
- ::std::list< FilterFieldItem >::const_iterator itr = maFields.begin(), itrEnd = maFields.end();
- for (sal_Int32 i = 0; itr != itrEnd && i < nMaxFieldCount; ++itr, ++i)
+ if( getCurrentElement() == BIFF12_ID_FILTERCOLUMN ) switch( nRecId )
{
-#if DEBUG_OOX_AUTOFILTER
- lclPrintFilterField(*itr);
-#endif
- switch ( itr->meType )
- {
- case oox::xls::FilterFieldItem::MULTI_STRING:
- {
- // multi-string filter type
- TableFilterFieldMultiString* pField = static_cast<TableFilterFieldMultiString*>( itr->mpField.get() );
- xExtDescriptor->addFilterFieldMultiString( *pField );
- }
- break;
- case oox::xls::FilterFieldItem::NORMAL:
- default:
- // normal filter type
- TableFilterFieldNormal* pField = static_cast<TableFilterFieldNormal*>( itr->mpField.get() );
- xExtDescriptor->addFilterFieldNormal( *pField );
- }
+ case BIFF12_ID_DISCRETEFILTERS:
+ return new FilterSettingsContext( *this, mrFilterColumn.createFilterSettings< DiscreteFilter >() );
+ case BIFF12_ID_TOP10FILTER:
+ return new FilterSettingsContext( *this, mrFilterColumn.createFilterSettings< Top10Filter >() );
+ case BIFF12_ID_CUSTOMFILTERS:
+ return new FilterSettingsContext( *this, mrFilterColumn.createFilterSettings< CustomFilter >() );
}
- xExtDescriptor->commit();
-
-#else
- Sequence< TableFilterField > aFields(nSize);
- ::std::list< FilterFieldItem >::const_iterator itr = maFields.begin(), itrEnd = maFields.end();
- for (sal_Int32 i = 0; itr != itrEnd && i < nMaxFieldCount; ++itr, ++i)
- {
-#if DEBUG_OOX_AUTOFILTER
- lclPrintFilterField( *itr );
-#endif
- aFields[i] = *itr->mpField;
- }
- xDescriptor->setFilterFields( aFields );
-#endif
- xDB->refresh();
+ return 0;
}
-void AutoFilterContext::maybeShowBlank()
+void FilterColumnContext::onStartRecord( RecordInputStream& rStrm )
{
- using namespace ::com::sun::star::sheet;
-
- if ( !mbShowBlank )
- return;
-
-#if USE_SC_MULTI_STRING_FILTER_PATCH
- FilterFieldItem aItem(FilterFieldItem::NORMAL);
- TableFilterFieldNormal* pField = static_cast<TableFilterFieldNormal*>(aItem.mpField.get());
- pField->Field = mnCurColID;
- pField->Operator = FilterOperator_EMPTY;
- pField->Connection = FilterConnection_AND;
- pField->IsNumeric = false;
-#else
- FilterFieldItem aItem;
- aItem.mpField->Field = mnCurColID;
- aItem.mpField->Operator = FilterOperator_EMPTY;
- aItem.mpField->Connection = FilterConnection_AND;
- aItem.mpField->IsNumeric = false;
-#endif
- maFields.push_back(aItem);
+ mrFilterColumn.importFilterColumn( rStrm );
}
-void AutoFilterContext::setFilterNames()
-{
- using namespace ::com::sun::star::sheet;
-
-
- sal_Int32 size = maFilterNames.size();
- if ( !size )
- return;
-
-#if USE_SC_MULTI_STRING_FILTER_PATCH
- Sequence< OUString > aStrList(size);
- ::std::list< OUString >::const_iterator itr = maFilterNames.begin(), itrEnd = maFilterNames.end();
- for (sal_Int32 i = 0; itr != itrEnd; ++itr, ++i)
- aStrList[i] = *itr;
-
- FilterFieldItem aItem(FilterFieldItem::MULTI_STRING);
- TableFilterFieldMultiString* pField = static_cast<TableFilterFieldMultiString*>( aItem.mpField.get() );
- pField->Field = mnCurColID;
- pField->Connection = FilterConnection_AND;
- pField->StringSet = aStrList;
-
- maFields.push_back(aItem);
-#else
- static const OUString sSep = CREATE_OUSTRING("|");
-
- OUStringBuffer buf;
- if ( size > 1 )
- {
- buf.append( CREATE_OUSTRING("^(") );
- mbUseRegex = true;
- }
-
- ::std::list< OUString >::const_iterator itr = maFilterNames.begin(), itrEnd = maFilterNames.end();
- bool bFirst = true;
- for (; itr != itrEnd; ++itr)
- {
- if (bFirst)
- bFirst = false;
- else
- buf.append( sSep );
- buf.append( *itr );
- }
- if ( size > 1 )
- buf.append( CREATE_OUSTRING(")$") );
-
- FilterFieldItem aItem;
- aItem.mpField->Field = mnCurColID;
- aItem.mpField->StringValue = buf.makeStringAndClear();
- aItem.mpField->Operator = FilterOperator_EQUAL;
- aItem.mpField->Connection = FilterConnection_AND;
- aItem.mpField->IsNumeric = false;
- maFields.push_back(aItem);
-#endif
-}
+// ============================================================================
-void AutoFilterContext::importAutoFilter( const AttributeList& rAttribs )
+AutoFilterContext::AutoFilterContext( WorksheetFragmentBase& rFragment, AutoFilter& rAutoFilter ) :
+ WorksheetContextBase( rFragment ),
+ mrAutoFilter( rAutoFilter )
{
- initialize();
-
- mbValidAddress = getAddressConverter().convertToCellRange(
- maAutoFilterRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex(), true, true );
}
-void AutoFilterContext::importFilterColumn( const AttributeList& rAttribs )
+ContextHandlerRef AutoFilterContext::onCreateContext( sal_Int32 nElement, const AttributeList& /*rAttribs*/ )
{
- // hiddenButton and showButton attributes are not used for now.
- mnCurColID = rAttribs.getInteger( XML_colId, -1 );
+ if( (getCurrentElement() == XLS_TOKEN( autoFilter )) && (nElement == XLS_TOKEN( filterColumn )) )
+ return new FilterColumnContext( *this, mrAutoFilter.createFilterColumn() );
+ return 0;
}
-void AutoFilterContext::importTop10( const AttributeList& rAttribs )
+void AutoFilterContext::onStartElement( const AttributeList& rAttribs )
{
- using namespace ::com::sun::star::sheet;
-
- // filterVal attribute is not necessarily, since Calc also supports top 10
- // and top 10% filter type.
- FilterFieldItem aItem;
-#if USE_SC_MULTI_STRING_FILTER_PATCH
- TableFilterFieldNormal* pField = static_cast<TableFilterFieldNormal*>(aItem.mpField.get());
-#else
- TableFilterField* pField = aItem.mpField.get();
-#endif
- pField->Field = mnCurColID;
-
- bool bPercent = rAttribs.getBool( XML_percent, false );
- bool bTop = rAttribs.getBool( XML_top, true );
- pField->NumericValue = rAttribs.getDouble( XML_val, 0.0 );
- pField->IsNumeric = true;
-
- // When top10 filter item is present, that's the only filter item for that column.
- if ( bTop )
- if ( bPercent )
- pField->Operator = FilterOperator_TOP_PERCENT;
- else
- pField->Operator = FilterOperator_TOP_VALUES;
- else
- if ( bPercent )
- pField->Operator = FilterOperator_BOTTOM_PERCENT;
- else
- pField->Operator = FilterOperator_BOTTOM_VALUES;
-
- maFields.push_back(aItem);
+ mrAutoFilter.importAutoFilter( rAttribs, getSheetIndex() );
}
-void AutoFilterContext::importCustomFilters( const AttributeList& rAttribs )
+ContextHandlerRef AutoFilterContext::onCreateRecordContext( sal_Int32 nRecId, RecordInputStream& /*rStrm*/ )
{
- // OR is default when the 'and' attribute is absent.
- mbConnectionAnd = rAttribs.getBool( XML_and, false );
+ if( (getCurrentElement() == BIFF12_ID_AUTOFILTER) && (nRecId == BIFF12_ID_FILTERCOLUMN) )
+ return new FilterColumnContext( *this, mrAutoFilter.createFilterColumn() );
+ return 0;
}
-/** Do a best-effort guess of whether or not the given string is numerical. */
-static bool lclIsNumeric( const OUString& _str, const LocaleDataItem& aLocaleItem )
+void AutoFilterContext::onStartRecord( RecordInputStream& rStrm )
{
- OUString str = _str.trim();
- sal_Int32 size = str.getLength();
-
- if ( !size )
- // Empty string. This can't be a number.
- return false;
-
- // Get the decimal separator for the current locale.
- const OUString& sep = aLocaleItem.decimalSeparator;
-
- bool bDecimalSep = false;
- for (sal_Int32 i = 0; i < size; ++i)
- {
- OUString c = str.copy(i, 1);
- if ( !c.compareTo(sep) )
- {
- if ( bDecimalSep )
- return false;
- else
- {
- bDecimalSep = true;
- continue;
- }
- }
- if ( (0 > c.compareToAscii("0") || 0 < c.compareToAscii("9")) )
- return false;
- }
-
- return true;
+ mrAutoFilter.importAutoFilter( rStrm, getSheetIndex() );
}
-/** Convert wildcard characters to regex equivalent. Returns true if any
- wildcard character is found. */
-static bool lclWildcard2Regex( OUString& str )
-{
- bool bWCFound = false;
- OUStringBuffer buf;
- sal_Int32 size = str.getLength();
- buf.ensureCapacity(size + 6); // pure heuristics.
-
- sal_Unicode dot = '.', star = '*', hat = '^', dollar = '$';
- buf.append(hat);
- for (sal_Int32 i = 0; i < size; ++i)
- {
- OUString c = str.copy(i, 1);
- if ( !c.compareToAscii("?") )
- {
- buf.append(dot);
- bWCFound = true;
- }
- else if ( !c.compareToAscii("*") )
- {
- buf.append(dot);
- buf.append(star);
- bWCFound = true;
- }
- else
- buf.append(c);
- }
- buf.append(dollar);
-
- if (bWCFound)
- str = buf.makeStringAndClear();
-
- return bWCFound;
-}
+// ============================================================================
-/** Translate Excel's filter operator to Calc's. */
-static ::com::sun::star::sheet::FilterOperator lclTranslateFilterOp( sal_Int32 nToken )
+BiffAutoFilterContext::BiffAutoFilterContext( const WorksheetHelper& rHelper, AutoFilter& rAutoFilter ) :
+ BiffWorksheetContextBase( rHelper ),
+ mrAutoFilter( rAutoFilter )
{
- using namespace ::com::sun::star::sheet;
-
- switch ( nToken )
- {
- case XML_equal:
- return FilterOperator_EQUAL;
- case XML_notEqual:
- return FilterOperator_NOT_EQUAL;
- case XML_greaterThan:
- return FilterOperator_GREATER;
- case XML_greaterThanOrEqual:
- return FilterOperator_GREATER_EQUAL;
- case XML_lessThan:
- return FilterOperator_LESS;
- case XML_lessThanOrEqual:
- return FilterOperator_LESS_EQUAL;
- }
- return FilterOperator_EQUAL;
}
-void AutoFilterContext::importCustomFilter( const AttributeList& rAttribs )
+void BiffAutoFilterContext::importRecord( BiffInputStream& rStrm )
{
- using namespace ::com::sun::star::sheet;
-
- sal_Int32 nToken = rAttribs.getToken( XML_operator, XML_equal );
-#if USE_SC_MULTI_STRING_FILTER_PATCH
- FilterFieldItem aItem(FilterFieldItem::NORMAL);
- TableFilterFieldNormal* pField = static_cast<TableFilterFieldNormal*>(aItem.mpField.get());
-#else
- FilterFieldItem aItem;
- TableFilterField* pField = aItem.mpField.get();
-#endif
- pField->Field = mnCurColID;
- pField->StringValue = rAttribs.getString( XML_val, OUString() );
- pField->NumericValue = pField->StringValue.toDouble();
- pField->Operator = lclTranslateFilterOp( nToken );
-
- if ( nToken == XML_notEqual && !pField->StringValue.compareToAscii(" ") )
- {
- // Special case for hiding blanks. Excel translates "hide blanks" to
- // (filter if notEqual " "). So, we need to translate it back.
- pField->Operator = FilterOperator_NOT_EMPTY;
- pField->IsNumeric = false;
- maFields.push_back(aItem);
- return;
- }
-
- switch ( nToken )
+ switch( rStrm.getRecId() )
{
- case XML_equal:
- case XML_notEqual:
- {
- Reference< XLocaleData > xLocale( getGlobalFactory()->createInstance(
- CREATE_OUSTRING("com.sun.star.i18n.LocaleData") ), UNO_QUERY );
-
- if ( !xLocale.is() )
- return;
-
- LocaleDataItem aLocaleItem = xLocale->getLocaleItem( ::com::sun::star::lang::Locale() );
- pField->IsNumeric = lclIsNumeric(pField->StringValue, aLocaleItem);
-
- if ( !pField->IsNumeric && lclWildcard2Regex(pField->StringValue) )
- mbUseRegex = true;
-
- maFields.push_back(aItem);
- }
- break;
-
- case XML_greaterThan:
- case XML_greaterThanOrEqual:
- case XML_lessThan:
- case XML_lessThanOrEqual:
- {
- pField->IsNumeric = true;
- maFields.push_back(aItem);
- }
- break;
- default:
- OSL_ENSURE( false, "AutoFilterContext::importCustomFilter: unhandled case" );
+ // nothing to read for BIFF_ID_AUTOFILTER
+ case BIFF_ID_FILTERCOLUMN: mrAutoFilter.createFilterColumn().importFilterColumn( rStrm ); break;
}
}
-void AutoFilterContext::importFilters( const AttributeList& rAttribs )
-{
- // blank (boolean) and calendarType attributes can be present, but not used for now.
-
- mbShowBlank = rAttribs.getBool( XML_blank, false );
- maFilterNames.clear();
-}
-
-void AutoFilterContext::importFilter( const AttributeList& rAttribs )
-{
- if (mnCurColID == -1)
- return;
-
- OUString value = rAttribs.getString( XML_val, OUString() );
- if ( value.getLength() )
- maFilterNames.push_back(value);
-}
-
-void AutoFilterContext::importDynamicFilter( const AttributeList& /*rAttribs*/ )
-{
- // not implemented yet - Calc doesn't support this.
-}
-
// ============================================================================
} // namespace xls
diff --git a/oox/source/xls/connectionsbuffer.cxx b/oox/source/xls/connectionsbuffer.cxx
index 8a1d2c718948..12df30fe493f 100755
--- a/oox/source/xls/connectionsbuffer.cxx
+++ b/oox/source/xls/connectionsbuffer.cxx
@@ -51,6 +51,9 @@ const sal_Int32 BIFF12_RECONNECT_AS_REQUIRED = 1;
const sal_Int32 BIFF12_RECONNECT_ALWAYS = 2;
const sal_Int32 BIFF12_RECONNECT_NEVER = 3;
+const sal_uInt8 BIFF12_CONNECTION_SAVEPASSWORD_ON = 1;
+const sal_uInt8 BIFF12_CONNECTION_SAVEPASSWORD_OFF = 2;
+
const sal_uInt16 BIFF12_CONNECTION_KEEPALIVE = 0x0001;
const sal_uInt16 BIFF12_CONNECTION_NEW = 0x0002;
const sal_uInt16 BIFF12_CONNECTION_DELETED = 0x0004;
@@ -187,6 +190,7 @@ ConnectionModel::ConnectionModel() :
mnId( -1 ),
mnType( BIFF12_CONNECTION_UNKNOWN ),
mnReconnectMethod( BIFF12_RECONNECT_AS_REQUIRED ),
+ mnCredentials( XML_integrated ),
mnInterval( 0 ),
mbKeepAlive( false ),
mbNew( false ),
@@ -194,7 +198,8 @@ ConnectionModel::ConnectionModel() :
mbOnlyUseConnFile( false ),
mbBackground( false ),
mbRefreshOnLoad( false ),
- mbSaveData( false )
+ mbSaveData( false ),
+ mbSavePassword( false )
{
}
@@ -224,6 +229,7 @@ void Connection::importConnection( const AttributeList& rAttribs )
// type and reconnectionMethod are using the BIFF12 constants instead of XML tokens
maModel.mnType = rAttribs.getInteger( XML_type, BIFF12_CONNECTION_UNKNOWN );
maModel.mnReconnectMethod = rAttribs.getInteger( XML_reconnectionMethod, BIFF12_RECONNECT_AS_REQUIRED );
+ maModel.mnCredentials = rAttribs.getToken( XML_credentials, XML_integrated );
maModel.mnInterval = rAttribs.getInteger( XML_interval, 0 );
maModel.mbKeepAlive = rAttribs.getBool( XML_keepAlive, false );
maModel.mbNew = rAttribs.getBool( XML_new, false );
@@ -231,6 +237,8 @@ void Connection::importConnection( const AttributeList& rAttribs )
maModel.mbOnlyUseConnFile = rAttribs.getBool( XML_onlyUseConnectionFile, false );
maModel.mbBackground = rAttribs.getBool( XML_background, false );
maModel.mbRefreshOnLoad = rAttribs.getBool( XML_refreshOnLoad, false );
+ maModel.mbSaveData = rAttribs.getBool( XML_saveData, false );
+ maModel.mbSavePassword = rAttribs.getBool( XML_savePassword, false );
}
void Connection::importWebPr( const AttributeList& rAttribs )
@@ -281,11 +289,13 @@ void Connection::importTable( const AttributeList& rAttribs, sal_Int32 nElement
void Connection::importConnection( RecordInputStream& rStrm )
{
- rStrm.skip( 4 );
sal_uInt16 nFlags, nStrFlags;
+ sal_uInt8 nSavePassword, nCredentials;
+ rStrm.skip( 2 );
+ rStrm >> nSavePassword;
+ rStrm.skip( 1 );
maModel.mnInterval = rStrm.readuInt16();
- rStrm >> nFlags >> nStrFlags >> maModel.mnType >> maModel.mnReconnectMethod >> maModel.mnId;
- rStrm.skip( 1 ); // credentials
+ rStrm >> nFlags >> nStrFlags >> maModel.mnType >> maModel.mnReconnectMethod >> maModel.mnId >> nCredentials;
if( getFlag( nStrFlags, BIFF12_CONNECTION_HAS_SOURCEFILE ) )
rStrm >> maModel.maSourceFile;
@@ -298,6 +308,9 @@ void Connection::importConnection( RecordInputStream& rStrm )
if( getFlag( nStrFlags, BIFF12_CONNECTION_HAS_SSOID ) )
rStrm >> maModel.maSsoId;
+ static const sal_Int32 spnCredentials[] = { XML_integrated, XML_none, XML_stored, XML_prompt };
+ maModel.mnCredentials = STATIC_ARRAY_SELECT( spnCredentials, nCredentials, XML_integrated );
+
maModel.mbKeepAlive = getFlag( nFlags, BIFF12_CONNECTION_KEEPALIVE );
maModel.mbNew = getFlag( nFlags, BIFF12_CONNECTION_NEW );
maModel.mbDeleted = getFlag( nFlags, BIFF12_CONNECTION_DELETED );
@@ -305,6 +318,7 @@ void Connection::importConnection( RecordInputStream& rStrm )
maModel.mbBackground = getFlag( nFlags, BIFF12_CONNECTION_BACKGROUND );
maModel.mbRefreshOnLoad = getFlag( nFlags, BIFF12_CONNECTION_REFRESHONLOAD );
maModel.mbSaveData = getFlag( nFlags, BIFF12_CONNECTION_SAVEDATA );
+ maModel.mbSavePassword = nSavePassword == BIFF12_CONNECTION_SAVEPASSWORD_ON;
}
void Connection::importWebPr( RecordInputStream& rStrm )
@@ -370,6 +384,7 @@ void Connection::importDbQuery( BiffInputStream& rStrm )
// same type constants in all BIFF versions
maModel.mnType = extractValue< sal_Int32 >( nFlags, 0, 3 );
+ maModel.mbSavePassword = getFlag( nFlags, BIFF_DBQUERY_SAVEPASSWORD );
OSL_ENSURE( getFlag( nFlags, BIFF_DBQUERY_ODBC ) == (maModel.mnType == BIFF12_CONNECTION_ODBC), "Connection::importDbQuery - wrong ODBC flag" );
OSL_ENSURE( getFlag( nFlags, BIFF_DBQUERY_SQLQUERY ) != (maModel.mnType == BIFF12_CONNECTION_HTML), "Connection::importDbQuery - wrong SQL query flag" );
@@ -446,41 +461,39 @@ ConnectionsBuffer::ConnectionsBuffer( const WorkbookHelper& rHelper ) :
{
}
-ConnectionRef ConnectionsBuffer::importConnection( const AttributeList& rAttribs )
+Connection& ConnectionsBuffer::createConnection()
{
ConnectionRef xConnection( new Connection( *this ) );
- xConnection->importConnection( rAttribs );
- insertConnection( xConnection );
- return xConnection;
+ maConnections.push_back( xConnection );
+ return *xConnection;
}
-ConnectionRef ConnectionsBuffer::importConnection( RecordInputStream& rStrm )
+Connection& ConnectionsBuffer::createConnectionWithId()
{
- ConnectionRef xConnection( new Connection( *this ) );
- xConnection->importConnection( rStrm );
- insertConnection( xConnection );
- return xConnection;
+ ConnectionRef xConnection( new Connection( *this, mnUnusedId ) );
+ maConnections.push_back( xConnection );
+ insertConnectionToMap( xConnection );
+ return *xConnection;
}
-ConnectionRef ConnectionsBuffer::createConnection()
+void ConnectionsBuffer::finalizeImport()
{
- ConnectionRef xConnection( new Connection( *this, mnUnusedId ) );
- insertConnection( xConnection );
- return xConnection;
+ for( ConnectionVector::iterator aIt = maConnections.begin(), aEnd = maConnections.end(); aIt != aEnd; ++aIt )
+ insertConnectionToMap( *aIt );
}
ConnectionRef ConnectionsBuffer::getConnection( sal_Int32 nConnId ) const
{
- return maConnections.get( nConnId );
+ return maConnectionsById.get( nConnId );
}
-void ConnectionsBuffer::insertConnection( const ConnectionRef& rxConnection )
+void ConnectionsBuffer::insertConnectionToMap( const ConnectionRef& rxConnection )
{
sal_Int32 nConnId = rxConnection->getConnectionId();
if( nConnId > 0 )
{
- OSL_ENSURE( !maConnections.has( nConnId ), "ConnectionsBuffer::insertConnection - multiple connection identifier" );
- maConnections[ nConnId ] = rxConnection;
+ OSL_ENSURE( !maConnectionsById.has( nConnId ), "ConnectionsBuffer::insertConnectionToMap - multiple connection identifier" );
+ maConnectionsById[ nConnId ] = rxConnection;
mnUnusedId = ::std::max< sal_Int32 >( mnUnusedId, nConnId + 1 );
}
}
diff --git a/oox/source/xls/connectionsfragment.cxx b/oox/source/xls/connectionsfragment.cxx
index ee4aaa3a059e..f83f9028faa8 100644
--- a/oox/source/xls/connectionsfragment.cxx
+++ b/oox/source/xls/connectionsfragment.cxx
@@ -29,6 +29,7 @@
#include "oox/helper/attributelist.hxx"
#include "oox/xls/biffhelper.hxx"
+#include "oox/xls/connectionsbuffer.hxx"
namespace oox {
namespace xls {
@@ -41,11 +42,10 @@ using ::oox::core::RecordInfo;
// ============================================================================
-ConnectionContext::ConnectionContext( WorkbookFragmentBase& rParent, const ConnectionRef& rxConnection ) :
+ConnectionContext::ConnectionContext( WorkbookFragmentBase& rParent, Connection& rConnection ) :
WorkbookContextBase( rParent ),
- mxConnection( rxConnection )
+ mrConnection( rConnection )
{
- OSL_ENSURE( mxConnection.get(), "ConnectionContext::ConnectionContext - missing connection" );
}
ContextHandlerRef ConnectionContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
@@ -55,7 +55,7 @@ ContextHandlerRef ConnectionContext::onCreateContext( sal_Int32 nElement, const
case XLS_TOKEN( connection ):
if( nElement == XLS_TOKEN( webPr ) )
{
- mxConnection->importWebPr( rAttribs );
+ mrConnection.importWebPr( rAttribs );
return this;
}
break;
@@ -63,18 +63,24 @@ ContextHandlerRef ConnectionContext::onCreateContext( sal_Int32 nElement, const
case XLS_TOKEN( webPr ):
if( nElement == XLS_TOKEN( tables ) )
{
- mxConnection->importTables( rAttribs );
+ mrConnection.importTables( rAttribs );
return this;
}
break;
case XLS_TOKEN( tables ):
- mxConnection->importTable( rAttribs, nElement );
+ mrConnection.importTable( rAttribs, nElement );
break;
}
return 0;
}
+void ConnectionContext::onStartElement( const AttributeList& rAttribs )
+{
+ if( getCurrentElement() == XLS_TOKEN( connection ) )
+ mrConnection.importConnection( rAttribs );
+}
+
ContextHandlerRef ConnectionContext::onCreateRecordContext( sal_Int32 nRecId, RecordInputStream& rStrm )
{
switch( getCurrentElement() )
@@ -82,7 +88,7 @@ ContextHandlerRef ConnectionContext::onCreateRecordContext( sal_Int32 nRecId, Re
case BIFF12_ID_CONNECTION:
if( nRecId == BIFF12_ID_WEBPR )
{
- mxConnection->importWebPr( rStrm );
+ mrConnection.importWebPr( rStrm );
return this;
}
break;
@@ -90,18 +96,24 @@ ContextHandlerRef ConnectionContext::onCreateRecordContext( sal_Int32 nRecId, Re
case BIFF12_ID_WEBPR:
if( nRecId == BIFF12_ID_WEBPRTABLES )
{
- mxConnection->importWebPrTables( rStrm );
+ mrConnection.importWebPrTables( rStrm );
return this;
}
break;
case BIFF12_ID_WEBPRTABLES:
- mxConnection->importWebPrTable( rStrm, nRecId );
+ mrConnection.importWebPrTable( rStrm, nRecId );
break;
}
return 0;
}
+void ConnectionContext::onStartRecord( RecordInputStream& rStrm )
+{
+ if( getCurrentElement() == BIFF12_ID_CONNECTION )
+ mrConnection.importConnection( rStrm );
+}
+
// ============================================================================
ConnectionsFragment::ConnectionsFragment( const WorkbookHelper& rHelper, const OUString& rFragmentPath ) :
@@ -109,7 +121,7 @@ ConnectionsFragment::ConnectionsFragment( const WorkbookHelper& rHelper, const O
{
}
-ContextHandlerRef ConnectionsFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
+ContextHandlerRef ConnectionsFragment::onCreateContext( sal_Int32 nElement, const AttributeList& /*rAttribs*/ )
{
switch( getCurrentElement() )
{
@@ -120,17 +132,13 @@ ContextHandlerRef ConnectionsFragment::onCreateContext( sal_Int32 nElement, cons
case XLS_TOKEN( connections ):
if( nElement == XLS_TOKEN( connection ) )
- {
- ConnectionRef xConnection = getConnections().importConnection( rAttribs );
- if( xConnection.get() )
- return new ConnectionContext( *this, xConnection );
- }
+ return new ConnectionContext( *this, getConnections().createConnection() );
break;
}
return 0;
}
-ContextHandlerRef ConnectionsFragment::onCreateRecordContext( sal_Int32 nRecId, RecordInputStream& rStrm )
+ContextHandlerRef ConnectionsFragment::onCreateRecordContext( sal_Int32 nRecId, RecordInputStream& /*rStrm*/ )
{
switch( getCurrentElement() )
{
@@ -141,11 +149,7 @@ ContextHandlerRef ConnectionsFragment::onCreateRecordContext( sal_Int32 nRecId,
case BIFF12_ID_CONNECTIONS:
if( nRecId == BIFF12_ID_CONNECTION )
- {
- ConnectionRef xConnection = getConnections().importConnection( rStrm );
- if( xConnection.get() )
- return new ConnectionContext( *this, xConnection );
- }
+ return new ConnectionContext( *this, getConnections().createConnection() );
break;
}
return 0;
@@ -164,6 +168,11 @@ const RecordInfo* ConnectionsFragment::getRecordInfos() const
return spRecInfos;
}
+void ConnectionsFragment::finalizeImport()
+{
+ getConnections().finalizeImport();
+}
+
// ============================================================================
} // namespace xls
diff --git a/oox/source/xls/defnamesbuffer.cxx b/oox/source/xls/defnamesbuffer.cxx
index 6ff80e0efe64..94ca1fb321bf 100644
--- a/oox/source/xls/defnamesbuffer.cxx
+++ b/oox/source/xls/defnamesbuffer.cxx
@@ -81,6 +81,11 @@ const sal_uInt8 BIFF2_DEFNAME_FUNC = 0x02; /// BIFF2 function/comma
const sal_uInt16 BIFF_DEFNAME_GLOBAL = 0; /// 0 = Globally defined name.
+const sal_uInt16 BIFF_REFFLAG_COL1REL = 0x0001;
+const sal_uInt16 BIFF_REFFLAG_ROW1REL = 0x0002;
+const sal_uInt16 BIFF_REFFLAG_COL2REL = 0x0004;
+const sal_uInt16 BIFF_REFFLAG_ROW2REL = 0x0008;
+
// ----------------------------------------------------------------------------
const sal_Char* const spcLegacyPrefix = "Excel_BuiltIn_";
@@ -88,20 +93,20 @@ const sal_Char* const spcOoxPrefix = "_xlnm.";
const sal_Char* const sppcBaseNames[] =
{
- "Consolidate_Area", /* OOXML */
+ "Consolidate_Area",
"Auto_Open",
"Auto_Close",
- "Extract", /* OOXML */
- "Database", /* OOXML */
- "Criteria", /* OOXML */
- "Print_Area", /* OOXML */
- "Print_Titles", /* OOXML */
+ "Extract",
+ "Database",
+ "Criteria",
+ "Print_Area",
+ "Print_Titles",
"Recorder",
"Data_Form",
"Auto_Activate",
"Auto_Deactivate",
- "Sheet_Title", /* OOXML */
- "_FilterDatabase" /* OOXML */
+ "Sheet_Title",
+ "_FilterDatabase"
};
/** Localized names for _xlnm._FilterDatabase as used in BIFF5. */
@@ -113,7 +118,7 @@ const sal_Char* const sppcFilterDbNames[] =
OUString lclGetBaseName( sal_Unicode cBuiltinId )
{
- OSL_ENSURE( cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ), "lclGetBaseName - unknown builtin name" );
+ OSL_ENSURE( cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ), "lclGetBaseName - unsupported built-in identifier" );
OUStringBuffer aBuffer;
if( cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ) )
aBuffer.appendAscii( sppcBaseNames[ cBuiltinId ] );
@@ -122,67 +127,52 @@ OUString lclGetBaseName( sal_Unicode cBuiltinId )
return aBuffer.makeStringAndClear();
}
-OUString lclGetBuiltinName( sal_Unicode cBuiltinId )
+OUString lclGetPrefixedName( sal_Unicode cBuiltinId )
{
return OUStringBuffer().appendAscii( spcOoxPrefix ).append( lclGetBaseName( cBuiltinId ) ).makeStringAndClear();
}
-sal_Unicode lclGetBuiltinIdFromOox( const OUString& rOoxName )
+/** returns the built-in name identifier from a perfixed built-in name, e.g. '_xlnm.Print_Area'. */
+sal_Unicode lclGetBuiltinIdFromPrefixedName( const OUString& rModelName )
{
OUString aPrefix = OUString::createFromAscii( spcOoxPrefix );
sal_Int32 nPrefixLen = aPrefix.getLength();
- if( rOoxName.matchIgnoreAsciiCase( aPrefix ) )
+ if( rModelName.matchIgnoreAsciiCase( aPrefix ) )
{
for( sal_Unicode cBuiltinId = 0; cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ); ++cBuiltinId )
{
OUString aBaseName = lclGetBaseName( cBuiltinId );
sal_Int32 nBaseNameLen = aBaseName.getLength();
- if( (rOoxName.getLength() == nPrefixLen + nBaseNameLen) && rOoxName.matchIgnoreAsciiCase( aBaseName, nPrefixLen ) )
+ if( (rModelName.getLength() == nPrefixLen + nBaseNameLen) && rModelName.matchIgnoreAsciiCase( aBaseName, nPrefixLen ) )
return cBuiltinId;
}
}
return BIFF_DEFNAME_UNKNOWN;
}
-sal_Unicode lclGetBuiltinIdFromBiff( const OUString& rName )
+/** returns the built-in name identifier from a built-in base name, e.g. 'Print_Area'. */
+sal_Unicode lclGetBuiltinIdFromBaseName( const OUString& rModelName )
{
for( sal_Unicode cBuiltinId = 0; cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ); ++cBuiltinId )
- if( rName.equalsIgnoreAsciiCaseAscii( sppcBaseNames[ cBuiltinId ] ) )
+ if( rModelName.equalsIgnoreAsciiCaseAscii( sppcBaseNames[ cBuiltinId ] ) )
return cBuiltinId;
return BIFF_DEFNAME_UNKNOWN;
}
-bool lclIsFilterDatabaseName( const OUString& rName )
+bool lclIsFilterDatabaseName( const OUString& rModelName )
{
for( const sal_Char* const* ppcName = sppcFilterDbNames; ppcName < STATIC_ARRAY_END( sppcFilterDbNames ); ++ppcName )
- if( rName.equalsIgnoreAsciiCaseAscii( *ppcName ) )
+ if( rModelName.equalsIgnoreAsciiCaseAscii( *ppcName ) )
return true;
return false;
}
-} // namespace
-
-// ============================================================================
-
-DefinedNameModel::DefinedNameModel() :
- mnSheet( -1 ),
- mnFuncGroupId( -1 ),
- mbMacro( false ),
- mbFunction( false ),
- mbVBName( false ),
- mbHidden( false )
+OUString lclGetUpcaseModelName( const OUString& rModelName )
{
+ // TODO: i18n?
+ return rModelName.toAsciiUpperCase();
}
-// ============================================================================
-
-namespace {
-
-const sal_uInt16 BIFF_REFFLAG_COL1REL = 0x0001;
-const sal_uInt16 BIFF_REFFLAG_ROW1REL = 0x0002;
-const sal_uInt16 BIFF_REFFLAG_COL2REL = 0x0004;
-const sal_uInt16 BIFF_REFFLAG_ROW2REL = 0x0008;
-
void lclConvertRefFlags( sal_Int32& ornFlags, sal_Int32& ornAbsPos, sal_Int32& ornRelPos, sal_Int32 nBasePos, sal_Int32 nApiRelFlag, bool bRel )
{
if( getFlag( ornFlags, nApiRelFlag ) && !bRel )
@@ -232,7 +222,19 @@ Any lclConvertReference( const Any& rRefAny, const CellAddress& rBaseAddress, sa
} // namespace
-// ----------------------------------------------------------------------------
+// ============================================================================
+
+DefinedNameModel::DefinedNameModel() :
+ mnSheet( -1 ),
+ mnFuncGroupId( -1 ),
+ mbMacro( false ),
+ mbFunction( false ),
+ mbVBName( false ),
+ mbHidden( false )
+{
+}
+
+// ============================================================================
DefinedNameBase::DefinedNameBase( const WorkbookHelper& rHelper ) :
WorkbookHelper( rHelper )
@@ -242,7 +244,7 @@ DefinedNameBase::DefinedNameBase( const WorkbookHelper& rHelper ) :
const OUString& DefinedNameBase::getUpcaseModelName() const
{
if( maUpModelName.getLength() == 0 )
- maUpModelName = maModel.maName.toAsciiUpperCase();
+ maUpModelName = lclGetUpcaseModelName( maModel.maName );
return maUpModelName;
}
@@ -325,8 +327,11 @@ void DefinedName::importDefinedName( const AttributeList& rAttribs )
maModel.mbFunction = rAttribs.getBool( XML_function, false );
maModel.mbVBName = rAttribs.getBool( XML_vbProcedure, false );
maModel.mbHidden = rAttribs.getBool( XML_hidden, false );
- mcBuiltinId = lclGetBuiltinIdFromOox( maModel.maName );
mnCalcSheet = (maModel.mnSheet >= 0) ? getWorksheets().getCalcSheetIndex( maModel.mnSheet ) : -1;
+
+ /* Detect built-in state from name itself, there is no built-in flag.
+ Built-in names are prexixed with '_xlnm.' instead. */
+ mcBuiltinId = lclGetBuiltinIdFromPrefixedName( maModel.maName );
}
void DefinedName::setFormula( const OUString& rFormula )
@@ -349,12 +354,9 @@ void DefinedName::importDefinedName( RecordInputStream& rStrm )
maModel.mbVBName = getFlag( nFlags, BIFF12_DEFNAME_VBNAME );
maModel.mbHidden = getFlag( nFlags, BIFF12_DEFNAME_HIDDEN );
- // get builtin name index from name
+ // get built-in name index from name
if( getFlag( nFlags, BIFF12_DEFNAME_BUILTIN ) )
- mcBuiltinId = lclGetBuiltinIdFromBiff( maModel.maName );
- // unhide built-in names (_xlnm._FilterDatabase is always hidden)
- if( isBuiltinName() )
- maModel.mbHidden = false;
+ mcBuiltinId = lclGetBuiltinIdFromBaseName( maModel.maName );
// store token array data
sal_Int64 nRecPos = rStrm.tell();
@@ -416,24 +418,22 @@ void DefinedName::importDefinedName( BiffInputStream& rStrm, sal_Int16 nCalcShee
maModel.mbVBName = getFlag( nFlags, BIFF_DEFNAME_VBNAME );
maModel.mbHidden = getFlag( nFlags, BIFF_DEFNAME_HIDDEN );
- // get builtin name index from name
+ // get built-in name index from name
if( getFlag( nFlags, BIFF_DEFNAME_BUILTIN ) )
{
- OSL_ENSURE( maModel.maName.getLength() == 1, "DefinedName::importDefinedName - wrong builtin name" );
- if( maModel.maName.getLength() > 0 )
+ // name may be the built-in identifier or the built-in base name
+ if( maModel.maName.getLength() == 1 )
mcBuiltinId = maModel.maName[ 0 ];
+ else
+ mcBuiltinId = lclGetBuiltinIdFromBaseName( maModel.maName );
}
- /* In BIFF5, _xlnm._FilterDatabase appears as hidden user name without
+ /* In BIFF5, '_FilterDatabase' appears as hidden user name without
built-in flag, and even worse, localized. */
else if( (eBiff == BIFF5) && lclIsFilterDatabaseName( maModel.maName ) )
{
mcBuiltinId = BIFF_DEFNAME_FILTERDATABASE;
}
- // unhide built-in names (_xlnm._FilterDatabase is always hidden)
- if( isBuiltinName() )
- maModel.mbHidden = false;
-
// get sheet index for sheet-local names in BIFF5-BIFF8
switch( getBiff() )
{
@@ -483,18 +483,13 @@ void DefinedName::importDefinedName( BiffInputStream& rStrm, sal_Int16 nCalcShee
void DefinedName::createNameObject()
{
- // do not create names for (macro) functions
+ // do not create names for (macro) functions or VBA procedures
// #163146# do not ignore hidden names (may be regular names created by VBA scripts)
- if( /*maModel.mbHidden ||*/ maModel.mbFunction )
+ if( /*maModel.mbHidden ||*/ maModel.mbFunction || maModel.mbVBName )
return;
- // convert original name to final Calc name
- if( maModel.mbVBName )
- maCalcName = maModel.maName;
- else if( isBuiltinName() )
- maCalcName = lclGetBuiltinName( mcBuiltinId );
- else
- maCalcName = maModel.maName; //! TODO convert to valid name
+ // convert original name to final Calc name (TODO: filter invalid characters from model name)
+ maCalcName = isBuiltinName() ? lclGetPrefixedName( mcBuiltinId ) : maModel.maName;
// #163146# do not rename sheet-local names by default, this breaks VBA scripts
#if 0
@@ -544,7 +539,7 @@ void DefinedName::convertFormula()
case FILTER_UNKNOWN: break;
}
- // set builtin names (print ranges, repeated titles, filter ranges)
+ // set built-in names (print ranges, repeated titles, filter ranges)
if( !isGlobalName() ) switch( mcBuiltinId )
{
case BIFF_DEFNAME_PRINTAREA:
@@ -652,14 +647,20 @@ void DefinedNamesBuffer::importDefinedName( BiffInputStream& rStrm )
void DefinedNamesBuffer::finalizeImport()
{
- // first insert all names without formula definition into the document
+ // first insert all names without formula definition into the document, and insert them into the maps
for( DefNameVector::iterator aIt = maDefNames.begin(), aEnd = maDefNames.end(); aIt != aEnd; ++aIt )
{
DefinedNameRef xDefName = *aIt;
xDefName->createNameObject();
+ // map by sheet index and original model name
+ maModelNameMap[ SheetNameKey( xDefName->getLocalCalcSheet(), xDefName->getUpcaseModelName() ) ] = xDefName;
+ // map by sheet index and built-in identifier
+ if( !xDefName->isGlobalName() && xDefName->isBuiltinName() )
+ maBuiltinMap[ BuiltinKey( xDefName->getLocalCalcSheet(), xDefName->getBuiltinId() ) ] = xDefName;
+ // map by API formula token identifier
sal_Int32 nTokenIndex = xDefName->getTokenIndex();
if( nTokenIndex >= 0 )
- maDefNameMap[ nTokenIndex ] = xDefName;
+ maTokenIdMap[ nTokenIndex ] = xDefName;
}
/* Now convert all name formulas, so that the formula parser can find all
@@ -674,25 +675,22 @@ DefinedNameRef DefinedNamesBuffer::getByIndex( sal_Int32 nIndex ) const
DefinedNameRef DefinedNamesBuffer::getByTokenIndex( sal_Int32 nIndex ) const
{
- return maDefNameMap.get( nIndex );
+ return maTokenIdMap.get( nIndex );
}
DefinedNameRef DefinedNamesBuffer::getByModelName( const OUString& rModelName, sal_Int16 nCalcSheet ) const
{
- DefinedNameRef xGlobalName; // a found global name
- DefinedNameRef xLocalName; // a found local name
- for( DefNameVector::const_iterator aIt = maDefNames.begin(), aEnd = maDefNames.end(); (aIt != aEnd) && !xLocalName; ++aIt )
- {
- DefinedNameRef xCurrName = *aIt;
- if( xCurrName->getModelName() == rModelName )
- {
- if( xCurrName->getLocalCalcSheet() == nCalcSheet )
- xLocalName = xCurrName;
- else if( xCurrName->isGlobalName() )
- xGlobalName = xCurrName;
- }
- }
- return xLocalName.get() ? xLocalName : xGlobalName;
+ OUString aUpcaseName = lclGetUpcaseModelName( rModelName );
+ DefinedNameRef xDefName = maModelNameMap.get( SheetNameKey( nCalcSheet, aUpcaseName ) );
+ // lookup global name, if no local name exists
+ if( !xDefName && (nCalcSheet >= 0) )
+ xDefName = maModelNameMap.get( SheetNameKey( -1, aUpcaseName ) );
+ return xDefName;
+}
+
+DefinedNameRef DefinedNamesBuffer::getByBuiltinId( sal_Unicode cBuiltinId, sal_Int16 nCalcSheet ) const
+{
+ return maBuiltinMap.get( BuiltinKey( nCalcSheet, cBuiltinId ) );
}
DefinedNameRef DefinedNamesBuffer::createDefinedName()
diff --git a/oox/source/xls/makefile.mk b/oox/source/xls/makefile.mk
index b6d69dc5cf8c..6ca6e6a271b9 100644
--- a/oox/source/xls/makefile.mk
+++ b/oox/source/xls/makefile.mk
@@ -42,6 +42,7 @@ ENABLE_EXCEPTIONS=TRUE
SLOFILES = \
$(SLO)$/addressconverter.obj \
+ $(SLO)$/autofilterbuffer.obj \
$(SLO)$/autofiltercontext.obj \
$(SLO)$/biffcodec.obj \
$(SLO)$/biffdetector.obj \
@@ -94,7 +95,7 @@ SLOFILES = \
$(SLO)$/workbooksettings.obj \
$(SLO)$/worksheetbuffer.obj \
$(SLO)$/worksheetfragment.obj \
- $(SLO)$/worksheethelper.obj \
+ $(SLO)$/worksheethelper.obj \
$(SLO)$/worksheetsettings.obj
# --- Targets -------------------------------------------------------
diff --git a/oox/source/xls/pivotcachefragment.cxx b/oox/source/xls/pivotcachefragment.cxx
index 3d69928f7ee8..8c4f56c7c820 100644
--- a/oox/source/xls/pivotcachefragment.cxx
+++ b/oox/source/xls/pivotcachefragment.cxx
@@ -387,9 +387,8 @@ bool BiffPivotCacheFragment::importFragment()
// ============================================================================
-BiffPivotCacheRecordsContext::BiffPivotCacheRecordsContext(
- const BiffWorkbookFragmentBase& rFragment, const PivotCache& rPivotCache ) :
- BiffWorksheetContextBase( rFragment, ISegmentProgressBarRef(), SHEETTYPE_WORKSHEET, rPivotCache.getSourceRange().Sheet ),
+BiffPivotCacheRecordsContext::BiffPivotCacheRecordsContext( const WorkbookHelper& rHelper, const PivotCache& rPivotCache ) :
+ BiffWorksheetContextBase( rHelper, ISegmentProgressBarRef(), SHEETTYPE_WORKSHEET, rPivotCache.getSourceRange().Sheet ),
mrPivotCache( rPivotCache ),
mnColIdx( 0 ),
mnRow( 0 ),
diff --git a/oox/source/xls/pivottablefragment.cxx b/oox/source/xls/pivottablefragment.cxx
index 1486a600e131..1ed95b141b61 100644
--- a/oox/source/xls/pivottablefragment.cxx
+++ b/oox/source/xls/pivottablefragment.cxx
@@ -294,8 +294,8 @@ const RecordInfo* PivotTableFragment::getRecordInfos() const
// ============================================================================
// ============================================================================
-BiffPivotTableContext::BiffPivotTableContext( const BiffWorksheetFragmentBase& rFragment ) :
- BiffWorksheetContextBase( rFragment ),
+BiffPivotTableContext::BiffPivotTableContext( const WorksheetHelper& rHelper ) :
+ BiffWorksheetContextBase( rHelper ),
mrPivotTable( getPivotTables().createPivotTable() )
{
}
diff --git a/oox/source/xls/querytablebuffer.cxx b/oox/source/xls/querytablebuffer.cxx
index 8f65fe1438db..2a4df73287ca 100644
--- a/oox/source/xls/querytablebuffer.cxx
+++ b/oox/source/xls/querytablebuffer.cxx
@@ -283,18 +283,14 @@ void QueryTable::importQueryTable( BiffInputStream& rStrm )
// create a new connection object that will store settings from following records
OSL_ENSURE( maModel.mnConnId == -1, "QueryTable::importQueryTable - multiple call" );
- ConnectionRef xConnection = getConnections().createConnection();
- OSL_ENSURE( xConnection.get(), "QueryTable::importQueryTable - cannot create connection object" );
- if( xConnection.get() )
- {
- maModel.mnConnId = xConnection->getConnectionId();
-
- // a DBQUERY record with some PCITEM_STRING records must follow
- bool bHasDbQuery = (rStrm.getNextRecId() == BIFF_ID_DBQUERY) && rStrm.startNextRecord();
- OSL_ENSURE( bHasDbQuery, "QueryTable::importQueryTable - missing DBQUERY record" );
- if( bHasDbQuery )
- xConnection->importDbQuery( rStrm );
- }
+ Connection& rConnection = getConnections().createConnectionWithId();
+ maModel.mnConnId = rConnection.getConnectionId();
+
+ // a DBQUERY record with some PCITEM_STRING records must follow
+ bool bHasDbQuery = (rStrm.getNextRecId() == BIFF_ID_DBQUERY) && rStrm.startNextRecord();
+ OSL_ENSURE( bHasDbQuery, "QueryTable::importQueryTable - missing DBQUERY record" );
+ if( bHasDbQuery )
+ rConnection.importDbQuery( rStrm );
}
void QueryTable::importQueryTableRefresh( BiffInputStream& rStrm )
diff --git a/oox/source/xls/querytablefragment.cxx b/oox/source/xls/querytablefragment.cxx
index 493fb22bc632..2f4b2d06ff11 100644
--- a/oox/source/xls/querytablefragment.cxx
+++ b/oox/source/xls/querytablefragment.cxx
@@ -84,8 +84,8 @@ const RecordInfo* QueryTableFragment::getRecordInfos() const
// ============================================================================
-BiffQueryTableContext::BiffQueryTableContext( const BiffWorksheetFragmentBase& rFragment ) :
- BiffWorksheetContextBase( rFragment ),
+BiffQueryTableContext::BiffQueryTableContext( const WorksheetHelper& rHelper ) :
+ BiffWorksheetContextBase( rHelper ),
mrQueryTable( getQueryTables().createQueryTable() )
{
}
diff --git a/oox/source/xls/sheetdatacontext.cxx b/oox/source/xls/sheetdatacontext.cxx
index e132ec74b689..258ec995e9e0 100644
--- a/oox/source/xls/sheetdatacontext.cxx
+++ b/oox/source/xls/sheetdatacontext.cxx
@@ -77,9 +77,6 @@ const sal_uInt16 BIFF12_ROW_CUSTOMHEIGHT = 0x2000;
const sal_uInt16 BIFF12_ROW_CUSTOMFORMAT = 0x4000;
const sal_uInt8 BIFF12_ROW_SHOWPHONETIC = 0x01;
-const sal_uInt8 BIFF_BOOLERR_BOOL = 0;
-const sal_uInt8 BIFF_BOOLERR_ERROR = 1;
-
const sal_uInt16 BIFF_DATATABLE_ROW = 0x0004;
const sal_uInt16 BIFF_DATATABLE_2D = 0x0008;
const sal_uInt16 BIFF_DATATABLE_REF1DEL = 0x0010;
@@ -591,8 +588,8 @@ void SheetDataContext::importDataTable( RecordInputStream& rStrm )
// ============================================================================
-BiffSheetDataContext::BiffSheetDataContext( const BiffWorksheetFragmentBase& rParent ) :
- BiffWorksheetContextBase( rParent ),
+BiffSheetDataContext::BiffSheetDataContext( const WorksheetHelper& rHelper ) :
+ BiffWorksheetContextBase( rHelper ),
mnBiff2XfId( 0 )
{
mnArrayIgnoreSize = (getBiff() == BIFF2) ? 1 : ((getBiff() <= BIFF4) ? 2 : 6);
diff --git a/oox/source/xls/tablebuffer.cxx b/oox/source/xls/tablebuffer.cxx
index 1d4444986adc..53408f366ae5 100644
--- a/oox/source/xls/tablebuffer.cxx
+++ b/oox/source/xls/tablebuffer.cxx
@@ -28,9 +28,7 @@
#include "oox/xls/tablebuffer.hxx"
#include <com/sun/star/sheet/XDatabaseRange.hpp>
-#include <com/sun/star/sheet/XDatabaseRanges.hpp>
#include "oox/helper/attributelist.hxx"
-#include "oox/helper/containerhelper.hxx"
#include "oox/helper/propertyset.hxx"
#include "oox/helper/recordinputstream.hxx"
#include "oox/xls/addressconverter.hxx"
@@ -61,6 +59,7 @@ TableModel::TableModel() :
Table::Table( const WorkbookHelper& rHelper ) :
WorkbookHelper( rHelper ),
+ maAutoFilters( rHelper ),
mnTokenIndex( -1 )
{
}
@@ -91,24 +90,20 @@ void Table::importTable( RecordInputStream& rStrm, sal_Int16 nSheet )
void Table::finalizeImport()
{
- // validate cell range
- maDestRange = maModel.maRange;
- bool bValidRange = getAddressConverter().validateCellRange( maDestRange, true, true );
-
// create database range
- if( bValidRange && (maModel.mnId > 0) && (maModel.maDisplayName.getLength() > 0) ) try
+ if( (maModel.mnId > 0) && (maModel.maDisplayName.getLength() > 0) ) try
{
- // find an unused name
- PropertySet aDocProps( getDocument() );
- Reference< XDatabaseRanges > xDatabaseRanges( aDocProps.getAnyProperty( PROP_DatabaseRanges ), UNO_QUERY_THROW );
- Reference< XNameAccess > xNameAccess( xDatabaseRanges, UNO_QUERY_THROW );
- OUString aName = ContainerHelper::getUnusedName( xNameAccess, maModel.maDisplayName, '_' );
- xDatabaseRanges->addNewByName( aName, maModel.maRange );
- Reference< XDatabaseRange > xDatabaseRange( xDatabaseRanges->getByName( aName ), UNO_QUERY_THROW );
+ maDBRangeName = maModel.maDisplayName;
+ Reference< XDatabaseRange > xDatabaseRange( createDatabaseRangeObject( maDBRangeName, maModel.maRange ), UNO_SET_THROW );
+ maDestRange = xDatabaseRange->getDataArea();
+
// get formula token index of the database range
PropertySet aPropSet( xDatabaseRange );
if( !aPropSet.getProperty( mnTokenIndex, PROP_TokenIndex ) )
mnTokenIndex = -1;
+
+ // filter settings
+ maAutoFilters.finalizeImport( xDatabaseRange );
}
catch( Exception& )
{
@@ -123,24 +118,19 @@ TableBuffer::TableBuffer( const WorkbookHelper& rHelper ) :
{
}
-TableRef TableBuffer::importTable( const AttributeList& rAttribs, sal_Int16 nSheet )
-{
- TableRef xTable( new Table( *this ) );
- xTable->importTable( rAttribs, nSheet );
- insertTable( xTable );
- return xTable;
-}
-
-TableRef TableBuffer::importTable( RecordInputStream& rStrm, sal_Int16 nSheet )
+Table& TableBuffer::createTable()
{
- TableRef xTable( new Table( *this ) );
- xTable->importTable( rStrm, nSheet );
- insertTable( xTable );
- return xTable;
+ TableVector::value_type xTable( new Table( *this ) );
+ maTables.push_back( xTable );
+ return *xTable;
}
void TableBuffer::finalizeImport()
{
+ // map all tables by identifier and display name
+ for( TableVector::iterator aIt = maTables.begin(), aEnd = maTables.end(); aIt != aEnd; ++aIt )
+ insertTableToMaps( *aIt );
+ // finalize all valid tables
maIdTables.forEachMem( &Table::finalizeImport );
}
@@ -156,15 +146,15 @@ TableRef TableBuffer::getTable( const OUString& rDispName ) const
// private --------------------------------------------------------------------
-void TableBuffer::insertTable( const TableRef& rxTable )
+void TableBuffer::insertTableToMaps( const TableRef& rxTable )
{
sal_Int32 nTableId = rxTable->getTableId();
const OUString& rDispName = rxTable->getDisplayName();
if( (nTableId > 0) && (rDispName.getLength() > 0) )
{
- OSL_ENSURE( !maIdTables.has( nTableId ), "TableBuffer::insertTable - multiple table identifier" );
+ OSL_ENSURE( !maIdTables.has( nTableId ), "TableBuffer::insertTableToMaps - multiple table identifier" );
maIdTables[ nTableId ] = rxTable;
- OSL_ENSURE( !maNameTables.has( rDispName ), "TableBuffer::insertTable - multiple table name" );
+ OSL_ENSURE( !maNameTables.has( rDispName ), "TableBuffer::insertTableToMaps - multiple table name" );
maNameTables[ rDispName ] = rxTable;
}
}
diff --git a/oox/source/xls/tablefragment.cxx b/oox/source/xls/tablefragment.cxx
index 54415081a288..853a3d73ecd0 100644
--- a/oox/source/xls/tablefragment.cxx
+++ b/oox/source/xls/tablefragment.cxx
@@ -27,6 +27,10 @@
#include "oox/xls/tablefragment.hxx"
+#include "oox/xls/autofilterbuffer.hxx"
+#include "oox/xls/autofiltercontext.hxx"
+#include "oox/xls/tablebuffer.hxx"
+
namespace oox {
namespace xls {
@@ -39,7 +43,8 @@ using ::rtl::OUString;
// ============================================================================
TableFragment::TableFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) :
- WorksheetFragmentBase( rHelper, rFragmentPath )
+ WorksheetFragmentBase( rHelper, rFragmentPath ),
+ mrTable( getTables().createTable() )
{
}
@@ -49,7 +54,14 @@ ContextHandlerRef TableFragment::onCreateContext( sal_Int32 nElement, const Attr
{
case XML_ROOT_CONTEXT:
if( nElement == XLS_TOKEN( table ) )
- mxTable = getTables().importTable( rAttribs, getSheetIndex() );
+ {
+ mrTable.importTable( rAttribs, getSheetIndex() );
+ return this;
+ }
+ break;
+ case XLS_TOKEN( table ):
+ if( nElement == XLS_TOKEN( autoFilter ) )
+ return new AutoFilterContext( *this, mrTable.createAutoFilter() );
break;
}
return 0;
@@ -61,7 +73,14 @@ ContextHandlerRef TableFragment::onCreateRecordContext( sal_Int32 nRecId, Record
{
case XML_ROOT_CONTEXT:
if( nRecId == BIFF12_ID_TABLE )
- mxTable = getTables().importTable( rStrm, getSheetIndex() );
+ {
+ mrTable.importTable( rStrm, getSheetIndex() );
+ return this;
+ }
+ break;
+ case BIFF12_ID_TABLE:
+ if( nRecId == BIFF12_ID_AUTOFILTER )
+ return new AutoFilterContext( *this, mrTable.createAutoFilter() );
break;
}
return 0;
@@ -71,8 +90,12 @@ const RecordInfo* TableFragment::getRecordInfos() const
{
static const RecordInfo spRecInfos[] =
{
- { BIFF12_ID_TABLE, BIFF12_ID_TABLE + 1 },
- { -1, -1 }
+ { BIFF12_ID_AUTOFILTER, BIFF12_ID_AUTOFILTER + 1 },
+ { BIFF12_ID_CUSTOMFILTERS, BIFF12_ID_CUSTOMFILTERS + 1 },
+ { BIFF12_ID_DISCRETEFILTERS, BIFF12_ID_DISCRETEFILTERS + 1 },
+ { BIFF12_ID_FILTERCOLUMN, BIFF12_ID_FILTERCOLUMN + 1 },
+ { BIFF12_ID_TABLE, BIFF12_ID_TABLE + 1 },
+ { -1, -1 }
};
return spRecInfos;
}
diff --git a/oox/source/xls/workbookhelper.cxx b/oox/source/xls/workbookhelper.cxx
index aa29e45c1d19..e523d6e42111 100644
--- a/oox/source/xls/workbookhelper.cxx
+++ b/oox/source/xls/workbookhelper.cxx
@@ -30,6 +30,8 @@
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/document/XActionLockable.hpp>
+#include <com/sun/star/sheet/XDatabaseRange.hpp>
+#include <com/sun/star/sheet/XDatabaseRanges.hpp>
#include <com/sun/star/sheet/XNamedRange.hpp>
#include <com/sun/star/sheet/XNamedRanges.hpp>
#include <com/sun/star/sheet/XSpreadsheet.hpp>
@@ -136,6 +138,8 @@ public:
Reference< XStyle > getStyleObject( const OUString& rStyleName, bool bPageStyle ) const;
/** Creates and returns a defined name on-the-fly in the Calc document. */
Reference< XNamedRange > createNamedRangeObject( OUString& orName, sal_Int32 nNameFlags ) const;
+ /** Creates and returns a database range on-the-fly in the Calc document. */
+ Reference< XDatabaseRange > createDatabaseRangeObject( OUString& orName, const CellRangeAddress& rRangeAddr ) const;
/** Creates and returns a com.sun.star.style.Style object for cells or pages. */
Reference< XStyle > createStyleObject( OUString& orStyleName, bool bPageStyle ) const;
@@ -350,17 +354,16 @@ Reference< XStyle > WorkbookData::getStyleObject( const OUString& rStyleName, bo
Reference< XNamedRange > WorkbookData::createNamedRangeObject( OUString& orName, sal_Int32 nNameFlags ) const
{
- // find an unused name
- PropertySet aDocProps( mxDoc );
- Reference< XNamedRanges > xNamedRanges( aDocProps.getAnyProperty( PROP_NamedRanges ), UNO_QUERY );
- Reference< XNameAccess > xNameAccess( xNamedRanges, UNO_QUERY );
- if( xNameAccess.is() )
- orName = ContainerHelper::getUnusedName( xNameAccess, orName, '_' );
-
// create the name and insert it into the Calc document
Reference< XNamedRange > xNamedRange;
- if( xNamedRanges.is() && (orName.getLength() > 0) ) try
+ if( orName.getLength() > 0 ) try
{
+ // find an unused name
+ PropertySet aDocProps( mxDoc );
+ Reference< XNamedRanges > xNamedRanges( aDocProps.getAnyProperty( PROP_NamedRanges ), UNO_QUERY_THROW );
+ Reference< XNameAccess > xNameAccess( xNamedRanges, UNO_QUERY_THROW );
+ orName = ContainerHelper::getUnusedName( xNameAccess, orName, '_' );
+ // create the named range
xNamedRanges->addNewByName( orName, OUString(), CellAddress( 0, 0, 0 ), nNameFlags );
xNamedRange.set( xNamedRanges->getByName( orName ), UNO_QUERY );
}
@@ -371,6 +374,32 @@ Reference< XNamedRange > WorkbookData::createNamedRangeObject( OUString& orName,
return xNamedRange;
}
+Reference< XDatabaseRange > WorkbookData::createDatabaseRangeObject( OUString& orName, const CellRangeAddress& rRangeAddr ) const
+{
+ // validate cell range
+ CellRangeAddress aDestRange = rRangeAddr;
+ bool bValidRange = getAddressConverter().validateCellRange( aDestRange, true, true );
+
+ // create database range and insert it into the Calc document
+ Reference< XDatabaseRange > xDatabaseRange;
+ if( bValidRange && (orName.getLength() > 0) ) try
+ {
+ // find an unused name
+ PropertySet aDocProps( mxDoc );
+ Reference< XDatabaseRanges > xDatabaseRanges( aDocProps.getAnyProperty( PROP_DatabaseRanges ), UNO_QUERY_THROW );
+ Reference< XNameAccess > xNameAccess( xDatabaseRanges, UNO_QUERY_THROW );
+ orName = ContainerHelper::getUnusedName( xNameAccess, orName, '_' );
+ // create the database range
+ xDatabaseRanges->addNewByName( orName, aDestRange );
+ xDatabaseRange.set( xDatabaseRanges->getByName( orName ), UNO_QUERY );
+ }
+ catch( Exception& )
+ {
+ }
+ OSL_ENSURE( xDatabaseRange.is(), "WorkbookData::createDatabaseRangeObject - cannot create database range" );
+ return xDatabaseRange;
+}
+
Reference< XStyle > WorkbookData::createStyleObject( OUString& orStyleName, bool bPageStyle ) const
{
Reference< XStyle > xStyle;
@@ -714,6 +743,11 @@ Reference< XNamedRange > WorkbookHelper::createNamedRangeObject( OUString& orNam
return mrBookData.createNamedRangeObject( orName, nNameFlags );
}
+Reference< XDatabaseRange > WorkbookHelper::createDatabaseRangeObject( OUString& orName, const CellRangeAddress& rRangeAddr ) const
+{
+ return mrBookData.createDatabaseRangeObject( orName, rRangeAddr );
+}
+
Reference< XStyle > WorkbookHelper::createStyleObject( OUString& orStyleName, bool bPageStyle ) const
{
return mrBookData.createStyleObject( orStyleName, bPageStyle );
diff --git a/oox/source/xls/worksheetfragment.cxx b/oox/source/xls/worksheetfragment.cxx
index 19dc8e34c70f..dc51981fe230 100644
--- a/oox/source/xls/worksheetfragment.cxx
+++ b/oox/source/xls/worksheetfragment.cxx
@@ -32,6 +32,7 @@
#include "oox/helper/attributelist.hxx"
#include "oox/helper/recordinputstream.hxx"
#include "oox/xls/addressconverter.hxx"
+#include "oox/xls/autofilterbuffer.hxx"
#include "oox/xls/autofiltercontext.hxx"
#include "oox/xls/biffinputstream.hxx"
#include "oox/xls/commentsfragment.hxx"
@@ -267,9 +268,10 @@ ContextHandlerRef WorksheetFragment::onCreateContext( sal_Int32 nElement, const
switch( nElement )
{
case XLS_TOKEN( sheetData ): return new SheetDataContext( *this );
- case XLS_TOKEN( autoFilter ): return new AutoFilterContext( *this );
case XLS_TOKEN( conditionalFormatting ): return new CondFormatContext( *this );
case XLS_TOKEN( dataValidations ): return new DataValidationsContext( *this );
+ case XLS_TOKEN( autoFilter ): return new AutoFilterContext( *this, getAutoFilters().createAutoFilter() );
+ case XLS_TOKEN( scenarios ): return new ScenariosContext( *this );
case XLS_TOKEN( sheetViews ):
case XLS_TOKEN( cols ):
@@ -292,8 +294,6 @@ ContextHandlerRef WorksheetFragment::onCreateContext( sal_Int32 nElement, const
case XLS_TOKEN( picture ): getPageSettings().importPicture( getRelations(), rAttribs ); break;
case XLS_TOKEN( drawing ): importDrawing( rAttribs ); break;
case XLS_TOKEN( legacyDrawing ): importLegacyDrawing( rAttribs ); break;
- case XLS_TOKEN( scenarios ):
- return new ScenariosContext( *this );
}
break;
@@ -387,6 +387,7 @@ ContextHandlerRef WorksheetFragment::onCreateRecordContext( sal_Int32 nRecId, Re
case BIFF12_ID_SHEETDATA: return new SheetDataContext( *this );
case BIFF12_ID_CONDFORMATTING: return new CondFormatContext( *this );
case BIFF12_ID_DATAVALIDATIONS: return new DataValidationsContext( *this );
+ case BIFF12_ID_AUTOFILTER: return new AutoFilterContext( *this, getAutoFilters().createAutoFilter() );
case BIFF12_ID_SCENARIOS: return new ScenariosContext( *this );
case BIFF12_ID_SHEETVIEWS:
@@ -453,16 +454,20 @@ const RecordInfo* WorksheetFragment::getRecordInfos() const
{
static const RecordInfo spRecInfos[] =
{
+ { BIFF12_ID_AUTOFILTER, BIFF12_ID_AUTOFILTER + 1 },
{ BIFF12_ID_CFRULE, BIFF12_ID_CFRULE + 1 },
{ BIFF12_ID_COLBREAKS, BIFF12_ID_COLBREAKS + 1 },
{ BIFF12_ID_COLORSCALE, BIFF12_ID_COLORSCALE + 1 },
{ BIFF12_ID_COLS, BIFF12_ID_COLS + 1 },
{ BIFF12_ID_CONDFORMATTING, BIFF12_ID_CONDFORMATTING + 1 },
{ BIFF12_ID_CONTROLS, BIFF12_ID_CONTROLS + 2 },
+ { BIFF12_ID_CUSTOMFILTERS, BIFF12_ID_CUSTOMFILTERS + 1 },
{ BIFF12_ID_CUSTOMSHEETVIEW, BIFF12_ID_CUSTOMSHEETVIEW + 1 },
{ BIFF12_ID_CUSTOMSHEETVIEWS, BIFF12_ID_CUSTOMSHEETVIEWS + 3 },
{ BIFF12_ID_DATABAR, BIFF12_ID_DATABAR + 1 },
{ BIFF12_ID_DATAVALIDATIONS, BIFF12_ID_DATAVALIDATIONS + 1 },
+ { BIFF12_ID_DISCRETEFILTERS, BIFF12_ID_DISCRETEFILTERS + 1 },
+ { BIFF12_ID_FILTERCOLUMN, BIFF12_ID_FILTERCOLUMN + 1 },
{ BIFF12_ID_HEADERFOOTER, BIFF12_ID_HEADERFOOTER + 1 },
{ BIFF12_ID_ICONSET, BIFF12_ID_ICONSET + 1 },
{ BIFF12_ID_MERGECELLS, BIFF12_ID_MERGECELLS + 1 },
@@ -862,6 +867,7 @@ bool BiffWorksheetFragment::importFragment()
case BIFF5: switch( nRecId )
{
+ case BIFF_ID_AUTOFILTER: importAutoFilter( rStrm ); break;
case BIFF_ID_COLINFO: importColInfo( rStrm ); break;
case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break;
case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break;
@@ -882,6 +888,7 @@ bool BiffWorksheetFragment::importFragment()
case BIFF8: switch( nRecId )
{
+ case BIFF_ID_AUTOFILTER: importAutoFilter( rStrm ); break;
case BIFF_ID_CFHEADER: rCondFormats.importCfHeader( rStrm ); break;
case BIFF_ID_CODENAME: rWorksheetSett.importCodeName( rStrm ); break;
case BIFF_ID_COLINFO: importColInfo( rStrm ); break;
@@ -941,6 +948,12 @@ bool BiffWorksheetFragment::importFragment()
// private --------------------------------------------------------------------
+void BiffWorksheetFragment::importAutoFilter( BiffInputStream& rStrm )
+{
+ mxContext.reset( new BiffAutoFilterContext( *this, getAutoFilters().createAutoFilter() ) );
+ mxContext->importRecord( rStrm );
+}
+
void BiffWorksheetFragment::importColInfo( BiffInputStream& rStrm )
{
sal_uInt16 nFirstCol, nLastCol, nWidth, nXfId, nFlags;
diff --git a/oox/source/xls/worksheethelper.cxx b/oox/source/xls/worksheethelper.cxx
index 48a83ab07f11..de3b540df0a8 100644
--- a/oox/source/xls/worksheethelper.cxx
+++ b/oox/source/xls/worksheethelper.cxx
@@ -59,6 +59,7 @@
#include "oox/helper/containerhelper.hxx"
#include "oox/helper/propertyset.hxx"
#include "oox/xls/addressconverter.hxx"
+#include "oox/xls/autofilterbuffer.hxx"
#include "oox/xls/commentsbuffer.hxx"
#include "oox/xls/condformatbuffer.hxx"
#include "oox/xls/drawingfragment.hxx"
@@ -389,6 +390,8 @@ public:
inline CondFormatBuffer& getCondFormats() { return maCondFormats; }
/** Returns the buffer for all cell comments in this sheet. */
inline CommentsBuffer& getComments() { return maComments; }
+ /** Returns the auto filters for the sheet. */
+ inline AutoFilterBuffer& getAutoFilters() { return maAutoFilters; }
/** Returns the buffer for all web query tables in this sheet. */
inline QueryTableBuffer& getQueryTables() { return maQueryTables; }
/** Returns the page/print settings for this sheet. */
@@ -560,6 +563,7 @@ private:
SharedFormulaBuffer maSharedFmlas; /// Buffer for shared formulas in this sheet.
CondFormatBuffer maCondFormats; /// Buffer for conditional formattings.
CommentsBuffer maComments; /// Buffer for all cell comments in this sheet.
+ AutoFilterBuffer maAutoFilters; /// Sheet auto filters (not associated to a table).
QueryTableBuffer maQueryTables; /// Buffer for all web query tables in this sheet.
PageSettings maPageSett; /// Page/print settings for this sheet.
SheetViewSettings maSheetViewSett; /// View settings for this sheet.
@@ -589,6 +593,7 @@ WorksheetData::WorksheetData( const WorkbookHelper& rHelper, const ISegmentProgr
maSharedFmlas( *this ),
maCondFormats( *this ),
maComments( *this ),
+ maAutoFilters( *this ),
maQueryTables( *this ),
maPageSett( *this ),
maSheetViewSett( *this ),
@@ -1050,6 +1055,7 @@ void WorksheetData::finalizeWorksheetImport()
finalizeHyperlinkRanges();
finalizeValidationRanges();
finalizeMergedRanges();
+ maAutoFilters.finalizeImport( getSheetIndex() );
maSheetSett.finalizeImport();
maCondFormats.finalizeImport();
maQueryTables.finalizeImport();
@@ -1842,6 +1848,11 @@ CommentsBuffer& WorksheetHelper::getComments() const
return mrSheetData.getComments();
}
+AutoFilterBuffer& WorksheetHelper::getAutoFilters() const
+{
+ return mrSheetData.getAutoFilters();
+}
+
QueryTableBuffer& WorksheetHelper::getQueryTables() const
{
return mrSheetData.getQueryTables();