sc: support reading sparklines from OOXML document

Read sparklines and sparkline groups from the OOXML document and
add store it into a (temporary local) doc. model.

Change-Id: Id2d34db70300957735571875d6defb3d560fbb26
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131161
Tested-by: Tomaž Vajngerl <quikee@gmail.com>
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
This commit is contained in:
Tomaž Vajngerl
2022-02-02 15:25:28 +09:00
committed by Tomaž Vajngerl
parent f35d1a9f16
commit 04b3a9baf5
5 changed files with 310 additions and 0 deletions

View File

@@ -1291,9 +1291,17 @@ collapsedLevelsAreSubtotals
colon
color
color2
colorAxis
colorFilter
colorFirst
colorHigh
colorId
colorLast
colorLow
colorMarkers
colorNegative
colorScale
colorSeries
colorTemp
colorTemperature
colormenu
@@ -1662,6 +1670,7 @@ datastoreItem
date
date1904
dateAx
dateAxis
dateBetween
dateCompatibility
dateEqual
@@ -1825,12 +1834,15 @@ dispUnitsLbl
displacedByCustomXml
display
displayBackgroundShape
displayEmptyCellsAs
displayFolder
displayHangulFixedWidth
displayHidden
displayHorizontalDrawingGridEvery
displayName
displayText
displayVerticalDrawingGridEvery
displayXAxis
displayed
dissolve
dist
@@ -3136,6 +3148,7 @@ lineMarker
linePitch
lineRule
lineTo
lineWeight
lineWrapLikeWord6
linear
linen
@@ -3283,6 +3296,8 @@ manifestLocation
manual
manualBreakCount
manualLayout
manualMax
manualMin
map
mapId
mapPins
@@ -3303,6 +3318,7 @@ marTop
marW
margin
marker
markers
markup
maroon
marquee
@@ -3325,6 +3341,7 @@ mathPr
matrix
matte
max
maxAxisType
maxAng
maxDate
maxDepth
@@ -3402,6 +3419,7 @@ middleDot
midnightBlue
millions
min
minAxisType
minAng
minDate
minLength
@@ -3505,6 +3523,7 @@ nc
nd
ndxf
neCell
negative
negativeBarColorSameAsPositive
negativeFillColor
negativeInteger
@@ -4868,6 +4887,10 @@ span
spanAng
spans
sparkle
sparklineGroups
sparklineGroup
sparklines
sparkline
spc
spcAft
spcBef
@@ -5488,6 +5511,7 @@ ui8
uiCompat97To2003
uiExpand
uiPriority
uid
uint
ulTrailSpace
un

View File

@@ -202,6 +202,7 @@ $(eval $(call gb_Library_add_exception_objects,scfilt,\
sc/source/filter/oox/sharedstringsfragment \
sc/source/filter/oox/sheetdatabuffer \
sc/source/filter/oox/sheetdatacontext \
sc/source/filter/oox/SparklineFragment \
sc/source/filter/oox/stylesbuffer \
sc/source/filter/oox/stylesfragment \
sc/source/filter/oox/tablebuffer \

View File

@@ -0,0 +1,94 @@
/* -*- 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/.
*/
#pragma once
#include "excelhandlers.hxx"
#include <oox/core/contexthandler.hxx>
#include <vector>
#include <memory>
#include <optional>
namespace oox
{
class AttributeList;
}
namespace oox::xls
{
class Sparkline
{
public:
ScRangeList m_aInputRange;
ScRangeList m_aTargetRange;
Sparkline() {}
};
class SparklineGroup
{
private:
std::vector<Sparkline> m_aSparklines;
public:
Color m_aColorSeries;
Color m_aColorNegative;
Color m_aColorAxis;
Color m_aColorMarkers;
Color m_aColorFirst;
Color m_aColorLast;
Color m_aColorHigh;
Color m_aColorLow;
OUString m_sMinAxisType; // individual, group, custom
OUString m_sMaxAxisType;
double m_fLineWeight; // In pt
OUString m_sType; // line, column, stacked
bool m_bDateAxis;
OUString m_sDisplayEmptyCellsAs; // span, gap, zero
bool m_bMarkers;
bool m_bHigh;
bool m_bLow;
bool m_bFirst;
bool m_bLast;
bool m_bNegative;
bool m_bDisplayXAxis;
bool m_bDisplayHidden;
bool m_bRightToLeft;
std::optional<double> m_aManualMax;
std::optional<double> m_aManualMin;
OUString m_sUID;
std::vector<Sparkline>& getSparklines() { return m_aSparklines; }
};
class SparklineGroupsContext : public WorksheetContextBase
{
private:
std::vector<SparklineGroup> m_aSparklineGroups;
public:
explicit SparklineGroupsContext(WorksheetContextBase& rFragment);
oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement,
const AttributeList& rAttribs) override;
void onStartElement(const AttributeList& rAttribs) override;
void onCharacters(const OUString& rCharacters) override;
void onEndElement() override;
};
} //namespace oox::xls
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -0,0 +1,189 @@
/* -*- 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 <SparklineFragment.hxx>
#include <oox/core/contexthandler.hxx>
#include <oox/token/tokens.hxx>
#include <oox/token/namespaces.hxx>
#include <oox/helper/helper.hxx>
#include <oox/helper/attributelist.hxx>
#include <document.hxx>
#include <rangeutl.hxx>
using ::oox::core::ContextHandlerRef;
namespace oox::xls
{
namespace
{
Color getColor(const AttributeList& rAttribs)
{
if (rAttribs.hasAttribute(XML_rgb))
{
return Color(ColorTransparency,
rAttribs.getIntegerHex(XML_rgb, sal_Int32(API_RGB_TRANSPARENT)));
}
return Color();
}
void addColorsToSparklineGroup(SparklineGroup& rSparklineGroup, sal_Int32 nElement,
const AttributeList& rAttribs)
{
switch (nElement)
{
case XLS14_TOKEN(colorSeries):
rSparklineGroup.m_aColorSeries = getColor(rAttribs);
break;
case XLS14_TOKEN(colorNegative):
rSparklineGroup.m_aColorNegative = getColor(rAttribs);
break;
case XLS14_TOKEN(colorAxis):
rSparklineGroup.m_aColorAxis = getColor(rAttribs);
break;
case XLS14_TOKEN(colorMarkers):
rSparklineGroup.m_aColorMarkers = getColor(rAttribs);
break;
case XLS14_TOKEN(colorFirst):
rSparklineGroup.m_aColorFirst = getColor(rAttribs);
break;
case XLS14_TOKEN(colorLast):
rSparklineGroup.m_aColorLast = getColor(rAttribs);
break;
case XLS14_TOKEN(colorHigh):
rSparklineGroup.m_aColorHigh = getColor(rAttribs);
break;
case XLS14_TOKEN(colorLow):
rSparklineGroup.m_aColorLow = getColor(rAttribs);
break;
default:
break;
}
}
void addAttributesToSparklineGroup(SparklineGroup& rSparklineGroup, const AttributeList& rAttribs)
{
auto oManualMax = rAttribs.getDouble(XML_manualMax);
auto oManualMin = rAttribs.getDouble(XML_manualMin);
rSparklineGroup.m_fLineWeight = rAttribs.getDouble(XML_lineWeight, 0.75);
rSparklineGroup.m_sType = rAttribs.getString(XML_type, "line");
rSparklineGroup.m_bDateAxis = rAttribs.getBool(XML_dateAxis, false);
rSparklineGroup.m_sDisplayEmptyCellsAs = rAttribs.getString(XML_displayEmptyCellsAs, "zero");
rSparklineGroup.m_bMarkers = rAttribs.getBool(XML_markers, false);
rSparklineGroup.m_bHigh = rAttribs.getBool(XML_high, false);
rSparklineGroup.m_bLow = rAttribs.getBool(XML_low, false);
rSparklineGroup.m_bFirst = rAttribs.getBool(XML_first, false);
rSparklineGroup.m_bLast = rAttribs.getBool(XML_last, false);
rSparklineGroup.m_bNegative = rAttribs.getBool(XML_negative, false);
rSparklineGroup.m_bDisplayXAxis = rAttribs.getBool(XML_displayXAxis, false);
rSparklineGroup.m_bDisplayHidden = rAttribs.getBool(XML_displayHidden, false);
rSparklineGroup.m_sMinAxisType = rAttribs.getString(XML_minAxisType, "individual");
rSparklineGroup.m_sMaxAxisType = rAttribs.getString(XML_maxAxisType, "individual");
rSparklineGroup.m_bRightToLeft = rAttribs.getBool(XML_rightToLeft, false);
rSparklineGroup.m_sUID = rAttribs.getString(XML_uid, OUString());
if (rSparklineGroup.m_sMaxAxisType == "custom")
rSparklineGroup.m_aManualMax = oManualMax.get();
if (rSparklineGroup.m_sMinAxisType == "custom")
rSparklineGroup.m_aManualMin = oManualMin.get();
}
} // end anonymous namespace
SparklineGroupsContext::SparklineGroupsContext(WorksheetContextBase& rFragment)
: WorksheetContextBase(rFragment)
{
}
ContextHandlerRef SparklineGroupsContext::onCreateContext(sal_Int32 nElement,
const AttributeList& rAttribs)
{
switch (nElement)
{
case XLS14_TOKEN(sparklineGroup):
{
auto& rLastGroup = m_aSparklineGroups.emplace_back();
addAttributesToSparklineGroup(rLastGroup, rAttribs);
return this;
}
case XLS14_TOKEN(colorSeries):
case XLS14_TOKEN(colorNegative):
case XLS14_TOKEN(colorAxis):
case XLS14_TOKEN(colorMarkers):
case XLS14_TOKEN(colorFirst):
case XLS14_TOKEN(colorLast):
case XLS14_TOKEN(colorHigh):
case XLS14_TOKEN(colorLow):
{
auto& rLastGroup = m_aSparklineGroups.back();
addColorsToSparklineGroup(rLastGroup, nElement, rAttribs);
return this;
}
case XLS14_TOKEN(sparklines):
{
return this;
}
case XLS14_TOKEN(sparkline):
{
auto& rLastGroup = m_aSparklineGroups.back();
rLastGroup.getSparklines().emplace_back();
return this;
}
}
return this;
}
void SparklineGroupsContext::onStartElement(const AttributeList&) {}
void SparklineGroupsContext::onCharacters(const OUString& rChars)
{
if (getCurrentElement() == XM_TOKEN(sqref) || getCurrentElement() == XM_TOKEN(f))
{
ScDocument& rDocument = getScDocument();
auto& rLastGroup = m_aSparklineGroups.back();
auto& rLastSparkline = rLastGroup.getSparklines().back();
ScRangeList aRange;
if (ScRangeStringConverter::GetRangeListFromString(aRange, rChars, rDocument,
formula::FormulaGrammar::CONV_XL_OOX))
{
if (!aRange.empty())
{
if (getCurrentElement() == XM_TOKEN(sqref))
{
rLastSparkline.m_aTargetRange = aRange;
// Need to set the current sheet index to the range as
// it is assumed that the address string referes to
// the current sheet and is not defined in the string.
for (auto& rRange : rLastSparkline.m_aTargetRange)
{
rRange.aStart.SetTab(getSheetIndex());
rRange.aEnd.SetTab(getSheetIndex());
}
}
else if (getCurrentElement() == XM_TOKEN(f))
rLastSparkline.m_aInputRange = aRange;
}
}
}
}
void SparklineGroupsContext::onEndElement() {}
} //namespace oox::xls
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -22,6 +22,7 @@
#include <workbookfragment.hxx>
#include <stylesbuffer.hxx>
#include <stylesfragment.hxx>
#include <SparklineFragment.hxx>
#include <rangeutl.hxx>
#include <sal/log.hxx>
@@ -350,6 +351,7 @@ ContextHandlerRef ExtGlobalContext::onCreateContext( sal_Int32 nElement, const A
{
case XLS14_TOKEN(conditionalFormatting): return new ExtConditionalFormattingContext(*this);
case XLS14_TOKEN(dataValidations): return new ExtDataValidationsContext(*this);
case XLS14_TOKEN(sparklineGroups): return new SparklineGroupsContext(*this);
}
return this;
}