sc: sparkline import/export for ODF
Change-Id: I0d8293cdd35cc8c7afab98efac0a28a3613d122b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132505
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index 22e2459..86cc93f 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -449,8 +449,16 @@ namespace xmloff::token {
XML_CODEBASE,
XML_COLLAPSE,
XML_COLOR,
XML_COLOR_AXIS,
XML_COLOR_FIRST,
XML_COLOR_HIGH,
XML_COLOR_INVERSION,
XML_COLOR_LAST,
XML_COLOR_LOW,
XML_COLOR_MARKERS,
XML_COLOR_MODE,
XML_COLOR_NEGATIVE,
XML_COLOR_SERIES,
XML_COLOR_SCALE,
XML_COLOR_SCALE_ENTRY,
XML_COLOR_TABLE,
@@ -593,6 +601,7 @@ namespace xmloff::token {
XML_DATA_PILOT_TABLE,
XML_DATA_PILOT_TABLES,
XML_DATA_POINT,
XML_DATA_RANGE,
XML_DATA_STREAM_SOURCE,
XML_DATA_STYLE,
XML_DATA_STYLE_NAME,
@@ -609,6 +618,7 @@ namespace xmloff::token {
XML_DATABASE_SOURCE_TABLE,
XML_DATABASE_TABLE_NAME,
XML_DATE,
XML_DATE_AXIS,
XML_DATE_IS,
XML_DATE_ADJUST,
XML_DATE_STYLE,
@@ -668,12 +678,15 @@ namespace xmloff::token {
XML_DISPLAY_DETAILS,
XML_DISPLAY_DUPLICATES,
XML_DISPLAY_EMPTY,
XML_DISPLAY_EMPTY_CELLS_AS,
XML_DISPLAY_FILTER_BUTTONS,
XML_DISPLAY_FORMULA,
XML_DISPLAY_HIDDEN,
XML_DISPLAY_LABEL,
XML_DISPLAY_LEVELS,
XML_DISPLAY_NAME,
XML_DISPLAY_OUTLINE_LEVEL,
XML_DISPLAY_X_AXIS,
XML_DISSOLVE,
XML_DISTANCE,
XML_DISTANCE_AFTER_SEP,
@@ -1181,6 +1194,7 @@ namespace xmloff::token {
XML_LINE_SKEW,
XML_LINE_SPACING,
XML_LINE_STYLE,
XML_LINE_WIDTH,
XML_LINEAR,
XML_LINEARGRADIENT,
XML_LINENUMBERING_CONFIGURATION,
@@ -1208,6 +1222,7 @@ namespace xmloff::token {
XML_LOGARITHMIC,
XML_LOGBASE,
XML_LONG,
XML_LOW,
XML_LOWLIMIT,
XML_LR_TB,
XML_LT,
@@ -1221,6 +1236,8 @@ namespace xmloff::token {
XML_MALIGNGROUP,
XML_MALIGNMARK,
XML_MANUAL,
XML_MANUAL_MIN,
XML_MANUAL_MAX,
XML_MAP,
XML_MARGIN_BOTTOM,
XML_MARGIN_LEFT,
@@ -1228,6 +1245,7 @@ namespace xmloff::token {
XML_MARGIN_TOP,
XML_MARGINS,
XML_MARKER,
XML_MARKERS,
XML_MARKER_END,
XML_MARKER_END_CENTER,
XML_MARKER_END_WIDTH,
@@ -1246,6 +1264,7 @@ namespace xmloff::token {
XML_MATRIX_COVERED,
XML_MATRIXROW,
XML_MAX,
XML_MAX_AXIS_TYPE,
XML_MAX_EDGE,
XML_MAX_HEIGHT,
XML_MAX_LENGTH,
@@ -1271,6 +1290,7 @@ namespace xmloff::token {
XML_MIDDLE,
XML_MIME_TYPE,
XML_MIN,
XML_MIN_AXIS_TYPE,
XML_MIN_DENOMINATOR_DIGITS,
XML_MIN_EDGE,
XML_MIN_EXPONENT_DIGITS,
@@ -1345,6 +1365,7 @@ namespace xmloff::token {
XML_NAMED_RANGE,
XML_NAVIGATION_MODE,
XML_NAVY,
XML_NEGATIVE,
XML_NEGATIVE_COLOR,
XML_NEQ,
XML_NEW,
@@ -1606,6 +1627,7 @@ namespace xmloff::token {
XML_RIGHT,
XML_RIGHT_OUTSIDE,
XML_RIGHT_TEXT,
XML_RIGHT_TO_LEFT,
XML_RIGHTARC,
XML_RIGHTCIRCLE,
XML_RING,
@@ -1760,6 +1782,10 @@ namespace xmloff::token {
XML_SOURCE_RANGE_ADDRESS,
XML_SOURCE_SERVICE,
XML_SPACE_BEFORE,
XML_SPARKLINE_GROUPS,
XML_SPARKLINE_GROUP,
XML_SPARKLINES,
XML_SPARKLINE,
XML_SPAN,
XML_SPECULAR,
XML_SPECULAR_COLOR,
diff --git a/sc/CppunitTest_sc_sparkline_test.mk b/sc/CppunitTest_sc_sparkline_test.mk
index 7a46d5d..b756de2 100644
--- a/sc/CppunitTest_sc_sparkline_test.mk
+++ b/sc/CppunitTest_sc_sparkline_test.mk
@@ -18,6 +18,12 @@ $(eval $(call gb_CppunitTest_add_exception_objects,sc_sparkline_test, \
sc/qa/unit/SparklineTest \
))
$(eval $(call gb_CppunitTest_use_externals,sc_sparkline_test, \
boost_headers \
mdds_headers \
libxml2 \
))
$(eval $(call gb_CppunitTest_use_libraries,sc_sparkline_test, \
basegfx \
comphelper \
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 2c78147..e97f6e0 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -293,6 +293,8 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/tool/webservicelink \
sc/source/core/tool/zforauto \
sc/source/filter/xml/datastreamimport \
sc/source/filter/xml/SparklineGroupsExport \
sc/source/filter/xml/SparklineGroupsImportContext \
sc/source/filter/xml/XMLCalculationSettingsContext \
sc/source/filter/xml/XMLCellRangeSourceContext \
sc/source/filter/xml/XMLChangeTrackingExportHelper \
diff --git a/sc/inc/SparklineGroup.hxx b/sc/inc/SparklineGroup.hxx
index 051e45d..5a3bda6 100644
--- a/sc/inc/SparklineGroup.hxx
+++ b/sc/inc/SparklineGroup.hxx
@@ -26,6 +26,7 @@ private:
public:
SparklineAttributes& getAttributes() { return m_aAttributes; }
SparklineAttributes const& getAttributes() const { return m_aAttributes; }
OUString getID() { return m_sUID; }
diff --git a/sc/qa/unit/SparklineImportExportTest.cxx b/sc/qa/unit/SparklineImportExportTest.cxx
index 2c32412..6da76fb 100644
--- a/sc/qa/unit/SparklineImportExportTest.cxx
+++ b/sc/qa/unit/SparklineImportExportTest.cxx
@@ -8,6 +8,7 @@
*/
#include "helper/qahelper.hxx"
#include "helper/xpath.hxx"
#include <com/sun/star/lang/XComponent.hpp>
#include <docsh.hxx>
@@ -16,7 +17,7 @@
using namespace css;
class SparklineImportExportTest : public ScBootstrapFixture
class SparklineImportExportTest : public ScBootstrapFixture, public XmlTestTools
{
private:
uno::Reference<uno::XInterface> m_xCalcComponent;
@@ -44,10 +45,19 @@ public:
test::BootstrapFixture::tearDown();
}
void testSparklines();
virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathContextPtr) override
{
XmlTestTools::registerODFNamespaces(pXmlXPathContextPtr);
}
void testSparklinesRoundtripXLSX();
void testSparklinesExportODS();
void testSparklinesRoundtripODS();
CPPUNIT_TEST_SUITE(SparklineImportExportTest);
CPPUNIT_TEST(testSparklines);
CPPUNIT_TEST(testSparklinesRoundtripXLSX);
CPPUNIT_TEST(testSparklinesExportODS);
CPPUNIT_TEST(testSparklinesRoundtripODS);
CPPUNIT_TEST_SUITE_END();
};
@@ -74,7 +84,7 @@ void checkSparklines(ScDocument& rDocument)
CPPUNIT_ASSERT_EQUAL(Color(0x92d050), rAttributes.getColorHigh());
CPPUNIT_ASSERT_EQUAL(Color(0x00b0f0), rAttributes.getColorLow());
CPPUNIT_ASSERT_EQUAL(1.0, rAttributes.getLineWeight());
CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, rAttributes.getLineWeight(), 1E-2);
CPPUNIT_ASSERT_EQUAL(false, rAttributes.isDateAxis());
CPPUNIT_ASSERT_EQUAL(sc::DisplayEmptyCellsAs::Gap, rAttributes.getDisplayEmptyCellsAs());
@@ -153,7 +163,7 @@ void checkSparklines(ScDocument& rDocument)
}
} // end anonymous namespace
void SparklineImportExportTest::testSparklines()
void SparklineImportExportTest::testSparklinesRoundtripXLSX()
{
ScDocShellRef xDocSh = loadDoc(u"Sparklines.", FORMAT_XLSX);
CPPUNIT_ASSERT(xDocSh);
@@ -167,6 +177,70 @@ void SparklineImportExportTest::testSparklines()
xDocSh->DoClose();
}
void SparklineImportExportTest::testSparklinesExportODS()
{
// Load the document containing sparklines
ScDocShellRef xDocSh = loadDoc(u"Sparklines.", FORMAT_XLSX);
CPPUNIT_ASSERT(xDocSh);
// Save as ODS and check content.xml with XPath
std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(*xDocSh, FORMAT_ODS);
xmlDocUniquePtr pXmlDoc = XPathHelper::parseExport(pXPathFile, m_xSFactory, "content.xml");
// We have 3 sparkline groups = 3 tables that contain spakrlines
assertXPath(pXmlDoc, "//table:table/calcext:sparkline-groups", 3);
// Check the number of sparkline groups in table[1]
assertXPath(pXmlDoc, "//table:table[1]/calcext:sparkline-groups/calcext:sparkline-group", 2);
// Check the number of sparkline groups in table[2]
assertXPath(pXmlDoc, "//table:table[2]/calcext:sparkline-groups/calcext:sparkline-group", 2);
// Check the number of sparkline groups in table[3]
assertXPath(pXmlDoc, "//table:table[3]/calcext:sparkline-groups/calcext:sparkline-group", 3);
// Check table[1] - sparkline-group[1]
OString aSparklineGroupPath
= "//table:table[1]/calcext:sparkline-groups/calcext:sparkline-group[1]";
assertXPath(pXmlDoc, aSparklineGroupPath, "type", "line");
assertXPath(pXmlDoc, aSparklineGroupPath, "line-width", "1pt");
assertXPath(pXmlDoc, aSparklineGroupPath, "display-empty-cells-as", "gap");
assertXPath(pXmlDoc, aSparklineGroupPath, "markers", "true");
assertXPath(pXmlDoc, aSparklineGroupPath, "high", "true");
assertXPath(pXmlDoc, aSparklineGroupPath, "low", "true");
assertXPath(pXmlDoc, aSparklineGroupPath, "first", "true");
assertXPath(pXmlDoc, aSparklineGroupPath, "last", "true");
assertXPath(pXmlDoc, aSparklineGroupPath, "negative", "true");
assertXPath(pXmlDoc, aSparklineGroupPath, "display-x-axis", "true");
assertXPath(pXmlDoc, aSparklineGroupPath, "min-axis-type", "individual");
assertXPath(pXmlDoc, aSparklineGroupPath, "max-axis-type", "individual");
assertXPath(pXmlDoc, aSparklineGroupPath, "color-series", "#376092");
assertXPath(pXmlDoc, aSparklineGroupPath, "color-negative", "#00b050");
assertXPath(pXmlDoc, aSparklineGroupPath, "color-axis", "#000000");
assertXPath(pXmlDoc, aSparklineGroupPath, "color-markers", "#000000");
assertXPath(pXmlDoc, aSparklineGroupPath, "color-first", "#7030a0");
assertXPath(pXmlDoc, aSparklineGroupPath, "color-last", "#ff0000");
assertXPath(pXmlDoc, aSparklineGroupPath, "color-high", "#92d050");
assertXPath(pXmlDoc, aSparklineGroupPath, "color-low", "#00b0f0");
assertXPath(pXmlDoc, aSparklineGroupPath + "/calcext:sparklines/calcext:sparkline", 1);
assertXPath(pXmlDoc, aSparklineGroupPath + "/calcext:sparklines/calcext:sparkline[1]",
"cell-address", "Sheet1.A2");
}
void SparklineImportExportTest::testSparklinesRoundtripODS()
{
ScDocShellRef xDocSh = loadDoc(u"Sparklines.", FORMAT_XLSX);
CPPUNIT_ASSERT(xDocSh);
checkSparklines(xDocSh->GetDocument());
// Trigger export and import of sparklines
xDocSh = saveAndReload(*xDocSh, FORMAT_ODS);
checkSparklines(xDocSh->GetDocument());
xDocSh->DoClose();
}
CPPUNIT_TEST_SUITE_REGISTRATION(SparklineImportExportTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sc/source/filter/xml/SparklineGroupsExport.cxx b/sc/source/filter/xml/SparklineGroupsExport.cxx
new file mode 100644
index 0000000..6be8a61
--- /dev/null
+++ b/sc/source/filter/xml/SparklineGroupsExport.cxx
@@ -0,0 +1,222 @@
/* -*- 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 "SparklineGroupsExport.hxx"
#include "xmlexprt.hxx"
#include <rangeutl.hxx>
#include <xmloff/xmluconv.hxx>
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmlnamespace.hxx>
#include <xmloff/namespacemap.hxx>
#include <rtl/ustrbuf.hxx>
#include <sax/tools/converter.hxx>
#include <o3tl/unit_conversion.hxx>
using namespace css;
using namespace xmloff::token;
namespace sc
{
SparklineGroupsExport::SparklineGroupsExport(
ScXMLExport& rExport, SCTAB nTable, std::vector<std::shared_ptr<Sparkline>> const& rSparklines)
: m_rExport(rExport)
, m_nTable(nTable)
{
for (auto const& pSparkline : rSparklines)
{
auto* pGroupPointer = pSparkline->getSparklineGroup().get();
auto aIterator = m_aSparklineGroupMap.find(pGroupPointer);
if (aIterator == m_aSparklineGroupMap.end())
{
m_aSparklineGroups.push_back(pGroupPointer);
std::vector<std::shared_ptr<sc::Sparkline>> aSparklineVector;
aSparklineVector.push_back(pSparkline);
m_aSparklineGroupMap.emplace(pGroupPointer, aSparklineVector);
}
else
{
aIterator->second.push_back(pSparkline);
}
}
}
void SparklineGroupsExport::insertColor(Color aColor, XMLTokenEnum eToken)
{
OUStringBuffer aStringBuffer;
if (aColor != COL_TRANSPARENT)
{
sax::Converter::convertColor(aStringBuffer, aColor);
m_rExport.AddAttribute(XML_NAMESPACE_CALC_EXT, eToken, aStringBuffer.makeStringAndClear());
}
}
void SparklineGroupsExport::insertBool(bool bValue, XMLTokenEnum eToken)
{
if (bValue)
m_rExport.AddAttribute(XML_NAMESPACE_CALC_EXT, eToken, "true");
}
void SparklineGroupsExport::addSparklineAttributes(Sparkline const& rSparkline)
{
auto const* pDocument = m_rExport.GetDocument();
{
OUString sAddressString;
ScAddress aAddress(rSparkline.getColumn(), rSparkline.getRow(), m_nTable);
ScRangeStringConverter::GetStringFromAddress(sAddressString, aAddress, pDocument,
formula::FormulaGrammar::CONV_OOO);
m_rExport.AddAttribute(XML_NAMESPACE_CALC_EXT, XML_CELL_ADDRESS, sAddressString);
}
{
OUString sDataRangeString;
ScRangeList const& rRangeList = rSparkline.getInputRange();
ScRangeStringConverter::GetStringFromRangeList(sDataRangeString, &rRangeList, pDocument,
formula::FormulaGrammar::CONV_OOO);
m_rExport.AddAttribute(XML_NAMESPACE_CALC_EXT, XML_DATA_RANGE, sDataRangeString);
}
}
namespace
{
OUString convertSparklineType(sc::SparklineType eType)
{
switch (eType)
{
case sc::SparklineType::Line:
return u"line";
case sc::SparklineType::Column:
return u"column";
case sc::SparklineType::Stacked:
return u"stacked";
}
return u"";
}
OUString convertDisplayEmptyCellsAs(sc::DisplayEmptyCellsAs eType)
{
switch (eType)
{
case sc::DisplayEmptyCellsAs::Zero:
return u"zero";
case sc::DisplayEmptyCellsAs::Gap:
return u"gap";
case sc::DisplayEmptyCellsAs::Span:
return u"span";
}
return u"";
}
OUString convertAxisType(sc::AxisType eType)
{
switch (eType)
{
case sc::AxisType::Individual:
return u"individual";
case sc::AxisType::Group:
return u"group";
case sc::AxisType::Custom:
return u"custom";
}
return u"";
}
} // end anonymous ns
void SparklineGroupsExport::addSparklineGroupAttributes(SparklineAttributes const& rAttributes)
{
OUString sType = convertSparklineType(rAttributes.getType());
m_rExport.AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, sType);
// Line Weight = Line Width in ODF
m_rExport.AddAttribute(XML_NAMESPACE_CALC_EXT, XML_LINE_WIDTH,
OUString::number(rAttributes.getLineWeight()) + "pt");
insertBool(rAttributes.isDateAxis(), XML_DATE_AXIS);
OUString sDisplayEmptyCellsAs
= convertDisplayEmptyCellsAs(rAttributes.getDisplayEmptyCellsAs());
m_rExport.AddAttribute(XML_NAMESPACE_CALC_EXT, XML_DISPLAY_EMPTY_CELLS_AS,
sDisplayEmptyCellsAs);
insertBool(rAttributes.isMarkers(), XML_MARKERS);
insertBool(rAttributes.isHigh(), XML_HIGH);
insertBool(rAttributes.isLow(), XML_LOW);
insertBool(rAttributes.isFirst(), XML_FIRST);
insertBool(rAttributes.isLast(), XML_LAST);
insertBool(rAttributes.isNegative(), XML_NEGATIVE);
insertBool(rAttributes.shouldDisplayXAxis(), XML_DISPLAY_X_AXIS);
insertBool(rAttributes.shouldDisplayHidden(), XML_DISPLAY_HIDDEN);
OUString sMinAxisType = convertAxisType(rAttributes.getMinAxisType());
m_rExport.AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MIN_AXIS_TYPE, sMinAxisType);
OUString sMaxAxisType = convertAxisType(rAttributes.getMaxAxisType());
m_rExport.AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MAX_AXIS_TYPE, sMaxAxisType);
insertBool(rAttributes.isRightToLeft(), XML_RIGHT_TO_LEFT);
if (rAttributes.getManualMax() && rAttributes.getMaxAxisType() == sc::AxisType::Custom)
m_rExport.AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MANUAL_MAX,
OUString::number(*rAttributes.getManualMax()));
if (rAttributes.getManualMin() && rAttributes.getMinAxisType() == sc::AxisType::Custom)
m_rExport.AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MANUAL_MIN,
OUString::number(*rAttributes.getManualMin()));
insertColor(rAttributes.getColorSeries(), XML_COLOR_SERIES);
insertColor(rAttributes.getColorNegative(), XML_COLOR_NEGATIVE);
insertColor(rAttributes.getColorAxis(), XML_COLOR_AXIS);
insertColor(rAttributes.getColorMarkers(), XML_COLOR_MARKERS);
insertColor(rAttributes.getColorFirst(), XML_COLOR_FIRST);
insertColor(rAttributes.getColorLast(), XML_COLOR_LAST);
insertColor(rAttributes.getColorHigh(), XML_COLOR_HIGH);
insertColor(rAttributes.getColorLow(), XML_COLOR_LOW);
}
void SparklineGroupsExport::addSparklineGroup(SparklineGroup* pSparklineGroup)
{
auto const& rAttributes = pSparklineGroup->getAttributes();
OUString sID = pSparklineGroup->getID();
if (!sID.isEmpty())
{
m_rExport.AddAttribute(XML_NAMESPACE_CALC_EXT, XML_ID, sID);
}
addSparklineGroupAttributes(rAttributes);
SvXMLElementExport aElementSparklineGroup(m_rExport, XML_NAMESPACE_CALC_EXT,
XML_SPARKLINE_GROUP, true, true);
SvXMLElementExport aElementSparklines(m_rExport, XML_NAMESPACE_CALC_EXT, XML_SPARKLINES, true,
true);
for (auto const& rSparkline : m_aSparklineGroupMap[pSparklineGroup])
{
addSparklineAttributes(*rSparkline);
SvXMLElementExport aElementSparkline(m_rExport, XML_NAMESPACE_CALC_EXT, XML_SPARKLINE, true,
true);
}
}
void SparklineGroupsExport::write()
{
SvXMLElementExport aElement(m_rExport, XML_NAMESPACE_CALC_EXT, XML_SPARKLINE_GROUPS, true,
true);
for (auto* pSparklineGroup : m_aSparklineGroups)
{
addSparklineGroup(pSparklineGroup);
}
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/xml/SparklineGroupsExport.hxx b/sc/source/filter/xml/SparklineGroupsExport.hxx
new file mode 100644
index 0000000..4e49f58
--- /dev/null
+++ b/sc/source/filter/xml/SparklineGroupsExport.hxx
@@ -0,0 +1,48 @@
/* -*- 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 <memory>
#include <unordered_map>
#include <tools/color.hxx>
#include <xmloff/xmltoken.hxx>
#include <Sparkline.hxx>
#include <SparklineGroup.hxx>
class ScXMLExport;
namespace sc
{
class SparklineGroupsExport
{
ScXMLExport& m_rExport;
std::vector<SparklineGroup*> m_aSparklineGroups;
std::unordered_map<SparklineGroup*, std::vector<std::shared_ptr<Sparkline>>>
m_aSparklineGroupMap;
SCTAB m_nTable;
void addSparklineGroupAttributes(sc::SparklineAttributes const& rAttributes);
void addSparklineGroup(SparklineGroup* pSparklineGroup);
void addSparklineAttributes(Sparkline const& rSparkline);
void insertColor(Color aColor, xmloff::token::XMLTokenEnum eToken);
void insertBool(bool bValue, xmloff::token::XMLTokenEnum eToken);
public:
SparklineGroupsExport(ScXMLExport& rExport, SCTAB nTable,
std::vector<std::shared_ptr<Sparkline>> const& rSparklines);
void write();
};
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/xml/SparklineGroupsImportContext.cxx b/sc/source/filter/xml/SparklineGroupsImportContext.cxx
new file mode 100644
index 0000000..87acbd0
--- /dev/null
+++ b/sc/source/filter/xml/SparklineGroupsImportContext.cxx
@@ -0,0 +1,332 @@
/* -*- 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 "SparklineGroupsImportContext.hxx"
#include <sax/tools/converter.hxx>
#include <xmloff/xmlnamespace.hxx>
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmluconv.hxx>
#include <document.hxx>
#include <rangeutl.hxx>
#include <Sparkline.hxx>
#include <SparklineGroup.hxx>
#include <SparklineAttributes.hxx>
using namespace xmloff::token;
using namespace css;
namespace sc
{
SparklineGroupsImportContext::SparklineGroupsImportContext(ScXMLImport& rImport)
: ScXMLImportContext(rImport)
{
}
namespace
{
sc::SparklineType parseSparklineType(std::u16string_view aString)
{
if (aString == u"column")
return sc::SparklineType::Column;
else if (aString == u"stacked")
return sc::SparklineType::Stacked;
return sc::SparklineType::Line;
}
sc::DisplayEmptyCellsAs parseDisplayEmptyCellsAs(std::u16string_view aString)
{
if (aString == u"span")
return sc::DisplayEmptyCellsAs::Span;
else if (aString == u"gap")
return sc::DisplayEmptyCellsAs::Gap;
return sc::DisplayEmptyCellsAs::Zero;
}
sc::AxisType parseAxisType(std::u16string_view aString)
{
if (aString == u"group")
return sc::AxisType::Group;
else if (aString == u"custom")
return sc::AxisType::Custom;
return sc::AxisType::Individual;
}
} // end anonymous namespace
void SparklineGroupsImportContext::fillSparklineGroupID(
uno::Reference<xml::sax::XFastAttributeList> const& xAttrList)
{
for (auto& rIter : sax_fastparser::castToFastAttributeList(xAttrList))
{
switch (rIter.getToken())
{
case XML_ELEMENT(CALC_EXT, XML_ID):
{
m_pCurrentSparklineGroup->setID(rIter.toString());
break;
}
}
}
}
void SparklineGroupsImportContext::fillSparklineGroupAttributes(
uno::Reference<xml::sax::XFastAttributeList> const& xAttrList)
{
sc::SparklineAttributes& rAttributes = m_pCurrentSparklineGroup->getAttributes();
for (auto& rIter : sax_fastparser::castToFastAttributeList(xAttrList))
{
switch (rIter.getToken())
{
case XML_ELEMENT(CALC_EXT, XML_TYPE):
{
rAttributes.setType(parseSparklineType(rIter.toString()));
break;
}
case XML_ELEMENT(CALC_EXT, XML_LINE_WIDTH):
{
OUString sLineWidth = rIter.toString();
double fLineWidth;
sal_Int16 const eSrcUnit
= ::sax::Converter::GetUnitFromString(sLineWidth, util::MeasureUnit::POINT);
::sax::Converter::convertDouble(fLineWidth, sLineWidth, eSrcUnit,
util::MeasureUnit::POINT);
rAttributes.setLineWeight(fLineWidth);
break;
}
case XML_ELEMENT(CALC_EXT, XML_DATE_AXIS):
{
rAttributes.setDateAxis(rIter.toBoolean());
break;
}
case XML_ELEMENT(CALC_EXT, XML_DISPLAY_EMPTY_CELLS_AS):
{
auto eDisplayEmptyCellsAs = parseDisplayEmptyCellsAs(rIter.toString());
rAttributes.setDisplayEmptyCellsAs(eDisplayEmptyCellsAs);
break;
}
case XML_ELEMENT(CALC_EXT, XML_MARKERS):
{
rAttributes.setMarkers(rIter.toBoolean());
break;
}
case XML_ELEMENT(CALC_EXT, XML_HIGH):
{
rAttributes.setHigh(rIter.toBoolean());
break;
}
case XML_ELEMENT(CALC_EXT, XML_LOW):
{
rAttributes.setLow(rIter.toBoolean());
break;
}
case XML_ELEMENT(CALC_EXT, XML_FIRST):
{
rAttributes.setFirst(rIter.toBoolean());
break;
}
case XML_ELEMENT(CALC_EXT, XML_LAST):
{
rAttributes.setLast(rIter.toBoolean());
break;
}
case XML_ELEMENT(CALC_EXT, XML_NEGATIVE):
{
rAttributes.setNegative(rIter.toBoolean());
break;
}
case XML_ELEMENT(CALC_EXT, XML_DISPLAY_X_AXIS):
{
rAttributes.setDisplayXAxis(rIter.toBoolean());
break;
}
case XML_ELEMENT(CALC_EXT, XML_DISPLAY_HIDDEN):
{
rAttributes.setDisplayHidden(rIter.toBoolean());
break;
}
case XML_ELEMENT(CALC_EXT, XML_MIN_AXIS_TYPE):
{
rAttributes.setMinAxisType(parseAxisType(rIter.toString()));
break;
}
case XML_ELEMENT(CALC_EXT, XML_MAX_AXIS_TYPE):
{
rAttributes.setMaxAxisType(parseAxisType(rIter.toString()));
break;
}
case XML_ELEMENT(CALC_EXT, XML_RIGHT_TO_LEFT):
{
rAttributes.setRightToLeft(rIter.toBoolean());
break;
}
case XML_ELEMENT(CALC_EXT, XML_MANUAL_MAX):
{
rAttributes.setManualMax(rIter.toDouble());
break;
}
case XML_ELEMENT(CALC_EXT, XML_MANUAL_MIN):
{
rAttributes.setManualMin(rIter.toDouble());
break;
}
case XML_ELEMENT(CALC_EXT, XML_COLOR_SERIES):
{
Color aColor;
sax::Converter::convertColor(aColor, rIter.toString());
rAttributes.setColorSeries(aColor);
break;
}
case XML_ELEMENT(CALC_EXT, XML_COLOR_NEGATIVE):
{
Color aColor;
sax::Converter::convertColor(aColor, rIter.toString());
rAttributes.setColorNegative(aColor);
break;
}
case XML_ELEMENT(CALC_EXT, XML_COLOR_AXIS):
{
Color aColor;
sax::Converter::convertColor(aColor, rIter.toString());
rAttributes.setColorAxis(aColor);
break;
}
case XML_ELEMENT(CALC_EXT, XML_COLOR_MARKERS):
{
Color aColor;
sax::Converter::convertColor(aColor, rIter.toString());
rAttributes.setColorMarkers(aColor);
break;
}
case XML_ELEMENT(CALC_EXT, XML_COLOR_FIRST):
{
Color aColor;
sax::Converter::convertColor(aColor, rIter.toString());
rAttributes.setColorFirst(aColor);
break;
}
case XML_ELEMENT(CALC_EXT, XML_COLOR_LAST):
{
Color aColor;
sax::Converter::convertColor(aColor, rIter.toString());
rAttributes.setColorLast(aColor);
break;
}
case XML_ELEMENT(CALC_EXT, XML_COLOR_HIGH):
{
Color aColor;
sax::Converter::convertColor(aColor, rIter.toString());
rAttributes.setColorHigh(aColor);
break;
}
case XML_ELEMENT(CALC_EXT, XML_COLOR_LOW):
{
Color aColor;
sax::Converter::convertColor(aColor, rIter.toString());
rAttributes.setColorLow(aColor);
break;
}
default:
break;
}
}
}
void SparklineGroupsImportContext::fillSparklineAttributes(
SparklineImportData& rImportData, uno::Reference<xml::sax::XFastAttributeList> const& xAttrList)
{
ScDocument* pDocument = GetScImport().GetDocument();
for (auto& rIter : sax_fastparser::castToFastAttributeList(xAttrList))
{
switch (rIter.getToken())
{
case XML_ELEMENT(CALC_EXT, XML_CELL_ADDRESS):
{
sal_Int32 nOffset = 0;
ScRangeStringConverter::GetAddressFromString(
rImportData.m_aAddress, rIter.toString(), *pDocument,
formula::FormulaGrammar::CONV_OOO, nOffset);
break;
}
case XML_ELEMENT(CALC_EXT, XML_DATA_RANGE):
{
ScRangeStringConverter::GetRangeListFromString(rImportData.m_aDataRangeList,
rIter.toString(), *pDocument,
formula::FormulaGrammar::CONV_OOO);
break;
}
default:
break;
}
}
}
uno::Reference<xml::sax::XFastContextHandler>
SAL_CALL SparklineGroupsImportContext::createFastChildContext(
sal_Int32 nElement, uno::Reference<xml::sax::XFastAttributeList> const& xAttrList)
{
SvXMLImportContext* pContext = nullptr;
switch (nElement)
{
case XML_ELEMENT(CALC_EXT, XML_SPARKLINE_GROUP):
{
m_pCurrentSparklineGroup = std::make_shared<sc::SparklineGroup>();
fillSparklineGroupID(xAttrList);
fillSparklineGroupAttributes(xAttrList);
pContext = this;
break;
}
case XML_ELEMENT(CALC_EXT, XML_SPARKLINES):
{
pContext = this;
break;
}
case XML_ELEMENT(CALC_EXT, XML_SPARKLINE):
{
SparklineImportData& rImportData = m_aCurrentSparklineDataList.emplace_back();
fillSparklineAttributes(rImportData, xAttrList);
pContext = this;
break;
}
}
return pContext;
}
void SparklineGroupsImportContext::insertSparklines()
{
ScDocument* pDocument = GetScImport().GetDocument();
for (auto const& rSparklineImportData : m_aCurrentSparklineDataList)
{
auto* pSparkline
= pDocument->CreateSparkline(rSparklineImportData.m_aAddress, m_pCurrentSparklineGroup);
pSparkline->setInputRange(rSparklineImportData.m_aDataRangeList);
}
}
void SAL_CALL SparklineGroupsImportContext::endFastElement(sal_Int32 nElement)
{
switch (nElement)
{
case XML_ELEMENT(CALC_EXT, XML_SPARKLINE_GROUP):
{
insertSparklines();
m_pCurrentSparklineGroup.reset();
m_aCurrentSparklineDataList.clear();
break;
}
}
}
} // end sc
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/xml/SparklineGroupsImportContext.hxx b/sc/source/filter/xml/SparklineGroupsImportContext.hxx
new file mode 100644
index 0000000..f643c1c
--- /dev/null
+++ b/sc/source/filter/xml/SparklineGroupsImportContext.hxx
@@ -0,0 +1,61 @@
/* -*- 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 <memory>
#include "importcontext.hxx"
#include "xmlimprt.hxx"
#include <address.hxx>
#include <rangelst.hxx>
namespace sax_fastparser
{
class FastAttributeList;
}
namespace sc
{
class SparklineGroup;
struct SparklineImportData
{
ScAddress m_aAddress;
ScRangeList m_aDataRangeList;
};
class SparklineGroupsImportContext : public ScXMLImportContext
{
private:
std::shared_ptr<sc::SparklineGroup> m_pCurrentSparklineGroup;
std::vector<SparklineImportData> m_aCurrentSparklineDataList;
void
fillSparklineGroupID(css::uno::Reference<css::xml::sax::XFastAttributeList> const& xAttrList);
void fillSparklineGroupAttributes(
css::uno::Reference<css::xml::sax::XFastAttributeList> const& xAttrList);
void fillSparklineAttributes(
SparklineImportData& rImportData,
css::uno::Reference<css::xml::sax::XFastAttributeList> const& xAttrList);
void insertSparklines();
public:
SparklineGroupsImportContext(ScXMLImport& rImport);
css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
sal_Int32 nElement,
css::uno::Reference<css::xml::sax::XFastAttributeList> const& xAttrList) override;
void SAL_CALL endFastElement(sal_Int32 nElement) override;
};
} // end sc
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index daee5e7..20da166 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -67,6 +67,7 @@
#include <cellform.hxx>
#include <datamapper.hxx>
#include <datatransformation.hxx>
#include "SparklineGroupsExport.hxx"
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmlnamespace.hxx>
@@ -2984,6 +2985,7 @@ void ScXMLExport::WriteTable(sal_Int32 nTable, const uno::Reference<sheet::XSpre
{
//export new conditional format information
ExportConditionalFormat(nTable);
exportSparklineGroups(nTable);
}
}
@@ -4512,6 +4514,19 @@ void ScXMLExport::WriteNamedRange(ScRangeName* pRangeName)
}
}
void ScXMLExport::exportSparklineGroups(SCTAB nTable)
{
if (sc::SparklineList* pSparklineList = pDoc->GetSparklineList(nTable))
{
auto pSparklines = pSparklineList->getSparklines();
if (!pSparklines.empty())
{
sc::SparklineGroupsExport aSparklineGroupExport(*this, nTable, pSparklines);
aSparklineGroupExport.write();
}
}
}
namespace {
OUString getCondFormatEntryType(const ScColorScaleEntry& rEntry, bool bFirst = true)
diff --git a/sc/source/filter/xml/xmlexprt.hxx b/sc/source/filter/xml/xmlexprt.hxx
index e4a165a..8ab8901 100644
--- a/sc/source/filter/xml/xmlexprt.hxx
+++ b/sc/source/filter/xml/xmlexprt.hxx
@@ -198,6 +198,7 @@ class ScXMLExport : public SvXMLExport
void WriteExternalDataTransformations(const std::vector<std::shared_ptr<sc::DataTransformation>>& aDataTransformations);
void WriteDataStream();
void WriteNamedRange(ScRangeName* pRangeName);
void exportSparklineGroups(SCTAB nTab);
void ExportConditionalFormat(SCTAB nTab);
void WriteExternalRefCaches();
void WriteConsolidation(); // core implementation
diff --git a/sc/source/filter/xml/xmltabi.cxx b/sc/source/filter/xml/xmltabi.cxx
index dd1baf29..8354745 100644
--- a/sc/source/filter/xml/xmltabi.cxx
+++ b/sc/source/filter/xml/xmltabi.cxx
@@ -34,6 +34,7 @@
#include <externalrefmgr.hxx>
#include <sheetdata.hxx>
#include "xmlcondformat.hxx"
#include "SparklineGroupsImportContext.hxx"
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmlnamespace.hxx>
@@ -298,6 +299,9 @@ uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
case XML_ELEMENT( CALC_EXT, XML_CONDITIONAL_FORMATS ):
pContext = new ScXMLConditionalFormatsContext( GetScImport() );
break;
case XML_ELEMENT(CALC_EXT, XML_SPARKLINE_GROUPS):
pContext = new sc::SparklineGroupsImportContext(GetScImport());
break;
case XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS):
case XML_ELEMENT(OFFICE_EXT, XML_EVENT_LISTENERS):
{
@@ -315,6 +319,7 @@ uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
break;
default:
XMLOFF_WARN_UNKNOWN_ELEMENT("sc", nElement);
break;
}
return pContext;
diff --git a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
index 1dff482..ccbc6e4 100644
--- a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
+++ b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
@@ -1535,6 +1535,171 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
</rng:oneOrMore>
</rng:element>
</rng:optional>
<!-- Sparklines-->
<rng:optional>
<rng:element name="calcext:sparkline-groups">
<rng:oneOrMore>
<rng:element name="calcext:sparkline-group">
<rng:attribute name="calcext:id">
<rng:ref name="string"/>
</rng:attribute>
<rng:optional>
<rng:attribute name="calcext:type">
<rng:choice>
<rng:value>line</rng:value>
<rng:value>column</rng:value>
<rng:value>stacked</rng:value>
</rng:choice>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:line-width">
<rng:ref name="length"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:date-axis">
<rng:ref name="boolean"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:display-empty-cells-as">
<rng:choice>
<rng:value>zero</rng:value>
<rng:value>gap</rng:value>
<rng:value>span</rng:value>
</rng:choice>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:markers">
<rng:ref name="boolean"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:high">
<rng:ref name="boolean"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:low">
<rng:ref name="boolean"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:first">
<rng:ref name="boolean"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:last">
<rng:ref name="boolean"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:negative">
<rng:ref name="boolean"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:display-x-axis">
<rng:ref name="boolean"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:display-hidden">
<rng:ref name="boolean"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:min-axis-type">
<rng:choice>
<rng:value>individual</rng:value>
<rng:value>group</rng:value>
<rng:value>custom</rng:value>
</rng:choice>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:max-axis-type">
<rng:choice>
<rng:value>individual</rng:value>
<rng:value>group</rng:value>
<rng:value>custom</rng:value>
</rng:choice>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:right-to-left">
<rng:ref name="boolean"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:manual-max">
<rng:ref name="double"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:manual-min">
<rng:ref name="double"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:color-series">
<rng:ref name="color"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:color-negative">
<rng:ref name="color"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:color-axis">
<rng:ref name="color"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:color-markers">
<rng:ref name="color"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:color-first">
<rng:ref name="color"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:color-last">
<rng:ref name="color"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:color-high">
<rng:ref name="color"/>
</rng:attribute>
</rng:optional>
<rng:optional>
<rng:attribute name="calcext:color-low">
<rng:ref name="color"/>
</rng:attribute>
</rng:optional>
<rng:element name="calcext:sparklines">
<rng:oneOrMore>
<rng:element name="calcext:sparkline">
<rng:attribute name="calcext:cell-address">
<rng:ref name="cellAddress"/>
</rng:attribute>
<rng:attribute name="calcext:data-range">
<rng:ref name="cellRangeAddressList"/>
</rng:attribute>
</rng:element>
</rng:oneOrMore>
</rng:element>
</rng:element>
</rng:oneOrMore>
</rng:element>
</rng:optional>
</rng:element>
</rng:define>
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index 0b8f36b..34ae9d9 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -461,8 +461,16 @@ namespace xmloff::token {
TOKEN( "codebase", XML_CODEBASE ),
TOKEN( "collapse", XML_COLLAPSE ),
TOKEN( "color", XML_COLOR ),
TOKEN( "color-axis", XML_COLOR_AXIS ),
TOKEN( "color-first", XML_COLOR_FIRST ),
TOKEN( "color-high", XML_COLOR_HIGH ),
TOKEN( "color-inversion", XML_COLOR_INVERSION ),
TOKEN( "color-last", XML_COLOR_LAST ),
TOKEN( "color-low", XML_COLOR_LOW ),
TOKEN( "color-markers", XML_COLOR_MARKERS ),
TOKEN( "color-mode", XML_COLOR_MODE ),
TOKEN( "color-negative", XML_COLOR_NEGATIVE ),
TOKEN( "color-series", XML_COLOR_SERIES ),
TOKEN( "color-scale", XML_COLOR_SCALE ),
TOKEN( "color-scale-entry", XML_COLOR_SCALE_ENTRY ),
TOKEN( "color-table", XML_COLOR_TABLE ),
@@ -605,6 +613,7 @@ namespace xmloff::token {
TOKEN( "data-pilot-table", XML_DATA_PILOT_TABLE ),
TOKEN( "data-pilot-tables", XML_DATA_PILOT_TABLES ),
TOKEN( "data-point", XML_DATA_POINT ),
TOKEN( "data-range", XML_DATA_RANGE ),
TOKEN( "data-stream-source", XML_DATA_STREAM_SOURCE ),
TOKEN( "data-style", XML_DATA_STYLE ),
TOKEN( "data-style-name", XML_DATA_STYLE_NAME ),
@@ -621,6 +630,7 @@ namespace xmloff::token {
TOKEN( "database-source-table", XML_DATABASE_SOURCE_TABLE ),
TOKEN( "database-table-name", XML_DATABASE_TABLE_NAME ),
TOKEN( "date", XML_DATE ),
TOKEN( "date-axis", XML_DATE_AXIS ),
TOKEN( "date-is", XML_DATE_IS ),
TOKEN( "date-adjust", XML_DATE_ADJUST ),
TOKEN( "date-style", XML_DATE_STYLE ),
@@ -680,12 +690,15 @@ namespace xmloff::token {
TOKEN( "display-details", XML_DISPLAY_DETAILS ),
TOKEN( "display-duplicates", XML_DISPLAY_DUPLICATES ),
TOKEN( "display-empty", XML_DISPLAY_EMPTY ),
TOKEN( "display-empty-cells-as", XML_DISPLAY_EMPTY_CELLS_AS ),
TOKEN( "display-filter-buttons", XML_DISPLAY_FILTER_BUTTONS ),
TOKEN( "display-formula", XML_DISPLAY_FORMULA ),
TOKEN( "display-hidden", XML_DISPLAY_HIDDEN ),
TOKEN( "display-label", XML_DISPLAY_LABEL ),
TOKEN( "display-levels", XML_DISPLAY_LEVELS ),
TOKEN( "display-name", XML_DISPLAY_NAME ),
TOKEN( "display-outline-level", XML_DISPLAY_OUTLINE_LEVEL ),
TOKEN( "display-x-axis", XML_DISPLAY_X_AXIS ),
TOKEN( "dissolve", XML_DISSOLVE ),
TOKEN( "distance", XML_DISTANCE ),
TOKEN( "distance-after-sep", XML_DISTANCE_AFTER_SEP ),
@@ -1194,6 +1207,7 @@ namespace xmloff::token {
TOKEN( "line-skew", XML_LINE_SKEW ),
TOKEN( "line-spacing", XML_LINE_SPACING ),
TOKEN( "line-style", XML_LINE_STYLE ),
TOKEN( "line-width", XML_LINE_WIDTH ),
TOKEN( "linear", XML_LINEAR ),
TOKEN( "linearGradient", XML_LINEARGRADIENT ),
TOKEN( "linenumbering-configuration", XML_LINENUMBERING_CONFIGURATION ),
@@ -1221,6 +1235,7 @@ namespace xmloff::token {
TOKEN( "logarithmic", XML_LOGARITHMIC ),
TOKEN( "logbase", XML_LOGBASE ),
TOKEN( "long", XML_LONG ),
TOKEN( "low", XML_LOW ),
TOKEN( "lowlimit", XML_LOWLIMIT ),
TOKEN( "lr-tb", XML_LR_TB ),
TOKEN( "lt", XML_LT ),
@@ -1234,6 +1249,8 @@ namespace xmloff::token {
TOKEN( "maligngroup", XML_MALIGNGROUP ),
TOKEN( "malignmark", XML_MALIGNMARK ),
TOKEN( "manual", XML_MANUAL ),
TOKEN( "manual-min", XML_MANUAL_MIN ),
TOKEN( "manual-max", XML_MANUAL_MAX ),
TOKEN( "map", XML_MAP ),
TOKEN( "margin-bottom", XML_MARGIN_BOTTOM ),
TOKEN( "margin-left", XML_MARGIN_LEFT ),
@@ -1241,6 +1258,7 @@ namespace xmloff::token {
TOKEN( "margin-top", XML_MARGIN_TOP ),
TOKEN( "margins", XML_MARGINS ),
TOKEN( "marker", XML_MARKER ),
TOKEN( "markers", XML_MARKERS ),
TOKEN( "marker-end", XML_MARKER_END ),
TOKEN( "marker-end-center", XML_MARKER_END_CENTER ),
TOKEN( "marker-end-width", XML_MARKER_END_WIDTH ),
@@ -1259,6 +1277,7 @@ namespace xmloff::token {
TOKEN( "matrix-covered", XML_MATRIX_COVERED ),
TOKEN( "matrixrow", XML_MATRIXROW ),
TOKEN( "max", XML_MAX ),
TOKEN( "max-axis-type", XML_MAX_AXIS_TYPE ),
TOKEN( "max-edge", XML_MAX_EDGE ),
TOKEN( "max-height", XML_MAX_HEIGHT ),
TOKEN( "max-length", XML_MAX_LENGTH ),
@@ -1284,6 +1303,7 @@ namespace xmloff::token {
TOKEN( "middle", XML_MIDDLE ),
TOKEN( "mime-type", XML_MIME_TYPE ),
TOKEN( "min", XML_MIN ),
TOKEN( "min-axis-type", XML_MIN_AXIS_TYPE ),
TOKEN( "min-denominator-digits", XML_MIN_DENOMINATOR_DIGITS ),
TOKEN( "min-edge", XML_MIN_EDGE ),
TOKEN( "min-exponent-digits", XML_MIN_EXPONENT_DIGITS ),
@@ -1358,7 +1378,8 @@ namespace xmloff::token {
TOKEN( "named-range", XML_NAMED_RANGE ),
TOKEN( "navigation-mode", XML_NAVIGATION_MODE ),
TOKEN( "navy", XML_NAVY ),
TOKEN( "negative-color", XML_NEGATIVE_COLOR ),
TOKEN( "negative", XML_NEGATIVE ),
TOKEN( "negative-color", XML_NEGATIVE_COLOR ),
TOKEN( "neq", XML_NEQ ),
TOKEN( "new", XML_NEW ),
TOKEN( "next", XML_NEXT ),
@@ -1619,6 +1640,7 @@ namespace xmloff::token {
TOKEN( "right", XML_RIGHT ),
TOKEN( "right-outside", XML_RIGHT_OUTSIDE ),
TOKEN( "right-text", XML_RIGHT_TEXT ),
TOKEN( "right-to-left", XML_RIGHT_TO_LEFT ),
TOKEN( "right-arc", XML_RIGHTARC ),
TOKEN( "right-circle", XML_RIGHTCIRCLE ),
TOKEN( "ring", XML_RING ),
@@ -1773,6 +1795,10 @@ namespace xmloff::token {
TOKEN( "source-range-address", XML_SOURCE_RANGE_ADDRESS ),
TOKEN( "source-service", XML_SOURCE_SERVICE ),
TOKEN( "space-before", XML_SPACE_BEFORE ),
TOKEN( "sparkline-groups", XML_SPARKLINE_GROUPS ),
TOKEN( "sparkline-group", XML_SPARKLINE_GROUP ),
TOKEN( "sparklines", XML_SPARKLINES ),
TOKEN( "sparkline", XML_SPARKLINE ),
TOKEN( "span", XML_SPAN ),
TOKEN( "specular", XML_SPECULAR ),
TOKEN( "specular-color", XML_SPECULAR_COLOR ),
diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt
index 8639006..da3080a 100644
--- a/xmloff/source/token/tokens.txt
+++ b/xmloff/source/token/tokens.txt
@@ -366,8 +366,16 @@ code
codebase
collapse
color
color-axis
color-first
color-high
color-inversion
color-last
color-low
color-markers
color-mode
color-negative
color-series
color-scale
color-scale-entry
color-table
@@ -510,6 +518,7 @@ data-pilot-subtotals
data-pilot-table
data-pilot-tables
data-point
data-range
data-stream-source
data-style
data-style-name
@@ -526,6 +535,7 @@ database-source-sql
database-source-table
database-table-name
date
date-axis
date-is
date-adjust
date-style
@@ -585,12 +595,15 @@ display-border
display-details
display-duplicates
display-empty
display-empty-cells-as
display-filter-buttons
display-formula
display-hidden
display-label
display-levels
display-name
display-outline-level
display-x-axis
dissolve
distance
distance-after-sep
@@ -1094,6 +1107,7 @@ line-number
line-skew
line-spacing
line-style
line-width
linear
linearGradient
linenumbering-configuration
@@ -1121,6 +1135,7 @@ log
logarithmic
logbase
long
low
lowlimit
lr-tb
lt
@@ -1134,6 +1149,8 @@ major-origin
maligngroup
malignmark
manual
manual-min
manual-max
map
margin-bottom
margin-left
@@ -1141,6 +1158,7 @@ margin-right
margin-top
margins
marker
markers
marker-end
marker-end-center
marker-end-width
@@ -1159,6 +1177,7 @@ matrix
matrix-covered
matrixrow
max
max-axis-type
max-edge
max-height
max-length
@@ -1184,6 +1203,7 @@ mi
middle
mime-type
min
min-axis-type
min-denominator-digits
min-edge
min-exponent-digits
@@ -1258,6 +1278,7 @@ named-expressions
named-range
navigation-mode
navy
negative
negative-color
neq
new
@@ -1519,6 +1540,7 @@ ridge
right
right-outside
right-text
right-to-left
right-arc
right-circle
ring
@@ -1673,6 +1695,10 @@ source-name
source-range-address
source-service
space-before
sparkline-groups
sparkline-group
sparklines
sparkline
span
specular
specular-color