LibreOffice Module sc (master) 1
condformatbuffer.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <memory>
21#include <unordered_set>
22#include <unordered_map>
23#include <condformatbuffer.hxx>
24#include <formulaparser.hxx>
25
26#include <com/sun/star/sheet/ConditionOperator2.hpp>
27#include <sal/log.hxx>
28#include <osl/diagnose.h>
29#include <o3tl/string_view.hxx>
34#include <oox/token/tokens.hxx>
35#include <addressconverter.hxx>
36#include <biffhelper.hxx>
37#include <stylesbuffer.hxx>
38#include <themebuffer.hxx>
39
40#include <colorscale.hxx>
41#include <conditio.hxx>
42#include <document.hxx>
43#include <tokenarray.hxx>
44#include <tokenuno.hxx>
45#include <extlstcontext.hxx>
46#include <utility>
47
48namespace oox::xls {
49
50using namespace ::com::sun::star::sheet;
51using namespace ::com::sun::star::uno;
52
53namespace {
54
55const sal_Int32 BIFF12_CFRULE_TYPE_CELLIS = 1;
56const sal_Int32 BIFF12_CFRULE_TYPE_EXPRESSION = 2;
57const sal_Int32 BIFF12_CFRULE_TYPE_COLORSCALE = 3;
58const sal_Int32 BIFF12_CFRULE_TYPE_DATABAR = 4;
59const sal_Int32 BIFF12_CFRULE_TYPE_TOPTEN = 5;
60const sal_Int32 BIFF12_CFRULE_TYPE_ICONSET = 6;
61
62const sal_Int32 BIFF12_CFRULE_SUB_CELLIS = 0;
63const sal_Int32 BIFF12_CFRULE_SUB_EXPRESSION = 1;
64const sal_Int32 BIFF12_CFRULE_SUB_COLORSCALE = 2;
65const sal_Int32 BIFF12_CFRULE_SUB_DATABAR = 3;
66const sal_Int32 BIFF12_CFRULE_SUB_ICONSET = 4;
67const sal_Int32 BIFF12_CFRULE_SUB_TOPTEN = 5;
68const sal_Int32 BIFF12_CFRULE_SUB_UNIQUE = 7;
69const sal_Int32 BIFF12_CFRULE_SUB_TEXT = 8;
70const sal_Int32 BIFF12_CFRULE_SUB_BLANK = 9;
71const sal_Int32 BIFF12_CFRULE_SUB_NOTBLANK = 10;
72const sal_Int32 BIFF12_CFRULE_SUB_ERROR = 11;
73const sal_Int32 BIFF12_CFRULE_SUB_NOTERROR = 12;
74const sal_Int32 BIFF12_CFRULE_SUB_TODAY = 15;
75const sal_Int32 BIFF12_CFRULE_SUB_TOMORROW = 16;
76const sal_Int32 BIFF12_CFRULE_SUB_YESTERDAY = 17;
77const sal_Int32 BIFF12_CFRULE_SUB_LAST7DAYS = 18;
78const sal_Int32 BIFF12_CFRULE_SUB_LASTMONTH = 19;
79const sal_Int32 BIFF12_CFRULE_SUB_NEXTMONTH = 20;
80const sal_Int32 BIFF12_CFRULE_SUB_THISWEEK = 21;
81const sal_Int32 BIFF12_CFRULE_SUB_NEXTWEEK = 22;
82const sal_Int32 BIFF12_CFRULE_SUB_LASTWEEK = 23;
83const sal_Int32 BIFF12_CFRULE_SUB_THISMONTH = 24;
84const sal_Int32 BIFF12_CFRULE_SUB_ABOVEAVERAGE = 25;
85const sal_Int32 BIFF12_CFRULE_SUB_BELOWAVERAGE = 26;
86const sal_Int32 BIFF12_CFRULE_SUB_DUPLICATE = 27;
87const sal_Int32 BIFF12_CFRULE_SUB_EQABOVEAVERAGE = 29;
88const sal_Int32 BIFF12_CFRULE_SUB_EQBELOWAVERAGE = 30;
89
90const sal_Int32 BIFF12_CFRULE_TIMEOP_TODAY = 0;
91const sal_Int32 BIFF12_CFRULE_TIMEOP_YESTERDAY = 1;
92const sal_Int32 BIFF12_CFRULE_TIMEOP_LAST7DAYS = 2;
93const sal_Int32 BIFF12_CFRULE_TIMEOP_THISWEEK = 3;
94const sal_Int32 BIFF12_CFRULE_TIMEOP_LASTWEEK = 4;
95const sal_Int32 BIFF12_CFRULE_TIMEOP_LASTMONTH = 5;
96const sal_Int32 BIFF12_CFRULE_TIMEOP_TOMORROW = 6;
97const sal_Int32 BIFF12_CFRULE_TIMEOP_NEXTWEEK = 7;
98const sal_Int32 BIFF12_CFRULE_TIMEOP_NEXTMONTH = 8;
99const sal_Int32 BIFF12_CFRULE_TIMEOP_THISMONTH = 9;
100
101const sal_uInt16 BIFF12_CFRULE_STOPIFTRUE = 0x0002;
102const sal_uInt16 BIFF12_CFRULE_ABOVEAVERAGE = 0x0004;
103const sal_uInt16 BIFF12_CFRULE_BOTTOM = 0x0008;
104const sal_uInt16 BIFF12_CFRULE_PERCENT = 0x0010;
105
106bool isValue(std::u16string_view rStr, double& rVal)
107{
108 sal_Int32 nEnd = -1;
109 rVal = rtl::math::stringToDouble(o3tl::trim(rStr), '.', ',', nullptr, &nEnd);
110
111 return nEnd >= static_cast<sal_Int32>(rStr.size());
112}
113
114void SetCfvoData( ColorScaleRuleModelEntry* pEntry, const AttributeList& rAttribs )
115{
116 OUString aType = rAttribs.getString( XML_type, OUString() );
117 OUString aVal = rAttribs.getString(XML_val, OUString());
118
119 if (aVal != "\"\"")
120 {
121 double nVal = 0.0;
122 bool bVal = isValue(aVal, nVal);
123 if( !bVal || aType == "formula" )
124 {
125 pEntry->maFormula = aVal;
126 }
127 else
128 {
129 pEntry->mnVal = nVal;
130 }
131 }
132
133 if (aType == "num")
134 {
135 pEntry->mbNum = true;
136 }
137 else if( aType == "min" )
138 {
139 pEntry->mbMin = true;
140 }
141 else if( aType == "max" )
142 {
143 pEntry->mbMax = true;
144 }
145 else if( aType == "percent" )
146 {
147 pEntry->mbPercent = true;
148 }
149 else if( aType == "percentile" )
150 {
151 pEntry->mbPercentile = true;
152 }
153}
154
155}
156
158 WorksheetHelper( rFormat ),
159 mnCfvo(0),
160 mnCol(0)
161{
162}
163
165{
166 if(mnCfvo >= maColorScaleRuleEntries.size())
167 maColorScaleRuleEntries.emplace_back();
168
169 SetCfvoData( &maColorScaleRuleEntries[mnCfvo], rAttribs );
170
171 ++mnCfvo;
172}
173
174// https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.spreadsheet.indexedcolors?view=openxml-2.8.1
175static ::Color IndexedColors[] = {
176 0x00000000,
177 0x00FFFFFF,
178 0x00FF0000,
179 0x0000FF00,
180 0x000000FF,
181 0x00FFFF00,
182 0x00FF00FF,
183 0x0000FFFF,
184 0x00000000,
185 0x00FFFFFF,
186 0x00FF0000,
187 0x0000FF00,
188 0x000000FF,
189 0x00FFFF00,
190 0x00FF00FF,
191 0x0000FFFF,
192 0x00800000,
193 0x00008000,
194 0x00000080,
195 0x00808000,
196 0x00800080,
197 0x00008080,
198 0x00C0C0C0,
199 0x00808080,
200 0x009999FF,
201 0x00993366,
202 0x00FFFFCC,
203 0x00CCFFFF,
204 0x00660066,
205 0x00FF8080,
206 0x000066CC,
207 0x00CCCCFF,
208 0x00000080,
209 0x00FF00FF,
210 0x00FFFF00,
211 0x0000FFFF,
212 0x00800080,
213 0x00800000,
214 0x00008080,
215 0x000000FF,
216 0x0000CCFF,
217 0x00CCFFFF,
218 0x00CCFFCC,
219 0x00FFFF99,
220 0x0099CCFF,
221 0x00FF99CC,
222 0x00CC99FF,
223 0x00FFCC99,
224 0x003366FF,
225 0x0033CCCC,
226 0x0099CC00,
227 0x00FFCC00,
228 0x00FF9900,
229 0x00FF6600,
230 0x00666699,
231 0x00969696,
232 0x00003366,
233 0x00339966,
234 0x00003300,
235 0x00333300,
236 0x00993300,
237 0x00993366,
238 0x00333399,
239 0x00333333,
240 0x00000000, // System Foreground ?
241 0x00000000, // System Background ?
242};
243
244namespace {
245
246::Color importOOXColor(const AttributeList& rAttribs, const ThemeBuffer& rThemeBuffer, const GraphicHelper& rGraphicHelper)
247{
248 ::Color nColor;
249 if( rAttribs.hasAttribute( XML_rgb ) )
250 nColor = ::Color(ColorTransparency, rAttribs.getUnsignedHex( XML_rgb, UNSIGNED_RGB_TRANSPARENT ));
251 else if( rAttribs.hasAttribute( XML_theme ) )
252 {
253 sal_uInt32 nThemeIndex = rAttribs.getUnsigned( XML_theme, 0 );
254
255 // Excel has a bug in the mapping of index 0, 1, 2 and 3.
256 if (nThemeIndex == 0)
257 nThemeIndex = 1;
258 else if (nThemeIndex == 1)
259 nThemeIndex = 0;
260 else if (nThemeIndex == 2)
261 nThemeIndex = 3;
262 else if (nThemeIndex == 3)
263 nThemeIndex = 2;
264
265 nColor = rThemeBuffer.getColorByIndex( nThemeIndex );
266 }
267 else if (rAttribs.hasAttribute(XML_indexed))
268 {
269 sal_uInt32 nIndexed = rAttribs.getUnsigned(XML_indexed, 0);
270 if (nIndexed < std::size(IndexedColors))
271 nColor = IndexedColors[nIndexed];
272 }
273
274 ::Color aColor;
275 double nTint = rAttribs.getDouble(XML_tint, 0.0);
276 if (nTint != 0.0)
277 {
278 oox::drawingml::Color aDMColor;
279 aDMColor.setSrgbClr(nColor);
280 aDMColor.addExcelTintTransformation(nTint);
281 aColor = aDMColor.getColor(rGraphicHelper);
282 }
283 else
284 aColor = nColor.GetRGBColor();
285
286 return aColor;
287}
288
289}
290
292{
293 ThemeBuffer& rThemeBuffer = getTheme();
294 GraphicHelper& rGraphicHelper = getBaseFilter().getGraphicHelper();
295 ::Color aColor = importOOXColor(rAttribs, rThemeBuffer, rGraphicHelper);
296
297 if(mnCol >= maColorScaleRuleEntries.size())
298 maColorScaleRuleEntries.emplace_back();
299
300 maColorScaleRuleEntries[mnCol].maColor = aColor;
301 ++mnCol;
302}
303
304namespace {
305
306ScColorScaleEntry* ConvertToModel( const ColorScaleRuleModelEntry& rEntry, ScDocument* pDoc, const ScAddress& rAddr )
307{
308 ScColorScaleEntry* pEntry = new ScColorScaleEntry(rEntry.mnVal, rEntry.maColor);
309
310 if(rEntry.mbMin)
311 pEntry->SetType(COLORSCALE_MIN);
312 if(rEntry.mbMax)
313 pEntry->SetType(COLORSCALE_MAX);
314 if(rEntry.mbPercent)
316 if(rEntry.mbPercentile)
318 if (rEntry.mbNum)
319 pEntry->SetType(COLORSCALE_VALUE);
320
321 if(!rEntry.maFormula.isEmpty())
322 {
325 }
326
327 return pEntry;
328}
329
330}
331
333{
335 {
336 ScColorScaleEntry* pEntry = ConvertToModel( rEntry, pDoc, rAddr );
337
338 pFormat->AddEntry( pEntry );
339 }
340}
341
343 WorksheetHelper( rFormat ),
344 mxFormat(new ScDataBarFormatData)
345{
346 mxFormat->meAxisPosition = databar::NONE;
347}
348
350{
351 ThemeBuffer& rThemeBuffer = getTheme();
352 GraphicHelper& rGraphicHelper = getBaseFilter().getGraphicHelper();
353 ::Color aColor = importOOXColor(rAttribs, rThemeBuffer, rGraphicHelper);
354
355 mxFormat->maPositiveColor = aColor;
356}
357
359{
361 if(!mpLowerLimit)
362 {
364 pEntry = mpLowerLimit.get();
365 }
366 else
367 {
369 pEntry = mpUpperLimit.get();
370 }
371
372 SetCfvoData( pEntry, rAttribs );
373}
374
376{
377 mxFormat->mbOnlyBar = !rAttribs.getBool( XML_showValue, true );
378 mxFormat->mnMinLength = rAttribs.getUnsigned( XML_minLength, 10);
379 mxFormat->mnMaxLength = rAttribs.getUnsigned( XML_maxLength, 90);
380}
381
382void DataBarRule::SetData( ScDataBarFormat* pFormat, ScDocument* pDoc, const ScAddress& rAddr )
383{
384 ScColorScaleEntry* pUpperEntry = ConvertToModel(*mpUpperLimit, pDoc, rAddr);
385 ScColorScaleEntry* pLowerEntry = ConvertToModel(*mpLowerLimit, pDoc, rAddr);
386
387 mxFormat->mpUpperLimit.reset( pUpperEntry );
388 mxFormat->mpLowerLimit.reset( pLowerEntry );
389 pFormat->SetDataBarData(mxFormat.release());
390}
391
393 WorksheetHelper( rParent ),
394 mxFormatData( new ScIconSetFormatData ),
395 mbCustom(false)
396{
397}
398
400{
401 ColorScaleRuleModelEntry aNewEntry;
402 SetCfvoData(&aNewEntry, rAttribs);
403
404 maEntries.push_back(aNewEntry);
405}
406
408{
409 maIconSetType = rAttribs.getString( XML_iconSet, "3TrafficLights1" );
410 mxFormatData->mbShowValue = rAttribs.getBool( XML_showValue, true );
411 mxFormatData->mbReverse = rAttribs.getBool( XML_reverse, false );
412 mbCustom = rAttribs.getBool(XML_custom, false);
413}
414
415void IconSetRule::importFormula(const OUString& rFormula)
416{
417 ColorScaleRuleModelEntry& rEntry = maEntries.back();
418 double nVal = 0.0;
419 if ((rEntry.mbNum || rEntry.mbPercent || rEntry.mbPercentile) && isValue(rFormula, nVal))
420 {
421 rEntry.mnVal = nVal;
422 }
423 else if (!rFormula.isEmpty())
424 rEntry.maFormula = rFormula;
425}
426
427namespace {
428
429ScIconSetType getType(std::u16string_view rName)
430{
432 const ScIconSetMap* pIconSetMap = ScIconSetFormat::g_IconSetMap;
433 for(size_t i = 0; pIconSetMap[i].pName; ++i)
434 {
435 if(OUString::createFromAscii(pIconSetMap[i].pName) == rName)
436 {
437 eIconSetType = pIconSetMap[i].eType;
438 break;
439 }
440 }
441
442 return eIconSetType;
443}
444
445}
446
448{
449 OUString aIconSet = rAttribs.getString(XML_iconSet, OUString());
450 sal_Int32 nIndex = rAttribs.getInteger(XML_iconId, -1);
451 if (aIconSet == "NoIcons")
452 {
453 nIndex = -1;
454 }
455
456 ScIconSetType eIconSetType = getType(aIconSet);
457 mxFormatData->maCustomVector.emplace_back(eIconSetType, nIndex);
458}
459
460void IconSetRule::SetData( ScIconSetFormat* pFormat, ScDocument* pDoc, const ScAddress& rPos )
461{
462 for(const ColorScaleRuleModelEntry & rEntry : maEntries)
463 {
464 ScColorScaleEntry* pModelEntry = ConvertToModel( rEntry, pDoc, rPos );
465 mxFormatData->m_Entries.emplace_back(pModelEntry);
466 }
467
468 mxFormatData->eIconSetType = getType(maIconSetType);
469 mxFormatData->mbCustom = mbCustom;
470 pFormat->SetIconSetData(mxFormatData.release());
471}
472
474 mnPriority( -1 ),
476 mnOperator( XML_TOKEN_INVALID ),
477 mnTimePeriod( XML_TOKEN_INVALID ),
478 mnRank( 0 ),
479 mnStdDev( 0 ),
480 mnDxfId( -1 ),
481 mbStopIfTrue( false ),
482 mbBottom( false ),
483 mbPercent( false ),
484 mbAboveAverage( true ),
485 mbEqualAverage( false )
486{
487}
488
489void CondFormatRuleModel::setBiffOperator( sal_Int32 nOperator )
490{
491 static const sal_Int32 spnOperators[] = {
492 XML_TOKEN_INVALID, XML_between, XML_notBetween, XML_equal, XML_notEqual,
493 XML_greaterThan, XML_lessThan, XML_greaterThanOrEqual, XML_lessThanOrEqual };
494 mnOperator = STATIC_ARRAY_SELECT( spnOperators, nOperator, XML_TOKEN_INVALID );
495}
496
497void CondFormatRuleModel::setBiff12TextType( sal_Int32 nOperator )
498{
499 // note: type XML_notContainsText vs. operator XML_notContains
500 static const sal_Int32 spnTypes[] = { XML_containsText, XML_notContainsText, XML_beginsWith, XML_endsWith };
501 mnType = STATIC_ARRAY_SELECT( spnTypes, nOperator, XML_TOKEN_INVALID );
502 static const sal_Int32 spnOperators[] = { XML_containsText, XML_notContains, XML_beginsWith, XML_endsWith };
503 mnOperator = STATIC_ARRAY_SELECT( spnOperators, nOperator, XML_TOKEN_INVALID );
504}
505
507 WorksheetHelper( rCondFormat ),
508 mrCondFormat( rCondFormat ),
509 mpFormat(pFormat),
510 mpFormatEntry(nullptr)
511{
512}
513
515{
516 maModel.maText = rAttribs.getString( XML_text, OUString() );
517 maModel.mnPriority = rAttribs.getInteger( XML_priority, -1 );
519 maModel.mnOperator = rAttribs.getToken( XML_operator, XML_TOKEN_INVALID );
520 maModel.mnTimePeriod = rAttribs.getToken( XML_timePeriod, XML_TOKEN_INVALID );
521 maModel.mnRank = rAttribs.getInteger( XML_rank, 0 );
522 maModel.mnStdDev = rAttribs.getInteger( XML_stdDev, 0 );
523 maModel.mnDxfId = rAttribs.getInteger( XML_dxfId, -1 );
524 maModel.mbStopIfTrue = rAttribs.getBool( XML_stopIfTrue, false );
525 maModel.mbBottom = rAttribs.getBool( XML_bottom, false );
526 maModel.mbPercent = rAttribs.getBool( XML_percent, false );
527 maModel.mbAboveAverage = rAttribs.getBool( XML_aboveAverage, true );
528 maModel.mbEqualAverage = rAttribs.getBool( XML_equalAverage, false );
529
530 if(maModel.mnType == XML_colorScale)
531 {
532 //import the remaining values
533
534 }
535}
536
537void CondFormatRule::appendFormula( const OUString& rFormula )
538{
540 ApiTokenSequence aTokens = getFormulaParser().importFormula( aBaseAddr, rFormula );
541 maModel.maFormulas.push_back( aTokens );
542}
543
545{
546 sal_Int32 nType, nSubType, nOperator, nFmla1Size, nFmla2Size, nFmla3Size;
547 sal_uInt16 nFlags;
548 nType = rStrm.readInt32();
549 nSubType = rStrm.readInt32();
550 maModel.mnDxfId = rStrm.readInt32();
551 maModel.mnPriority = rStrm.readInt32();
552 nOperator = rStrm.readInt32();
553 rStrm.skip( 8 );
554 nFlags = rStrm.readuInt16();
555 nFmla1Size = rStrm.readInt32();
556 nFmla2Size = rStrm.readInt32();
557 nFmla3Size = rStrm.readInt32();
559
560 /* Import the formulas. For no obvious reason, the sizes of the formulas
561 are already stored before. Nevertheless the following formulas contain
562 their own sizes. */
563
564 // first formula
565 // I am not bored enough to bother simplifying these expressions
566 SAL_WARN_IF( !( (nFmla1Size >= 0) || ((nFmla2Size == 0) && (nFmla3Size == 0)) ), "sc.filter", "CondFormatRule::importCfRule - missing first formula" );
567 SAL_WARN_IF( !( (nFmla1Size > 0) == (rStrm.getRemaining() >= 8) ), "sc.filter", "CondFormatRule::importCfRule - formula size mismatch" );
568 if( rStrm.getRemaining() >= 8 )
569 {
572 maModel.maFormulas.push_back( aTokens );
573
574 // second formula
575 OSL_ENSURE( (nFmla2Size >= 0) || (nFmla3Size == 0), "CondFormatRule::importCfRule - missing second formula" );
576 OSL_ENSURE( (nFmla2Size > 0) == (rStrm.getRemaining() >= 8), "CondFormatRule::importCfRule - formula size mismatch" );
577 if( rStrm.getRemaining() >= 8 )
578 {
580 maModel.maFormulas.push_back( aTokens );
581
582 // third formula
583 OSL_ENSURE( (nFmla3Size > 0) == (rStrm.getRemaining() >= 8), "CondFormatRule::importCfRule - formula size mismatch" );
584 if( rStrm.getRemaining() >= 8 )
585 {
587 maModel.maFormulas.push_back( aTokens );
588 }
589 }
590 }
591
592 // flags
593 maModel.mbStopIfTrue = getFlag( nFlags, BIFF12_CFRULE_STOPIFTRUE );
594 maModel.mbBottom = getFlag( nFlags, BIFF12_CFRULE_BOTTOM );
595 maModel.mbPercent = getFlag( nFlags, BIFF12_CFRULE_PERCENT );
596 maModel.mbAboveAverage = getFlag( nFlags, BIFF12_CFRULE_ABOVEAVERAGE );
597 // no flag for equalAverage, must be determined from subtype below...
598
599 // Convert the type/operator settings. This is a real mess...
600 switch( nType )
601 {
602 case BIFF12_CFRULE_TYPE_CELLIS:
604 nSubType != BIFF12_CFRULE_SUB_CELLIS, "sc.filter",
605 "CondFormatRule::importCfRule - rule type/subtype mismatch");
606 maModel.mnType = XML_cellIs;
607 maModel.setBiffOperator( nOperator );
608 OSL_ENSURE( maModel.mnOperator != XML_TOKEN_INVALID, "CondFormatRule::importCfRule - unknown operator" );
609 break;
610 case BIFF12_CFRULE_TYPE_EXPRESSION:
611 // here we have to look at the subtype to find the real type...
612 switch( nSubType )
613 {
614 case BIFF12_CFRULE_SUB_EXPRESSION:
615 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
616 maModel.mnType = XML_expression;
617 break;
618 case BIFF12_CFRULE_SUB_UNIQUE:
619 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
620 maModel.mnType = XML_uniqueValues;
621 break;
622 case BIFF12_CFRULE_SUB_TEXT:
623 maModel.setBiff12TextType( nOperator );
624 OSL_ENSURE( maModel.mnType != XML_TOKEN_INVALID, "CondFormatRule::importCfRule - unexpected operator value" );
625 break;
626 case BIFF12_CFRULE_SUB_BLANK:
627 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
628 maModel.mnType = XML_containsBlanks;
629 break;
630 case BIFF12_CFRULE_SUB_NOTBLANK:
631 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
632 maModel.mnType = XML_notContainsBlanks;
633 break;
634 case BIFF12_CFRULE_SUB_ERROR:
635 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
636 maModel.mnType = XML_containsErrors;
637 break;
638 case BIFF12_CFRULE_SUB_NOTERROR:
639 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
640 maModel.mnType = XML_notContainsErrors;
641 break;
642 case BIFF12_CFRULE_SUB_TODAY:
644 nOperator != BIFF12_CFRULE_TIMEOP_TODAY, "sc.filter",
645 "CondFormatRule::importCfRule - unexpected time operator value");
646 maModel.mnType = XML_timePeriod;
647 maModel.mnTimePeriod = XML_today;
648 break;
649 case BIFF12_CFRULE_SUB_TOMORROW:
651 nOperator != BIFF12_CFRULE_TIMEOP_TOMORROW, "sc.filter",
652 "CondFormatRule::importCfRule - unexpected time operator value");
653 maModel.mnType = XML_timePeriod;
654 maModel.mnTimePeriod = XML_tomorrow;
655 break;
656 case BIFF12_CFRULE_SUB_YESTERDAY:
658 nOperator != BIFF12_CFRULE_TIMEOP_YESTERDAY,
659 "sc.filter",
660 "CondFormatRule::importCfRule - unexpected time operator value");
661 maModel.mnType = XML_timePeriod;
662 maModel.mnTimePeriod = XML_yesterday;
663 break;
664 case BIFF12_CFRULE_SUB_LAST7DAYS:
666 nOperator != BIFF12_CFRULE_TIMEOP_LAST7DAYS,
667 "sc.filter",
668 "CondFormatRule::importCfRule - unexpected time operator value");
669 maModel.mnType = XML_timePeriod;
670 maModel.mnTimePeriod = XML_last7Days;
671 break;
672 case BIFF12_CFRULE_SUB_LASTMONTH:
674 nOperator != BIFF12_CFRULE_TIMEOP_LASTMONTH,
675 "sc.filter",
676 "CondFormatRule::importCfRule - unexpected time operator value");
677 maModel.mnType = XML_timePeriod;
678 maModel.mnTimePeriod = XML_lastMonth;
679 break;
680 case BIFF12_CFRULE_SUB_NEXTMONTH:
682 nOperator != BIFF12_CFRULE_TIMEOP_NEXTMONTH,
683 "sc.filter",
684 "CondFormatRule::importCfRule - unexpected time operator value");
685 maModel.mnType = XML_timePeriod;
686 maModel.mnTimePeriod = XML_nextMonth;
687 break;
688 case BIFF12_CFRULE_SUB_THISWEEK:
690 nOperator != BIFF12_CFRULE_TIMEOP_THISWEEK, "sc.filter",
691 "CondFormatRule::importCfRule - unexpected time operator value");
692 maModel.mnType = XML_timePeriod;
693 maModel.mnTimePeriod = XML_thisWeek;
694 break;
695 case BIFF12_CFRULE_SUB_NEXTWEEK:
697 nOperator != BIFF12_CFRULE_TIMEOP_NEXTWEEK, "sc.filter",
698 "CondFormatRule::importCfRule - unexpected time operator value");
699 maModel.mnType = XML_timePeriod;
700 maModel.mnTimePeriod = XML_nextWeek;
701 break;
702 case BIFF12_CFRULE_SUB_LASTWEEK:
704 nOperator != BIFF12_CFRULE_TIMEOP_LASTWEEK, "sc.filter",
705 "CondFormatRule::importCfRule - unexpected time operator value");
706 maModel.mnType = XML_timePeriod;
707 maModel.mnTimePeriod = XML_lastWeek;
708 break;
709 case BIFF12_CFRULE_SUB_THISMONTH:
711 nOperator != BIFF12_CFRULE_TIMEOP_THISMONTH,
712 "sc.filter",
713 "CondFormatRule::importCfRule - unexpected time operator value");
714 maModel.mnType = XML_timePeriod;
715 maModel.mnTimePeriod = XML_thisMonth;
716 break;
717 case BIFF12_CFRULE_SUB_ABOVEAVERAGE:
718 OSL_ENSURE( maModel.mbAboveAverage, "CondFormatRule::importCfRule - wrong above-average flag" );
719 maModel.mnType = XML_aboveAverage;
720 maModel.mnStdDev = nOperator; // operator field used for standard deviation
721 maModel.mbAboveAverage = true;
722 maModel.mbEqualAverage = false; // does not exist as real flag...
723 break;
724 case BIFF12_CFRULE_SUB_BELOWAVERAGE:
725 OSL_ENSURE( !maModel.mbAboveAverage, "CondFormatRule::importCfRule - wrong above-average flag" );
726 maModel.mnType = XML_aboveAverage;
727 maModel.mnStdDev = nOperator; // operator field used for standard deviation
728 maModel.mbAboveAverage = false;
729 maModel.mbEqualAverage = false; // does not exist as real flag...
730 break;
731 case BIFF12_CFRULE_SUB_DUPLICATE:
732 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
733 maModel.mnType = XML_duplicateValues;
734 break;
735 case BIFF12_CFRULE_SUB_EQABOVEAVERAGE:
736 OSL_ENSURE( maModel.mbAboveAverage, "CondFormatRule::importCfRule - wrong above-average flag" );
737 maModel.mnType = XML_aboveAverage;
738 maModel.mnStdDev = nOperator; // operator field used for standard deviation
739 maModel.mbAboveAverage = true;
740 maModel.mbEqualAverage = true; // does not exist as real flag...
741 break;
742 case BIFF12_CFRULE_SUB_EQBELOWAVERAGE:
743 OSL_ENSURE( !maModel.mbAboveAverage, "CondFormatRule::importCfRule - wrong above-average flag" );
744 maModel.mnType = XML_aboveAverage;
745 maModel.mnStdDev = nOperator; // operator field used for standard deviation
746 maModel.mbAboveAverage = false;
747 maModel.mbEqualAverage = true; // does not exist as real flag...
748 break;
749 }
750 break;
751 case BIFF12_CFRULE_TYPE_COLORSCALE:
753 nSubType != BIFF12_CFRULE_SUB_COLORSCALE, "sc.filter",
754 "CondFormatRule::importCfRule - rule type/subtype mismatch");
755 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
756 maModel.mnType = XML_colorScale;
757 break;
758 case BIFF12_CFRULE_TYPE_DATABAR:
760 nSubType != BIFF12_CFRULE_SUB_DATABAR, "sc.filter",
761 "CondFormatRule::importCfRule - rule type/subtype mismatch");
762 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
763 maModel.mnType = XML_dataBar;
764 break;
765 case BIFF12_CFRULE_TYPE_TOPTEN:
767 nSubType != BIFF12_CFRULE_SUB_TOPTEN, "sc.filter",
768 "CondFormatRule::importCfRule - rule type/subtype mismatch");
769 maModel.mnType = XML_top10;
770 maModel.mnRank = nOperator; // operator field used for rank value
771 break;
772 case BIFF12_CFRULE_TYPE_ICONSET:
774 nSubType != BIFF12_CFRULE_SUB_ICONSET, "sc.filter",
775 "CondFormatRule::importCfRule - rule type/subtype mismatch");
776 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
777 maModel.mnType = XML_iconSet;
778 break;
779 default:
780 OSL_FAIL( "CondFormatRule::importCfRule - unknown rule type" );
781 }
782}
783
784void CondFormatRule::setFormatEntry(sal_Int32 nPriority, ScFormatEntry* pEntry)
785{
786 maModel.mnPriority = nPriority;
787 mpFormatEntry = pEntry;
788}
789
791{
792 if (mpFormatEntry)
793 {
795 return;
796 }
797
799
800 /* Replacement formula for unsupported rule types (text comparison rules,
801 time period rules, cell type rules). The replacement formulas below may
802 contain several placeholders:
803 - '#B' will be replaced by the current relative base address (may occur
804 several times).
805 - '#R' will be replaced by the entire range list of the conditional
806 formatting (absolute addresses).
807 - '#T' will be replaced by the quoted comparison text.
808 - '#L' will be replaced by the length of the comparison text (from
809 the 'text' attribute) used in text comparison rules.
810 - '#K' will be replaced by the rank (from the 'rank' attribute) used in
811 top-10 rules.
812 - '#M' will be replaced by the top/bottom flag (from the 'bottom'
813 attribute) used in the RANK function in top-10 rules.
814 - '#C' will be replaced by one of the comparison operators <, >, <=, or
815 >=, according to the 'aboveAverage' and 'equalAverage' flags.
816 */
817 OUString aReplaceFormula;
818
819 switch( maModel.mnType )
820 {
821 case XML_cellIs:
823 break;
824 case XML_duplicateValues:
825 eOperator = ScConditionMode::Duplicate;
826 break;
827 case XML_uniqueValues:
829 break;
830 case XML_expression:
831 eOperator = ScConditionMode::Direct;
832 break;
833 case XML_containsText:
834 OSL_ENSURE( maModel.mnOperator == XML_containsText, "CondFormatRule::finalizeImport - unexpected operator" );
836 break;
837 case XML_notContainsText:
838 // note: type XML_notContainsText vs. operator XML_notContains
839 OSL_ENSURE( maModel.mnOperator == XML_notContains, "CondFormatRule::finalizeImport - unexpected operator" );
841 break;
842 case XML_beginsWith:
843 OSL_ENSURE( maModel.mnOperator == XML_beginsWith, "CondFormatRule::finalizeImport - unexpected operator" );
844 eOperator = ScConditionMode::BeginsWith;
845 break;
846 case XML_endsWith:
847 OSL_ENSURE( maModel.mnOperator == XML_endsWith, "CondFormatRule::finalizeImport - unexpected operator" );
848 eOperator = ScConditionMode::EndsWith;
849 break;
850 case XML_timePeriod:
851 break;
852 case XML_containsBlanks:
853 aReplaceFormula = "LEN(TRIM(#B))=0";
854 break;
855 case XML_notContainsBlanks:
856 aReplaceFormula = "LEN(TRIM(#B))>0";
857 break;
858 case XML_containsErrors:
859 eOperator = ScConditionMode::Error;
860 break;
861 case XML_notContainsErrors:
862 eOperator = ScConditionMode::NoError;
863 break;
864 case XML_top10:
866 {
867 if(maModel.mbBottom)
869 else
870 eOperator = ScConditionMode::TopPercent;
871 }
872 else
873 {
874 if(maModel.mbBottom)
875 eOperator = ScConditionMode::Bottom10;
876 else
877 eOperator = ScConditionMode::Top10;
878 }
879 break;
880 case XML_aboveAverage:
882 {
885 else
887 }
888 else
889 {
892 else
894 }
895 break;
896 case XML_colorScale:
897 break;
898 }
899
900 if( !aReplaceFormula.isEmpty() )
901 {
902 OUString aAddress;
903 sal_Int32 nStrPos = aReplaceFormula.getLength();
904 while( (nStrPos = aReplaceFormula.lastIndexOf( '#', nStrPos )) >= 0 )
905 {
906 switch( aReplaceFormula[ nStrPos + 1 ] )
907 {
908 case 'B': // current base address
909 if( aAddress.isEmpty() )
911 aReplaceFormula = aReplaceFormula.replaceAt( nStrPos, 2, aAddress );
912 break;
913 default:
914 OSL_FAIL( "CondFormatRule::finalizeImport - unknown placeholder" );
915 }
916 }
917
918 // set the replacement formula
919 maModel.maFormulas.clear();
920 appendFormula( aReplaceFormula );
921 eOperator = ScConditionMode::Direct;
922 }
923
925
926 if( eOperator == ScConditionMode::Error || eOperator == ScConditionMode::NoError )
927 {
928 ScDocument& rDoc = getScDocument();
929 OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
930 ScCondFormatEntry* pNewEntry = new ScCondFormatEntry( eOperator, nullptr, nullptr, rDoc, aPos, aStyleName );
931 mpFormat->AddEntry(pNewEntry);
932 }
933 else if( eOperator == ScConditionMode::BeginsWith || eOperator == ScConditionMode::EndsWith ||
935 {
936 ScDocument& rDoc = getScDocument();
937 ScTokenArray aTokenArray(rDoc);
939 aTokenArray.AddString(rSPool.intern(maModel.maText));
940 OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
941 ScCondFormatEntry* pNewEntry = new ScCondFormatEntry( eOperator, &aTokenArray, nullptr, rDoc, aPos, aStyleName );
942 mpFormat->AddEntry(pNewEntry);
943 }
944 else if( (eOperator != ScConditionMode::NONE) && !maModel.maFormulas.empty() )
945 {
946 ScDocument& rDoc = getScDocument();
947 std::unique_ptr<ScTokenArray> pTokenArray2;
948 if( maModel.maFormulas.size() >= 2)
949 {
950 pTokenArray2.reset(new ScTokenArray(rDoc));
952 rDoc.CheckLinkFormulaNeedingCheck(*pTokenArray2);
953 }
954
955 ScTokenArray aTokenArray(rDoc);
956 OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
958 rDoc.CheckLinkFormulaNeedingCheck( aTokenArray);
959 ScCondFormatEntry* pNewEntry = new ScCondFormatEntry(eOperator,
960 &aTokenArray, pTokenArray2.get(), rDoc, aPos, aStyleName);
961 mpFormat->AddEntry(pNewEntry);
962 }
963 else if ( eOperator == ScConditionMode::Top10 || eOperator == ScConditionMode::Bottom10 ||
965 {
966 ScDocument& rDoc = getScDocument();
967 ScTokenArray aTokenArray(rDoc);
968 aTokenArray.AddDouble( maModel.mnRank );
969 OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
970 ScCondFormatEntry* pNewEntry = new ScCondFormatEntry( eOperator, &aTokenArray, nullptr, rDoc, aPos, aStyleName );
971 mpFormat->AddEntry(pNewEntry);
972 }
973 else if( eOperator == ScConditionMode::AboveAverage || eOperator == ScConditionMode::BelowAverage ||
975 {
976 ScDocument& rDoc = getScDocument();
977 // actually that is still unsupported
978 ScTokenArray aTokenArrayDev(rDoc);
979 aTokenArrayDev.AddDouble( maModel.mnStdDev );
980 OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
981 ScCondFormatEntry* pNewEntry = new ScCondFormatEntry( eOperator, &aTokenArrayDev, nullptr, rDoc, aPos, aStyleName );
982 mpFormat->AddEntry(pNewEntry);
983 }
984 else if( eOperator == ScConditionMode::Duplicate || eOperator == ScConditionMode::NotDuplicate )
985 {
986 ScDocument& rDoc = getScDocument();
987 OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
988 ScCondFormatEntry* pNewEntry = new ScCondFormatEntry( eOperator, nullptr, nullptr, rDoc, aPos, aStyleName );
989 mpFormat->AddEntry(pNewEntry);
990 }
991 else if( maModel.mnType == XML_timePeriod )
992 {
994 switch( maModel.mnTimePeriod )
995 {
996 case XML_yesterday:
997 eDateType = condformat::YESTERDAY;
998 break;
999 case XML_today:
1000 eDateType = condformat::TODAY;
1001 break;
1002 case XML_tomorrow:
1003 eDateType = condformat::TOMORROW;
1004 break;
1005 case XML_last7Days:
1006 eDateType = condformat::LAST7DAYS;
1007 break;
1008 case XML_lastWeek:
1009 eDateType = condformat::LASTWEEK;
1010 break;
1011 case XML_thisWeek:
1012 eDateType = condformat::THISWEEK;
1013 break;
1014 case XML_nextWeek:
1015 eDateType = condformat::NEXTWEEK;
1016 break;
1017 case XML_lastMonth:
1018 eDateType = condformat::LASTMONTH;
1019 break;
1020 case XML_thisMonth:
1021 eDateType = condformat::THISMONTH;
1022 break;
1023 case XML_nextMonth:
1024 eDateType = condformat::NEXTMONTH;
1025 break;
1026 default:
1027 SAL_WARN("sc.filter", "CondFormatRule::finalizeImport - unknown time period type" );
1028 }
1029
1030 ScDocument& rDoc = getScDocument();
1031 ScCondDateFormatEntry* pFormatEntry = new ScCondDateFormatEntry(&rDoc);
1032 pFormatEntry->SetDateType(eDateType);
1033 OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
1034 pFormatEntry->SetStyleName( aStyleName );
1035
1036 mpFormat->AddEntry(pFormatEntry);
1037 }
1038 else if( mpColor )
1039 {
1040 ScDocument& rDoc = getScDocument();
1041 ScColorScaleFormat* pFormatEntry = new ScColorScaleFormat(&rDoc);
1042
1043 mpFormat->AddEntry(pFormatEntry);
1044
1045 mpColor->AddEntries( pFormatEntry, &rDoc, aPos );
1046 }
1047 else if (mpDataBar)
1048 {
1049 ScDocument& rDoc = getScDocument();
1050 ScDataBarFormat* pFormatEntry = new ScDataBarFormat(&rDoc);
1051
1052 mpFormat->AddEntry(pFormatEntry);
1053 mpDataBar->SetData( pFormatEntry, &rDoc, aPos );
1054
1055 }
1056 else if(mpIconSet)
1057 {
1058 ScDocument& rDoc = getScDocument();
1059 ScIconSetFormat* pFormatEntry = new ScIconSetFormat(&rDoc);
1060
1061 mpFormat->AddEntry(pFormatEntry);
1062 mpIconSet->SetData( pFormatEntry, &rDoc, aPos );
1063 }
1064}
1065
1067{
1068 if(!mpColor)
1069 mpColor.reset( new ColorScaleRule(mrCondFormat) );
1070
1071 return mpColor.get();
1072}
1073
1075{
1076 if(!mpDataBar)
1077 mpDataBar.reset( new DataBarRule(mrCondFormat) );
1078
1079 return mpDataBar.get();
1080}
1081
1083{
1084 if(!mpIconSet)
1085 mpIconSet.reset( new IconSetRule(mrCondFormat) );
1086
1087 return mpIconSet.get();
1088}
1089
1091 mbPivot( false )
1092{
1093}
1094
1096 WorksheetHelper( rHelper ),
1097 mpFormat(nullptr),
1098 mbReadyForFinalize(false)
1099{
1100}
1101
1103{
1105 delete mpFormat;
1106}
1107
1109{
1110 getAddressConverter().convertToCellRangeList( maModel.maRanges, rAttribs.getString( XML_sqref, OUString() ), getSheetIndex(), true );
1111 maModel.mbPivot = rAttribs.getBool( XML_pivot, false );
1113}
1114
1116{
1117 CondFormatRuleRef xRule = createRule();
1118 xRule->importCfRule( rAttribs );
1119 return xRule;
1120}
1121
1123{
1124 BinRangeList aRanges;
1125 rStrm.skip( 8 );
1126 rStrm >> aRanges;
1129}
1130
1132{
1133 CondFormatRuleRef xRule = createRule();
1134 xRule->importCfRule( rStrm );
1135 insertRule( xRule );
1136}
1137
1139{
1140 // probably some error in the xml if we are not ready
1141 if ( !mbReadyForFinalize )
1142 return;
1143 ScDocument& rDoc = getScDocument();
1146
1147 if (mpFormat->size() > 0)
1148 {
1150 sal_Int32 nIndex = getScDocument().AddCondFormat(std::unique_ptr<ScConditionalFormat>(mpFormat), nTab);
1151
1153 }
1154 else
1155 mbReadyForFinalize = false;
1156}
1157
1159{
1160 return std::make_shared<CondFormatRule>( *this, mpFormat );
1161}
1162
1164{
1165 if( xRule && (xRule->getPriority() > 0) )
1166 {
1167 OSL_ENSURE( maRules.find( xRule->getPriority() ) == maRules.end(), "CondFormat::insertRule - multiple rules with equal priority" );
1168 maRules[ xRule->getPriority() ] = xRule;
1169 }
1170}
1171
1173 WorksheetHelper( rHelper )
1174{
1175}
1176
1178{
1179 CondFormatRef xCondFmt = createCondFormat();
1180 xCondFmt->importConditionalFormatting( rAttribs );
1181 return xCondFmt;
1182}
1183
1184namespace {
1185
1186ScConditionalFormat* findFormatByRange(const ScRangeList& rRange, const ScDocument* pDoc, SCTAB nTab)
1187{
1188 ScConditionalFormatList* pList = pDoc->GetCondFormList(nTab);
1189 for (auto const& it : *pList)
1190 {
1191 if (it->GetRange() == rRange)
1192 {
1193 return it.get();
1194 }
1195 }
1196
1197 return nullptr;
1198}
1199
1200class ScRangeListHasher
1201{
1202public:
1203 size_t operator() (ScRangeList const& rRanges) const
1204 {
1205 size_t nHash = 0;
1206 for (size_t nIdx = 0; nIdx < rRanges.size(); ++nIdx)
1207 nHash += rRanges[nIdx].hashArea();
1208 return nHash;
1209 }
1210};
1211
1212}
1213
1215{
1216 for ( const auto& rRule : maCfRules )
1217 {
1218 if ( rRule && rRule->GetDataBarData() == pTarget )
1219 rRule->finalizeImport();
1220 }
1221}
1222
1224{
1225 CondFormatRef xFoundFmt;
1226 ScRangeList aRanges = xCondFmt->getRanges();
1227
1228 for (auto& rCondFmt : maCondFormats)
1229 {
1230 if (xCondFmt == rCondFmt)
1231 continue;
1232
1233 if (aRanges == rCondFmt->getRanges())
1234 {
1235 xFoundFmt = rCondFmt;
1236 break;
1237 }
1238 }
1239
1240 if (xFoundFmt)
1241 {
1242 xRule->mpFormat = xFoundFmt->mpFormat;
1243 xFoundFmt->insertRule(xRule);
1244 }
1245
1246 return static_cast<bool>(xFoundFmt);
1247}
1248
1250{
1251 std::unordered_set<size_t> aDoneExtCFs;
1252 typedef std::unordered_map<ScRangeList, CondFormat*, ScRangeListHasher> RangeMap;
1253 RangeMap aRangeMap;
1254 for (auto& rxCondFormat : maCondFormats)
1255 {
1256 if (aRangeMap.find(rxCondFormat->getRanges()) != aRangeMap.end())
1257 continue;
1258 aRangeMap[rxCondFormat->getRanges()] = rxCondFormat.get();
1259 }
1260
1261 size_t nExtCFIndex = 0;
1262 for (const auto& rxExtCondFormat : maExtCondFormats)
1263 {
1264 ScDocument* pDoc = &getScDocument();
1265 const ScRangeList& rRange = rxExtCondFormat->getRange();
1266 RangeMap::iterator it = aRangeMap.find(rRange);
1267 if (it != aRangeMap.end())
1268 {
1269 CondFormat& rCondFormat = *it->second;
1270 const std::vector<std::unique_ptr<ScFormatEntry>>& rEntries = rxExtCondFormat->getEntries();
1271 const std::vector<sal_Int32>& rPriorities = rxExtCondFormat->getPriorities();
1272 size_t nEntryIdx = 0;
1273 for (const auto& rxEntry : rEntries)
1274 {
1275 CondFormatRuleRef xRule = rCondFormat.createRule();
1276 if (ScDataBarFormat *pData = dynamic_cast<ScDataBarFormat*>(rxEntry.get()))
1277 updateImport(pData->GetDataBarData());
1278 ScFormatEntry* pNewEntry = rxEntry->Clone(pDoc);
1279 sal_Int32 nPriority = rPriorities[nEntryIdx];
1280 if (nPriority == -1)
1282 xRule->setFormatEntry(nPriority, pNewEntry);
1283 rCondFormat.insertRule(xRule);
1284 ++nEntryIdx;
1285 }
1286
1287 aDoneExtCFs.insert(nExtCFIndex);
1288 }
1289
1290 ++nExtCFIndex;
1291 }
1292
1293 // tdf#138601 sort conditional formatting rules by their priority
1294 if (maCondFormats.size() > 1)
1295 {
1296 size_t minIndex;
1297 for (size_t i = 0; i < maCondFormats.size() - 1; ++i)
1298 {
1299 minIndex = i;
1300 for (size_t j = i + 1; j < maCondFormats.size(); ++j)
1301 {
1302 const CondFormat::CondFormatRuleMap& rNextRules = maCondFormats[j]->maRules;
1303 const CondFormat::CondFormatRuleMap& rMinRules = maCondFormats[minIndex]->maRules;
1304 if (rNextRules.empty() || rMinRules.empty())
1305 continue;
1306 if (rNextRules.begin()->first < rMinRules.begin()->first)
1307 minIndex = j;
1308 }
1309 if (i != minIndex)
1310 std::swap(maCondFormats[i], maCondFormats[minIndex]);
1311 }
1312 }
1313
1314 for( const auto& rxCondFormat : maCondFormats )
1315 {
1316 if ( rxCondFormat)
1317 rxCondFormat->finalizeImport();
1318 }
1319 for ( const auto& rxCfRule : maCfRules )
1320 {
1321 if ( rxCfRule )
1322 rxCfRule->finalizeImport();
1323 }
1324
1325 nExtCFIndex = 0;
1326 for (const auto& rxExtCondFormat : maExtCondFormats)
1327 {
1328 if (aDoneExtCFs.count(nExtCFIndex))
1329 {
1330 ++nExtCFIndex;
1331 continue;
1332 }
1333
1334 ScDocument* pDoc = &getScDocument();
1335 const ScRangeList& rRange = rxExtCondFormat->getRange();
1336 SCTAB nTab = rRange.front().aStart.Tab();
1337 ScConditionalFormat* pFormat = findFormatByRange(rRange, pDoc, nTab);
1338 if (!pFormat)
1339 {
1340 // create new conditional format and insert it
1341 auto pNewFormat = std::make_unique<ScConditionalFormat>(0, pDoc);
1342 pFormat = pNewFormat.get();
1343 pNewFormat->SetRange(rRange);
1344 sal_uLong nKey = pDoc->AddCondFormat(std::move(pNewFormat), nTab);
1345 pDoc->AddCondFormatData(rRange, nTab, nKey);
1346 }
1347
1348 const std::vector< std::unique_ptr<ScFormatEntry> >& rEntries = rxExtCondFormat->getEntries();
1349 for (const auto& rxEntry : rEntries)
1350 {
1351 pFormat->AddEntry(rxEntry->Clone(pDoc));
1352 }
1353
1354 ++nExtCFIndex;
1355 }
1356
1357 rStyleIdx = 0; // Resets <extlst> <cfRule> style index.
1358}
1359
1361{
1362 CondFormatRef xCondFmt = createCondFormat();
1363 xCondFmt->importCondFormatting( rStrm );
1364 return xCondFmt;
1365}
1366
1368{
1369 ExtCfDataBarRuleRef extRule = std::make_shared<ExtCfDataBarRule>( pTarget, *this );
1370 maCfRules.push_back( extRule );
1371 return extRule;
1372}
1373
1374std::vector< std::unique_ptr<ExtCfCondFormat> >& CondFormatBuffer::importExtCondFormat()
1375{
1376 return maExtCondFormats;
1377}
1378
1379std::vector<std::unique_ptr<ScFormatEntry> >& CondFormatBuffer::importExtFormatEntries()
1380{
1381 return maExtFormatEntries;
1382}
1383
1385{
1386 switch( nToken )
1387 {
1388 case XML_between: return ConditionOperator2::BETWEEN;
1389 case XML_equal: return ConditionOperator2::EQUAL;
1390 case XML_greaterThan: return ConditionOperator2::GREATER;
1391 case XML_greaterThanOrEqual: return ConditionOperator2::GREATER_EQUAL;
1392 case XML_lessThan: return ConditionOperator2::LESS;
1393 case XML_lessThanOrEqual: return ConditionOperator2::LESS_EQUAL;
1394 case XML_notBetween: return ConditionOperator2::NOT_BETWEEN;
1395 case XML_notEqual: return ConditionOperator2::NOT_EQUAL;
1396 case XML_duplicateValues: return ConditionOperator2::DUPLICATE;
1397 }
1399}
1400
1402{
1403 switch( nToken )
1404 {
1405 case XML_between: return ScConditionMode::Between;
1406 case XML_equal: return ScConditionMode::Equal;
1407 case XML_greaterThan: return ScConditionMode::Greater;
1408 case XML_greaterThanOrEqual: return ScConditionMode::EqGreater;
1409 case XML_lessThan: return ScConditionMode::Less;
1410 case XML_lessThanOrEqual: return ScConditionMode::EqLess;
1411 case XML_notBetween: return ScConditionMode::NotBetween;
1412 case XML_notEqual: return ScConditionMode::NotEqual;
1413 case XML_duplicateValues: return ScConditionMode::Duplicate;
1414 case XML_uniqueValues: return ScConditionMode::NotDuplicate;
1415 }
1416 return ScConditionMode::NONE;
1417}
1418
1419// private --------------------------------------------------------------------
1420
1422{
1423 CondFormatRef xCondFmt = std::make_shared<CondFormat>( *this );
1424 maCondFormats.push_back( xCondFmt );
1425 return xCondFmt;
1426}
1427
1429 WorksheetHelper(rParent),
1430 mnRuleType( ExtCfDataBarRule::UNKNOWN ),
1431 mpTarget(pTarget)
1432{
1433}
1434
1436{
1437 switch ( mnRuleType )
1438 {
1439 case DATABAR:
1440 {
1441 ScDataBarFormatData* pDataBar = mpTarget;
1442 if( maModel.maAxisPosition == "none" )
1443 pDataBar->meAxisPosition = databar::NONE;
1444 else if( maModel.maAxisPosition == "middle" )
1445 pDataBar->meAxisPosition = databar::MIDDLE;
1446 else
1448 pDataBar->mbGradient = maModel.mbGradient;
1449 break;
1450 }
1451 case AXISCOLOR:
1452 {
1453 ScDataBarFormatData* pDataBar = mpTarget;
1454 pDataBar->maAxisColor = maModel.mnAxisColor;
1455 break;
1456 }
1457 case POSITIVEFILLCOLOR:
1458 {
1459 ScDataBarFormatData* pDataBar = mpTarget;
1461 break;
1462 }
1463 case NEGATIVEFILLCOLOR:
1464 {
1465 ScDataBarFormatData* pDataBar = mpTarget;
1467 pDataBar->mbNeg = true;
1468 break;
1469 }
1470 case CFVO:
1471 {
1472 ScDataBarFormatData* pDataBar = mpTarget;
1473 ScColorScaleEntry* pEntry = nullptr;
1474 if(maModel.mbIsLower)
1475 pEntry = pDataBar->mpLowerLimit.get();
1476 else
1477 pEntry = pDataBar->mpUpperLimit.get();
1478
1479 if(maModel.maColorScaleType == "min")
1480 pEntry->SetType(COLORSCALE_MIN);
1481 else if (maModel.maColorScaleType == "max")
1482 pEntry->SetType(COLORSCALE_MAX);
1483 else if (maModel.maColorScaleType == "autoMin")
1484 pEntry->SetType(COLORSCALE_AUTO);
1485 else if (maModel.maColorScaleType == "autoMax")
1486 pEntry->SetType(COLORSCALE_AUTO);
1487 else if (maModel.maColorScaleType == "percentile")
1489 else if (maModel.maColorScaleType == "percent")
1490 pEntry->SetType(COLORSCALE_PERCENT);
1491 else if (maModel.maColorScaleType == "formula")
1492 pEntry->SetType(COLORSCALE_FORMULA);
1493 else if (maModel.maColorScaleType == "num")
1494 {
1495 pEntry->SetType(COLORSCALE_VALUE);
1496 if (!maModel.msScaleTypeValue.isEmpty())
1497 {
1498 sal_Int32 nSize = 0;
1499 rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
1500 double fValue = rtl::math::stringToDouble(maModel.msScaleTypeValue, '.', '\0', &eStatus, &nSize);
1501 if (eStatus == rtl_math_ConversionStatus_Ok && nSize == maModel.msScaleTypeValue.getLength())
1502 {
1503 pEntry->SetValue(fValue);
1504 }
1505 }
1506 }
1507 break;
1508 }
1509 case UNKNOWN: // nothing to do
1510 default:
1511 break;
1512 }
1513}
1514
1516{
1518 maModel.mbGradient = rAttribs.getBool( XML_gradient, true );
1519 maModel.maAxisPosition = rAttribs.getString( XML_axisPosition, "automatic" );
1520}
1521
1523{
1525 ThemeBuffer& rThemeBuffer = getTheme();
1526 GraphicHelper& rGraphicHelper = getBaseFilter().getGraphicHelper();
1527 ::Color aColor = importOOXColor(rAttribs, rThemeBuffer, rGraphicHelper);
1528 maModel.mnPositiveColor = aColor;
1529}
1530
1532{
1534 ThemeBuffer& rThemeBuffer = getTheme();
1535 GraphicHelper& rGraphicHelper = getBaseFilter().getGraphicHelper();
1536 ::Color aColor = importOOXColor(rAttribs, rThemeBuffer, rGraphicHelper);
1537 maModel.mnNegativeColor = aColor;
1538}
1539
1541{
1543 ThemeBuffer& rThemeBuffer = getTheme();
1544 GraphicHelper& rGraphicHelper = getBaseFilter().getGraphicHelper();
1545 ::Color aColor = importOOXColor(rAttribs, rThemeBuffer, rGraphicHelper);
1546 maModel.mnAxisColor = aColor;
1547}
1548
1550{
1551 mnRuleType = CFVO;
1552 maModel.maColorScaleType = rAttribs.getString( XML_type, OUString() );
1553}
1554
1555ExtCfCondFormat::ExtCfCondFormat(ScRangeList aRange, std::vector< std::unique_ptr<ScFormatEntry> >& rEntries,
1556 const std::vector<sal_Int32>* pPriorities):
1557 maRange(std::move(aRange))
1558{
1559 maEntries.swap(rEntries);
1560 if (pPriorities)
1561 maPriorities = *pPriorities;
1562 else
1563 maPriorities.resize(maEntries.size(), -1);
1564}
1565
1567{
1568}
1569
1571{
1572 return maRange;
1573}
1574
1575const std::vector< std::unique_ptr<ScFormatEntry> >& ExtCfCondFormat::getEntries() const
1576{
1577 return maEntries;
1578}
1579
1580} // namespace oox
1581
1582/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
B2DRange maRange
Color GetRGBColor() const
SCTAB Tab() const
Definition: address.hxx:283
void SetType(ScColorScaleEntryType eType)
Definition: colorscale.cxx:323
void SetFormula(const OUString &rFormula, ScDocument &rDoc, const ScAddress &rAddr, formula::FormulaGrammar::Grammar eGrammar=formula::FormulaGrammar::GRAM_DEFAULT)
Definition: colorscale.cxx:207
void SetValue(double nValue)
Definition: colorscale.cxx:250
void AddEntry(ScColorScaleEntry *pEntry)
Definition: colorscale.cxx:404
void SetDateType(condformat::ScCondFormatDateType eType)
Definition: conditio.cxx:1693
void SetStyleName(const OUString &rStyleName)
Definition: conditio.cxx:1698
void SetRange(const ScRangeList &rRanges)
Definition: conditio.cxx:1762
void AddEntry(ScFormatEntry *pNew)
Definition: conditio.cxx:1768
size_t size() const
Definition: conditio.cxx:1788
void SetDataBarData(ScDataBarFormatData *pData)
Definition: colorscale.cxx:769
SC_DLLPUBLIC void CheckLinkFormulaNeedingCheck(const ScTokenArray &rCode)
Check token array and set link check if ocDde/ocWebservice is contained.
Definition: documen8.cxx:1149
SC_DLLPUBLIC svl::SharedStringPool & GetSharedStringPool()
Definition: documen2.cxx:601
SC_DLLPUBLIC void AddCondFormatData(const ScRangeList &rRange, SCTAB nTab, sal_uInt32 nIndex)
Definition: document.cxx:4790
SC_DLLPUBLIC ScConditionalFormatList * GetCondFormList(SCTAB nTab) const
Definition: documen4.cxx:860
SC_DLLPUBLIC sal_uLong AddCondFormat(std::unique_ptr< ScConditionalFormat > pNew, SCTAB nTab)
Definition: documen4.cxx:708
virtual ScFormatEntry * Clone(ScDocument *pDoc) const =0
static const ScIconSetMap g_IconSetMap[]
Definition: colorscale.hxx:387
void SetIconSetData(ScIconSetFormatData *pData)
ScRange & front()
Definition: rangelst.hxx:92
ScAddress GetTopLeftCorner() const
Definition: rangelst.cxx:1150
size_t size() const
Definition: rangelst.hxx:89
ScAddress aStart
Definition: address.hxx:497
static SC_DLLPUBLIC bool ConvertToTokenArray(ScDocument &rDoc, ScTokenArray &rTokenArray, const css::uno::Sequence< css::sheet::FormulaToken > &rSequence)
Definition: tokenuno.cxx:374
FormulaToken * AddDouble(double fVal)
FormulaToken * AddString(const svl::SharedString &rStr)
sal_uInt32 getUnsignedHex(sal_Int32 nAttrToken, sal_uInt32 nDefault) const
bool hasAttribute(sal_Int32 nAttrToken) const
std::optional< sal_uInt32 > getUnsigned(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
void forEachMem(FuncType pFunc) const
GraphicHelper & getGraphicHelper() const
void addExcelTintTransformation(double fTint)
::Color getColor(const GraphicHelper &rGraphicHelper, ::Color nPhClr=API_RGB_TRANSPARENT) const
void setSrgbClr(sal_Int32 nRgb)
void convertToCellRangeList(ScRangeList &orRanges, std::u16string_view aString, sal_Int16 nSheet, bool bTrackOverflow)
Tries to convert the passed string to a cell range list.
A 2D cell range address list for binary filters.
std::vector< ColorScaleRuleModelEntry > maColorScaleRuleEntries
void importColor(const AttributeList &rAttribs)
ColorScaleRule(const CondFormat &rFormat)
void importCfvo(const AttributeList &rAttribs)
void AddEntries(ScColorScaleFormat *pFormat, ScDocument *pDoc, const ScAddress &rAddr)
std::vector< std::unique_ptr< ExtCfCondFormat > > & importExtCondFormat()
ExtCfDataBarRuleVec maCfRules
All conditional formatting in a sheet.
ExtCfDataBarRuleRef createExtCfDataBarRule(ScDataBarFormatData *pTarget)
CondFormatRef importConditionalFormatting(const AttributeList &rAttribs)
Imports settings from the conditionalFormatting element.
std::vector< std::unique_ptr< ScFormatEntry > > & importExtFormatEntries()
static ScConditionMode convertToInternalOperator(sal_Int32 nToken)
std::vector< std::unique_ptr< ExtCfCondFormat > > maExtCondFormats
All external conditional formatting rules in a sheet.
CondFormatBuffer(const WorksheetHelper &rHelper)
bool insertRule(CondFormatRef const &xCondFmt, CondFormatRuleRef const &xRule)
void updateImport(const ScDataBarFormatData *pTarget)
static sal_Int32 convertToApiOperator(sal_Int32 nToken)
Converts an OOXML condition operator token to the API constant.
CondFormatRef importCondFormatting(SequenceInputStream &rStrm)
Imports settings from the CONDFORMATTING record.
std::vector< std::unique_ptr< ScFormatEntry > > maExtFormatEntries
void importCfRule(const AttributeList &rAttribs)
Imports rule settings from the cfRule element.
CondFormatRuleModel maModel
void appendFormula(const OUString &rFormula)
Appends a new condition formula string.
std::unique_ptr< ColorScaleRule > mpColor
ScConditionalFormat * mpFormat
void finalizeImport()
Creates a conditional formatting rule in the Calc document.
const CondFormat & mrCondFormat
void setFormatEntry(sal_Int32 nPriority, ScFormatEntry *pEntry)
Directly set a ScFormatEntry with a priority ready for finalizeImport().
ColorScaleRule * getColorScale()
std::unique_ptr< IconSetRule > mpIconSet
CondFormatRule(const CondFormat &rCondFormat, ScConditionalFormat *pFormat)
std::unique_ptr< DataBarRule > mpDataBar
Represents a conditional formatting object with a list of affected cell ranges.
CondFormat(const WorksheetHelper &rHelper)
void insertRule(CondFormatRuleRef const &xRule)
const ScRangeList & getRanges() const
Returns the cell ranges this conditional formatting belongs to.
ScConditionalFormat * mpFormat
Maps formatting rules by priority.
void importConditionalFormatting(const AttributeList &rAttribs)
Imports settings from the conditionalFormatting element.
CondFormatRuleMap maRules
Model of this conditional formatting.
CondFormatRuleRef createRule()
void importCondFormatting(SequenceInputStream &rStrm)
Imports settings from the CONDFORMATTING record.
CondFormatRuleRef importCfRule(const AttributeList &rAttribs)
Imports a conditional formatting rule from the cfRule element.
void finalizeImport()
Creates the conditional formatting in the Calc document.
std::unique_ptr< ColorScaleRuleModelEntry > mpLowerLimit
void importCfvo(const AttributeList &rAttribs)
DataBarRule(const CondFormat &rFormat)
std::unique_ptr< ScDataBarFormatData > mxFormat
std::unique_ptr< ColorScaleRuleModelEntry > mpUpperLimit
void importColor(const AttributeList &rAttribs)
void SetData(ScDataBarFormat *pFormat, ScDocument *pDoc, const ScAddress &rAddr)
void importAttribs(const AttributeList &rAttribs)
const ScRangeList & getRange() const
std::vector< sal_Int32 > maPriorities
std::vector< std::unique_ptr< ScFormatEntry > > maEntries
const std::vector< std::unique_ptr< ScFormatEntry > > & getEntries() const
ExtCfCondFormat(ScRangeList aRange, std::vector< std::unique_ptr< ScFormatEntry > > &rEntries, const std::vector< sal_Int32 > *pPriorities=nullptr)
void importPositiveFillColor(const AttributeList &rAttribs)
ScDataBarFormatData * mpTarget
void importDataBar(const AttributeList &rAttribs)
void importNegativeFillColor(const AttributeList &rAttribs)
void importCfvo(const AttributeList &rAttribs)
ExtCfDataBarRule(ScDataBarFormatData *pTarget, const WorksheetHelper &rParent)
void importAxisColor(const AttributeList &rAttribs)
ApiTokenSequence importFormula(const ScAddress &rBaseAddr, const OUString &rFormulaString) const
Converts an OOXML formula string.
static OUString generateAddress2dString(const ScAddress &rAddress, bool bAbsolute)
Generates a cell address string in A1 notation from the passed cell address.
std::unique_ptr< ScIconSetFormatData > mxFormatData
void importIcon(const AttributeList &rAttribs)
std::vector< ColorScaleRuleModelEntry > maEntries
void SetData(ScIconSetFormat *pFormat, ScDocument *pDoc, const ScAddress &rAddr)
IconSetRule(const WorksheetHelper &rParent)
void importFormula(const OUString &rFormula)
void importAttribs(const AttributeList &rAttribs)
void importCfvo(const AttributeList &rAttribs)
OUString createDxfStyle(sal_Int32 nDxfId) const
Creates the style sheet described by the DXF with the passed identifier.
AddressConverter & getAddressConverter() const
Returns the converter for string to cell address/range conversion.
StylesBuffer & getStyles() const
Returns all cell formatting objects read from the styles substream.
ThemeBuffer & getTheme() const
Returns the office theme object read from the theme substorage.
::oox::core::FilterBase & getBaseFilter() const
Returns the base filter object (base class of all filters).
FormulaParser & getFormulaParser() const
Returns a shared import formula parser (import filter only!).
SCTAB getSheetIndex() const
Returns the index of the current sheet.
SharedString intern(const OUString &rStr)
ScIconSetType
Definition: colorscale.hxx:189
@ IconSet_3TrafficLights1
Definition: colorscale.hxx:193
@ COLORSCALE_MAX
Definition: colorscale.hxx:35
@ COLORSCALE_VALUE
Definition: colorscale.hxx:37
@ COLORSCALE_FORMULA
Definition: colorscale.hxx:39
@ COLORSCALE_PERCENT
Definition: colorscale.hxx:38
@ COLORSCALE_PERCENTILE
Definition: colorscale.hxx:36
@ COLORSCALE_AUTO
Definition: colorscale.hxx:33
@ COLORSCALE_MIN
Definition: colorscale.hxx:34
ScConditionMode
Definition: conditio.hxx:60
sal_Int32 mnCol
sal_Int32 rStyleIdx
UNKNOWN
#define STATIC_ARRAY_SELECT(array, index, def)
sal_Int32 nIndex
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
std::unique_ptr< sal_Int32[]> pData
ScCondFormatDateType
Definition: conditio.hxx:485
int i
void SvStream & rStrm
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
std::shared_ptr< CondFormatRule > CondFormatRuleRef
css::uno::Sequence< ApiToken > ApiTokenSequence
::Color IndexedColors[]
@ CondFormat
Shared formula definition.
std::shared_ptr< CondFormat > CondFormatRef
std::shared_ptr< ExtCfDataBarRule > ExtCfDataBarRuleRef
const sal_uInt32 UNSIGNED_RGB_TRANSPARENT
bool getFlag(Type nBitField, Type nMask)
XML_type
XML_TOKEN_INVALID
bool getType(BSTR name, Type &type)
DefTokenId nToken
Definition: qproform.cxx:397
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:398
sal_Int32 mnType
double mnPriority
sal_uIntPtr sal_uLong
T * mpTarget
Color maAxisColor
Color of the axis if used Default color is black.
Definition: colorscale.hxx:145
std::optional< Color > mxNegativeColor
Specifies the color for negative values.
Definition: colorscale.hxx:140
std::unique_ptr< ScColorScaleEntry, o3tl::default_delete< ScColorScaleEntry > > mpLowerLimit
Definition: colorscale.hxx:185
databar::ScAxisPosition meAxisPosition
Paint negative values into the same direction as positive values If false we will set the mid point a...
Definition: colorscale.hxx:167
Color maPositiveColor
Color for all Positive Values and if mbNeg == false also for negative ones.
Definition: colorscale.hxx:134
bool mbNeg
Use different color for negative values.
Definition: colorscale.hxx:159
bool mbGradient
Paint the bars with gradient.
Definition: colorscale.hxx:152
std::unique_ptr< ScColorScaleEntry, o3tl::default_delete< ScColorScaleEntry > > mpUpperLimit
Definition: colorscale.hxx:184
ScIconSetType eType
Definition: colorscale.hxx:216
const char * pName
Definition: colorscale.hxx:215
bool mbPivot
Cell ranges for this conditional format.
CondFormatModel()
Conditional formatting belongs to pivot table.
bool mbEqualAverage
In average rules: True = above average, false = below.
bool mbAboveAverage
In top-10 rules: True = percent, false = rank.
sal_Int32 mnTimePeriod
In cell-is rules: Comparison operator.
sal_Int32 mnPriority
Text for 'contains' rules.
CondFormatRuleModel()
In average rules: True = include average, false = exclude.
bool mbPercent
In top-10 rules: True = bottom, false = top.
sal_Int32 mnType
Priority of this rule.
bool mbStopIfTrue
Differential formatting identifier.
ApiTokenSequenceVector maFormulas
sal_Int32 mnRank
In time-period rules: Type of time period.
OUString maText
Formulas for rule conditions.
bool mbBottom
True = stop evaluating rules, if this rule is true.
sal_Int32 mnStdDev
In top-10 rules: True = bottom, false = top.
void setBiff12TextType(sal_Int32 nOperator)
Sets the passed BIFF12 text comparison type and operator.
sal_Int32 mnOperator
Type of the rule.
void setBiffOperator(sal_Int32 nOperator)
Sets the passed BIFF operator for condition type cellIs.
sal_Int32 mnDxfId
In average rules: Number of std deviations.
sal_Int16 SCTAB
Definition: types.hxx:22