summaryrefslogtreecommitdiff
path: root/oox/source/xls/autofiltercontext.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'oox/source/xls/autofiltercontext.cxx')
-rw-r--r--oox/source/xls/autofiltercontext.cxx775
1 files changed, 775 insertions, 0 deletions
diff --git a/oox/source/xls/autofiltercontext.cxx b/oox/source/xls/autofiltercontext.cxx
new file mode 100644
index 000000000000..4ae31fc94c56
--- /dev/null
+++ b/oox/source/xls/autofiltercontext.cxx
@@ -0,0 +1,775 @@
+/*************************************************************************
+ *
+ * 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/autofiltercontext.hxx"
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/table/XCellRange.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/sheet/FilterOperator.hpp>
+#include <com/sun/star/sheet/FilterConnection.hpp>
+#include <com/sun/star/i18n/XLocaleData.hpp>
+#include "properties.hxx"
+#include "oox/helper/attributelist.hxx"
+#include "oox/helper/propertyset.hxx"
+#include "oox/core/filterbase.hxx"
+#include "oox/xls/addressconverter.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;
+
+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
+}
+
+// ============================================================================
+
+OoxAutoFilterContext::OoxAutoFilterContext( OoxWorksheetFragmentBase& rFragment ) :
+ OoxWorksheetContextBase( rFragment ),
+ mbValidAddress( false ),
+ mbUseRegex( false ),
+ mbShowBlank( false ),
+ mbConnectionAnd( false )
+{
+}
+
+// oox.core.ContextHandler2Helper interface -----------------------------------
+
+ContextHandlerRef OoxAutoFilterContext::onCreateContext( sal_Int32 nElement, const AttributeList& )
+{
+ 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;
+ }
+ break;
+
+ case XLS_TOKEN( customFilters ):
+ switch( nElement )
+ {
+ case XLS_TOKEN( customFilter ): return this;
+ }
+ break;
+ }
+ return 0;
+}
+
+void OoxAutoFilterContext::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;
+ }
+}
+
+void OoxAutoFilterContext::onEndElement( const OUString& /*rChars*/ )
+{
+ switch( getCurrentElement() )
+ {
+ case XLS_TOKEN( autoFilter ):
+ maybeShowBlank();
+ setAutoFilter();
+ break;
+ case XLS_TOKEN( filters ):
+ setFilterNames();
+ break;
+ }
+}
+
+#if DEBUG_OOX_AUTOFILTER
+static void lclPrintNormalField(
+#if USE_SC_MULTI_STRING_FILTER_PATCH
+ TableFilterFieldNormal* pField
+#else
+ TableFilterField* pField
+#endif
+)
+{
+ 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");
+}
+
+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");
+}
+
+static void lclPrintFilterField( const FilterFieldItem& aItem )
+{
+ 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 )
+ {
+ 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;
+ }
+#else
+ TableFilterField* pField = aItem.mpField.get();
+ printf(" Field: %ld\n", pField->Field);
+ lclPrintFieldConnection(pField->Connection);
+ lclPrintNormalField(pField);
+
+#endif
+ fflush(stdout);
+}
+#endif
+
+void OoxAutoFilterContext::initialize()
+{
+ maFields.clear();
+ maFilterNames.clear();
+ mbValidAddress = mbShowBlank = mbUseRegex = mbConnectionAnd = false;
+}
+
+void OoxAutoFilterContext::setAutoFilter()
+{
+ 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.
+
+ Reference< XDatabaseRanges > xDBRanges = getDatabaseRanges();
+ if ( !xDBRanges.is() )
+ {
+ OSL_ENSURE( false, "OoxAutoFilterContext::setAutoFilter: DBRange empty" );
+ 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, "OoxAutoFilterContext::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, "OoxAutoFilterContext::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 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 );
+ }
+ }
+ 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();
+}
+
+void OoxAutoFilterContext::maybeShowBlank()
+{
+ 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);
+}
+
+void OoxAutoFilterContext::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 OoxAutoFilterContext::importAutoFilter( const AttributeList& rAttribs )
+{
+ initialize();
+
+ mbValidAddress = getAddressConverter().convertToCellRange(
+ maAutoFilterRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex(), true, true );
+}
+
+void OoxAutoFilterContext::importFilterColumn( const AttributeList& rAttribs )
+{
+ // hiddenButton and showButton attributes are not used for now.
+ mnCurColID = rAttribs.getInteger( XML_colId, -1 );
+}
+
+void OoxAutoFilterContext::importTop10( 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);
+}
+
+void OoxAutoFilterContext::importCustomFilters( const AttributeList& rAttribs )
+{
+ // OR is default when the 'and' attribute is absent.
+ mbConnectionAnd = rAttribs.getBool( XML_and, false );
+}
+
+/** Do a best-effort guess of whether or not the given string is numerical. */
+static bool lclIsNumeric( const OUString& _str, const LocaleDataItem& aLocaleItem )
+{
+ 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;
+}
+
+/** 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 )
+{
+ 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 OoxAutoFilterContext::importCustomFilter( const AttributeList& rAttribs )
+{
+ 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 )
+ {
+ 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, "OoxAutoFilterContext::importCustomFilter: unhandled case" );
+ }
+}
+
+void OoxAutoFilterContext::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 OoxAutoFilterContext::importFilter( const AttributeList& rAttribs )
+{
+ if (mnCurColID == -1)
+ return;
+
+ OUString value = rAttribs.getString( XML_val, OUString() );
+ if ( value.getLength() )
+ maFilterNames.push_back(value);
+}
+
+void OoxAutoFilterContext::importDynamicFilter( const AttributeList& /*rAttribs*/ )
+{
+ // not implemented yet - Calc doesn't support this.
+}
+
+// ============================================================================
+
+} // namespace xls
+} // namespace oox
+