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
47namespace oox::xls {
48
49using namespace ::com::sun::star::sheet;
50using namespace ::com::sun::star::uno;
51
52namespace {
53
54const sal_Int32 BIFF12_CFRULE_TYPE_CELLIS = 1;
55const sal_Int32 BIFF12_CFRULE_TYPE_EXPRESSION = 2;
56const sal_Int32 BIFF12_CFRULE_TYPE_COLORSCALE = 3;
57const sal_Int32 BIFF12_CFRULE_TYPE_DATABAR = 4;
58const sal_Int32 BIFF12_CFRULE_TYPE_TOPTEN = 5;
59const sal_Int32 BIFF12_CFRULE_TYPE_ICONSET = 6;
60
61const sal_Int32 BIFF12_CFRULE_SUB_CELLIS = 0;
62const sal_Int32 BIFF12_CFRULE_SUB_EXPRESSION = 1;
63const sal_Int32 BIFF12_CFRULE_SUB_COLORSCALE = 2;
64const sal_Int32 BIFF12_CFRULE_SUB_DATABAR = 3;
65const sal_Int32 BIFF12_CFRULE_SUB_ICONSET = 4;
66const sal_Int32 BIFF12_CFRULE_SUB_TOPTEN = 5;
67const sal_Int32 BIFF12_CFRULE_SUB_UNIQUE = 7;
68const sal_Int32 BIFF12_CFRULE_SUB_TEXT = 8;
69const sal_Int32 BIFF12_CFRULE_SUB_BLANK = 9;
70const sal_Int32 BIFF12_CFRULE_SUB_NOTBLANK = 10;
71const sal_Int32 BIFF12_CFRULE_SUB_ERROR = 11;
72const sal_Int32 BIFF12_CFRULE_SUB_NOTERROR = 12;
73const sal_Int32 BIFF12_CFRULE_SUB_TODAY = 15;
74const sal_Int32 BIFF12_CFRULE_SUB_TOMORROW = 16;
75const sal_Int32 BIFF12_CFRULE_SUB_YESTERDAY = 17;
76const sal_Int32 BIFF12_CFRULE_SUB_LAST7DAYS = 18;
77const sal_Int32 BIFF12_CFRULE_SUB_LASTMONTH = 19;
78const sal_Int32 BIFF12_CFRULE_SUB_NEXTMONTH = 20;
79const sal_Int32 BIFF12_CFRULE_SUB_THISWEEK = 21;
80const sal_Int32 BIFF12_CFRULE_SUB_NEXTWEEK = 22;
81const sal_Int32 BIFF12_CFRULE_SUB_LASTWEEK = 23;
82const sal_Int32 BIFF12_CFRULE_SUB_THISMONTH = 24;
83const sal_Int32 BIFF12_CFRULE_SUB_ABOVEAVERAGE = 25;
84const sal_Int32 BIFF12_CFRULE_SUB_BELOWAVERAGE = 26;
85const sal_Int32 BIFF12_CFRULE_SUB_DUPLICATE = 27;
86const sal_Int32 BIFF12_CFRULE_SUB_EQABOVEAVERAGE = 29;
87const sal_Int32 BIFF12_CFRULE_SUB_EQBELOWAVERAGE = 30;
88
89const sal_Int32 BIFF12_CFRULE_TIMEOP_TODAY = 0;
90const sal_Int32 BIFF12_CFRULE_TIMEOP_YESTERDAY = 1;
91const sal_Int32 BIFF12_CFRULE_TIMEOP_LAST7DAYS = 2;
92const sal_Int32 BIFF12_CFRULE_TIMEOP_THISWEEK = 3;
93const sal_Int32 BIFF12_CFRULE_TIMEOP_LASTWEEK = 4;
94const sal_Int32 BIFF12_CFRULE_TIMEOP_LASTMONTH = 5;
95const sal_Int32 BIFF12_CFRULE_TIMEOP_TOMORROW = 6;
96const sal_Int32 BIFF12_CFRULE_TIMEOP_NEXTWEEK = 7;
97const sal_Int32 BIFF12_CFRULE_TIMEOP_NEXTMONTH = 8;
98const sal_Int32 BIFF12_CFRULE_TIMEOP_THISMONTH = 9;
99
100const sal_uInt16 BIFF12_CFRULE_STOPIFTRUE = 0x0002;
101const sal_uInt16 BIFF12_CFRULE_ABOVEAVERAGE = 0x0004;
102const sal_uInt16 BIFF12_CFRULE_BOTTOM = 0x0008;
103const sal_uInt16 BIFF12_CFRULE_PERCENT = 0x0010;
104
105bool isValue(std::u16string_view rStr, double& rVal)
106{
107 sal_Int32 nEnd = -1;
108 rVal = rtl::math::stringToDouble(o3tl::trim(rStr), '.', ',', nullptr, &nEnd);
109
110 return nEnd >= static_cast<sal_Int32>(rStr.size());
111}
112
113void SetCfvoData( ColorScaleRuleModelEntry* pEntry, const AttributeList& rAttribs )
114{
115 OUString aType = rAttribs.getString( XML_type, OUString() );
116 OUString aVal = rAttribs.getString(XML_val, OUString());
117
118 double nVal = 0.0;
119 bool bVal = isValue(aVal, nVal);
120 if( !bVal || aType == "formula" )
121 {
122 pEntry->maFormula = aVal;
123 }
124 else
125 {
126 pEntry->mnVal = nVal;
127 }
128
129 if (aType == "num")
130 {
131 pEntry->mbNum = true;
132 }
133 else if( aType == "min" )
134 {
135 pEntry->mbMin = true;
136 }
137 else if( aType == "max" )
138 {
139 pEntry->mbMax = true;
140 }
141 else if( aType == "percent" )
142 {
143 pEntry->mbPercent = true;
144 }
145 else if( aType == "percentile" )
146 {
147 pEntry->mbPercentile = true;
148 }
149}
150
151}
152
154 WorksheetHelper( rFormat ),
155 mnCfvo(0),
156 mnCol(0)
157{
158}
159
161{
162 if(mnCfvo >= maColorScaleRuleEntries.size())
163 maColorScaleRuleEntries.emplace_back();
164
165 SetCfvoData( &maColorScaleRuleEntries[mnCfvo], rAttribs );
166
167 ++mnCfvo;
168}
169
170namespace {
171
172::Color importOOXColor(const AttributeList& rAttribs, const ThemeBuffer& rThemeBuffer, const GraphicHelper& rGraphicHelper)
173{
174 ::Color nColor;
175 if( rAttribs.hasAttribute( XML_rgb ) )
176 nColor = ::Color(ColorTransparency, rAttribs.getUnsignedHex( XML_rgb, UNSIGNED_RGB_TRANSPARENT ));
177 else if( rAttribs.hasAttribute( XML_theme ) )
178 {
179 sal_uInt32 nThemeIndex = rAttribs.getUnsigned( XML_theme, 0 );
180
181 // Excel has a bug in the mapping of index 0, 1, 2 and 3.
182 if (nThemeIndex == 0)
183 nThemeIndex = 1;
184 else if (nThemeIndex == 1)
185 nThemeIndex = 0;
186 else if (nThemeIndex == 2)
187 nThemeIndex = 3;
188 else if (nThemeIndex == 3)
189 nThemeIndex = 2;
190
191 nColor = rThemeBuffer.getColorByIndex( nThemeIndex );
192 }
193
194 ::Color aColor;
195 double nTint = rAttribs.getDouble(XML_tint, 0.0);
196 if (nTint != 0.0)
197 {
198 oox::drawingml::Color aDMColor;
199 aDMColor.setSrgbClr(nColor);
200 aDMColor.addExcelTintTransformation(nTint);
201 aColor = aDMColor.getColor(rGraphicHelper);
202 }
203 else
204 aColor = nColor.GetRGBColor();
205
206 return aColor;
207}
208
209}
210
212{
213 ThemeBuffer& rThemeBuffer = getTheme();
214 GraphicHelper& rGraphicHelper = getBaseFilter().getGraphicHelper();
215 ::Color aColor = importOOXColor(rAttribs, rThemeBuffer, rGraphicHelper);
216
217 if(mnCol >= maColorScaleRuleEntries.size())
218 maColorScaleRuleEntries.emplace_back();
219
220 maColorScaleRuleEntries[mnCol].maColor = aColor;
221 ++mnCol;
222}
223
224namespace {
225
226ScColorScaleEntry* ConvertToModel( const ColorScaleRuleModelEntry& rEntry, ScDocument* pDoc, const ScAddress& rAddr )
227{
228 ScColorScaleEntry* pEntry = new ScColorScaleEntry(rEntry.mnVal, rEntry.maColor);
229
230 if(rEntry.mbMin)
231 pEntry->SetType(COLORSCALE_MIN);
232 if(rEntry.mbMax)
233 pEntry->SetType(COLORSCALE_MAX);
234 if(rEntry.mbPercent)
236 if(rEntry.mbPercentile)
238 if (rEntry.mbNum)
239 pEntry->SetType(COLORSCALE_VALUE);
240
241 if(!rEntry.maFormula.isEmpty())
242 {
245 }
246
247 return pEntry;
248}
249
250}
251
253{
255 {
256 ScColorScaleEntry* pEntry = ConvertToModel( rEntry, pDoc, rAddr );
257
258 pFormat->AddEntry( pEntry );
259 }
260}
261
263 WorksheetHelper( rFormat ),
264 mxFormat(new ScDataBarFormatData)
265{
266 mxFormat->meAxisPosition = databar::NONE;
267}
268
270{
271 ThemeBuffer& rThemeBuffer = getTheme();
272 GraphicHelper& rGraphicHelper = getBaseFilter().getGraphicHelper();
273 ::Color aColor = importOOXColor(rAttribs, rThemeBuffer, rGraphicHelper);
274
275 mxFormat->maPositiveColor = aColor;
276}
277
279{
281 if(!mpLowerLimit)
282 {
284 pEntry = mpLowerLimit.get();
285 }
286 else
287 {
289 pEntry = mpUpperLimit.get();
290 }
291
292 SetCfvoData( pEntry, rAttribs );
293}
294
296{
297 mxFormat->mbOnlyBar = !rAttribs.getBool( XML_showValue, true );
298 mxFormat->mnMinLength = rAttribs.getUnsigned( XML_minLength, 10);
299 mxFormat->mnMaxLength = rAttribs.getUnsigned( XML_maxLength, 90);
300}
301
302void DataBarRule::SetData( ScDataBarFormat* pFormat, ScDocument* pDoc, const ScAddress& rAddr )
303{
304 ScColorScaleEntry* pUpperEntry = ConvertToModel(*mpUpperLimit, pDoc, rAddr);
305 ScColorScaleEntry* pLowerEntry = ConvertToModel(*mpLowerLimit, pDoc, rAddr);
306
307 mxFormat->mpUpperLimit.reset( pUpperEntry );
308 mxFormat->mpLowerLimit.reset( pLowerEntry );
309 pFormat->SetDataBarData(mxFormat.release());
310}
311
313 WorksheetHelper( rParent ),
314 mxFormatData( new ScIconSetFormatData ),
315 mbCustom(false)
316{
317}
318
320{
321 ColorScaleRuleModelEntry aNewEntry;
322 SetCfvoData(&aNewEntry, rAttribs);
323
324 maEntries.push_back(aNewEntry);
325}
326
328{
329 maIconSetType = rAttribs.getString( XML_iconSet, "3TrafficLights1" );
330 mxFormatData->mbShowValue = rAttribs.getBool( XML_showValue, true );
331 mxFormatData->mbReverse = rAttribs.getBool( XML_reverse, false );
332 mbCustom = rAttribs.getBool(XML_custom, false);
333}
334
335void IconSetRule::importFormula(const OUString& rFormula)
336{
337 ColorScaleRuleModelEntry& rEntry = maEntries.back();
338 double nVal = 0.0;
339 if ((rEntry.mbNum || rEntry.mbPercent || rEntry.mbPercentile) && isValue(rFormula, nVal))
340 {
341 rEntry.mnVal = nVal;
342 }
343 else if (!rFormula.isEmpty())
344 rEntry.maFormula = rFormula;
345}
346
347namespace {
348
349ScIconSetType getType(std::u16string_view rName)
350{
352 const ScIconSetMap* pIconSetMap = ScIconSetFormat::g_IconSetMap;
353 for(size_t i = 0; pIconSetMap[i].pName; ++i)
354 {
355 if(OUString::createFromAscii(pIconSetMap[i].pName) == rName)
356 {
357 eIconSetType = pIconSetMap[i].eType;
358 break;
359 }
360 }
361
362 return eIconSetType;
363}
364
365}
366
368{
369 OUString aIconSet = rAttribs.getString(XML_iconSet, OUString());
370 sal_Int32 nIndex = rAttribs.getInteger(XML_iconId, -1);
371 if (aIconSet == "NoIcons")
372 {
373 nIndex = -1;
374 }
375
376 ScIconSetType eIconSetType = getType(aIconSet);
377 mxFormatData->maCustomVector.emplace_back(eIconSetType, nIndex);
378}
379
380void IconSetRule::SetData( ScIconSetFormat* pFormat, ScDocument* pDoc, const ScAddress& rPos )
381{
382 for(const ColorScaleRuleModelEntry & rEntry : maEntries)
383 {
384 ScColorScaleEntry* pModelEntry = ConvertToModel( rEntry, pDoc, rPos );
385 mxFormatData->m_Entries.emplace_back(pModelEntry);
386 }
387
388 mxFormatData->eIconSetType = getType(maIconSetType);
389 mxFormatData->mbCustom = mbCustom;
390 pFormat->SetIconSetData(mxFormatData.release());
391}
392
394 mnPriority( -1 ),
396 mnOperator( XML_TOKEN_INVALID ),
397 mnTimePeriod( XML_TOKEN_INVALID ),
398 mnRank( 0 ),
399 mnStdDev( 0 ),
400 mnDxfId( -1 ),
401 mbStopIfTrue( false ),
402 mbBottom( false ),
403 mbPercent( false ),
404 mbAboveAverage( true ),
405 mbEqualAverage( false )
406{
407}
408
409void CondFormatRuleModel::setBiffOperator( sal_Int32 nOperator )
410{
411 static const sal_Int32 spnOperators[] = {
412 XML_TOKEN_INVALID, XML_between, XML_notBetween, XML_equal, XML_notEqual,
413 XML_greaterThan, XML_lessThan, XML_greaterThanOrEqual, XML_lessThanOrEqual };
414 mnOperator = STATIC_ARRAY_SELECT( spnOperators, nOperator, XML_TOKEN_INVALID );
415}
416
417void CondFormatRuleModel::setBiff12TextType( sal_Int32 nOperator )
418{
419 // note: type XML_notContainsText vs. operator XML_notContains
420 static const sal_Int32 spnTypes[] = { XML_containsText, XML_notContainsText, XML_beginsWith, XML_endsWith };
421 mnType = STATIC_ARRAY_SELECT( spnTypes, nOperator, XML_TOKEN_INVALID );
422 static const sal_Int32 spnOperators[] = { XML_containsText, XML_notContains, XML_beginsWith, XML_endsWith };
423 mnOperator = STATIC_ARRAY_SELECT( spnOperators, nOperator, XML_TOKEN_INVALID );
424}
425
427 WorksheetHelper( rCondFormat ),
428 mrCondFormat( rCondFormat ),
429 mpFormat(pFormat),
430 mpFormatEntry(nullptr)
431{
432}
433
435{
436 maModel.maText = rAttribs.getString( XML_text, OUString() );
437 maModel.mnPriority = rAttribs.getInteger( XML_priority, -1 );
439 maModel.mnOperator = rAttribs.getToken( XML_operator, XML_TOKEN_INVALID );
440 maModel.mnTimePeriod = rAttribs.getToken( XML_timePeriod, XML_TOKEN_INVALID );
441 maModel.mnRank = rAttribs.getInteger( XML_rank, 0 );
442 maModel.mnStdDev = rAttribs.getInteger( XML_stdDev, 0 );
443 maModel.mnDxfId = rAttribs.getInteger( XML_dxfId, -1 );
444 maModel.mbStopIfTrue = rAttribs.getBool( XML_stopIfTrue, false );
445 maModel.mbBottom = rAttribs.getBool( XML_bottom, false );
446 maModel.mbPercent = rAttribs.getBool( XML_percent, false );
447 maModel.mbAboveAverage = rAttribs.getBool( XML_aboveAverage, true );
448 maModel.mbEqualAverage = rAttribs.getBool( XML_equalAverage, false );
449
450 if(maModel.mnType == XML_colorScale)
451 {
452 //import the remaining values
453
454 }
455}
456
457void CondFormatRule::appendFormula( const OUString& rFormula )
458{
460 ApiTokenSequence aTokens = getFormulaParser().importFormula( aBaseAddr, rFormula );
461 maModel.maFormulas.push_back( aTokens );
462}
463
465{
466 sal_Int32 nType, nSubType, nOperator, nFmla1Size, nFmla2Size, nFmla3Size;
467 sal_uInt16 nFlags;
468 nType = rStrm.readInt32();
469 nSubType = rStrm.readInt32();
470 maModel.mnDxfId = rStrm.readInt32();
471 maModel.mnPriority = rStrm.readInt32();
472 nOperator = rStrm.readInt32();
473 rStrm.skip( 8 );
474 nFlags = rStrm.readuInt16();
475 nFmla1Size = rStrm.readInt32();
476 nFmla2Size = rStrm.readInt32();
477 nFmla3Size = rStrm.readInt32();
479
480 /* Import the formulas. For no obvious reason, the sizes of the formulas
481 are already stored before. Nevertheless the following formulas contain
482 their own sizes. */
483
484 // first formula
485 // I am not bored enough to bother simplifying these expressions
486 SAL_WARN_IF( !( (nFmla1Size >= 0) || ((nFmla2Size == 0) && (nFmla3Size == 0)) ), "sc.filter", "CondFormatRule::importCfRule - missing first formula" );
487 SAL_WARN_IF( !( (nFmla1Size > 0) == (rStrm.getRemaining() >= 8) ), "sc.filter", "CondFormatRule::importCfRule - formula size mismatch" );
488 if( rStrm.getRemaining() >= 8 )
489 {
492 maModel.maFormulas.push_back( aTokens );
493
494 // second formula
495 OSL_ENSURE( (nFmla2Size >= 0) || (nFmla3Size == 0), "CondFormatRule::importCfRule - missing second formula" );
496 OSL_ENSURE( (nFmla2Size > 0) == (rStrm.getRemaining() >= 8), "CondFormatRule::importCfRule - formula size mismatch" );
497 if( rStrm.getRemaining() >= 8 )
498 {
500 maModel.maFormulas.push_back( aTokens );
501
502 // third formula
503 OSL_ENSURE( (nFmla3Size > 0) == (rStrm.getRemaining() >= 8), "CondFormatRule::importCfRule - formula size mismatch" );
504 if( rStrm.getRemaining() >= 8 )
505 {
507 maModel.maFormulas.push_back( aTokens );
508 }
509 }
510 }
511
512 // flags
513 maModel.mbStopIfTrue = getFlag( nFlags, BIFF12_CFRULE_STOPIFTRUE );
514 maModel.mbBottom = getFlag( nFlags, BIFF12_CFRULE_BOTTOM );
515 maModel.mbPercent = getFlag( nFlags, BIFF12_CFRULE_PERCENT );
516 maModel.mbAboveAverage = getFlag( nFlags, BIFF12_CFRULE_ABOVEAVERAGE );
517 // no flag for equalAverage, must be determined from subtype below...
518
519 // Convert the type/operator settings. This is a real mess...
520 switch( nType )
521 {
522 case BIFF12_CFRULE_TYPE_CELLIS:
524 nSubType != BIFF12_CFRULE_SUB_CELLIS, "sc.filter",
525 "CondFormatRule::importCfRule - rule type/subtype mismatch");
526 maModel.mnType = XML_cellIs;
527 maModel.setBiffOperator( nOperator );
528 OSL_ENSURE( maModel.mnOperator != XML_TOKEN_INVALID, "CondFormatRule::importCfRule - unknown operator" );
529 break;
530 case BIFF12_CFRULE_TYPE_EXPRESSION:
531 // here we have to look at the subtype to find the real type...
532 switch( nSubType )
533 {
534 case BIFF12_CFRULE_SUB_EXPRESSION:
535 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
536 maModel.mnType = XML_expression;
537 break;
538 case BIFF12_CFRULE_SUB_UNIQUE:
539 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
540 maModel.mnType = XML_uniqueValues;
541 break;
542 case BIFF12_CFRULE_SUB_TEXT:
543 maModel.setBiff12TextType( nOperator );
544 OSL_ENSURE( maModel.mnType != XML_TOKEN_INVALID, "CondFormatRule::importCfRule - unexpected operator value" );
545 break;
546 case BIFF12_CFRULE_SUB_BLANK:
547 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
548 maModel.mnType = XML_containsBlanks;
549 break;
550 case BIFF12_CFRULE_SUB_NOTBLANK:
551 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
552 maModel.mnType = XML_notContainsBlanks;
553 break;
554 case BIFF12_CFRULE_SUB_ERROR:
555 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
556 maModel.mnType = XML_containsErrors;
557 break;
558 case BIFF12_CFRULE_SUB_NOTERROR:
559 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
560 maModel.mnType = XML_notContainsErrors;
561 break;
562 case BIFF12_CFRULE_SUB_TODAY:
564 nOperator != BIFF12_CFRULE_TIMEOP_TODAY, "sc.filter",
565 "CondFormatRule::importCfRule - unexpected time operator value");
566 maModel.mnType = XML_timePeriod;
567 maModel.mnTimePeriod = XML_today;
568 break;
569 case BIFF12_CFRULE_SUB_TOMORROW:
571 nOperator != BIFF12_CFRULE_TIMEOP_TOMORROW, "sc.filter",
572 "CondFormatRule::importCfRule - unexpected time operator value");
573 maModel.mnType = XML_timePeriod;
574 maModel.mnTimePeriod = XML_tomorrow;
575 break;
576 case BIFF12_CFRULE_SUB_YESTERDAY:
578 nOperator != BIFF12_CFRULE_TIMEOP_YESTERDAY,
579 "sc.filter",
580 "CondFormatRule::importCfRule - unexpected time operator value");
581 maModel.mnType = XML_timePeriod;
582 maModel.mnTimePeriod = XML_yesterday;
583 break;
584 case BIFF12_CFRULE_SUB_LAST7DAYS:
586 nOperator != BIFF12_CFRULE_TIMEOP_LAST7DAYS,
587 "sc.filter",
588 "CondFormatRule::importCfRule - unexpected time operator value");
589 maModel.mnType = XML_timePeriod;
590 maModel.mnTimePeriod = XML_last7Days;
591 break;
592 case BIFF12_CFRULE_SUB_LASTMONTH:
594 nOperator != BIFF12_CFRULE_TIMEOP_LASTMONTH,
595 "sc.filter",
596 "CondFormatRule::importCfRule - unexpected time operator value");
597 maModel.mnType = XML_timePeriod;
598 maModel.mnTimePeriod = XML_lastMonth;
599 break;
600 case BIFF12_CFRULE_SUB_NEXTMONTH:
602 nOperator != BIFF12_CFRULE_TIMEOP_NEXTMONTH,
603 "sc.filter",
604 "CondFormatRule::importCfRule - unexpected time operator value");
605 maModel.mnType = XML_timePeriod;
606 maModel.mnTimePeriod = XML_nextMonth;
607 break;
608 case BIFF12_CFRULE_SUB_THISWEEK:
610 nOperator != BIFF12_CFRULE_TIMEOP_THISWEEK, "sc.filter",
611 "CondFormatRule::importCfRule - unexpected time operator value");
612 maModel.mnType = XML_timePeriod;
613 maModel.mnTimePeriod = XML_thisWeek;
614 break;
615 case BIFF12_CFRULE_SUB_NEXTWEEK:
617 nOperator != BIFF12_CFRULE_TIMEOP_NEXTWEEK, "sc.filter",
618 "CondFormatRule::importCfRule - unexpected time operator value");
619 maModel.mnType = XML_timePeriod;
620 maModel.mnTimePeriod = XML_nextWeek;
621 break;
622 case BIFF12_CFRULE_SUB_LASTWEEK:
624 nOperator != BIFF12_CFRULE_TIMEOP_LASTWEEK, "sc.filter",
625 "CondFormatRule::importCfRule - unexpected time operator value");
626 maModel.mnType = XML_timePeriod;
627 maModel.mnTimePeriod = XML_lastWeek;
628 break;
629 case BIFF12_CFRULE_SUB_THISMONTH:
631 nOperator != BIFF12_CFRULE_TIMEOP_THISMONTH,
632 "sc.filter",
633 "CondFormatRule::importCfRule - unexpected time operator value");
634 maModel.mnType = XML_timePeriod;
635 maModel.mnTimePeriod = XML_thisMonth;
636 break;
637 case BIFF12_CFRULE_SUB_ABOVEAVERAGE:
638 OSL_ENSURE( maModel.mbAboveAverage, "CondFormatRule::importCfRule - wrong above-average flag" );
639 maModel.mnType = XML_aboveAverage;
640 maModel.mnStdDev = nOperator; // operator field used for standard deviation
641 maModel.mbAboveAverage = true;
642 maModel.mbEqualAverage = false; // does not exist as real flag...
643 break;
644 case BIFF12_CFRULE_SUB_BELOWAVERAGE:
645 OSL_ENSURE( !maModel.mbAboveAverage, "CondFormatRule::importCfRule - wrong above-average flag" );
646 maModel.mnType = XML_aboveAverage;
647 maModel.mnStdDev = nOperator; // operator field used for standard deviation
648 maModel.mbAboveAverage = false;
649 maModel.mbEqualAverage = false; // does not exist as real flag...
650 break;
651 case BIFF12_CFRULE_SUB_DUPLICATE:
652 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
653 maModel.mnType = XML_duplicateValues;
654 break;
655 case BIFF12_CFRULE_SUB_EQABOVEAVERAGE:
656 OSL_ENSURE( maModel.mbAboveAverage, "CondFormatRule::importCfRule - wrong above-average flag" );
657 maModel.mnType = XML_aboveAverage;
658 maModel.mnStdDev = nOperator; // operator field used for standard deviation
659 maModel.mbAboveAverage = true;
660 maModel.mbEqualAverage = true; // does not exist as real flag...
661 break;
662 case BIFF12_CFRULE_SUB_EQBELOWAVERAGE:
663 OSL_ENSURE( !maModel.mbAboveAverage, "CondFormatRule::importCfRule - wrong above-average flag" );
664 maModel.mnType = XML_aboveAverage;
665 maModel.mnStdDev = nOperator; // operator field used for standard deviation
666 maModel.mbAboveAverage = false;
667 maModel.mbEqualAverage = true; // does not exist as real flag...
668 break;
669 }
670 break;
671 case BIFF12_CFRULE_TYPE_COLORSCALE:
673 nSubType != BIFF12_CFRULE_SUB_COLORSCALE, "sc.filter",
674 "CondFormatRule::importCfRule - rule type/subtype mismatch");
675 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
676 maModel.mnType = XML_colorScale;
677 break;
678 case BIFF12_CFRULE_TYPE_DATABAR:
680 nSubType != BIFF12_CFRULE_SUB_DATABAR, "sc.filter",
681 "CondFormatRule::importCfRule - rule type/subtype mismatch");
682 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
683 maModel.mnType = XML_dataBar;
684 break;
685 case BIFF12_CFRULE_TYPE_TOPTEN:
687 nSubType != BIFF12_CFRULE_SUB_TOPTEN, "sc.filter",
688 "CondFormatRule::importCfRule - rule type/subtype mismatch");
689 maModel.mnType = XML_top10;
690 maModel.mnRank = nOperator; // operator field used for rank value
691 break;
692 case BIFF12_CFRULE_TYPE_ICONSET:
694 nSubType != BIFF12_CFRULE_SUB_ICONSET, "sc.filter",
695 "CondFormatRule::importCfRule - rule type/subtype mismatch");
696 OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" );
697 maModel.mnType = XML_iconSet;
698 break;
699 default:
700 OSL_FAIL( "CondFormatRule::importCfRule - unknown rule type" );
701 }
702}
703
704void CondFormatRule::setFormatEntry(sal_Int32 nPriority, ScFormatEntry* pEntry)
705{
706 maModel.mnPriority = nPriority;
707 mpFormatEntry = pEntry;
708}
709
711{
712 if (mpFormatEntry)
713 {
715 return;
716 }
717
719
720 /* Replacement formula for unsupported rule types (text comparison rules,
721 time period rules, cell type rules). The replacement formulas below may
722 contain several placeholders:
723 - '#B' will be replaced by the current relative base address (may occur
724 several times).
725 - '#R' will be replaced by the entire range list of the conditional
726 formatting (absolute addresses).
727 - '#T' will be replaced by the quoted comparison text.
728 - '#L' will be replaced by the length of the comparison text (from
729 the 'text' attribute) used in text comparison rules.
730 - '#K' will be replaced by the rank (from the 'rank' attribute) used in
731 top-10 rules.
732 - '#M' will be replaced by the top/bottom flag (from the 'bottom'
733 attribute) used in the RANK function in top-10 rules.
734 - '#C' will be replaced by one of the comparison operators <, >, <=, or
735 >=, according to the 'aboveAverage' and 'equalAverage' flags.
736 */
737 OUString aReplaceFormula;
738
739 switch( maModel.mnType )
740 {
741 case XML_cellIs:
743 break;
744 case XML_duplicateValues:
745 eOperator = ScConditionMode::Duplicate;
746 break;
747 case XML_uniqueValues:
749 break;
750 case XML_expression:
751 eOperator = ScConditionMode::Direct;
752 break;
753 case XML_containsText:
754 OSL_ENSURE( maModel.mnOperator == XML_containsText, "CondFormatRule::finalizeImport - unexpected operator" );
756 break;
757 case XML_notContainsText:
758 // note: type XML_notContainsText vs. operator XML_notContains
759 OSL_ENSURE( maModel.mnOperator == XML_notContains, "CondFormatRule::finalizeImport - unexpected operator" );
761 break;
762 case XML_beginsWith:
763 OSL_ENSURE( maModel.mnOperator == XML_beginsWith, "CondFormatRule::finalizeImport - unexpected operator" );
764 eOperator = ScConditionMode::BeginsWith;
765 break;
766 case XML_endsWith:
767 OSL_ENSURE( maModel.mnOperator == XML_endsWith, "CondFormatRule::finalizeImport - unexpected operator" );
768 eOperator = ScConditionMode::EndsWith;
769 break;
770 case XML_timePeriod:
771 break;
772 case XML_containsBlanks:
773 aReplaceFormula = "LEN(TRIM(#B))=0";
774 break;
775 case XML_notContainsBlanks:
776 aReplaceFormula = "LEN(TRIM(#B))>0";
777 break;
778 case XML_containsErrors:
779 eOperator = ScConditionMode::Error;
780 break;
781 case XML_notContainsErrors:
782 eOperator = ScConditionMode::NoError;
783 break;
784 case XML_top10:
786 {
787 if(maModel.mbBottom)
789 else
790 eOperator = ScConditionMode::TopPercent;
791 }
792 else
793 {
794 if(maModel.mbBottom)
795 eOperator = ScConditionMode::Bottom10;
796 else
797 eOperator = ScConditionMode::Top10;
798 }
799 break;
800 case XML_aboveAverage:
802 {
805 else
807 }
808 else
809 {
812 else
814 }
815 break;
816 case XML_colorScale:
817 break;
818 }
819
820 if( !aReplaceFormula.isEmpty() )
821 {
822 OUString aAddress;
823 sal_Int32 nStrPos = aReplaceFormula.getLength();
824 while( (nStrPos = aReplaceFormula.lastIndexOf( '#', nStrPos )) >= 0 )
825 {
826 switch( aReplaceFormula[ nStrPos + 1 ] )
827 {
828 case 'B': // current base address
829 if( aAddress.isEmpty() )
831 aReplaceFormula = aReplaceFormula.replaceAt( nStrPos, 2, aAddress );
832 break;
833 default:
834 OSL_FAIL( "CondFormatRule::finalizeImport - unknown placeholder" );
835 }
836 }
837
838 // set the replacement formula
839 maModel.maFormulas.clear();
840 appendFormula( aReplaceFormula );
841 eOperator = ScConditionMode::Direct;
842 }
843
845
846 if( eOperator == ScConditionMode::Error || eOperator == ScConditionMode::NoError )
847 {
848 ScDocument& rDoc = getScDocument();
849 OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
850 ScCondFormatEntry* pNewEntry = new ScCondFormatEntry( eOperator, nullptr, nullptr, rDoc, aPos, aStyleName );
851 mpFormat->AddEntry(pNewEntry);
852 }
853 else if( eOperator == ScConditionMode::BeginsWith || eOperator == ScConditionMode::EndsWith ||
855 {
856 ScDocument& rDoc = getScDocument();
857 ScTokenArray aTokenArray(rDoc);
859 aTokenArray.AddString(rSPool.intern(maModel.maText));
860 OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
861 ScCondFormatEntry* pNewEntry = new ScCondFormatEntry( eOperator, &aTokenArray, nullptr, rDoc, aPos, aStyleName );
862 mpFormat->AddEntry(pNewEntry);
863 }
864 else if( (eOperator != ScConditionMode::NONE) && !maModel.maFormulas.empty() )
865 {
866 ScDocument& rDoc = getScDocument();
867 std::unique_ptr<ScTokenArray> pTokenArray2;
868 if( maModel.maFormulas.size() >= 2)
869 {
870 pTokenArray2.reset(new ScTokenArray(rDoc));
872 rDoc.CheckLinkFormulaNeedingCheck(*pTokenArray2);
873 }
874
875 ScTokenArray aTokenArray(rDoc);
876 OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
878 rDoc.CheckLinkFormulaNeedingCheck( aTokenArray);
879 ScCondFormatEntry* pNewEntry = new ScCondFormatEntry(eOperator,
880 &aTokenArray, pTokenArray2.get(), rDoc, aPos, aStyleName);
881 mpFormat->AddEntry(pNewEntry);
882 }
883 else if ( eOperator == ScConditionMode::Top10 || eOperator == ScConditionMode::Bottom10 ||
885 {
886 ScDocument& rDoc = getScDocument();
887 ScTokenArray aTokenArray(rDoc);
888 aTokenArray.AddDouble( maModel.mnRank );
889 OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
890 ScCondFormatEntry* pNewEntry = new ScCondFormatEntry( eOperator, &aTokenArray, nullptr, rDoc, aPos, aStyleName );
891 mpFormat->AddEntry(pNewEntry);
892 }
893 else if( eOperator == ScConditionMode::AboveAverage || eOperator == ScConditionMode::BelowAverage ||
895 {
896 ScDocument& rDoc = getScDocument();
897 // actually that is still unsupported
898 ScTokenArray aTokenArrayDev(rDoc);
899 aTokenArrayDev.AddDouble( maModel.mnStdDev );
900 OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
901 ScCondFormatEntry* pNewEntry = new ScCondFormatEntry( eOperator, &aTokenArrayDev, nullptr, rDoc, aPos, aStyleName );
902 mpFormat->AddEntry(pNewEntry);
903 }
904 else if( eOperator == ScConditionMode::Duplicate || eOperator == ScConditionMode::NotDuplicate )
905 {
906 ScDocument& rDoc = getScDocument();
907 OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
908 ScCondFormatEntry* pNewEntry = new ScCondFormatEntry( eOperator, nullptr, nullptr, rDoc, aPos, aStyleName );
909 mpFormat->AddEntry(pNewEntry);
910 }
911 else if( maModel.mnType == XML_timePeriod )
912 {
914 switch( maModel.mnTimePeriod )
915 {
916 case XML_yesterday:
917 eDateType = condformat::YESTERDAY;
918 break;
919 case XML_today:
920 eDateType = condformat::TODAY;
921 break;
922 case XML_tomorrow:
923 eDateType = condformat::TOMORROW;
924 break;
925 case XML_last7Days:
926 eDateType = condformat::LAST7DAYS;
927 break;
928 case XML_lastWeek:
929 eDateType = condformat::LASTWEEK;
930 break;
931 case XML_thisWeek:
932 eDateType = condformat::THISWEEK;
933 break;
934 case XML_nextWeek:
935 eDateType = condformat::NEXTWEEK;
936 break;
937 case XML_lastMonth:
938 eDateType = condformat::LASTMONTH;
939 break;
940 case XML_thisMonth:
941 eDateType = condformat::THISMONTH;
942 break;
943 case XML_nextMonth:
944 eDateType = condformat::NEXTMONTH;
945 break;
946 default:
947 SAL_WARN("sc.filter", "CondFormatRule::finalizeImport - unknown time period type" );
948 }
949
950 ScDocument& rDoc = getScDocument();
951 ScCondDateFormatEntry* pFormatEntry = new ScCondDateFormatEntry(&rDoc);
952 pFormatEntry->SetDateType(eDateType);
953 OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
954 pFormatEntry->SetStyleName( aStyleName );
955
956 mpFormat->AddEntry(pFormatEntry);
957 }
958 else if( mpColor )
959 {
960 ScDocument& rDoc = getScDocument();
961 ScColorScaleFormat* pFormatEntry = new ScColorScaleFormat(&rDoc);
962
963 mpFormat->AddEntry(pFormatEntry);
964
965 mpColor->AddEntries( pFormatEntry, &rDoc, aPos );
966 }
967 else if (mpDataBar)
968 {
969 ScDocument& rDoc = getScDocument();
970 ScDataBarFormat* pFormatEntry = new ScDataBarFormat(&rDoc);
971
972 mpFormat->AddEntry(pFormatEntry);
973 mpDataBar->SetData( pFormatEntry, &rDoc, aPos );
974
975 }
976 else if(mpIconSet)
977 {
978 ScDocument& rDoc = getScDocument();
979 ScIconSetFormat* pFormatEntry = new ScIconSetFormat(&rDoc);
980
981 mpFormat->AddEntry(pFormatEntry);
982 mpIconSet->SetData( pFormatEntry, &rDoc, aPos );
983 }
984}
985
987{
988 if(!mpColor)
989 mpColor.reset( new ColorScaleRule(mrCondFormat) );
990
991 return mpColor.get();
992}
993
995{
996 if(!mpDataBar)
997 mpDataBar.reset( new DataBarRule(mrCondFormat) );
998
999 return mpDataBar.get();
1000}
1001
1003{
1004 if(!mpIconSet)
1005 mpIconSet.reset( new IconSetRule(mrCondFormat) );
1006
1007 return mpIconSet.get();
1008}
1009
1011 mbPivot( false )
1012{
1013}
1014
1016 WorksheetHelper( rHelper ),
1017 mpFormat(nullptr),
1018 mbReadyForFinalize(false)
1019{
1020}
1021
1023{
1024 getAddressConverter().convertToCellRangeList( maModel.maRanges, rAttribs.getString( XML_sqref, OUString() ), getSheetIndex(), true );
1025 maModel.mbPivot = rAttribs.getBool( XML_pivot, false );
1027}
1028
1030{
1031 CondFormatRuleRef xRule = createRule();
1032 xRule->importCfRule( rAttribs );
1033 insertRule( xRule );
1034 return xRule;
1035}
1036
1038{
1039 BinRangeList aRanges;
1040 rStrm.skip( 8 );
1041 rStrm >> aRanges;
1044}
1045
1047{
1048 CondFormatRuleRef xRule = createRule();
1049 xRule->importCfRule( rStrm );
1050 insertRule( xRule );
1051}
1052
1054{
1055 // probably some error in the xml if we are not ready
1056 if ( !mbReadyForFinalize )
1057 return;
1058 ScDocument& rDoc = getScDocument();
1062 sal_Int32 nIndex = getScDocument().AddCondFormat(std::unique_ptr<ScConditionalFormat>(mpFormat), nTab);
1063
1065}
1066
1068{
1069 return std::make_shared<CondFormatRule>( *this, mpFormat );
1070}
1071
1073{
1074 if( xRule && (xRule->getPriority() > 0) )
1075 {
1076 OSL_ENSURE( maRules.find( xRule->getPriority() ) == maRules.end(), "CondFormat::insertRule - multiple rules with equal priority" );
1077 maRules[ xRule->getPriority() ] = xRule;
1078 }
1079}
1080
1082 WorksheetHelper( rHelper )
1083{
1084}
1085
1087{
1088 CondFormatRef xCondFmt = createCondFormat();
1089 xCondFmt->importConditionalFormatting( rAttribs );
1090 return xCondFmt;
1091}
1092
1093namespace {
1094
1095ScConditionalFormat* findFormatByRange(const ScRangeList& rRange, const ScDocument* pDoc, SCTAB nTab)
1096{
1097 ScConditionalFormatList* pList = pDoc->GetCondFormList(nTab);
1098 for (auto const& it : *pList)
1099 {
1100 if (it->GetRange() == rRange)
1101 {
1102 return it.get();
1103 }
1104 }
1105
1106 return nullptr;
1107}
1108
1109class ScRangeListHasher
1110{
1111public:
1112 size_t operator() (ScRangeList const& rRanges) const
1113 {
1114 size_t nHash = 0;
1115 for (size_t nIdx = 0; nIdx < rRanges.size(); ++nIdx)
1116 nHash += rRanges[nIdx].hashArea();
1117 return nHash;
1118 }
1119};
1120
1121}
1122
1124{
1125 std::unordered_set<size_t> aDoneExtCFs;
1126 typedef std::unordered_map<ScRangeList, CondFormat*, ScRangeListHasher> RangeMap;
1127 RangeMap aRangeMap;
1128 for (auto& rxCondFormat : maCondFormats)
1129 {
1130 if (aRangeMap.find(rxCondFormat->getRanges()) != aRangeMap.end())
1131 continue;
1132 aRangeMap[rxCondFormat->getRanges()] = rxCondFormat.get();
1133 }
1134
1135 size_t nExtCFIndex = 0;
1136 for (const auto& rxExtCondFormat : maExtCondFormats)
1137 {
1138 ScDocument* pDoc = &getScDocument();
1139 const ScRangeList& rRange = rxExtCondFormat->getRange();
1140 RangeMap::iterator it = aRangeMap.find(rRange);
1141 if (it != aRangeMap.end())
1142 {
1143 CondFormat& rCondFormat = *it->second;
1144 const std::vector<std::unique_ptr<ScFormatEntry>>& rEntries = rxExtCondFormat->getEntries();
1145 const std::vector<sal_Int32>& rPriorities = rxExtCondFormat->getPriorities();
1146 size_t nEntryIdx = 0;
1147 for (const auto& rxEntry : rEntries)
1148 {
1149 CondFormatRuleRef xRule = rCondFormat.createRule();
1150 ScFormatEntry* pNewEntry = rxEntry->Clone(pDoc);
1151 sal_Int32 nPriority = rPriorities[nEntryIdx];
1152 if (nPriority == -1)
1154 xRule->setFormatEntry(nPriority, pNewEntry);
1155 rCondFormat.insertRule(xRule);
1156 ++nEntryIdx;
1157 }
1158
1159 aDoneExtCFs.insert(nExtCFIndex);
1160 }
1161
1162 ++nExtCFIndex;
1163 }
1164
1165 for( const auto& rxCondFormat : maCondFormats )
1166 {
1167 if ( rxCondFormat)
1168 rxCondFormat->finalizeImport();
1169 }
1170 for ( const auto& rxCfRule : maCfRules )
1171 {
1172 if ( rxCfRule )
1173 rxCfRule->finalizeImport();
1174 }
1175
1176 nExtCFIndex = 0;
1177 for (const auto& rxExtCondFormat : maExtCondFormats)
1178 {
1179 if (aDoneExtCFs.count(nExtCFIndex))
1180 {
1181 ++nExtCFIndex;
1182 continue;
1183 }
1184
1185 ScDocument* pDoc = &getScDocument();
1186 const ScRangeList& rRange = rxExtCondFormat->getRange();
1187 SCTAB nTab = rRange.front().aStart.Tab();
1188 ScConditionalFormat* pFormat = findFormatByRange(rRange, pDoc, nTab);
1189 if (!pFormat)
1190 {
1191 // create new conditional format and insert it
1192 auto pNewFormat = std::make_unique<ScConditionalFormat>(0, pDoc);
1193 pFormat = pNewFormat.get();
1194 pNewFormat->SetRange(rRange);
1195 sal_uLong nKey = pDoc->AddCondFormat(std::move(pNewFormat), nTab);
1196 pDoc->AddCondFormatData(rRange, nTab, nKey);
1197 }
1198
1199 const std::vector< std::unique_ptr<ScFormatEntry> >& rEntries = rxExtCondFormat->getEntries();
1200 for (const auto& rxEntry : rEntries)
1201 {
1202 pFormat->AddEntry(rxEntry->Clone(pDoc));
1203 }
1204
1205 ++nExtCFIndex;
1206 }
1207
1208 rStyleIdx = 0; // Resets <extlst> <cfRule> style index.
1209}
1210
1212{
1213 CondFormatRef xCondFmt = createCondFormat();
1214 xCondFmt->importCondFormatting( rStrm );
1215 return xCondFmt;
1216}
1217
1219{
1220 ExtCfDataBarRuleRef extRule = std::make_shared<ExtCfDataBarRule>( pTarget, *this );
1221 maCfRules.push_back( extRule );
1222 return extRule;
1223}
1224
1225std::vector< std::unique_ptr<ExtCfCondFormat> >& CondFormatBuffer::importExtCondFormat()
1226{
1227 return maExtCondFormats;
1228}
1229
1231{
1232 switch( nToken )
1233 {
1234 case XML_between: return ConditionOperator2::BETWEEN;
1235 case XML_equal: return ConditionOperator2::EQUAL;
1236 case XML_greaterThan: return ConditionOperator2::GREATER;
1237 case XML_greaterThanOrEqual: return ConditionOperator2::GREATER_EQUAL;
1238 case XML_lessThan: return ConditionOperator2::LESS;
1239 case XML_lessThanOrEqual: return ConditionOperator2::LESS_EQUAL;
1240 case XML_notBetween: return ConditionOperator2::NOT_BETWEEN;
1241 case XML_notEqual: return ConditionOperator2::NOT_EQUAL;
1242 case XML_duplicateValues: return ConditionOperator2::DUPLICATE;
1243 }
1245}
1246
1248{
1249 switch( nToken )
1250 {
1251 case XML_between: return ScConditionMode::Between;
1252 case XML_equal: return ScConditionMode::Equal;
1253 case XML_greaterThan: return ScConditionMode::Greater;
1254 case XML_greaterThanOrEqual: return ScConditionMode::EqGreater;
1255 case XML_lessThan: return ScConditionMode::Less;
1256 case XML_lessThanOrEqual: return ScConditionMode::EqLess;
1257 case XML_notBetween: return ScConditionMode::NotBetween;
1258 case XML_notEqual: return ScConditionMode::NotEqual;
1259 case XML_duplicateValues: return ScConditionMode::Duplicate;
1260 case XML_uniqueValues: return ScConditionMode::NotDuplicate;
1261 }
1262 return ScConditionMode::NONE;
1263}
1264
1265// private --------------------------------------------------------------------
1266
1268{
1269 CondFormatRef xCondFmt = std::make_shared<CondFormat>( *this );
1270 maCondFormats.push_back( xCondFmt );
1271 return xCondFmt;
1272}
1273
1275 WorksheetHelper(rParent),
1276 mnRuleType( ExtCfDataBarRule::UNKNOWN ),
1277 mpTarget(pTarget)
1278{
1279}
1280
1282{
1283 switch ( mnRuleType )
1284 {
1285 case DATABAR:
1286 {
1287 ScDataBarFormatData* pDataBar = mpTarget;
1288 if( maModel.maAxisPosition == "none" )
1289 pDataBar->meAxisPosition = databar::NONE;
1290 else if( maModel.maAxisPosition == "middle" )
1291 pDataBar->meAxisPosition = databar::MIDDLE;
1292 else
1294 pDataBar->mbGradient = maModel.mbGradient;
1295 break;
1296 }
1297 case AXISCOLOR:
1298 {
1299 ScDataBarFormatData* pDataBar = mpTarget;
1300 pDataBar->maAxisColor = maModel.mnAxisColor;
1301 break;
1302 }
1303 case NEGATIVEFILLCOLOR:
1304 {
1305 ScDataBarFormatData* pDataBar = mpTarget;
1307 pDataBar->mbNeg = true;
1308 break;
1309 }
1310 case CFVO:
1311 {
1312 ScDataBarFormatData* pDataBar = mpTarget;
1313 ScColorScaleEntry* pEntry = nullptr;
1314 if(maModel.mbIsLower)
1315 pEntry = pDataBar->mpLowerLimit.get();
1316 else
1317 pEntry = pDataBar->mpUpperLimit.get();
1318
1319 if(maModel.maColorScaleType == "min")
1320 pEntry->SetType(COLORSCALE_MIN);
1321 else if (maModel.maColorScaleType == "max")
1322 pEntry->SetType(COLORSCALE_MAX);
1323 else if (maModel.maColorScaleType == "autoMin")
1324 pEntry->SetType(COLORSCALE_AUTO);
1325 else if (maModel.maColorScaleType == "autoMax")
1326 pEntry->SetType(COLORSCALE_AUTO);
1327 else if (maModel.maColorScaleType == "percentile")
1329 else if (maModel.maColorScaleType == "percent")
1330 pEntry->SetType(COLORSCALE_PERCENT);
1331 else if (maModel.maColorScaleType == "formula")
1332 pEntry->SetType(COLORSCALE_FORMULA);
1333 break;
1334 }
1335 case UNKNOWN: // nothing to do
1336 default:
1337 break;
1338 }
1339}
1340
1342{
1344 maModel.mbGradient = rAttribs.getBool( XML_gradient, true );
1345 maModel.maAxisPosition = rAttribs.getString( XML_axisPosition, "automatic" );
1346}
1347
1349{
1351 ThemeBuffer& rThemeBuffer = getTheme();
1352 GraphicHelper& rGraphicHelper = getBaseFilter().getGraphicHelper();
1353 ::Color aColor = importOOXColor(rAttribs, rThemeBuffer, rGraphicHelper);
1354 maModel.mnNegativeColor = aColor;
1355}
1356
1358{
1360 ThemeBuffer& rThemeBuffer = getTheme();
1361 GraphicHelper& rGraphicHelper = getBaseFilter().getGraphicHelper();
1362 ::Color aColor = importOOXColor(rAttribs, rThemeBuffer, rGraphicHelper);
1363 maModel.mnAxisColor = aColor;
1364}
1365
1367{
1368 mnRuleType = CFVO;
1369 maModel.maColorScaleType = rAttribs.getString( XML_type, OUString() );
1370}
1371
1372ExtCfCondFormat::ExtCfCondFormat(const ScRangeList& rRange, std::vector< std::unique_ptr<ScFormatEntry> >& rEntries,
1373 const std::vector<sal_Int32>* pPriorities):
1374 maRange(rRange)
1375{
1376 maEntries.swap(rEntries);
1377 if (pPriorities)
1378 maPriorities = *pPriorities;
1379 else
1380 maPriorities.resize(maEntries.size(), -1);
1381}
1382
1384{
1385}
1386
1388{
1389 return maRange;
1390}
1391
1392const std::vector< std::unique_ptr<ScFormatEntry> >& ExtCfCondFormat::getEntries() const
1393{
1394 return maEntries;
1395}
1396
1397} // namespace oox
1398
1399/* 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 AddEntry(ScColorScaleEntry *pEntry)
Definition: colorscale.cxx:401
void SetDateType(condformat::ScCondFormatDateType eType)
Definition: conditio.cxx:1676
void SetStyleName(const OUString &rStyleName)
Definition: conditio.cxx:1681
void SetRange(const ScRangeList &rRanges)
Definition: conditio.cxx:1745
void AddEntry(ScFormatEntry *pNew)
Definition: conditio.cxx:1751
void SetDataBarData(ScDataBarFormatData *pData)
Definition: colorscale.cxx:726
SC_DLLPUBLIC void CheckLinkFormulaNeedingCheck(const ScTokenArray &rCode)
Check token array and set link check if ocDde/ocWebservice is contained.
Definition: documen8.cxx:1154
SC_DLLPUBLIC svl::SharedStringPool & GetSharedStringPool()
Definition: documen2.cxx:585
SC_DLLPUBLIC void AddCondFormatData(const ScRangeList &rRange, SCTAB nTab, sal_uInt32 nIndex)
Definition: document.cxx:4878
SC_DLLPUBLIC ScConditionalFormatList * GetCondFormList(SCTAB nTab) const
Definition: documen4.cxx:867
SC_DLLPUBLIC sal_uLong AddCondFormat(std::unique_ptr< ScConditionalFormat > pNew, SCTAB nTab)
Definition: documen4.cxx:715
virtual ScFormatEntry * Clone(ScDocument *pDoc) const =0
static const ScIconSetMap g_IconSetMap[]
Definition: colorscale.hxx:380
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:375
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, const OUString &rString, 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.
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)
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.
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)
ExtCfCondFormat(const ScRangeList &aRange, std::vector< std::unique_ptr< ScFormatEntry > > &rEntries, const std::vector< sal_Int32 > *pPriorities=nullptr)
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
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.
::Color getColorByIndex(size_t nIndex) const
Definition: themebuffer.cxx:46
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)
ScCondFormatDateType
Definition: conditio.hxx:484
int i
void SvStream & rStrm
std::u16string_view trim(std::u16string_view str)
std::shared_ptr< CondFormatRule > CondFormatRuleRef
css::uno::Sequence< ApiToken > ApiTokenSequence
@ 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
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