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>
26 #include <rangeutl.hxx>
27 #include <sal/log.hxx>
29 using ::oox::core::ContextHandlerRef
;
30 using ::oox::xls::CondFormatBuffer
;
32 sal_Int32 rStyleIdx
= 0;
36 ExtCfRuleContext::ExtCfRuleContext( WorksheetContextBase
& rFragment
, ScDataBarFormatData
* pTarget
):
37 WorksheetContextBase( rFragment
),
43 ContextHandlerRef
ExtCfRuleContext::onCreateContext( sal_Int32
, const AttributeList
& )
48 void ExtCfRuleContext::onStartElement( const AttributeList
& rAttribs
)
50 switch( getCurrentElement() )
52 case XLS14_TOKEN( dataBar
):
54 ExtCfDataBarRuleRef xRule
= getCondFormats().createExtCfDataBarRule(mpTarget
);
55 xRule
->importDataBar( rAttribs
);
58 case XLS14_TOKEN( negativeFillColor
):
60 ExtCfDataBarRuleRef xRule
= getCondFormats().createExtCfDataBarRule(mpTarget
);
61 xRule
->importNegativeFillColor( rAttribs
);
64 case XLS14_TOKEN( axisColor
):
66 ExtCfDataBarRuleRef xRule
= getCondFormats().createExtCfDataBarRule(mpTarget
);
67 xRule
->importAxisColor( rAttribs
);
70 case XLS14_TOKEN( cfvo
):
72 ExtCfDataBarRuleRef xRule
= getCondFormats().createExtCfDataBarRule(mpTarget
);
73 xRule
->importCfvo( rAttribs
);
74 xRule
->getModel().mbIsLower
= mbFirstEntry
;
84 bool IsSpecificTextCondMode(ScConditionMode eMode
)
88 case ScConditionMode::BeginsWith
:
89 case ScConditionMode::EndsWith
:
90 case ScConditionMode::ContainsText
:
91 case ScConditionMode::NotContainsText
:
100 ExtConditionalFormattingContext::ExtConditionalFormattingContext(WorksheetContextBase
& rFragment
)
101 : WorksheetContextBase(rFragment
)
104 , eOperator(ScConditionMode::NONE
)
105 , isPreviousElementF(false)
109 ContextHandlerRef
ExtConditionalFormattingContext::onCreateContext(sal_Int32 nElement
, const AttributeList
& rAttribs
)
113 ScFormatEntry
& rFormat
= **maEntries
.rbegin();
114 assert(rFormat
.GetType() == ScFormatEntry::Type::Iconset
);
115 ScIconSetFormat
& rIconSet
= static_cast<ScIconSetFormat
&>(rFormat
);
116 ScDocument
& rDoc
= getScDocument();
117 SCTAB nTab
= getSheetIndex();
118 ScAddress
aPos(0, 0, nTab
);
119 mpCurrentRule
->SetData(&rIconSet
, &rDoc
, aPos
);
120 mpCurrentRule
.reset();
122 if (nElement
== XLS14_TOKEN(cfRule
))
124 OUString aType
= rAttribs
.getString(XML_type
, OUString());
125 OUString aId
= rAttribs
.getString(XML_id
, OUString());
126 nPriority
= rAttribs
.getInteger( XML_priority
, -1 );
127 maPriorities
.push_back(nPriority
);
128 maModel
.nPriority
= nPriority
;
130 if (aType
== "dataBar")
132 // an ext entry does not need to have an existing corresponding entry
133 ExtLst::const_iterator aExt
= getExtLst().find( aId
);
134 if(aExt
== getExtLst().end())
137 ScDataBarFormatData
* pInfo
= aExt
->second
;
142 return new ExtCfRuleContext( *this, pInfo
);
144 else if (aType
== "iconSet")
146 ScDocument
& rDoc
= getScDocument();
147 mpCurrentRule
.reset(new IconSetRule(*this));
148 maEntries
.push_back(std::make_unique
<ScIconSetFormat
>(&rDoc
));
149 return new IconSetContext(*this, mpCurrentRule
.get());
151 else if (aType
== "cellIs")
153 sal_Int32 aToken
= rAttribs
.getToken( XML_operator
, XML_TOKEN_INVALID
);
154 eOperator
= CondFormatBuffer::convertToInternalOperator(aToken
);
155 maModel
.eOperator
= eOperator
;
158 else if (aType
== "containsText")
160 eOperator
= ScConditionMode::ContainsText
;
161 maModel
.eOperator
= eOperator
;
164 else if (aType
== "notContainsText")
166 eOperator
= ScConditionMode::NotContainsText
;
167 maModel
.eOperator
= eOperator
;
170 else if (aType
== "beginsWith")
172 eOperator
= ScConditionMode::BeginsWith
;
173 maModel
.eOperator
= eOperator
;
176 else if (aType
== "endsWith")
178 eOperator
= ScConditionMode::EndsWith
;
179 maModel
.eOperator
= eOperator
;
182 else if (aType
== "expression")
184 eOperator
= ScConditionMode::Direct
;
185 maModel
.eOperator
= eOperator
;
190 SAL_WARN("sc", "unhandled XLS14_TOKEN(cfRule) with type: " << aType
);
193 else if (nElement
== XLS14_TOKEN( dxf
))
195 return new DxfContext( *this, getStyles().createExtDxf() );
197 else if (nElement
== XM_TOKEN( sqref
) || nElement
== XM_TOKEN( f
))
199 if(nElement
== XM_TOKEN( f
))
207 void ExtConditionalFormattingContext::onStartElement(const AttributeList
& /*Attribs*/)
211 void ExtConditionalFormattingContext::onCharacters(const OUString
& rCharacters
)
213 switch (getCurrentElement())
217 aChars
= rCharacters
;
218 isPreviousElementF
= true;
221 case XM_TOKEN(sqref
):
223 aChars
= rCharacters
;
230 void ExtConditionalFormattingContext::onEndElement()
232 switch (getCurrentElement())
236 if(!IsSpecificTextCondMode(eOperator
) || nFormulaCount
== 2)
237 maModel
.aFormula
= aChars
;
240 case XLS14_TOKEN( cfRule
):
242 getStyles().getExtDxfs().forEachMem( &Dxf::finalizeImport
);
243 maModel
.aStyle
= getStyles().createExtDxfStyle(rStyleIdx
);
246 maModels
.push_back(maModel
);
249 case XM_TOKEN(sqref
):
252 ScDocument
& rDoc
= getScDocument();
253 bool bSuccess
= ScRangeStringConverter::GetRangeListFromString(aRange
, aChars
, rDoc
, formula::FormulaGrammar::CONV_XL_OOX
);
254 if (!bSuccess
|| aRange
.empty())
257 SCTAB nTab
= getSheetIndex();
258 for (size_t i
= 0; i
< aRange
.size(); ++i
)
260 aRange
[i
].aStart
.SetTab(nTab
);
261 aRange
[i
].aEnd
.SetTab(nTab
);
264 if (maModels
.size() > 1)
266 std::sort(maModels
.begin(), maModels
.end(),
267 [](const ExtCondFormatRuleModel
& lhs
, const ExtCondFormatRuleModel
& rhs
) {
268 return lhs
.nPriority
< rhs
.nPriority
;
272 if (isPreviousElementF
) // sqref can be alone in some cases.
274 for (size_t i
= 0; i
< maModels
.size(); ++i
)
276 ScAddress rPos
= aRange
.GetTopLeftCorner();
277 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(maModels
[i
].eOperator
, maModels
[i
].aFormula
, "", rDoc
,
278 rPos
, maModels
[i
].aStyle
, "", "",
279 formula::FormulaGrammar::GRAM_OOXML
,
280 formula::FormulaGrammar::GRAM_OOXML
,
281 ScFormatEntry::Type::ExtCondition
);
282 maEntries
.push_back(std::unique_ptr
<ScFormatEntry
>(pEntry
));
285 assert(maModels
.size() == maPriorities
.size());
289 std::vector
< std::unique_ptr
<ExtCfCondFormat
> >& rExtFormats
= getCondFormats().importExtCondFormat();
290 rExtFormats
.push_back(std::make_unique
<ExtCfCondFormat
>(aRange
, maEntries
, &maPriorities
));
292 maPriorities
.clear();
293 isPreviousElementF
= false;
301 ExtLstLocalContext::ExtLstLocalContext( WorksheetContextBase
& rFragment
, ScDataBarFormatData
* pTarget
):
302 WorksheetContextBase(rFragment
),
307 ContextHandlerRef
ExtLstLocalContext::onCreateContext( sal_Int32 nElement
, const AttributeList
& )
309 switch( getCurrentElement() )
311 case XLS_TOKEN( extLst
):
312 if(nElement
== XLS_TOKEN( ext
))
317 case XLS_TOKEN( ext
):
318 if (nElement
== XLS14_TOKEN( id
))
326 void ExtLstLocalContext::onStartElement( const AttributeList
& )
328 switch( getCurrentElement() )
330 case XLS14_TOKEN( id
):
335 void ExtLstLocalContext::onCharacters( const OUString
& rChars
)
337 if (getCurrentElement() == XLS14_TOKEN( id
))
339 getExtLst().insert( std::pair
< OUString
, ScDataBarFormatData
*>(rChars
, mpTarget
) );
343 ExtGlobalContext::ExtGlobalContext( WorksheetContextBase
& rFragment
):
344 WorksheetContextBase(rFragment
)
348 ContextHandlerRef
ExtGlobalContext::onCreateContext( sal_Int32 nElement
, const AttributeList
& /*rAttribs*/ )
352 case XLS14_TOKEN(conditionalFormatting
): return new ExtConditionalFormattingContext(*this);
353 case XLS14_TOKEN(dataValidations
): return new ExtDataValidationsContext(*this);
358 void ExtGlobalContext::onStartElement( const AttributeList
& /*rAttribs*/ )
362 ExtLstGlobalContext::ExtLstGlobalContext( WorksheetFragment
& rFragment
):
363 WorksheetContextBase(rFragment
)
367 ContextHandlerRef
ExtLstGlobalContext::onCreateContext( sal_Int32 nElement
, const AttributeList
& )
369 if (nElement
== XLS_TOKEN( ext
))
370 return new ExtGlobalContext( *this );
375 ExtGlobalWorkbookContext::ExtGlobalWorkbookContext( WorkbookContextBase
& rFragment
):
376 WorkbookContextBase(rFragment
)
380 ContextHandlerRef
ExtGlobalWorkbookContext::onCreateContext( sal_Int32 nElement
, const AttributeList
& rAttribs
)
382 if (nElement
== LOEXT_TOKEN(extCalcPr
))
384 ScDocument
& rDoc
= getScDocument();
385 sal_Int32 nToken
= rAttribs
.getToken( XML_stringRefSyntax
, XML_CalcA1
);
386 ScCalcConfig aCalcConfig
= rDoc
.GetCalcConfig();
391 aCalcConfig
.SetStringRefSyntax( formula::FormulaGrammar::CONV_OOO
);
394 aCalcConfig
.SetStringRefSyntax( formula::FormulaGrammar::CONV_XL_A1
);
397 aCalcConfig
.SetStringRefSyntax( formula::FormulaGrammar::CONV_XL_R1C1
);
399 case XML_CalcA1ExcelA1
:
400 aCalcConfig
.SetStringRefSyntax( formula::FormulaGrammar::CONV_A1_XL_A1
);
403 aCalcConfig
.SetStringRefSyntax( formula::FormulaGrammar::CONV_UNSPECIFIED
);
406 rDoc
.SetCalcConfig(aCalcConfig
);
412 void ExtGlobalWorkbookContext::onStartElement( const AttributeList
& /*rAttribs*/ )
416 ExtLstGlobalWorkbookContext::ExtLstGlobalWorkbookContext( WorkbookFragment
& rFragment
):
417 WorkbookContextBase(rFragment
)
421 ContextHandlerRef
ExtLstGlobalWorkbookContext::onCreateContext( sal_Int32 nElement
, const AttributeList
& )
423 if (nElement
== XLS_TOKEN( ext
))
424 return new ExtGlobalWorkbookContext( *this );
429 } //namespace oox::xls
431 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */