1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
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)
37 ExtCfRuleContext::ExtCfRuleContext( WorksheetContextBase
& rFragment
, ScDataBarFormatData
* pTarget
):
38 WorksheetContextBase( rFragment
),
44 ContextHandlerRef
ExtCfRuleContext::onCreateContext( sal_Int32
, const AttributeList
& )
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
);
59 case XLS14_TOKEN( fillColor
):
61 ExtCfDataBarRuleRef xRule
= getCondFormats().createExtCfDataBarRule(mpTarget
);
62 xRule
->importPositiveFillColor( rAttribs
);
65 case XLS14_TOKEN( negativeFillColor
):
67 ExtCfDataBarRuleRef xRule
= getCondFormats().createExtCfDataBarRule(mpTarget
);
68 xRule
->importNegativeFillColor( rAttribs
);
71 case XLS14_TOKEN( axisColor
):
73 ExtCfDataBarRuleRef xRule
= getCondFormats().createExtCfDataBarRule(mpTarget
);
74 xRule
->importAxisColor( rAttribs
);
77 case XLS14_TOKEN( cfvo
):
79 ExtCfDataBarRuleRef xRule
= getCondFormats().createExtCfDataBarRule(mpTarget
);
80 xRule
->importCfvo( rAttribs
);
81 xRule
->getModel().mbIsLower
= mbFirstEntry
;
83 mpRule
= std::move(xRule
);
91 void ExtCfRuleContext::onCharacters( const OUString
& rChars
)
93 switch( getCurrentElement() )
99 mpRule
->getModel().msScaleTypeValue
= rChars
;
106 void ExtCfRuleContext::onEndElement()
108 switch( getCurrentElement() )
110 case XLS14_TOKEN( cfvo
):
119 bool IsSpecificTextCondMode(ScConditionMode eMode
)
123 case ScConditionMode::BeginsWith
:
124 case ScConditionMode::EndsWith
:
125 case ScConditionMode::ContainsText
:
126 case ScConditionMode::NotContainsText
:
135 ExtConditionalFormattingContext::ExtConditionalFormattingContext(WorksheetContextBase
& rFragment
)
136 : WorksheetContextBase(rFragment
)
139 , eOperator(ScConditionMode::NONE
)
140 , isPreviousElementF(false)
144 ContextHandlerRef
ExtConditionalFormattingContext::onCreateContext(sal_Int32 nElement
, const AttributeList
& rAttribs
)
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
));
179 pInfo
= aExt
->second
;
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
;
202 else if (aType
== "containsText")
204 eOperator
= ScConditionMode::ContainsText
;
205 maModel
.eOperator
= eOperator
;
208 else if (aType
== "notContainsText")
210 eOperator
= ScConditionMode::NotContainsText
;
211 maModel
.eOperator
= eOperator
;
214 else if (aType
== "beginsWith")
216 eOperator
= ScConditionMode::BeginsWith
;
217 maModel
.eOperator
= eOperator
;
220 else if (aType
== "endsWith")
222 eOperator
= ScConditionMode::EndsWith
;
223 maModel
.eOperator
= eOperator
;
226 else if (aType
== "expression")
228 eOperator
= ScConditionMode::Direct
;
229 maModel
.eOperator
= eOperator
;
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
))
251 void ExtConditionalFormattingContext::onStartElement(const AttributeList
& /*Attribs*/)
255 void ExtConditionalFormattingContext::onCharacters(const OUString
& rCharacters
)
257 switch (getCurrentElement())
261 aChars
= rCharacters
;
262 isPreviousElementF
= true;
265 case XM_TOKEN(sqref
):
267 aChars
= rCharacters
;
274 void ExtConditionalFormattingContext::onEndElement()
276 switch (getCurrentElement())
280 if(!IsSpecificTextCondMode(eOperator
) || nFormulaCount
== 2)
281 maModel
.aFormula
= aChars
;
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
);
297 maModels
.push_back(maModel
);
300 case XM_TOKEN(sqref
):
303 ScDocument
& rDoc
= getScDocument();
304 bool bSuccess
= ScRangeStringConverter::GetRangeListFromString(aRange
, aChars
, rDoc
, formula::FormulaGrammar::CONV_XL_OOX
);
305 if (!bSuccess
|| aRange
.empty())
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());
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;
352 ExtLstLocalContext::ExtLstLocalContext( WorksheetContextBase
& rFragment
, ScDataBarFormatData
* pTarget
):
353 WorksheetContextBase(rFragment
),
358 ContextHandlerRef
ExtLstLocalContext::onCreateContext( sal_Int32 nElement
, const AttributeList
& )
360 switch( getCurrentElement() )
362 case XLS_TOKEN( extLst
):
363 if(nElement
== XLS_TOKEN( ext
))
367 case XLS_TOKEN( ext
):
368 if (nElement
== XLS14_TOKEN( id
))
376 void ExtLstLocalContext::onStartElement( const AttributeList
& )
378 switch( getCurrentElement() )
380 case XLS14_TOKEN( id
):
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*/ )
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);
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 );
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();
442 aCalcConfig
.SetStringRefSyntax( formula::FormulaGrammar::CONV_OOO
);
445 aCalcConfig
.SetStringRefSyntax( formula::FormulaGrammar::CONV_XL_A1
);
448 aCalcConfig
.SetStringRefSyntax( formula::FormulaGrammar::CONV_XL_R1C1
);
450 case XML_CalcA1ExcelA1
:
451 aCalcConfig
.SetStringRefSyntax( formula::FormulaGrammar::CONV_A1_XL_A1
);
454 aCalcConfig
.SetStringRefSyntax( formula::FormulaGrammar::CONV_UNSPECIFIED
);
457 rDoc
.SetCalcConfig(aCalcConfig
);
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 );
480 } //namespace oox::xls
482 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */