/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <sal/config.h>
#include <string_view>
#include <utility>
#include <xeextlst.hxx>
#include <xeroot.hxx>
#include <xestyle.hxx>
#include <stlpool.hxx>
#include <scitems.hxx>
#include <svl/itemset.hxx>
#include <svl/intitem.hxx>
#include <oox/export/utils.hxx>
#include <oox/token/namespaces.hxx>
using namespace ::oox;
XclExpExt::XclExpExt( const XclExpRoot& rRoot ):
XclExpRoot(rRoot)
{
}
XclExtLst::XclExtLst( const XclExpRoot& rRoot ):
XclExpRoot(rRoot)
{
}
XclExpExtNegativeColor::XclExpExtNegativeColor( const Color& rColor ):
maColor(rColor)
{
}
void XclExpExtNegativeColor::SaveXml( XclExpXmlStream& rStrm )
{
rStrm.GetCurrentStream()->singleElementNS( XML_x14, XML_negativeFillColor,
XML_rgb, XclXmlUtils::ToOString(maColor) );
}
XclExpExtAxisColor::XclExpExtAxisColor( const Color& rColor ):
maAxisColor(rColor)
{
}
void XclExpExtAxisColor::SaveXml( XclExpXmlStream& rStrm )
{
rStrm.GetCurrentStream()->singleElementNS( XML_x14, XML_axisColor,
XML_rgb, XclXmlUtils::ToOString(maAxisColor) );
}
XclExpExtIcon::XclExpExtIcon(const XclExpRoot& rRoot, const std::pair<ScIconSetType, sal_Int32>& rCustomEntry):
XclExpRoot(rRoot),
nIndex(rCustomEntry.second)
{
maIconSetName = ScIconSetFormat::getIconSetName(rCustomEntry.first);
}
void XclExpExtIcon::SaveXml(XclExpXmlStream& rStrm)
{
sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
if (nIndex == -1)
{
nIndex = 0;
maIconSetName = u"NoIcons"_ustr;
}
rWorksheet->singleElementNS(XML_x14, XML_cfIcon,
XML_iconSet, maIconSetName,
XML_iconId, OString::number(nIndex));
}
XclExpExtCfvo::XclExpExtCfvo( const XclExpRoot& rRoot, const ScColorScaleEntry& rEntry, const ScAddress& rSrcPos, bool bFirst ):
XclExpRoot(rRoot),
meType(rEntry.GetType()),
mbFirst(bFirst)
{
if( rEntry.GetType() == COLORSCALE_FORMULA )
{
const ScTokenArray* pArr = rEntry.GetFormula();
OUString aFormula;
if(pArr)
{
aFormula = XclXmlUtils::ToOUString( GetCompileFormulaContext(), rSrcPos, pArr);
}
maValue = OUStringToOString(aFormula, RTL_TEXTENCODING_UTF8 );
}
else
maValue = OString::number(rEntry.GetValue());
}
namespace {
const char* getColorScaleType( ScColorScaleEntryType eType, bool bFirst )
{
switch(eType)
{
case COLORSCALE_MIN:
return "min";
case COLORSCALE_MAX:
return "max";
case COLORSCALE_PERCENT:
return "percent";
case COLORSCALE_FORMULA:
return "formula";
case COLORSCALE_AUTO:
if(bFirst)
return "autoMin";
else
return "autoMax";
case COLORSCALE_PERCENTILE:
return "percentile";
default:
break;
}
return "num";
}
}
void XclExpExtCfvo::SaveXml( XclExpXmlStream& rStrm )
{
sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
rWorksheet->startElementNS(XML_x14, XML_cfvo, XML_type, getColorScaleType(meType, mbFirst));
if (meType == COLORSCALE_FORMULA ||
meType == COLORSCALE_PERCENT ||
meType == COLORSCALE_PERCENTILE ||
meType == COLORSCALE_VALUE)
{
rWorksheet->startElementNS(XML_xm, XML_f);
rWorksheet->writeEscaped(maValue.getStr());
rWorksheet->endElementNS(XML_xm, XML_f);
}
rWorksheet->endElementNS(XML_x14, XML_cfvo);
}
XclExpExtCF::XclExpExtCF( const XclExpRoot& rRoot, const ScCondFormatEntry& rFormat ):
XclExpRoot(rRoot),
mrFormat(rFormat)
{
}
namespace {
bool RequiresFixedFormula(ScConditionMode eMode)
{
switch (eMode)
{
case ScConditionMode::BeginsWith:
case ScConditionMode::EndsWith:
case ScConditionMode::ContainsText:
case ScConditionMode::NotContainsText:
return true;
default:
break;
}
return false;
}
OString GetFixedFormula(ScConditionMode eMode, const ScAddress& rAddress, std::string_view rText)
{
OStringBuffer aBuffer;
XclXmlUtils::ToOString(aBuffer, rAddress);
OString aPos = aBuffer.makeStringAndClear();
switch (eMode)
{
case ScConditionMode::BeginsWith:
return OString("LEFT(" + aPos + ",LEN(" + rText + "))=" + rText);
case ScConditionMode::EndsWith:
return OString("RIGHT(" + aPos + ",LEN(" + rText + "))=" + rText);
case ScConditionMode::ContainsText:
return OString(OString::Concat("NOT(ISERROR(SEARCH(") + rText + "," + aPos + ")))");
case ScConditionMode::NotContainsText:
return OString(OString::Concat("ISERROR(SEARCH(") + rText + "," + aPos + "))");
default:
break;
}
return ""_ostr;
}
}
void XclExpExtCF::SaveXml( XclExpXmlStream& rStrm )
{
OUString aStyleName = mrFormat.GetStyle();
SfxStyleSheetBasePool* pPool = GetDoc().GetStyleSheetPool();
SfxStyleSheetBase* pStyle = pPool->Find(aStyleName, SfxStyleFamily::Para);
SfxItemSet& rSet = pStyle->GetItemSet();
std::unique_ptr<ScTokenArray> pTokenArray(mrFormat.CreateFlatCopiedTokenArray(0));
aFormula = XclXmlUtils::ToOUString( GetCompileFormulaContext(), mrFormat.GetValidSrcPos(), pTokenArray.get());
std::unique_ptr<XclExpColor> pColor(new XclExpColor);
if(!pColor->FillFromItemSet( rSet ))
pColor.reset();
std::unique_ptr<XclExpCellBorder> pBorder(new XclExpCellBorder);
if (!pBorder->FillFromItemSet( rSet, GetPalette(), GetBiff()) )
pBorder.reset();
std::unique_ptr<XclExpCellAlign> pAlign(new XclExpCellAlign);
if (!pAlign->FillFromItemSet(*this, rSet, false, GetBiff()))
pAlign.reset();
std::unique_ptr<XclExpCellProt> pCellProt(new XclExpCellProt);
if (!pCellProt->FillFromItemSet( rSet ))
pCellProt.reset();
std::unique_ptr<XclExpDxfFont> pFont(new XclExpDxfFont(GetRoot(), rSet));
std::unique_ptr<XclExpNumFmt> pNumFormat;
if( const SfxUInt32Item* pPoolItem = rSet.GetItemIfSet( ATTR_VALUE_FORMAT ) )
{
sal_uInt32 nScNumFmt = pPoolItem->GetValue();
XclExpNumFmtBuffer& rNumFmtBuffer = GetRoot().GetNumFmtBuffer();
sal_uInt32 nXclNumFmt = rNumFmtBuffer.Insert(nScNumFmt);
pNumFormat.reset(new XclExpNumFmt(nScNumFmt, nXclNumFmt, rNumFmtBuffer.GetFormatCode(nScNumFmt)));
}
XclExpDxf rDxf( GetRoot(),
std::move(pAlign),
std::move(pBorder),
std::move(pFont),
std::move(pNumFormat),
std::move(pCellProt),
std::move(pColor) );
sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
ScConditionMode eOperation = mrFormat.GetOperation();
if (RequiresFixedFormula(eOperation))
{
ScAddress aFixedFormulaPos = mrFormat.GetValidSrcPos();
OString aFixedFormulaText = aFormula.toUtf8();
OString aFixedFormula = GetFixedFormula(eOperation, aFixedFormulaPos, aFixedFormulaText);
rWorksheet->startElementNS( XML_xm, XML_f );
rWorksheet->writeEscaped(aFixedFormula.getStr());
rWorksheet->endElementNS( XML_xm, XML_f );
rWorksheet->startElementNS( XML_xm, XML_f );
rWorksheet->writeEscaped( aFormula );
rWorksheet->endElementNS( XML_xm, XML_f );
rDxf.SaveXmlExt(rStrm);
}
else
{
rWorksheet->startElementNS(XML_xm, XML_f);
rWorksheet->writeEscaped(aFormula);
rWorksheet->endElementNS(XML_xm, XML_f);
rDxf.SaveXmlExt(rStrm);
}
}
XclExpExtDataBar::XclExpExtDataBar( const XclExpRoot& rRoot, const ScDataBarFormat& rFormat, const ScAddress& rPos ):
XclExpRoot(rRoot)
{
const ScDataBarFormatData& rFormatData = *rFormat.GetDataBarData();
mpLowerLimit.reset(new XclExpExtCfvo(*this, *rFormatData.mpLowerLimit, rPos, true));
mpUpperLimit.reset(new XclExpExtCfvo(*this, *rFormatData.mpUpperLimit, rPos, false));
if (rFormatData.mxNegativeColor)
mpNegativeColor.reset(new XclExpExtNegativeColor(*rFormatData.mxNegativeColor));
else
mpNegativeColor.reset( new XclExpExtNegativeColor( rFormatData.maPositiveColor ) );
mpAxisColor.reset( new XclExpExtAxisColor( rFormatData.maAxisColor ) );
meAxisPosition = rFormatData.meAxisPosition;
mbGradient = rFormatData.mbGradient;
mnMinLength = rFormatData.mnMinLength;
mnMaxLength = rFormatData.mnMaxLength;
}
namespace {
const char* getAxisPosition(databar::ScAxisPosition eAxisPosition)
{
switch(eAxisPosition)
{
case databar::NONE:
return "none";
case databar::AUTOMATIC:
return "automatic";
case databar::MIDDLE:
return "middle";
}
return "";
}
const char* GetOperatorString(ScConditionMode eMode)
{
const char* pRet = nullptr;
switch(eMode)
{
case ScConditionMode::Equal:
pRet = "equal";
break;
case ScConditionMode::Less:
pRet = "lessThan";
break;
case ScConditionMode::Greater:
pRet = "greaterThan";
break;
case ScConditionMode::EqLess:
pRet = "lessThanOrEqual";
break;
case ScConditionMode::EqGreater:
pRet = "greaterThanOrEqual";
break;
case ScConditionMode::NotEqual:
pRet = "notEqual";
break;
case ScConditionMode::Between:
pRet = "between";
break;
case ScConditionMode::NotBetween:
pRet = "notBetween";
break;
case ScConditionMode::Duplicate:
case ScConditionMode::NotDuplicate:
pRet = nullptr;
break;
case ScConditionMode::BeginsWith:
pRet = "beginsWith";
break;
case ScConditionMode::EndsWith:
pRet = "endsWith";
break;
case ScConditionMode::ContainsText:
pRet = "containsText";
break;
case ScConditionMode::NotContainsText:
pRet = "notContains";
break;
case ScConditionMode::Direct:
break;
case ScConditionMode::NONE:
default:
break;
}
return pRet;
}
const char* GetTypeString(ScConditionMode eMode)
{
switch(eMode)
{
case ScConditionMode::Direct:
return "expression";
case ScConditionMode::BeginsWith:
return "beginsWith";
case ScConditionMode::EndsWith:
return "endsWith";
case ScConditionMode::ContainsText:
return "containsText";
case ScConditionMode::NotContainsText:
return "notContainsText";
default:
return "cellIs";
}
}
}
void XclExpExtDataBar::SaveXml( XclExpXmlStream& rStrm )
{
sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
rWorksheet->startElementNS( XML_x14, XML_dataBar,
XML_minLength, OString::number(mnMinLength),
XML_maxLength, OString::number(mnMaxLength),
XML_axisPosition, getAxisPosition(meAxisPosition),
XML_gradient, ToPsz(mbGradient) );
mpLowerLimit->SaveXml( rStrm );
mpUpperLimit->SaveXml( rStrm );
mpNegativeColor->SaveXml( rStrm );
mpAxisColor->SaveXml( rStrm );
rWorksheet->endElementNS( XML_x14, XML_dataBar );
}
XclExpExtIconSet::XclExpExtIconSet(const XclExpRoot& rRoot, const ScIconSetFormat& rFormat, const ScAddress& rPos):
XclExpRoot(rRoot)
{
const ScIconSetFormatData& rData = *rFormat.GetIconSetData();
for (auto const& itr : rData.m_Entries)
{
maCfvos.AppendNewRecord(new XclExpExtCfvo(*this, *itr, rPos, false));
}
mbCustom = rData.mbCustom;
mbReverse = rData.mbReverse;
mbShowValue = rData.mbShowValue;
maIconSetName = ScIconSetFormat::getIconSetName(rData.eIconSetType);
if (mbCustom)
{
for (const auto& rItem : rData.maCustomVector)
{
maCustom.AppendNewRecord(new XclExpExtIcon(*this, rItem));
}
}
}
void XclExpExtIconSet::SaveXml(XclExpXmlStream& rStrm)
{
sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
rWorksheet->startElementNS(XML_x14, XML_iconSet,
XML_iconSet, maIconSetName,
XML_custom, sax_fastparser::UseIf(ToPsz10(mbCustom), mbCustom),
XML_reverse, ToPsz10(mbReverse),
XML_showValue, ToPsz10(mbShowValue));
maCfvos.SaveXml(rStrm);
if (mbCustom)
{
maCustom.SaveXml(rStrm);
}
rWorksheet->endElementNS(XML_x14, XML_iconSet);
}
XclExpExtCfRule::XclExpExtCfRule( const XclExpRoot& rRoot, const ScFormatEntry& rFormat, const ScAddress& rPos, OString aId, sal_Int32 nPriority ):
XclExpRoot(rRoot),
maId(std::move(aId)),
pType(nullptr),
mnPriority(nPriority),
mOperator(nullptr)
{
switch (rFormat.GetType())
{
case ScFormatEntry::Type::Databar:
{
const ScDataBarFormat& rDataBar = static_cast<const ScDataBarFormat&>(rFormat);
mxEntry = new XclExpExtDataBar( *this, rDataBar, rPos );
pType = "dataBar";
}
break;
case ScFormatEntry::Type::Iconset:
{
const ScIconSetFormat& rIconSet = static_cast<const ScIconSetFormat&>(rFormat);
mxEntry = new XclExpExtIconSet(*this, rIconSet, rPos);
pType = "iconSet";
}
break;
case ScFormatEntry::Type::ExtCondition:
{
const ScCondFormatEntry& rCondFormat = static_cast<const ScCondFormatEntry&>(rFormat);
mxEntry = new XclExpExtCF(*this, rCondFormat);
pType = GetTypeString(rCondFormat.GetOperation());
mOperator = GetOperatorString( rCondFormat.GetOperation() );
}
break;
default:
break;
}
}
void XclExpExtCfRule::SaveXml( XclExpXmlStream& rStrm )
{
if (!mxEntry)
return;
sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
rWorksheet->startElementNS( XML_x14, XML_cfRule,
XML_type, pType,
XML_priority, sax_fastparser::UseIf(OString::number(mnPriority + 1), mnPriority != -1),
XML_operator, mOperator,
XML_id, maId );
mxEntry->SaveXml( rStrm );
rWorksheet->endElementNS( XML_x14, XML_cfRule );
}
XclExpExtConditionalFormatting::XclExpExtConditionalFormatting( const XclExpRoot& rRoot,
std::vector<XclExpExtCondFormatData>& rData, ScRangeList aRange):
XclExpRoot(rRoot),
maRange(std::move(aRange))
{
ScAddress aAddr = maRange.front().aStart;
for (const auto& rItem : rData)
{
const ScFormatEntry* pEntry = rItem.pEntry;
switch (pEntry->GetType())
{
case ScFormatEntry::Type::Iconset:
{
const ScIconSetFormat& rIconSet = static_cast<const ScIconSetFormat&>(*pEntry);
bool bNeedsExt = false;
switch (rIconSet.GetIconSetData()->eIconSetType)
{
case IconSet_3Triangles:
case IconSet_3Smilies:
case IconSet_3ColorSmilies:
case IconSet_5Boxes:
case IconSet_3Stars:
bNeedsExt = true;
break;
default:
break;
}
if (rIconSet.GetIconSetData()->mbCustom)
bNeedsExt = true;
if (bNeedsExt)
{
maCfRules.AppendNewRecord(new XclExpExtCfRule(*this, *pEntry, aAddr, rItem.aGUID, rItem.nPriority));
}
}
break;
case ScFormatEntry::Type::Databar:
case ScFormatEntry::Type::ExtCondition:
maCfRules.AppendNewRecord(new XclExpExtCfRule( *this, *pEntry, aAddr, rItem.aGUID, rItem.nPriority));
break;
default:
break;
}
}
}
void XclExpExtConditionalFormatting::SaveXml( XclExpXmlStream& rStrm )
{
sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
rWorksheet->startElementNS( XML_x14, XML_conditionalFormatting,
FSNS( XML_xmlns, XML_xm ), rStrm.getNamespaceURL(OOX_NS(xm)) );
maCfRules.SaveXml( rStrm );
rWorksheet->startElementNS(XML_xm, XML_sqref);
rWorksheet->write(XclXmlUtils::ToOString(rStrm.GetRoot().GetDoc(), maRange));
rWorksheet->endElementNS( XML_xm, XML_sqref );
rWorksheet->endElementNS( XML_x14, XML_conditionalFormatting );
}
XclExpExtCalcPr::XclExpExtCalcPr( const XclExpRoot& rRoot, formula::FormulaGrammar::AddressConvention eConv ):
XclExpExt( rRoot )
{
maURI = "{7626C862-2A13-11E5-B345-FEFF819CDC9F}"_ostr;
switch (eConv)
{
case formula::FormulaGrammar::CONV_OOO:
maSyntax = "CalcA1"_ostr;
break;
case formula::FormulaGrammar::CONV_XL_A1:
maSyntax = "ExcelA1"_ostr;
break;
case formula::FormulaGrammar::CONV_XL_R1C1:
maSyntax = "ExcelR1C1"_ostr;
break;
case formula::FormulaGrammar::CONV_A1_XL_A1:
maSyntax = "CalcA1ExcelA1"_ostr;
break;
case formula::FormulaGrammar::CONV_UNSPECIFIED:
case formula::FormulaGrammar::CONV_ODF:
case formula::FormulaGrammar::CONV_XL_OOX:
case formula::FormulaGrammar::CONV_LOTUS_A1:
case formula::FormulaGrammar::CONV_LAST:
maSyntax = "Unspecified"_ostr;
break;
}
}
void XclExpExtCalcPr::SaveXml( XclExpXmlStream& rStrm )
{
sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
rWorksheet->startElement( XML_ext,
FSNS(XML_xmlns, XML_loext), rStrm.getNamespaceURL(OOX_NS(loext)),
XML_uri, maURI );
rWorksheet->singleElementNS(XML_loext, XML_extCalcPr, XML_stringRefSyntax, maSyntax);
rWorksheet->endElement( XML_ext );
}
XclExpExtCondFormat::XclExpExtCondFormat( const XclExpRoot& rRoot ):
XclExpExt( rRoot )
{
maURI = "{78C0D931-6437-407d-A8EE-F0AAD7539E65}"_ostr;
}
void XclExpExtCondFormat::SaveXml( XclExpXmlStream& rStrm )
{
sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
rWorksheet->startElement( XML_ext,
FSNS(XML_xmlns, XML_x14), rStrm.getNamespaceURL(OOX_NS(xls14Lst)),
XML_uri, maURI );
rWorksheet->startElementNS(XML_x14, XML_conditionalFormattings);
maCF.SaveXml( rStrm );
rWorksheet->endElementNS( XML_x14, XML_conditionalFormattings );
rWorksheet->endElement( XML_ext );
}
void XclExpExtCondFormat::AddRecord( XclExpExtConditionalFormatting* pEntry )
{
maCF.AppendRecord( pEntry );
}
void XclExtLst::SaveXml( XclExpXmlStream& rStrm )
{
if(maExtEntries.IsEmpty())
return;
sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
rWorksheet->startElement(XML_extLst);
maExtEntries.SaveXml(rStrm);
rWorksheet->endElement( XML_extLst );
}
void XclExtLst::AddRecord( XclExpExt* pEntry )
{
maExtEntries.AppendRecord( pEntry );
}
XclExpExt* XclExtLst::GetItem( XclExpExtType eType )
{
size_t n = maExtEntries.GetSize();
for( size_t i = 0; i < n; ++i )
{
if (maExtEntries.GetRecord( i )->GetType() == eType)
return maExtEntries.GetRecord( i );
}
return nullptr;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V530 The return value of function 'ToOString' is required to be utilized.