use insert function instead of for loop
[LibreOffice.git] / sc / source / filter / excel / xeextlst.cxx
blob8d36f639b1f30481c272772cbcc0009b86b68b0c
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 <sal/config.h>
12 #include <string_view>
14 #include <utility>
15 #include <xeextlst.hxx>
16 #include <xeroot.hxx>
17 #include <xestyle.hxx>
18 #include <stlpool.hxx>
19 #include <scitems.hxx>
20 #include <svl/itemset.hxx>
21 #include <svl/intitem.hxx>
23 #include <oox/export/utils.hxx>
24 #include <oox/token/namespaces.hxx>
26 using namespace ::oox;
28 XclExpExt::XclExpExt( const XclExpRoot& rRoot ):
29 XclExpRoot(rRoot)
33 XclExtLst::XclExtLst( const XclExpRoot& rRoot ):
34 XclExpRoot(rRoot)
38 XclExpExtNegativeColor::XclExpExtNegativeColor( const Color& rColor ):
39 maColor(rColor)
43 void XclExpExtNegativeColor::SaveXml( XclExpXmlStream& rStrm )
45 rStrm.GetCurrentStream()->singleElementNS( XML_x14, XML_negativeFillColor,
46 XML_rgb, XclXmlUtils::ToOString(maColor) );
49 XclExpExtAxisColor::XclExpExtAxisColor( const Color& rColor ):
50 maAxisColor(rColor)
54 void XclExpExtAxisColor::SaveXml( XclExpXmlStream& rStrm )
56 rStrm.GetCurrentStream()->singleElementNS( XML_x14, XML_axisColor,
57 XML_rgb, XclXmlUtils::ToOString(maAxisColor) );
60 XclExpExtIcon::XclExpExtIcon(const XclExpRoot& rRoot, const std::pair<ScIconSetType, sal_Int32>& rCustomEntry):
61 XclExpRoot(rRoot),
62 nIndex(rCustomEntry.second)
64 maIconSetName = ScIconSetFormat::getIconSetName(rCustomEntry.first);
67 void XclExpExtIcon::SaveXml(XclExpXmlStream& rStrm)
69 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
71 if (nIndex == -1)
73 nIndex = 0;
74 maIconSetName = u"NoIcons"_ustr;
77 rWorksheet->singleElementNS(XML_x14, XML_cfIcon,
78 XML_iconSet, maIconSetName,
79 XML_iconId, OString::number(nIndex));
82 XclExpExtCfvo::XclExpExtCfvo( const XclExpRoot& rRoot, const ScColorScaleEntry& rEntry, const ScAddress& rSrcPos, bool bFirst ):
83 XclExpRoot(rRoot),
84 meType(rEntry.GetType()),
85 mbFirst(bFirst)
87 if( rEntry.GetType() == COLORSCALE_FORMULA )
89 const ScTokenArray* pArr = rEntry.GetFormula();
90 OUString aFormula;
91 if(pArr)
93 aFormula = XclXmlUtils::ToOUString( GetCompileFormulaContext(), rSrcPos, pArr);
95 maValue = OUStringToOString(aFormula, RTL_TEXTENCODING_UTF8 );
97 else
98 maValue = OString::number(rEntry.GetValue());
101 namespace {
103 const char* getColorScaleType( ScColorScaleEntryType eType, bool bFirst )
105 switch(eType)
107 case COLORSCALE_MIN:
108 return "min";
109 case COLORSCALE_MAX:
110 return "max";
111 case COLORSCALE_PERCENT:
112 return "percent";
113 case COLORSCALE_FORMULA:
114 return "formula";
115 case COLORSCALE_AUTO:
116 if(bFirst)
117 return "autoMin";
118 else
119 return "autoMax";
120 case COLORSCALE_PERCENTILE:
121 return "percentile";
122 default:
123 break;
125 return "num";
130 void XclExpExtCfvo::SaveXml( XclExpXmlStream& rStrm )
132 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
133 rWorksheet->startElementNS(XML_x14, XML_cfvo, XML_type, getColorScaleType(meType, mbFirst));
135 if (meType == COLORSCALE_FORMULA ||
136 meType == COLORSCALE_PERCENT ||
137 meType == COLORSCALE_PERCENTILE ||
138 meType == COLORSCALE_VALUE)
140 rWorksheet->startElementNS(XML_xm, XML_f);
141 rWorksheet->writeEscaped(maValue.getStr());
142 rWorksheet->endElementNS(XML_xm, XML_f);
145 rWorksheet->endElementNS(XML_x14, XML_cfvo);
148 XclExpExtCF::XclExpExtCF( const XclExpRoot& rRoot, const ScCondFormatEntry& rFormat ):
149 XclExpRoot(rRoot),
150 mrFormat(rFormat)
154 namespace {
156 bool RequiresFixedFormula(ScConditionMode eMode)
158 switch (eMode)
160 case ScConditionMode::BeginsWith:
161 case ScConditionMode::EndsWith:
162 case ScConditionMode::ContainsText:
163 case ScConditionMode::NotContainsText:
164 return true;
165 default:
166 break;
169 return false;
172 OString GetFixedFormula(ScConditionMode eMode, const ScAddress& rAddress, std::string_view rText)
174 OStringBuffer aBuffer;
175 XclXmlUtils::ToOString(aBuffer, rAddress);
176 OString aPos = aBuffer.makeStringAndClear();
177 switch (eMode)
179 case ScConditionMode::BeginsWith:
180 return OString("LEFT(" + aPos + ",LEN(" + rText + "))=" + rText);
181 case ScConditionMode::EndsWith:
182 return OString("RIGHT(" + aPos + ",LEN(" + rText + "))=" + rText);
183 case ScConditionMode::ContainsText:
184 return OString(OString::Concat("NOT(ISERROR(SEARCH(") + rText + "," + aPos + ")))");
185 case ScConditionMode::NotContainsText:
186 return OString(OString::Concat("ISERROR(SEARCH(") + rText + "," + aPos + "))");
187 default:
188 break;
191 return ""_ostr;
196 void XclExpExtCF::SaveXml( XclExpXmlStream& rStrm )
198 OUString aStyleName = mrFormat.GetStyle();
199 SfxStyleSheetBasePool* pPool = GetDoc().GetStyleSheetPool();
200 SfxStyleSheetBase* pStyle = pPool->Find(aStyleName, SfxStyleFamily::Para);
201 SfxItemSet& rSet = pStyle->GetItemSet();
203 std::unique_ptr<ScTokenArray> pTokenArray(mrFormat.CreateFlatCopiedTokenArray(0));
204 aFormula = XclXmlUtils::ToOUString( GetCompileFormulaContext(), mrFormat.GetValidSrcPos(), pTokenArray.get());
206 std::unique_ptr<XclExpColor> pColor(new XclExpColor);
207 if(!pColor->FillFromItemSet( rSet ))
208 pColor.reset();
210 std::unique_ptr<XclExpCellBorder> pBorder(new XclExpCellBorder);
211 if (!pBorder->FillFromItemSet( rSet, GetPalette(), GetBiff()) )
212 pBorder.reset();
214 std::unique_ptr<XclExpCellAlign> pAlign(new XclExpCellAlign);
215 if (!pAlign->FillFromItemSet(*this, rSet, false, GetBiff()))
216 pAlign.reset();
218 std::unique_ptr<XclExpCellProt> pCellProt(new XclExpCellProt);
219 if (!pCellProt->FillFromItemSet( rSet ))
220 pCellProt.reset();
222 std::unique_ptr<XclExpDxfFont> pFont(new XclExpDxfFont(GetRoot(), rSet));
224 std::unique_ptr<XclExpNumFmt> pNumFormat;
225 if( const SfxUInt32Item* pPoolItem = rSet.GetItemIfSet( ATTR_VALUE_FORMAT ) )
227 sal_uInt32 nScNumFmt = pPoolItem->GetValue();
228 XclExpNumFmtBuffer& rNumFmtBuffer = GetRoot().GetNumFmtBuffer();
229 sal_uInt32 nXclNumFmt = rNumFmtBuffer.Insert(nScNumFmt);
230 pNumFormat.reset(new XclExpNumFmt(nScNumFmt, nXclNumFmt, rNumFmtBuffer.GetFormatCode(nScNumFmt)));
233 XclExpDxf rDxf( GetRoot(),
234 std::move(pAlign),
235 std::move(pBorder),
236 std::move(pFont),
237 std::move(pNumFormat),
238 std::move(pCellProt),
239 std::move(pColor) );
241 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
243 ScConditionMode eOperation = mrFormat.GetOperation();
244 if (RequiresFixedFormula(eOperation))
246 ScAddress aFixedFormulaPos = mrFormat.GetValidSrcPos();
247 OString aFixedFormulaText = aFormula.toUtf8();
248 OString aFixedFormula = GetFixedFormula(eOperation, aFixedFormulaPos, aFixedFormulaText);
249 rWorksheet->startElementNS( XML_xm, XML_f );
250 rWorksheet->writeEscaped(aFixedFormula.getStr());
251 rWorksheet->endElementNS( XML_xm, XML_f );
253 rWorksheet->startElementNS( XML_xm, XML_f );
254 rWorksheet->writeEscaped( aFormula );
255 rWorksheet->endElementNS( XML_xm, XML_f );
256 rDxf.SaveXmlExt(rStrm);
258 else
260 rWorksheet->startElementNS(XML_xm, XML_f);
261 rWorksheet->writeEscaped(aFormula);
262 rWorksheet->endElementNS(XML_xm, XML_f);
263 rDxf.SaveXmlExt(rStrm);
267 XclExpExtDataBar::XclExpExtDataBar( const XclExpRoot& rRoot, const ScDataBarFormat& rFormat, const ScAddress& rPos ):
268 XclExpRoot(rRoot)
270 const ScDataBarFormatData& rFormatData = *rFormat.GetDataBarData();
271 mpLowerLimit.reset(new XclExpExtCfvo(*this, *rFormatData.mpLowerLimit, rPos, true));
272 mpUpperLimit.reset(new XclExpExtCfvo(*this, *rFormatData.mpUpperLimit, rPos, false));
273 if (rFormatData.mxNegativeColor)
274 mpNegativeColor.reset(new XclExpExtNegativeColor(*rFormatData.mxNegativeColor));
275 else
276 mpNegativeColor.reset( new XclExpExtNegativeColor( rFormatData.maPositiveColor ) );
277 mpAxisColor.reset( new XclExpExtAxisColor( rFormatData.maAxisColor ) );
279 meAxisPosition = rFormatData.meAxisPosition;
280 mbGradient = rFormatData.mbGradient;
281 mnMinLength = rFormatData.mnMinLength;
282 mnMaxLength = rFormatData.mnMaxLength;
285 namespace {
287 const char* getAxisPosition(databar::ScAxisPosition eAxisPosition)
289 switch(eAxisPosition)
291 case databar::NONE:
292 return "none";
293 case databar::AUTOMATIC:
294 return "automatic";
295 case databar::MIDDLE:
296 return "middle";
298 return "";
301 const char* GetOperatorString(ScConditionMode eMode)
303 const char* pRet = nullptr;
304 switch(eMode)
306 case ScConditionMode::Equal:
307 pRet = "equal";
308 break;
309 case ScConditionMode::Less:
310 pRet = "lessThan";
311 break;
312 case ScConditionMode::Greater:
313 pRet = "greaterThan";
314 break;
315 case ScConditionMode::EqLess:
316 pRet = "lessThanOrEqual";
317 break;
318 case ScConditionMode::EqGreater:
319 pRet = "greaterThanOrEqual";
320 break;
321 case ScConditionMode::NotEqual:
322 pRet = "notEqual";
323 break;
324 case ScConditionMode::Between:
325 pRet = "between";
326 break;
327 case ScConditionMode::NotBetween:
328 pRet = "notBetween";
329 break;
330 case ScConditionMode::Duplicate:
331 case ScConditionMode::NotDuplicate:
332 pRet = nullptr;
333 break;
334 case ScConditionMode::BeginsWith:
335 pRet = "beginsWith";
336 break;
337 case ScConditionMode::EndsWith:
338 pRet = "endsWith";
339 break;
340 case ScConditionMode::ContainsText:
341 pRet = "containsText";
342 break;
343 case ScConditionMode::NotContainsText:
344 pRet = "notContains";
345 break;
346 case ScConditionMode::Direct:
347 break;
348 case ScConditionMode::NONE:
349 default:
350 break;
352 return pRet;
355 const char* GetTypeString(ScConditionMode eMode)
357 switch(eMode)
359 case ScConditionMode::Direct:
360 return "expression";
361 case ScConditionMode::BeginsWith:
362 return "beginsWith";
363 case ScConditionMode::EndsWith:
364 return "endsWith";
365 case ScConditionMode::ContainsText:
366 return "containsText";
367 case ScConditionMode::NotContainsText:
368 return "notContainsText";
369 default:
370 return "cellIs";
376 void XclExpExtDataBar::SaveXml( XclExpXmlStream& rStrm )
378 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
379 rWorksheet->startElementNS( XML_x14, XML_dataBar,
380 XML_minLength, OString::number(mnMinLength),
381 XML_maxLength, OString::number(mnMaxLength),
382 XML_axisPosition, getAxisPosition(meAxisPosition),
383 XML_gradient, ToPsz(mbGradient) );
385 mpLowerLimit->SaveXml( rStrm );
386 mpUpperLimit->SaveXml( rStrm );
387 mpNegativeColor->SaveXml( rStrm );
388 mpAxisColor->SaveXml( rStrm );
390 rWorksheet->endElementNS( XML_x14, XML_dataBar );
393 XclExpExtIconSet::XclExpExtIconSet(const XclExpRoot& rRoot, const ScIconSetFormat& rFormat, const ScAddress& rPos):
394 XclExpRoot(rRoot)
396 const ScIconSetFormatData& rData = *rFormat.GetIconSetData();
397 for (auto const& itr : rData.m_Entries)
399 maCfvos.AppendNewRecord(new XclExpExtCfvo(*this, *itr, rPos, false));
401 mbCustom = rData.mbCustom;
402 mbReverse = rData.mbReverse;
403 mbShowValue = rData.mbShowValue;
404 maIconSetName = ScIconSetFormat::getIconSetName(rData.eIconSetType);
406 if (mbCustom)
408 for (const auto& rItem : rData.maCustomVector)
410 maCustom.AppendNewRecord(new XclExpExtIcon(*this, rItem));
415 void XclExpExtIconSet::SaveXml(XclExpXmlStream& rStrm)
417 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
419 rWorksheet->startElementNS(XML_x14, XML_iconSet,
420 XML_iconSet, maIconSetName,
421 XML_custom, sax_fastparser::UseIf(ToPsz10(mbCustom), mbCustom),
422 XML_reverse, ToPsz10(mbReverse),
423 XML_showValue, ToPsz10(mbShowValue));
425 maCfvos.SaveXml(rStrm);
427 if (mbCustom)
429 maCustom.SaveXml(rStrm);
432 rWorksheet->endElementNS(XML_x14, XML_iconSet);
435 XclExpExtCfRule::XclExpExtCfRule( const XclExpRoot& rRoot, const ScFormatEntry& rFormat, const ScAddress& rPos, OString aId, sal_Int32 nPriority ):
436 XclExpRoot(rRoot),
437 maId(std::move(aId)),
438 pType(nullptr),
439 mnPriority(nPriority),
440 mOperator(nullptr)
442 switch (rFormat.GetType())
444 case ScFormatEntry::Type::Databar:
446 const ScDataBarFormat& rDataBar = static_cast<const ScDataBarFormat&>(rFormat);
447 mxEntry = new XclExpExtDataBar( *this, rDataBar, rPos );
448 pType = "dataBar";
450 break;
451 case ScFormatEntry::Type::Iconset:
453 const ScIconSetFormat& rIconSet = static_cast<const ScIconSetFormat&>(rFormat);
454 mxEntry = new XclExpExtIconSet(*this, rIconSet, rPos);
455 pType = "iconSet";
457 break;
458 case ScFormatEntry::Type::ExtCondition:
460 const ScCondFormatEntry& rCondFormat = static_cast<const ScCondFormatEntry&>(rFormat);
461 mxEntry = new XclExpExtCF(*this, rCondFormat);
462 pType = GetTypeString(rCondFormat.GetOperation());
463 mOperator = GetOperatorString( rCondFormat.GetOperation() );
465 break;
466 default:
467 break;
471 void XclExpExtCfRule::SaveXml( XclExpXmlStream& rStrm )
473 if (!mxEntry)
474 return;
476 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
477 rWorksheet->startElementNS( XML_x14, XML_cfRule,
478 XML_type, pType,
479 XML_priority, sax_fastparser::UseIf(OString::number(mnPriority + 1), mnPriority != -1),
480 XML_operator, mOperator,
481 XML_id, maId );
483 mxEntry->SaveXml( rStrm );
485 rWorksheet->endElementNS( XML_x14, XML_cfRule );
489 XclExpExtConditionalFormatting::XclExpExtConditionalFormatting( const XclExpRoot& rRoot,
490 std::vector<XclExpExtCondFormatData>& rData, ScRangeList aRange):
491 XclExpRoot(rRoot),
492 maRange(std::move(aRange))
494 ScAddress aAddr = maRange.front().aStart;
495 for (const auto& rItem : rData)
497 const ScFormatEntry* pEntry = rItem.pEntry;
498 switch (pEntry->GetType())
500 case ScFormatEntry::Type::Iconset:
502 const ScIconSetFormat& rIconSet = static_cast<const ScIconSetFormat&>(*pEntry);
503 bool bNeedsExt = false;
504 switch (rIconSet.GetIconSetData()->eIconSetType)
506 case IconSet_3Triangles:
507 case IconSet_3Smilies:
508 case IconSet_3ColorSmilies:
509 case IconSet_5Boxes:
510 case IconSet_3Stars:
511 bNeedsExt = true;
512 break;
513 default:
514 break;
517 if (rIconSet.GetIconSetData()->mbCustom)
518 bNeedsExt = true;
520 if (bNeedsExt)
522 maCfRules.AppendNewRecord(new XclExpExtCfRule(*this, *pEntry, aAddr, rItem.aGUID, rItem.nPriority));
525 break;
526 case ScFormatEntry::Type::Databar:
527 case ScFormatEntry::Type::ExtCondition:
528 maCfRules.AppendNewRecord(new XclExpExtCfRule( *this, *pEntry, aAddr, rItem.aGUID, rItem.nPriority));
529 break;
530 default:
531 break;
536 void XclExpExtConditionalFormatting::SaveXml( XclExpXmlStream& rStrm )
538 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
539 rWorksheet->startElementNS( XML_x14, XML_conditionalFormatting,
540 FSNS( XML_xmlns, XML_xm ), rStrm.getNamespaceURL(OOX_NS(xm)) );
542 maCfRules.SaveXml( rStrm );
543 rWorksheet->startElementNS(XML_xm, XML_sqref);
544 rWorksheet->write(XclXmlUtils::ToOString(rStrm.GetRoot().GetDoc(), maRange));
546 rWorksheet->endElementNS( XML_xm, XML_sqref );
548 rWorksheet->endElementNS( XML_x14, XML_conditionalFormatting );
551 XclExpExtCalcPr::XclExpExtCalcPr( const XclExpRoot& rRoot, formula::FormulaGrammar::AddressConvention eConv ):
552 XclExpExt( rRoot )
554 maURI = "{7626C862-2A13-11E5-B345-FEFF819CDC9F}"_ostr;
556 switch (eConv)
558 case formula::FormulaGrammar::CONV_OOO:
559 maSyntax = "CalcA1"_ostr;
560 break;
561 case formula::FormulaGrammar::CONV_XL_A1:
562 maSyntax = "ExcelA1"_ostr;
563 break;
564 case formula::FormulaGrammar::CONV_XL_R1C1:
565 maSyntax = "ExcelR1C1"_ostr;
566 break;
567 case formula::FormulaGrammar::CONV_A1_XL_A1:
568 maSyntax = "CalcA1ExcelA1"_ostr;
569 break;
570 case formula::FormulaGrammar::CONV_UNSPECIFIED:
571 case formula::FormulaGrammar::CONV_ODF:
572 case formula::FormulaGrammar::CONV_XL_OOX:
573 case formula::FormulaGrammar::CONV_LOTUS_A1:
574 case formula::FormulaGrammar::CONV_LAST:
575 maSyntax = "Unspecified"_ostr;
576 break;
580 void XclExpExtCalcPr::SaveXml( XclExpXmlStream& rStrm )
582 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
583 rWorksheet->startElement( XML_ext,
584 FSNS(XML_xmlns, XML_loext), rStrm.getNamespaceURL(OOX_NS(loext)),
585 XML_uri, maURI );
587 rWorksheet->singleElementNS(XML_loext, XML_extCalcPr, XML_stringRefSyntax, maSyntax);
589 rWorksheet->endElement( XML_ext );
592 XclExpExtCondFormat::XclExpExtCondFormat( const XclExpRoot& rRoot ):
593 XclExpExt( rRoot )
595 maURI = "{78C0D931-6437-407d-A8EE-F0AAD7539E65}"_ostr;
598 void XclExpExtCondFormat::SaveXml( XclExpXmlStream& rStrm )
600 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
601 rWorksheet->startElement( XML_ext,
602 FSNS(XML_xmlns, XML_x14), rStrm.getNamespaceURL(OOX_NS(xls14Lst)),
603 XML_uri, maURI );
605 rWorksheet->startElementNS(XML_x14, XML_conditionalFormattings);
607 maCF.SaveXml( rStrm );
609 rWorksheet->endElementNS( XML_x14, XML_conditionalFormattings );
610 rWorksheet->endElement( XML_ext );
613 void XclExpExtCondFormat::AddRecord( XclExpExtConditionalFormatting* pEntry )
615 maCF.AppendRecord( pEntry );
618 void XclExtLst::SaveXml( XclExpXmlStream& rStrm )
620 if(maExtEntries.IsEmpty())
621 return;
623 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
624 rWorksheet->startElement(XML_extLst);
626 maExtEntries.SaveXml(rStrm);
628 rWorksheet->endElement( XML_extLst );
631 void XclExtLst::AddRecord( XclExpExt* pEntry )
633 maExtEntries.AppendRecord( pEntry );
636 XclExpExt* XclExtLst::GetItem( XclExpExtType eType )
638 size_t n = maExtEntries.GetSize();
639 for( size_t i = 0; i < n; ++i )
641 if (maExtEntries.GetRecord( i )->GetType() == eType)
642 return maExtEntries.GetRecord( i );
645 return nullptr;
649 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */