1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_SC_INC_CONDITIO_HXX
21 #define INCLUDED_SC_INC_CONDITIO_HXX
24 #include "address.hxx"
25 #include <formula/grammar.hxx>
27 #include "rangelst.hxx"
29 #include <svl/listener.hxx>
31 #include <comphelper/stl_types.hxx>
32 #include <com/sun/star/sheet/ConditionOperator.hpp>
34 #include <rtl/math.hxx>
35 #include <tools/date.hxx>
36 #include <tools/link.hxx>
44 struct ScRefCellValue
;
48 struct RefUpdateContext
;
49 struct RefUpdateInsertTabContext
;
50 struct RefUpdateDeleteTabContext
;
51 struct RefUpdateMoveTabContext
;
56 #define SC_COND_NOBLANKS 1
58 enum class ScConditionMode
88 // For use in SAL_DEBUG etc. Output format not guaranteed to be stable.
89 template<typename charT
, typename traits
>
90 inline std::basic_ostream
<charT
, traits
> & operator <<(std::basic_ostream
<charT
, traits
> & stream
, const ScConditionMode
& rMode
)
94 case ScConditionMode::Equal
:
97 case ScConditionMode::Less
:
100 case ScConditionMode::Greater
:
103 case ScConditionMode::EqLess
:
106 case ScConditionMode::EqGreater
:
107 stream
<< "EQGREATER";
109 case ScConditionMode::NotEqual
:
110 stream
<< "NOTEQUAL";
112 case ScConditionMode::Between
:
115 case ScConditionMode::NotBetween
:
116 stream
<< "NOTBETWEEN";
118 case ScConditionMode::Duplicate
:
119 stream
<< "DUPLICATE";
121 case ScConditionMode::NotDuplicate
:
122 stream
<< "NOTDUPLICATE";
124 case ScConditionMode::Direct
:
127 case ScConditionMode::Top10
:
130 case ScConditionMode::Bottom10
:
131 stream
<< "BOTTOM10";
133 case ScConditionMode::TopPercent
:
134 stream
<< "TOPPERCENT";
136 case ScConditionMode::BottomPercent
:
137 stream
<< "BOTTOMPERCENT";
139 case ScConditionMode::AboveAverage
:
140 stream
<< "ABOVEAVERAGE";
142 case ScConditionMode::BelowAverage
:
143 stream
<< "BELOWAVERAGE";
145 case ScConditionMode::AboveEqualAverage
:
146 stream
<< "ABOVEEQUALAVERAGE";
148 case ScConditionMode::BelowEqualAverage
:
149 stream
<< "BELOWEQUALAVERAGE";
151 case ScConditionMode::Error
:
154 case ScConditionMode::NoError
:
157 case ScConditionMode::BeginsWith
:
158 stream
<< "BEGINSWITH";
160 case ScConditionMode::EndsWith
:
161 stream
<< "ENDSWITH";
163 case ScConditionMode::ContainsText
:
164 stream
<< "CONTAINSTEXT";
166 case ScConditionMode::NotContainsText
:
167 stream
<< "NOTCONTAINSTEXT";
169 case ScConditionMode::NONE
:
173 stream
<< "?(" << static_cast<int>(rMode
) << ")";
180 class ScFormulaListener
: public SvtListener
183 mutable bool mbDirty
;
185 std::function
<void()> maCallbackFunction
;
187 void startListening(const ScTokenArray
* pTokens
, const ScRange
& rPos
);
190 explicit ScFormulaListener(ScFormulaCell
* pCell
);
191 explicit ScFormulaListener(ScDocument
* pDoc
);
192 virtual ~ScFormulaListener() override
;
194 void Notify( const SfxHint
& rHint
) override
;
196 bool NeedsRepaint() const;
198 void addTokenArray(const ScTokenArray
* pTokens
, const ScRange
& rRange
);
199 void stopListening();
200 void setCallback(const std::function
<void()>& aCallbackFunction
);
203 class ScConditionalFormat
;
204 struct ScDataBarInfo
;
205 struct ScIconSetInfo
;
207 struct ScCondFormatData
210 pColorScale(nullptr),
215 ScDataBarInfo
* pDataBar
;
216 ScIconSetInfo
* pIconSet
;
220 class SC_DLLPUBLIC ScFormatEntry
223 ScFormatEntry(ScDocument
* pDoc
);
224 virtual ~ScFormatEntry() {}
235 virtual Type
GetType() const = 0;
236 virtual void UpdateReference( sc::RefUpdateContext
& rCxt
) = 0;
237 virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
) = 0;
238 virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
) = 0;
239 virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext
& rCxt
) = 0;
241 virtual ScFormatEntry
* Clone( ScDocument
* pDoc
) const = 0;
243 virtual void SetParent( ScConditionalFormat
* pNew
) = 0;
245 bool operator==( const ScFormatEntry
& ) const;
246 virtual bool IsEqual( const ScFormatEntry
&, bool bIgnoreSrcPos
) const;
248 virtual void startRendering();
249 virtual void endRendering();
255 template<typename charT
, typename traits
>
256 inline std::basic_ostream
<charT
, traits
> & operator <<(std::basic_ostream
<charT
, traits
> & stream
, const ScFormatEntry::Type
& rType
)
260 case ScFormatEntry::Type::Condition
:
261 stream
<< "Condition";
263 case ScFormatEntry::Type::Colorscale
:
264 stream
<< "Colorscale";
266 case ScFormatEntry::Type::Databar
:
269 case ScFormatEntry::Type::Iconset
:
272 case ScFormatEntry::Type::Date
:
276 stream
<< "?(" << static_cast<int>(rType
) << ")";
285 bool operator() (double nVal1
, double nVal2
) const
287 if(nVal1
< nVal2
&& !rtl::math::approxEqual(nVal1
, nVal2
))
294 class SC_DLLPUBLIC ScConditionEntry
: public ScFormatEntry
299 double nVal1
; // input or calculated
301 OUString aStrVal1
; // input or calculated
303 const OUString aStrNmsp1
; // namespace to be used on (re)compilation, e.g. in XML import
304 const OUString aStrNmsp2
; // namespace to be used on (re)compilation, e.g. in XML import
305 const formula::FormulaGrammar::Grammar eTempGrammar1
; // grammar to be used on (re)compilation, e.g. in XML import
306 const formula::FormulaGrammar::Grammar eTempGrammar2
; // grammar to be used on (re)compilation, e.g. in XML import
307 bool bIsStr1
; // for recognition of empty strings
309 std::unique_ptr
<ScTokenArray
> pFormula1
; // entered formula
310 std::unique_ptr
<ScTokenArray
> pFormula2
;
311 ScAddress aSrcPos
; // source position for formulas
313 OUString aSrcString
; // formula source position as text during XML import
314 std::unique_ptr
<ScFormulaCell
> pFCell1
;
315 std::unique_ptr
<ScFormulaCell
> pFCell2
;
319 std::unique_ptr
<ScFormulaListener
> mpListener
;
321 void SimplifyCompiledFormula( std::unique_ptr
<ScTokenArray
>& rFormula
,
326 void MakeCells( const ScAddress
& rPos
);
327 void Compile( const OUString
& rExpr1
, const OUString
& rExpr2
,
328 const OUString
& rExprNmsp1
, const OUString
& rExprNmsp2
,
329 formula::FormulaGrammar::Grammar eGrammar1
,
330 formula::FormulaGrammar::Grammar eGrammar2
,
332 void Interpret( const ScAddress
& rPos
);
334 bool IsValid( double nArg
, const ScAddress
& rPos
) const;
335 bool IsValidStr( const OUString
& rArg
, const ScAddress
& rPos
) const;
336 void StartListening();
339 ScConditionEntry( ScConditionMode eOper
,
340 const OUString
& rExpr1
, const OUString
& rExpr2
,
341 ScDocument
* pDocument
, const ScAddress
& rPos
,
342 const OUString
& rExprNmsp1
, const OUString
& rExprNmsp2
,
343 formula::FormulaGrammar::Grammar eGrammar1
,
344 formula::FormulaGrammar::Grammar eGrammar2
);
345 ScConditionEntry( ScConditionMode eOper
,
346 const ScTokenArray
* pArr1
, const ScTokenArray
* pArr2
,
347 ScDocument
* pDocument
, const ScAddress
& rPos
);
348 ScConditionEntry( const ScConditionEntry
& r
); // flat copy of formulas
349 // true copy of formulas (for Ref-Undo):
350 ScConditionEntry( ScDocument
* pDocument
, const ScConditionEntry
& r
);
351 virtual ~ScConditionEntry() override
;
353 bool IsEqual( const ScFormatEntry
& r
, bool bIgnoreSrcPos
) const override
;
355 virtual void SetParent( ScConditionalFormat
* pNew
) override
;
357 bool IsCellValid( ScRefCellValue
& rCell
, const ScAddress
& rPos
) const;
359 ScConditionMode
GetOperation() const { return eOp
; }
360 void SetOperation(ScConditionMode eMode
);
361 bool IsIgnoreBlank() const { return ( nOptions
& SC_COND_NOBLANKS
) == 0; }
362 void SetIgnoreBlank(bool bSet
);
363 const OUString
& GetSrcString() const { return aSrcString
; }
364 const ScAddress
& GetSrcPos() const { return aSrcPos
; }
366 ScAddress
GetValidSrcPos() const; // adjusted to allow textual representation of expressions
368 void SetSrcString( const OUString
& rNew
); // for XML import
370 void SetFormula1( const ScTokenArray
& rArray
);
371 void SetFormula2( const ScTokenArray
& rArray
);
373 OUString
GetExpression( const ScAddress
& rCursor
, sal_uInt16 nPos
, sal_uInt32 nNumFmt
= 0,
374 const formula::FormulaGrammar::Grammar eGrammar
= formula::FormulaGrammar::GRAM_DEFAULT
) const;
376 /** Create a flat copy using ScTokenArray copy-ctor with
378 ScTokenArray
* CreateFlatCopiedTokenArray( sal_uInt16 nPos
) const;
382 virtual void UpdateReference( sc::RefUpdateContext
& rCxt
) override
;
383 virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
) override
;
384 virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
) override
;
385 virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext
& rCxt
) override
;
387 bool MarkUsedExternalReferences() const;
389 virtual Type
GetType() const override
{ return Type::Condition
; }
391 virtual ScFormatEntry
* Clone(ScDocument
* pDoc
) const override
;
393 static ScConditionMode
GetModeFromApi(css::sheet::ConditionOperator nOperator
);
395 virtual void endRendering() override
;
396 virtual void startRendering() override
;
398 bool NeedsRepaint() const;
401 virtual void DataChanged() const;
402 ScDocument
* GetDocument() const { return mpDoc
; }
403 ScConditionalFormat
* pCondFormat
;
407 bool IsDuplicate(double nArg
, const OUString
& rStr
) const;
408 bool IsTopNElement( double nArg
) const;
409 bool IsTopNPercent( double nArg
) const;
410 bool IsBottomNElement( double nArg
) const;
411 bool IsBottomNPercent( double nArg
) const;
412 bool IsAboveAverage( double nArg
, bool bEqual
) const;
413 bool IsBelowAverage( double nArg
, bool bEqual
) const;
415 bool IsError( const ScAddress
& rPos
) const;
417 void FillCache() const;
419 struct ScConditionEntryCache
421 typedef std::map
<OUString
, sal_Int32
> StringCacheType
;
422 StringCacheType maStrings
;
423 typedef std::map
<double, sal_Int32
, approx_less
> ValueCacheType
;
424 ValueCacheType maValues
;
426 // cache them for easier access
429 ScConditionEntryCache():
433 mutable std::unique_ptr
<ScConditionEntryCache
> mpCache
;
436 // single condition entry for conditional formatting
437 class SC_DLLPUBLIC ScCondFormatEntry
: public ScConditionEntry
442 ScCondFormatEntry( ScConditionMode eOper
,
443 const OUString
& rExpr1
, const OUString
& rExpr2
,
444 ScDocument
* pDocument
, const ScAddress
& rPos
,
445 const OUString
& rStyle
,
446 const OUString
& rExprNmsp1
= EMPTY_OUSTRING
,
447 const OUString
& rExprNmsp2
= EMPTY_OUSTRING
,
448 formula::FormulaGrammar::Grammar eGrammar1
= formula::FormulaGrammar::GRAM_DEFAULT
,
449 formula::FormulaGrammar::Grammar eGrammar2
= formula::FormulaGrammar::GRAM_DEFAULT
);
450 ScCondFormatEntry( ScConditionMode eOper
,
451 const ScTokenArray
* pArr1
, const ScTokenArray
* pArr2
,
452 ScDocument
* pDocument
, const ScAddress
& rPos
,
453 const OUString
& rStyle
);
454 ScCondFormatEntry( const ScCondFormatEntry
& r
);
455 ScCondFormatEntry( ScDocument
* pDocument
, const ScCondFormatEntry
& r
);
456 virtual ~ScCondFormatEntry() override
;
458 bool IsEqual( const ScFormatEntry
& r
, bool bIgnoreSrcPos
) const override
;
460 const OUString
& GetStyle() const { return aStyleName
; }
461 void UpdateStyleName(const OUString
& rNew
) { aStyleName
=rNew
; }
462 virtual ScFormatEntry
* Clone(ScDocument
* pDoc
) const override
;
465 virtual void DataChanged() const override
;
468 namespace condformat
{
470 enum ScCondFormatDateType
489 class SC_DLLPUBLIC ScCondDateFormatEntry
: public ScFormatEntry
492 ScCondDateFormatEntry(ScDocument
* pDoc
);
493 ScCondDateFormatEntry(ScDocument
* pDoc
, const ScCondDateFormatEntry
& rEntry
);
495 bool IsValid( const ScAddress
& rPos
) const;
497 void SetDateType(condformat::ScCondFormatDateType eType
);
498 condformat::ScCondFormatDateType
GetDateType() const { return meType
;}
500 const OUString
& GetStyleName() const { return maStyleName
;}
501 void SetStyleName( const OUString
& rStyleName
);
503 virtual Type
GetType() const override
{ return Type::Date
; }
504 virtual void UpdateReference( sc::RefUpdateContext
& ) override
{}
505 virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext
& ) override
{}
506 virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& ) override
{}
507 virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext
& ) override
{}
509 virtual ScFormatEntry
* Clone( ScDocument
* pDoc
) const override
;
511 virtual void SetParent( ScConditionalFormat
* ) override
{}
513 virtual void startRendering() override
;
514 virtual void endRendering() override
;
517 condformat::ScCondFormatDateType meType
;
519 mutable std::unique_ptr
<Date
> mpCache
;
521 OUString maStyleName
;
524 // complete conditional formatting
525 class SC_DLLPUBLIC ScConditionalFormat
528 sal_uInt32 nKey
; // Index in attributes
530 std::vector
<std::unique_ptr
<ScFormatEntry
>> maEntries
;
531 ScRangeList maRanges
; // Ranges for conditional format
534 ScConditionalFormat(sal_uInt32 nNewKey
, ScDocument
* pDocument
);
535 ~ScConditionalFormat();
536 ScConditionalFormat(const ScConditionalFormat
&) = delete;
537 const ScConditionalFormat
& operator=(const ScConditionalFormat
&) = delete;
539 // true copy of formulas (for Ref-Undo / between documents)
540 ScConditionalFormat
* Clone(ScDocument
* pNewDoc
= nullptr) const;
542 void AddEntry( ScFormatEntry
* pNew
);
543 void RemoveEntry(size_t nIndex
);
544 void SetRange( const ScRangeList
& rRanges
);
545 const ScRangeList
& GetRange() const { return maRanges
; }
546 // don't use the same name as for the const version
547 ScRangeList
& GetRangeList() { return maRanges
; }
549 bool IsEmpty() const;
554 void UpdateReference( sc::RefUpdateContext
& rCxt
, bool bCopyAsMove
= false );
555 void UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
);
556 void UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
);
557 void UpdateMoveTab( sc::RefUpdateMoveTabContext
& rCxt
);
559 void InsertRow(SCTAB nTab
, SCCOL nColStart
, SCCOL nColEnd
, SCROW nRowStart
, SCSIZE nSize
);
560 void InsertCol(SCTAB nTab
, SCROW nRowStart
, SCROW nRowEnd
, SCCOL nColStart
, SCSIZE nSize
);
562 void DeleteArea( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
);
563 void RenameCellStyle( const OUString
& rOld
, const OUString
& rNew
);
565 const ScFormatEntry
* GetEntry( sal_uInt16 nPos
) const;
567 const OUString
& GetCellStyle( ScRefCellValue
& rCell
, const ScAddress
& rPos
) const;
569 ScCondFormatData
GetData( ScRefCellValue
& rCell
, const ScAddress
& rPos
) const;
571 bool EqualEntries( const ScConditionalFormat
& r
, bool bIgnoreSrcPos
= false ) const;
575 sal_uInt32
GetKey() const { return nKey
; }
576 void SetKey(sal_uInt32 nNew
) { nKey
= nNew
; } // only if not inserted!
578 bool MarkUsedExternalReferences() const;
580 // sorted (via std::set) by Index
581 bool operator < ( const ScConditionalFormat
& r
) const { return nKey
< r
.nKey
; }
583 void startRendering();
587 // List of all conditional formats in a sheet
588 class SC_DLLPUBLIC ScConditionalFormatList
591 typedef std::set
<std::unique_ptr
<ScConditionalFormat
>,
592 comphelper::UniquePtrValueLess
<ScConditionalFormat
>> ConditionalFormatContainer
;
593 ConditionalFormatContainer m_ConditionalFormats
;
595 void operator =(ScConditionalFormatList
const &) = delete;
598 ScConditionalFormatList() {}
599 ScConditionalFormatList(const ScConditionalFormatList
& rList
);
600 ScConditionalFormatList(ScDocument
* pDoc
, const ScConditionalFormatList
& rList
);
602 void InsertNew( ScConditionalFormat
* pNew
);
605 * Checks that all cond formats have a non empty range.
606 * Deletes empty cond formats. Optionally call rLink
607 * on the empty format before deleting it.
608 * @return true if all cond formats were valid
610 bool CheckAllEntries(const Link
<ScConditionalFormat
*,void>& rLink
= Link
<ScConditionalFormat
*,void>());
612 ScConditionalFormat
* GetFormat( sal_uInt32 nKey
);
613 const ScConditionalFormat
* GetFormat( sal_uInt32 nKey
) const;
617 void UpdateReference( sc::RefUpdateContext
& rCxt
);
618 void UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
);
619 void UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
);
620 void UpdateMoveTab( sc::RefUpdateMoveTabContext
& rCxt
);
622 void InsertRow(SCTAB nTab
, SCCOL nColStart
, SCCOL nColEnd
, SCROW nRowStart
, SCSIZE nSize
);
623 void InsertCol(SCTAB nTab
, SCROW nRowStart
, SCROW nRowEnd
, SCCOL nColStart
, SCSIZE nSize
);
625 void RenameCellStyle( const OUString
& rOld
, const OUString
& rNew
);
626 void DeleteArea( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
);
628 typedef ConditionalFormatContainer::iterator iterator
;
629 typedef ConditionalFormatContainer::const_iterator const_iterator
;
631 ScRangeList
GetCombinedRange() const;
633 void RemoveFromDocument(ScDocument
* pDoc
) const;
634 void AddToDocument(ScDocument
* pDoc
) const;
637 const_iterator
begin() const;
639 const_iterator
end() const;
643 void erase(sal_uLong nIndex
);
646 void startRendering();
649 sal_uInt32
getMaxKey() const;
654 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */