Update git submodules
[LibreOffice.git] / sc / source / filter / oox / extlstcontext.cxx
blob80e0b8ef53d22a6c50ebc7aa1c975b535105c9ec
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <memory>
11 #include <extlstcontext.hxx>
12 #include <worksheethelper.hxx>
13 #include <oox/core/contexthandler.hxx>
14 #include <oox/helper/attributelist.hxx>
15 #include <oox/token/namespaces.hxx>
16 #include <oox/token/tokens.hxx>
17 #include <colorscale.hxx>
18 #include <condformatbuffer.hxx>
19 #include <condformatcontext.hxx>
20 #include <document.hxx>
21 #include <worksheetfragment.hxx>
22 #include <workbookfragment.hxx>
23 #include <stylesbuffer.hxx>
24 #include <stylesfragment.hxx>
25 #include <SparklineFragment.hxx>
27 #include <rangeutl.hxx>
28 #include <sal/log.hxx>
30 using ::oox::core::ContextHandlerRef;
31 using ::oox::xls::CondFormatBuffer;
33 sal_Int32 gnStyleIdx = 0; // Holds index of the <extlst> <cfRule> style (Will be reset by finalize import)
35 namespace oox::xls {
37 ExtCfRuleContext::ExtCfRuleContext( WorksheetContextBase& rFragment, ScDataBarFormatData* pTarget ):
38 WorksheetContextBase( rFragment ),
39 mpTarget( pTarget ),
40 mbFirstEntry(true)
44 ContextHandlerRef ExtCfRuleContext::onCreateContext( sal_Int32 , const AttributeList& )
46 return this;
49 void ExtCfRuleContext::onStartElement( const AttributeList& rAttribs )
51 switch( getCurrentElement() )
53 case XLS14_TOKEN( dataBar ):
55 ExtCfDataBarRuleRef xRule = getCondFormats().createExtCfDataBarRule(mpTarget);
56 xRule->importDataBar( rAttribs );
57 break;
59 case XLS14_TOKEN( fillColor ):
61 ExtCfDataBarRuleRef xRule = getCondFormats().createExtCfDataBarRule(mpTarget);
62 xRule->importPositiveFillColor( rAttribs );
63 break;
65 case XLS14_TOKEN( negativeFillColor ):
67 ExtCfDataBarRuleRef xRule = getCondFormats().createExtCfDataBarRule(mpTarget);
68 xRule->importNegativeFillColor( rAttribs );
69 break;
71 case XLS14_TOKEN( axisColor ):
73 ExtCfDataBarRuleRef xRule = getCondFormats().createExtCfDataBarRule(mpTarget);
74 xRule->importAxisColor( rAttribs );
75 break;
77 case XLS14_TOKEN( cfvo ):
79 ExtCfDataBarRuleRef xRule = getCondFormats().createExtCfDataBarRule(mpTarget);
80 xRule->importCfvo( rAttribs );
81 xRule->getModel().mbIsLower = mbFirstEntry;
82 mbFirstEntry = false;
83 mpRule = std::move(xRule);
84 break;
86 default:
87 break;
91 void ExtCfRuleContext::onCharacters( const OUString& rChars )
93 switch( getCurrentElement() )
95 case XM_TOKEN( f ):
97 if (mpRule)
99 mpRule->getModel().msScaleTypeValue = rChars;
102 break;
106 void ExtCfRuleContext::onEndElement()
108 switch( getCurrentElement() )
110 case XLS14_TOKEN( cfvo ):
112 mpRule.reset();
113 break;
118 namespace {
119 bool IsSpecificTextCondMode(ScConditionMode eMode)
121 switch (eMode)
123 case ScConditionMode::BeginsWith:
124 case ScConditionMode::EndsWith:
125 case ScConditionMode::ContainsText:
126 case ScConditionMode::NotContainsText:
127 return true;
128 default:
129 break;
131 return false;
135 ExtConditionalFormattingContext::ExtConditionalFormattingContext(WorksheetContextBase& rFragment)
136 : WorksheetContextBase(rFragment)
137 , nFormulaCount(0)
138 , nPriority(-1)
139 , eOperator(ScConditionMode::NONE)
140 , isPreviousElementF(false)
144 ContextHandlerRef ExtConditionalFormattingContext::onCreateContext(sal_Int32 nElement, const AttributeList& rAttribs)
146 if (mpCurrentRule)
148 ScFormatEntry& rFormat = **maEntries.rbegin();
149 assert(rFormat.GetType() == ScFormatEntry::Type::Iconset);
150 ScIconSetFormat& rIconSet = static_cast<ScIconSetFormat&>(rFormat);
151 ScDocument& rDoc = getScDocument();
152 SCTAB nTab = getSheetIndex();
153 ScAddress aPos(0, 0, nTab);
154 mpCurrentRule->SetData(&rIconSet, &rDoc, aPos);
155 mpCurrentRule.reset();
157 if (nElement == XLS14_TOKEN(cfRule))
159 OUString aType = rAttribs.getString(XML_type, OUString());
160 OUString aId = rAttribs.getString(XML_id, OUString());
161 nPriority = rAttribs.getInteger( XML_priority, -1 );
162 maPriorities.push_back(nPriority);
163 maModel.nPriority = nPriority;
165 if (aType == "dataBar")
167 // an ext entry does not need to have an existing corresponding entry
168 ScDataBarFormatData* pInfo;
169 ExtLst::const_iterator aExt = getExtLst().find( aId );
170 if (aExt == getExtLst().end())
172 pInfo = new ScDataBarFormatData();
173 auto pFormat = std::make_unique<ScDataBarFormat>(&getScDocument());
174 pFormat->SetDataBarData(pInfo);
175 getCondFormats().importExtFormatEntries().push_back(std::move(pFormat));
177 else
179 pInfo = aExt->second;
182 if (!pInfo)
184 return nullptr;
186 return new ExtCfRuleContext( *this, pInfo );
188 else if (aType == "iconSet")
190 ScDocument& rDoc = getScDocument();
191 mpCurrentRule.reset(new IconSetRule(*this));
192 maEntries.push_back(std::make_unique<ScIconSetFormat>(&rDoc));
193 return new IconSetContext(*this, mpCurrentRule.get());
195 else if (aType == "cellIs")
197 sal_Int32 aToken = rAttribs.getToken( XML_operator, XML_TOKEN_INVALID );
198 eOperator = CondFormatBuffer::convertToInternalOperator(aToken);
199 maModel.eOperator = eOperator;
200 return this;
202 else if (aType == "containsText")
204 eOperator = ScConditionMode::ContainsText;
205 maModel.eOperator = eOperator;
206 return this;
208 else if (aType == "notContainsText")
210 eOperator = ScConditionMode::NotContainsText;
211 maModel.eOperator = eOperator;
212 return this;
214 else if (aType == "beginsWith")
216 eOperator = ScConditionMode::BeginsWith;
217 maModel.eOperator = eOperator;
218 return this;
220 else if (aType == "endsWith")
222 eOperator = ScConditionMode::EndsWith;
223 maModel.eOperator = eOperator;
224 return this;
226 else if (aType == "expression")
228 eOperator = ScConditionMode::Direct;
229 maModel.eOperator = eOperator;
230 return this;
232 else
234 SAL_WARN("sc", "unhandled XLS14_TOKEN(cfRule) with type: " << aType);
237 else if (nElement == XLS14_TOKEN( dxf ))
239 return new DxfContext( *this, getStyles().createExtDxf() );
241 else if (nElement == XM_TOKEN( sqref ) || nElement == XM_TOKEN( f ))
243 if(nElement == XM_TOKEN( f ))
244 nFormulaCount++;
245 return this;
248 return nullptr;
251 void ExtConditionalFormattingContext::onStartElement(const AttributeList& /*Attribs*/)
255 void ExtConditionalFormattingContext::onCharacters(const OUString& rCharacters)
257 switch (getCurrentElement())
259 case XM_TOKEN(f):
261 aChars = rCharacters;
262 isPreviousElementF = true;
264 break;
265 case XM_TOKEN(sqref):
267 aChars = rCharacters;
269 break;
274 void ExtConditionalFormattingContext::onEndElement()
276 switch (getCurrentElement())
278 case XM_TOKEN(f):
280 if(!IsSpecificTextCondMode(eOperator) || nFormulaCount == 2)
281 maModel.aFormula = aChars;
283 break;
284 case XLS14_TOKEN( cfRule ):
286 if (IsSpecificTextCondMode(maModel.eOperator) && nFormulaCount == 1)
288 maModel.aFormula = aChars;
289 maModel.eOperator = ScConditionMode::Direct;
292 if (Dxf* pDxf = getStyles().getExtDxfs().get(gnStyleIdx).get())
293 pDxf->finalizeImport();
294 maModel.aStyle = getStyles().createExtDxfStyle(gnStyleIdx);
295 gnStyleIdx++;
296 nFormulaCount = 0;
297 maModels.push_back(maModel);
299 break;
300 case XM_TOKEN(sqref):
302 ScRangeList aRange;
303 ScDocument& rDoc = getScDocument();
304 bool bSuccess = ScRangeStringConverter::GetRangeListFromString(aRange, aChars, rDoc, formula::FormulaGrammar::CONV_XL_OOX);
305 if (!bSuccess || aRange.empty())
306 break;
308 SCTAB nTab = getSheetIndex();
309 for (size_t i = 0; i < aRange.size(); ++i)
311 aRange[i].aStart.SetTab(nTab);
312 aRange[i].aEnd.SetTab(nTab);
315 if (maModels.size() > 1)
317 std::sort(maModels.begin(), maModels.end(),
318 [](const ExtCondFormatRuleModel& lhs, const ExtCondFormatRuleModel& rhs) {
319 return lhs.nPriority < rhs.nPriority;
323 if (isPreviousElementF) // sqref can be alone in some cases.
325 for (size_t i = 0; i < maModels.size(); ++i)
327 ScAddress rPos = aRange.GetTopLeftCorner();
328 ScCondFormatEntry* pEntry = new ScCondFormatEntry(maModels[i].eOperator, maModels[i].aFormula, u""_ustr, rDoc,
329 rPos, maModels[i].aStyle, u""_ustr, u""_ustr,
330 formula::FormulaGrammar::GRAM_OOXML ,
331 formula::FormulaGrammar::GRAM_OOXML,
332 ScFormatEntry::Type::ExtCondition );
333 maEntries.push_back(std::unique_ptr<ScFormatEntry>(pEntry));
336 assert(maPriorities.size() >= maModels.size());
337 maModels.clear();
340 std::vector< std::unique_ptr<ExtCfCondFormat> >& rExtFormats = getCondFormats().importExtCondFormat();
341 rExtFormats.push_back(std::make_unique<ExtCfCondFormat>(aRange, maEntries, &maPriorities));
343 maPriorities.clear();
344 isPreviousElementF = false;
346 break;
347 default:
348 break;
352 ExtLstLocalContext::ExtLstLocalContext( WorksheetContextBase& rFragment, ScDataBarFormatData* pTarget ):
353 WorksheetContextBase(rFragment),
354 mpTarget(pTarget)
358 ContextHandlerRef ExtLstLocalContext::onCreateContext( sal_Int32 nElement, const AttributeList& )
360 switch( getCurrentElement() )
362 case XLS_TOKEN( extLst ):
363 if(nElement == XLS_TOKEN( ext ))
364 return this;
365 else
366 return nullptr;
367 case XLS_TOKEN( ext ):
368 if (nElement == XLS14_TOKEN( id ))
369 return this;
370 else
371 return nullptr;
373 return nullptr;
376 void ExtLstLocalContext::onStartElement( const AttributeList& )
378 switch( getCurrentElement() )
380 case XLS14_TOKEN( id ):
381 break;
385 void ExtLstLocalContext::onCharacters( const OUString& rChars )
387 if (getCurrentElement() == XLS14_TOKEN( id ))
389 getExtLst().insert( std::pair< OUString, ScDataBarFormatData*>(rChars, mpTarget) );
393 ExtGlobalContext::ExtGlobalContext( WorksheetContextBase& rFragment ):
394 WorksheetContextBase(rFragment)
398 ContextHandlerRef ExtGlobalContext::onCreateContext( sal_Int32 nElement, const AttributeList& /*rAttribs*/ )
400 switch (nElement)
402 case XLS14_TOKEN(conditionalFormatting): return new ExtConditionalFormattingContext(*this);
403 case XLS14_TOKEN(dataValidations): return new ExtDataValidationsContext(*this);
404 case XLS14_TOKEN(sparklineGroups): return new SparklineGroupsContext(*this);
406 return this;
409 void ExtGlobalContext::onStartElement( const AttributeList& /*rAttribs*/ )
413 ExtLstGlobalContext::ExtLstGlobalContext( WorksheetFragment& rFragment ):
414 WorksheetContextBase(rFragment)
418 ContextHandlerRef ExtLstGlobalContext::onCreateContext( sal_Int32 nElement, const AttributeList& )
420 if (nElement == XLS_TOKEN( ext ))
421 return new ExtGlobalContext( *this );
423 return this;
426 ExtGlobalWorkbookContext::ExtGlobalWorkbookContext( WorkbookContextBase& rFragment ):
427 WorkbookContextBase(rFragment)
431 ContextHandlerRef ExtGlobalWorkbookContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
433 if (nElement == LOEXT_TOKEN(extCalcPr))
435 ScDocument& rDoc = getScDocument();
436 sal_Int32 nToken = rAttribs.getToken( XML_stringRefSyntax, XML_CalcA1 );
437 ScCalcConfig aCalcConfig = rDoc.GetCalcConfig();
439 switch( nToken )
441 case XML_CalcA1:
442 aCalcConfig.SetStringRefSyntax( formula::FormulaGrammar::CONV_OOO );
443 break;
444 case XML_ExcelA1:
445 aCalcConfig.SetStringRefSyntax( formula::FormulaGrammar::CONV_XL_A1 );
446 break;
447 case XML_ExcelR1C1:
448 aCalcConfig.SetStringRefSyntax( formula::FormulaGrammar::CONV_XL_R1C1 );
449 break;
450 case XML_CalcA1ExcelA1:
451 aCalcConfig.SetStringRefSyntax( formula::FormulaGrammar::CONV_A1_XL_A1 );
452 break;
453 default:
454 aCalcConfig.SetStringRefSyntax( formula::FormulaGrammar::CONV_UNSPECIFIED );
455 break;
457 rDoc.SetCalcConfig(aCalcConfig);
460 return this;
463 void ExtGlobalWorkbookContext::onStartElement( const AttributeList& /*rAttribs*/ )
467 ExtLstGlobalWorkbookContext::ExtLstGlobalWorkbookContext( WorkbookFragment& rFragment ):
468 WorkbookContextBase(rFragment)
472 ContextHandlerRef ExtLstGlobalWorkbookContext::onCreateContext( sal_Int32 nElement, const AttributeList& )
474 if (nElement == XLS_TOKEN( ext ))
475 return new ExtGlobalWorkbookContext( *this );
477 return this;
480 } //namespace oox::xls
482 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */