22#include <com/sun/star/beans/XPropertySet.hpp>
23#include <com/sun/star/sheet/FilterFieldType.hpp>
24#include <com/sun/star/sheet/FilterConnection.hpp>
25#include <com/sun/star/sheet/FilterOperator2.hpp>
26#include <com/sun/star/sheet/TableFilterField3.hpp>
27#include <com/sun/star/sheet/XDatabaseRange.hpp>
28#include <com/sun/star/sheet/XSheetFilterDescriptor3.hpp>
29#include <com/sun/star/table/TableOrientation.hpp>
30#include <com/sun/star/table/CellAddress.hpp>
34#include <rtl/ustrbuf.hxx>
35#include <osl/diagnose.h>
39#include <oox/token/namespaces.hxx>
40#include <oox/token/properties.hxx>
41#include <oox/token/tokens.hxx>
45#include <document.hxx>
50#include <stlsheet.hxx>
63const sal_uInt8 BIFF12_TOP10FILTER_TOP = 0x01;
64const sal_uInt8 BIFF12_TOP10FILTER_PERCENT = 0x02;
66const sal_uInt16 BIFF12_FILTERCOLUMN_HIDDENBUTTON = 0x0001;
67const sal_uInt16 BIFF12_FILTERCOLUMN_SHOWBUTTON = 0x0002;
69const sal_uInt8 BIFF_FILTER_DATATYPE_NONE = 0;
70const sal_uInt8 BIFF_FILTER_DATATYPE_DOUBLE = 4;
71const sal_uInt8 BIFF_FILTER_DATATYPE_STRING = 6;
72const sal_uInt8 BIFF_FILTER_DATATYPE_BOOLEAN = 8;
73const sal_uInt8 BIFF_FILTER_DATATYPE_EMPTY = 12;
74const sal_uInt8 BIFF_FILTER_DATATYPE_NOTEMPTY = 14;
76bool lclGetApiOperatorFromToken( sal_Int32& rnApiOperator, sal_Int32
nToken )
80 case XML_lessThan: rnApiOperator = FilterOperator2::LESS;
return true;
81 case XML_equal: rnApiOperator = FilterOperator2::EQUAL;
return true;
82 case XML_lessThanOrEqual: rnApiOperator = FilterOperator2::LESS_EQUAL;
return true;
83 case XML_greaterThan: rnApiOperator = FilterOperator2::GREATER;
return true;
84 case XML_notEqual: rnApiOperator = FilterOperator2::NOT_EQUAL;
return true;
85 case XML_greaterThanOrEqual: rnApiOperator = FilterOperator2::GREATER_EQUAL;
return true;
92bool lclTrimLeadingAsterisks( OUString& rValue )
94 sal_Int32
nLength = rValue.getLength();
96 while( (nPos < nLength) && (rValue[ nPos ] ==
'*') )
100 rValue = rValue.copy( nPos );
108bool lclTrimTrailingAsterisks( OUString& rValue )
110 sal_Int32
nLength = rValue.getLength();
112 while( (nPos > 0) && (rValue[ nPos - 1 ] ==
'*') )
116 rValue = rValue.copy( 0, nPos );
125bool lclConvertWildcardsToRegExp( OUString& rValue )
128 if( !rValue.isEmpty() && ((rValue.indexOf(
'*' ) >= 0) || (rValue.indexOf(
'?' ) >= 0)) )
131 aBuffer.ensureCapacity( rValue.getLength() + 5 );
133 const sal_Unicode* pcEnd = pcChar + rValue.getLength();
134 for( ; pcChar < pcEnd; ++pcChar )
144 case '\\':
case '.':
case '|':
case '(':
case ')':
case '^':
case '$':
146 aBuffer.append(
"\\" + OUStringChar(*pcChar) );
152 rValue =
aBuffer.makeStringAndClear();
168 rFilterField.Connection = bAnd ? FilterConnection_AND : FilterConnection_OR;
169 rFilterField.Operator = nOperator;
170 rFilterField.Values.realloc(1);
171 auto pValues = rFilterField.Values.getArray();
172 pValues[0].FilterType = FilterFieldType::NUMERIC;
173 pValues[0].NumericValue = fValue;
180 rFilterField.Connection = bAnd ? FilterConnection_AND : FilterConnection_OR;
181 rFilterField.Operator = nOperator;
182 rFilterField.Values.realloc(1);
183 auto pValues = rFilterField.Values.getArray();
184 pValues[0].FilterType = FilterFieldType::STRING;
185 pValues[0].StringValue = rValue;
192 rFilterField.Connection = bAnd ? FilterConnection_AND : FilterConnection_OR;
193 rFilterField.Operator = FilterOperator2::EQUAL;
194 rFilterField.Values.realloc(1);
195 auto pValues = rFilterField.Values.getArray();
197 = bIsBackgroundColor ? FilterFieldType::BACKGROUND_COLOR : FilterFieldType::TEXT_COLOR;
198 pValues[0].ColorValue = aColor;
205 rFilterField.Connection = bAnd ? FilterConnection_AND : FilterConnection_OR;
206 rFilterField.Operator = FilterOperator2::EQUAL;
207 rFilterField.Values.realloc(rValues.size());
208 auto pValues = rFilterField.Values.getArray();
211 for(
auto const& it : rValues )
248 case XLS_TOKEN( filters ):
255 OUString aValue = rAttribs.
getXString( XML_val, OUString() );
256 if( !aValue.isEmpty() )
257 maValues.push_back( std::make_pair(aValue,
false) );
261 case XLS_TOKEN( dateGroupItem ):
266 sal_uInt16
nToken = rAttribs.
getToken(XML_dateTimeGrouping, XML_day);
270 aDateValue = rAttribs.
getString(XML_year, OUString());
275 OUString aMonthName = rAttribs.
getString(XML_month, OUString());
276 if( aMonthName.getLength() == 1 )
277 aMonthName =
"0" + aMonthName;
278 aDateValue +=
"-" + aMonthName;
283 OUString aDayName = rAttribs.
getString(XML_day, OUString());
284 if( aDayName.getLength() == 1 )
285 aDayName =
"0" + aDayName;
286 aDateValue +=
"-" + aDayName;
290 OUString aHourName = rAttribs.
getString(XML_hour, OUString());
291 if( aHourName.getLength() == 1 )
292 aHourName =
"0" + aHourName;
293 aDateValue +=
" " + aHourName;
297 OUString aMinName = rAttribs.
getString(XML_minute, OUString());
298 if( aMinName.getLength() == 1 )
299 aMinName =
"0" + aMinName;
300 aDateValue +=
":" + aMinName;
302 if(
nToken == XML_second )
304 OUString aSecName = rAttribs.
getString(XML_second, OUString());
305 if( aSecName.getLength() == 1 )
306 aSecName =
"0" + aSecName;
307 aDateValue +=
":" + aSecName;
314 if( !aDateValue.isEmpty() )
315 maValues.push_back( std::make_pair(aDateValue,
true) );
327 sal_Int32 nShowBlank, nCalendarType;
328 nShowBlank =
rStrm.readInt32();
329 nCalendarType =
rStrm.readInt32();
331 static const sal_Int32 spnCalendarTypes[] = {
332 XML_none, XML_gregorian, XML_gregorianUs, XML_japan, XML_taiwan, XML_korea, XML_hijri, XML_thai, XML_hebrew,
333 XML_gregorianMeFrench, XML_gregorianArabic, XML_gregorianXlitEnglish, XML_gregorianXlitFrench };
342 if( !aValue.isEmpty() )
343 maValues.push_back( std::make_pair(aValue,
false) );
359 aSettings.
appendField(
false, FilterOperator2::EMPTY, OUString() );
379 if( nElement == XLS_TOKEN( top10 ) )
392 nFlags =
rStrm.readuChar();
401 sal_Int32 nOperator =
mbTop ?
402 (
mbPercent ? FilterOperator2::TOP_PERCENT : FilterOperator2::TOP_VALUES) :
403 (
mbPercent ? FilterOperator2::BOTTOM_PERCENT : FilterOperator2::BOTTOM_VALUES);
411 , mbIsBackgroundColor(false)
417 if (nElement == XLS_TOKEN(colorFilter))
445 ::Color aColor = pItem->GetFiltColor();
446 util::Color nColor(aColor);
453 mnOperator( XML_equal ),
454 mnDataType( BIFF_FILTER_DATATYPE_NONE )
461 XML_lessThan, XML_equal, XML_lessThanOrEqual, XML_greaterThan, XML_notEqual, XML_greaterThanOrEqual };
469 nOperator =
rStrm.readuChar();
474 case BIFF_FILTER_DATATYPE_DOUBLE:
477 case BIFF_FILTER_DATATYPE_STRING:
481 if( !aValue.isEmpty() )
485 case BIFF_FILTER_DATATYPE_BOOLEAN:
489 case BIFF_FILTER_DATATYPE_EMPTY:
494 case BIFF_FILTER_DATATYPE_NOTEMPTY:
500 OSL_ENSURE(
false,
"FilterCriterionModel::readBiffData - unexpected data type" );
515 case XLS_TOKEN( customFilters ):
519 case XLS_TOKEN( customFilter ):
523 OUString aValue = rAttribs.
getXString( XML_val, OUString() ).trim();
524 if( (aCriterion.
mnOperator == XML_equal) || (aCriterion.
mnOperator == XML_notEqual) || (!aValue.isEmpty()) )
553 OSL_ENSURE(
maCriteria.size() <= 2,
"CustomFilter::finalizeImport - too many filter criteria" );
557 sal_Int32 nOperator = 0;
558 bool bValidOperator = lclGetApiOperatorFromToken( nOperator, rCriterion.mnOperator );
561 if( rCriterion.maValue.has< OUString >() )
565 rCriterion.maValue >>= aValue;
567 bool bEqual = nOperator == FilterOperator2::EQUAL;
568 bool bNotEqual = nOperator == FilterOperator2::NOT_EQUAL;
569 if( bEqual || bNotEqual )
571 if( aValue.isEmpty() )
574 nOperator = bNotEqual ? FilterOperator2::NOT_EMPTY : FilterOperator2::EMPTY;
579 bool bHasLeadingAsterisk = lclTrimLeadingAsterisks( aValue );
580 bool bHasTrailingAsterisk = lclTrimTrailingAsterisks( aValue );
582 bValidOperator = !aValue.isEmpty();
585 if( bHasLeadingAsterisk && bHasTrailingAsterisk )
586 nOperator = bNotEqual ? FilterOperator2::DOES_NOT_CONTAIN : FilterOperator2::CONTAINS;
587 else if( bHasLeadingAsterisk )
588 nOperator = bNotEqual ? FilterOperator2::DOES_NOT_END_WITH : FilterOperator2::ENDS_WITH;
589 else if( bHasTrailingAsterisk )
590 nOperator = bNotEqual ? FilterOperator2::DOES_NOT_BEGIN_WITH : FilterOperator2::BEGINS_WITH;
599 if( lclConvertWildcardsToRegExp( aValue ) )
605 else if( rCriterion.maValue.has<
double >() )
609 rCriterion.maValue >>= fValue;
626 mbHiddenButton( false ),
642 nFlags =
rStrm.readuInt16();
670 mbDescending( false )
676 OUString aRangeStr = rAttribs.
getString( XML_ref, OUString() );
692 OUString aRangeStr = rAttribs.
getString( XML_ref, OUString() );
705 OUString aRangeStr = rAttribs.
getString( XML_ref, OUString() );
713 return *xFilterColumn;
720 return *xSortCondition;
726 const Reference<XSheetFilterDescriptor3> xFilterDesc( rxDatabaseRange->getFilterDescriptor(), UNO_QUERY_THROW );
727 if( !xFilterDesc.is() )
732 aDescProps.
setProperty( PROP_IsCaseSensitive,
false );
733 aDescProps.
setProperty( PROP_SkipDuplicates,
false );
734 aDescProps.
setProperty( PROP_Orientation, TableOrientation_ROWS );
735 aDescProps.
setProperty( PROP_ContainsHeader,
true );
736 aDescProps.
setProperty( PROP_CopyOutputData,
false );
739 ::std::vector<TableFilterField3> aFilterFields;
742 std::optional< bool > obNeedsRegExp;
751 bool bHasOrConnection =
false;
765 if (rxFilterColumn->isButtonHidden())
779 if( rColumnFields.size() >= 2 )
780 bHasOrConnection = std::any_of(rColumnFields.begin() + 1, rColumnFields.end(),
781 [](
const css::sheet::TableFilterField3& rColumnField) {
return rColumnField.Connection == FilterConnection_OR; });
786 if( !rColumnFields.empty() && bRegExpCompatible )
790 rColumnFields[ 0 ].Connection = FilterConnection_AND;
793 aFilterFields.insert( aFilterFields.end(), rColumnFields.begin(), rColumnFields.end() );
799 if( bHasOrConnection )
804 if( !aFilterFields.empty() )
808 bool bUseRegExp = obNeedsRegExp.value_or(
false );
809 aDescProps.
setProperty( PROP_UseRegularExpressions, bUseRegExp );
816 const SortCondition& rSorConditionLoaded = *xSortConditionPointer;
826 for (
size_t i=0; pUserList &&
i < pUserList->
size();
i++)
828 const OUString aEntry((*pUserList)[
i].
GetString());
868 OSL_FAIL(
"AutoFilter::finalizeImport(): cannot find matching DBData");
899 if( bHasAutoFilter || !xDatabaseRange.is() )
912 PropertySet aDescProps( xDatabaseRange->getFilterDescriptor() );
913 aDescProps.
setProperty( PROP_IsCaseSensitive,
false );
914 aDescProps.
setProperty( PROP_SkipDuplicates,
false );
915 aDescProps.
setProperty( PROP_Orientation, TableOrientation_ROWS );
916 aDescProps.
setProperty( PROP_ContainsHeader,
true );
918 aDescProps.
setProperty( PROP_UseRegularExpressions,
false );
923 bool bHasOutputRange = xExtractName && xExtractName->getAbsoluteRange( aOutputRange );
924 aDescProps.
setProperty( PROP_CopyOutputData, bHasOutputRange );
925 if( bHasOutputRange )
927 aDescProps.
setProperty( PROP_SaveOutputPosition,
true );
937 aRangeProps.
setProperty( PROP_FilterCriteriaSource,
938 CellRangeAddress( aCriteriaRange.
aStart.
Tab(),
946 if( pAutoFilter && rxDatabaseRange.is() )
try
950 aRangeProps.setProperty( PROP_AutoFilter,
true );
966 OSL_ENSURE(
maAutoFilters.size() <= 1,
"AutoFilterBuffer::getActiveAutoFilter - too many auto filters" );
const PropertyValue * pValues
SC_DLLPUBLIC void SetSortParam(const ScSortParam &rSortParam)
SC_DLLPUBLIC const ScDBData * GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
SC_DLLPUBLIC void ApplyAttr(SCCOL nCol, SCROW nRow, SCTAB nTab, const SfxPoolItem &rAttr)
SC_DLLPUBLIC ScStyleSheetPool * GetStyleSheetPool() const
SC_DLLPUBLIC const SfxPoolItem * GetAttr(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich) const
static SC_DLLPUBLIC ScUserList * GetUserList()
virtual SC_DLLPUBLIC SfxItemSet & GetItemSet() override
Collection of user-defined sort lists.
void emplace_back(Args &&... args)
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
virtual SfxStyleSheetBase * Find(const OUString &, SfxStyleFamily eFam, SfxStyleSearchBits n=SfxStyleSearchBits::All)
std::optional< OUString > getXString(sal_Int32 nAttrToken) const
std::optional< sal_Int32 > getInteger(sal_Int32 nAttrToken) const
std::optional< OUString > getString(sal_Int32 nAttrToken) const
std::optional< bool > getBool(sal_Int32 nAttrToken) const
std::optional< sal_Int32 > getToken(sal_Int32 nAttrToken) const
std::optional< double > getDouble(sal_Int32 nAttrToken) const
bool setProperty(sal_Int32 nPropId, const Type &rValue)
value_type get(sal_Int32 nIndex) const
container_type::value_type value_type
static bool convertToCellRangeUnchecked(ScRange &orRange, std::u16string_view aString, sal_Int16 nSheet)
Converts the passed string to a cell range address, without checking any sheet limits.
AutoFilter * getActiveAutoFilter()
Returns the auto filter object used to perform auto filtering.
void finalizeImport(sal_Int16 nSheet)
Applies filter settings to a new database range object (used for sheet autofilter or advanced filter ...
AutoFilter & createAutoFilter()
Creates a new auto filter and stores it internally.
AutoFilterVector maAutoFilters
AutoFilterBuffer(const WorkbookHelper &rHelper)
AutoFilter(const WorkbookHelper &rHelper)
SortCondition & createSortCondition()
void importSortState(const AttributeList &rAttribs, sal_Int16 nSheet)
void finalizeImport(const css::uno::Reference< css::sheet::XDatabaseRange > &rxDatabaseRange, sal_Int16 nSheet)
Applies the filter to the passed filter descriptor.
void importAutoFilter(const AttributeList &rAttribs, sal_Int16 nSheet)
Imports auto filter settings from the autoFilter element.
FilterColumnVector maFilterColumns
FilterColumn & createFilterColumn()
Creates a new auto filter column and stores it internally.
SortConditionVector maSortConditions
static OUString readString(SequenceInputStream &rStrm, bool b32BitLen=true)
Reads a BIFF12 string with leading 16-bit or 32-bit length field.
OUString msStyleName
Style name to retrieve the color from.
virtual void importRecord(sal_Int32 nRecId, SequenceInputStream &rStrm) override
Imports filter settings from the FILTERS and FILTER records.
ColorFilter(const WorkbookHelper &rHelper)
virtual void importAttribs(sal_Int32 nElement, const AttributeList &rAttribs) override
Imports filter settings from the filters and filter elements.
virtual ApiFilterSettings finalizeImport() override
Returns converted UNO API filter settings representing all filter settings.
bool mbIsBackgroundColor
Whether we are dealing with the background color (vs. text color)
virtual void importAttribs(sal_Int32 nElement, const AttributeList &rAttribs) override
Imports filter settings from the filters and filter elements.
void appendCriterion(const FilterCriterionModel &rCriterion)
Appends the passed filter criterion, if it contains valid settings.
FilterCriterionVector maCriteria
CustomFilter(const WorkbookHelper &rHelper)
virtual ApiFilterSettings finalizeImport() override
Returns converted UNO API filter settings representing all filter settings.
virtual void importRecord(sal_Int32 nRecId, SequenceInputStream &rStrm) override
Imports filter settings from the FILTERS and FILTER records.
bool getAbsoluteRange(ScRange &orRange) const
Tries to resolve the defined name to an absolute cell range.
DefinedNameRef getByBuiltinId(sal_Unicode cBuiltinId, sal_Int16 nCalcSheet) const
Returns a built-in defined name by its built-in identifier.
DiscreteFilter(const WorkbookHelper &rHelper)
virtual void importRecord(sal_Int32 nRecId, SequenceInputStream &rStrm) override
Imports filter settings from the FILTERS and FILTER records.
std::vector< std::pair< OUString, bool > > maValues
virtual ApiFilterSettings finalizeImport() override
Returns converted UNO API filter settings representing all filter settings.
virtual void importAttribs(sal_Int32 nElement, const AttributeList &rAttribs) override
Imports filter settings from the filters and filter elements.
A column in a filtered range.
FilterColumn(const WorkbookHelper &rHelper)
void importFilterColumn(const AttributeList &rAttribs)
Imports auto filter column settings from the filterColumn element.
ApiFilterSettings finalizeImport()
Returns converted UNO API filter settings representing all filter settings of this column.
std::shared_ptr< FilterSettingsBase > mxSettings
Base class for specific filter settings for a column in a filtered range.
virtual void importAttribs(sal_Int32 nElement, const AttributeList &rAttribs)
Derived classes import filter settings from the passed attribute list.
virtual void importRecord(sal_Int32 nRecId, SequenceInputStream &rStrm)
Derived classes import filter settings from the passed record.
FilterSettingsBase(const WorkbookHelper &rHelper)
virtual ApiFilterSettings finalizeImport()
Derived classes return converted UNO API filter settings representing all filter settings.
SortCondition(const WorkbookHelper &rHelper)
OUString maSortCustomList
void importSortCondition(const AttributeList &rAttribs, sal_Int16 nSheet)
OUString createDxfStyle(sal_Int32 nDxfId) const
Creates the style sheet described by the DXF with the passed identifier.
Top10Filter(const WorkbookHelper &rHelper)
bool mbTop
Number of items or percentage.
virtual void importAttribs(sal_Int32 nElement, const AttributeList &rAttribs) override
Imports filter settings from the filters and filter elements.
virtual void importRecord(sal_Int32 nRecId, SequenceInputStream &rStrm) override
Imports filter settings from the FILTERS and FILTER records.
virtual ApiFilterSettings finalizeImport() override
Returns converted UNO API filter settings representing all filter settings.
bool mbPercent
True = show top (greatest) items/percentage.
Helper class to provide access to global workbook data.
StylesBuffer & getStyles() const
Returns all cell formatting objects read from the styles substream.
ScDocument & getScDocument()
DefinedNamesBuffer & getDefinedNames() const
Returns the defined names read from the workbook globals.
css::uno::Reference< css::sheet::XDatabaseRange > createUnnamedDatabaseRangeObject(const ScRange &rRangeAddr) const
Creates and returns an unnamed database range on-the-fly in the Calc document.
#define STATIC_ARRAY_SELECT(array, index, def)
OUString GetString(int nId)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
const sal_Unicode BIFF_DEFNAME_CRITERIA
const sal_Int32 BIFF12_ID_DISCRETEFILTER
const sal_Int32 BIFF12_ID_CUSTOMFILTER
const sal_Int32 BIFF12_ID_CUSTOMFILTERS
std::shared_ptr< DefinedName > DefinedNameRef
const sal_Int32 BIFF12_ID_DISCRETEFILTERS
const sal_Int32 BIFF12_ID_TOP10FILTER
const sal_Unicode BIFF_DEFNAME_EXTRACT
const sal_Unicode BIFF_DEFNAME_FILTERDATABASE
void assignIfUsed(std::optional< Type > &rDestValue, const std::optional< Type > &rSourceValue)
bool getFlag(Type nBitField, Type nMask)
constexpr TypedWhichId< ScMergeFlagAttr > ATTR_MERGE_FLAG(145)
constexpr TypedWhichId< SvxBrushItem > ATTR_BACKGROUND(148)
::std::vector< ScSortKeyState > maKeyState
sal_uInt16 GetSortKeyCount() const
Contains UNO API filter settings for a column in a filtered range.
::std::vector< css::sheet::TableFilterField3 > FilterFieldVector
FilterFieldVector maFilterFields
std::optional< bool > mobNeedsRegExp
List of UNO API filter settings.
void appendField(bool bAnd, sal_Int32 nOperator, double fValue)
ApiFilterSettings()
If set, requires regular expressions to be enabled/disabled.
A 2D cell range address struct for binary filters.
A filter criterion for a custom filter.
void readBiffData(SequenceInputStream &rStrm)
Imports the criterion model from the passed BIFF12 stream.
sal_Int32 mnOperator
Comparison operand.
void setBiffOperator(sal_uInt8 nOperator)
Sets the passed BIFF operator constant.
FilterCriterionModel()
Operand data type (BIFF only).
sal_uInt8 mnDataType
Comparison operator.
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
std::unique_ptr< char[]> aBuffer