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 )
142 aBuffer.append(
'.' ).append(
'*' );
144 case '\\':
case '.':
case '|':
case '(':
case ')':
case '^':
case '$':
146 aBuffer.append(
'\\' ).append( *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 util::Color nColor(aColor);
451 mnOperator( XML_equal ),
452 mnDataType( BIFF_FILTER_DATATYPE_NONE )
459 XML_lessThan, XML_equal, XML_lessThanOrEqual, XML_greaterThan, XML_notEqual, XML_greaterThanOrEqual };
467 nOperator =
rStrm.readuChar();
472 case BIFF_FILTER_DATATYPE_DOUBLE:
475 case BIFF_FILTER_DATATYPE_STRING:
479 if( !aValue.isEmpty() )
483 case BIFF_FILTER_DATATYPE_BOOLEAN:
487 case BIFF_FILTER_DATATYPE_EMPTY:
492 case BIFF_FILTER_DATATYPE_NOTEMPTY:
498 OSL_ENSURE(
false,
"FilterCriterionModel::readBiffData - unexpected data type" );
513 case XLS_TOKEN( customFilters ):
517 case XLS_TOKEN( customFilter ):
521 OUString aValue = rAttribs.
getXString( XML_val, OUString() ).trim();
522 if( (aCriterion.
mnOperator == XML_equal) || (aCriterion.
mnOperator == XML_notEqual) || (!aValue.isEmpty()) )
551 OSL_ENSURE(
maCriteria.size() <= 2,
"CustomFilter::finalizeImport - too many filter criteria" );
555 sal_Int32 nOperator = 0;
556 bool bValidOperator = lclGetApiOperatorFromToken( nOperator, rCriterion.mnOperator );
559 if( rCriterion.maValue.has< OUString >() )
563 rCriterion.maValue >>= aValue;
565 bool bEqual = nOperator == FilterOperator2::EQUAL;
566 bool bNotEqual = nOperator == FilterOperator2::NOT_EQUAL;
567 if( bEqual || bNotEqual )
569 if( aValue.isEmpty() )
572 nOperator = bNotEqual ? FilterOperator2::NOT_EMPTY : FilterOperator2::EMPTY;
577 bool bHasLeadingAsterisk = lclTrimLeadingAsterisks( aValue );
578 bool bHasTrailingAsterisk = lclTrimTrailingAsterisks( aValue );
580 bValidOperator = !aValue.isEmpty();
583 if( bHasLeadingAsterisk && bHasTrailingAsterisk )
584 nOperator = bNotEqual ? FilterOperator2::DOES_NOT_CONTAIN : FilterOperator2::CONTAINS;
585 else if( bHasLeadingAsterisk )
586 nOperator = bNotEqual ? FilterOperator2::DOES_NOT_END_WITH : FilterOperator2::ENDS_WITH;
587 else if( bHasTrailingAsterisk )
588 nOperator = bNotEqual ? FilterOperator2::DOES_NOT_BEGIN_WITH : FilterOperator2::BEGINS_WITH;
597 if( lclConvertWildcardsToRegExp( aValue ) )
603 else if( rCriterion.maValue.has<
double >() )
607 rCriterion.maValue >>= fValue;
624 mbHiddenButton( false ),
640 nFlags =
rStrm.readuInt16();
668 mbDescending( false )
674 OUString aRangeStr = rAttribs.
getString( XML_ref, OUString() );
690 OUString aRangeStr = rAttribs.
getString( XML_ref, OUString() );
703 OUString aRangeStr = rAttribs.
getString( XML_ref, OUString() );
711 return *xFilterColumn;
718 return *xSortCondition;
724 const Reference<XSheetFilterDescriptor3> xFilterDesc( rxDatabaseRange->getFilterDescriptor(), UNO_QUERY_THROW );
725 if( !xFilterDesc.is() )
730 aDescProps.
setProperty( PROP_IsCaseSensitive,
false );
731 aDescProps.
setProperty( PROP_SkipDuplicates,
false );
732 aDescProps.
setProperty( PROP_Orientation, TableOrientation_ROWS );
733 aDescProps.
setProperty( PROP_ContainsHeader,
true );
734 aDescProps.
setProperty( PROP_CopyOutputData,
false );
737 ::std::vector<TableFilterField3> aFilterFields;
740 std::optional< bool > obNeedsRegExp;
749 bool bHasOrConnection =
false;
763 if (rxFilterColumn->isButtonHidden())
777 if( rColumnFields.size() >= 2 )
778 bHasOrConnection = std::any_of(rColumnFields.begin() + 1, rColumnFields.end(),
779 [](
const css::sheet::TableFilterField3& rColumnField) {
return rColumnField.Connection == FilterConnection_OR; });
784 if( !rColumnFields.empty() && bRegExpCompatible )
788 rColumnFields[ 0 ].Connection = FilterConnection_AND;
791 aFilterFields.insert( aFilterFields.end(), rColumnFields.begin(), rColumnFields.end() );
797 if( bHasOrConnection )
802 if( !aFilterFields.empty() )
806 bool bUseRegExp = obNeedsRegExp.value_or(
false );
807 aDescProps.
setProperty( PROP_UseRegularExpressions, bUseRegExp );
814 const SortCondition& rSorConditionLoaded = *xSortConditionPointer;
824 for (
size_t i=0; pUserList &&
i < pUserList->
size();
i++)
826 const OUString aEntry((*pUserList)[
i].
GetString());
866 OSL_FAIL(
"AutoFilter::finalizeImport(): cannot find matching DBData");
897 if( bHasAutoFilter || !xDatabaseRange.is() )
910 PropertySet aDescProps( xDatabaseRange->getFilterDescriptor() );
911 aDescProps.
setProperty( PROP_IsCaseSensitive,
false );
912 aDescProps.
setProperty( PROP_SkipDuplicates,
false );
913 aDescProps.
setProperty( PROP_Orientation, TableOrientation_ROWS );
914 aDescProps.
setProperty( PROP_ContainsHeader,
true );
916 aDescProps.
setProperty( PROP_UseRegularExpressions,
false );
921 bool bHasOutputRange = xExtractName && xExtractName->getAbsoluteRange( aOutputRange );
922 aDescProps.
setProperty( PROP_CopyOutputData, bHasOutputRange );
923 if( bHasOutputRange )
925 aDescProps.
setProperty( PROP_SaveOutputPosition,
true );
935 aRangeProps.
setProperty( PROP_FilterCriteriaSource,
936 CellRangeAddress( aCriteriaRange.
aStart.
Tab(),
944 if( pAutoFilter && rxDatabaseRange.is() )
try
948 aRangeProps.setProperty( PROP_AutoFilter,
true );
964 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
Stores individual user-defined sort list.
Collection of user-defined sort lists.
void push_back(ScUserListData *p)
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
virtual SfxStyleSheetBase * Find(const OUString &, SfxStyleFamily eFam, SfxStyleSearchBits n=SfxStyleSearchBits::All) const
const Color & GetFiltColor() const
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