Rebased ref, commits from common ancestor:
commit 30b6ff2279d4659ef9936563231414b740a1e61e
Author: Tomaž Vajngerl <[email protected]>
AuthorDate: Thu Feb 24 18:04:37 2022 +0900
Commit: Tomaž Vajngerl <[email protected]>
CommitDate: Thu Feb 24 20:32:17 2022 +0900
sc: first simple test for Sparklines
Change-Id: I513571de398be419074d54c5861374effae07709
diff --git a/sc/CppunitTest_sc_sparkline_test.mk
b/sc/CppunitTest_sc_sparkline_test.mk
new file mode 100644
index 000000000000..edf7a3cac7da
--- /dev/null
+++ b/sc/CppunitTest_sc_sparkline_test.mk
@@ -0,0 +1,60 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# 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/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,sc_sparkline_test))
+
+$(eval $(call gb_CppunitTest_use_common_precompiled_header,sc_sparkline_test))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,sc_sparkline_test, \
+ sc/qa/extras/SparklineTest \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,sc_sparkline_test, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ salhelper \
+ sax \
+ sc \
+ scqahelper \
+ sfx \
+ subsequenttest \
+ test \
+ tl \
+ unotest \
+ vcl \
+))
+
+$(eval $(call gb_CppunitTest_set_include,sc_sparkline_test,\
+ -I$(SRCDIR)/sc/source/ui/inc \
+ -I$(SRCDIR)/sc/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_api,sc_sparkline_test,\
+ offapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,sc_sparkline_test))
+
+$(eval $(call gb_CppunitTest_use_ure,sc_sparkline_test))
+$(eval $(call gb_CppunitTest_use_vcl,sc_sparkline_test))
+
+$(eval $(call gb_CppunitTest_use_rdb,sc_sparkline_test,services))
+
+$(eval $(call gb_CppunitTest_use_components,sc_sparkline_test))
+
+$(eval $(call gb_CppunitTest_use_configuration,sc_sparkline_test))
+
+# vim: set noet sw=4 ts=4:
diff --git a/sc/Module_sc.mk b/sc/Module_sc.mk
index c37b37dd2a14..d877627b20e2 100644
--- a/sc/Module_sc.mk
+++ b/sc/Module_sc.mk
@@ -204,6 +204,7 @@ $(eval $(call gb_Module_add_subsequentcheck_targets,sc,\
CppunitTest_sc_sheetlinkobj \
CppunitTest_sc_sheetlinksobj \
CppunitTest_sc_sortdescriptorbaseobj \
+ CppunitTest_sc_sparkline_test \
CppunitTest_sc_spreadsheetsettings \
CppunitTest_sc_spreadsheetsettingsobj \
CppunitTest_sc_styleobj \
diff --git a/sc/qa/extras/SparklineTest.cxx b/sc/qa/extras/SparklineTest.cxx
new file mode 100644
index 000000000000..dc7e308b991a
--- /dev/null
+++ b/sc/qa/extras/SparklineTest.cxx
@@ -0,0 +1,79 @@
+/* -*- 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 <test/calc_unoapi_test.hxx>
+
+#include <com/sun/star/lang/XComponent.hpp>
+#include <docsh.hxx>
+
+using namespace css;
+
+namespace sc_apitest
+{
+class SparklineTest : public CalcUnoApiTest
+{
+ uno::Reference<lang::XComponent> mxComponent;
+
+public:
+ SparklineTest();
+
+ void testSparklines();
+
+ CPPUNIT_TEST_SUITE(SparklineTest);
+ CPPUNIT_TEST(testSparklines);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+SparklineTest::SparklineTest()
+ : CalcUnoApiTest("sc/qa/extras/testdocuments")
+{
+}
+
+void SparklineTest::testSparklines()
+{
+ OUString aFileURL;
+ createFileURL(u"Sparklines.xlsx", aFileURL);
+ mxComponent = loadFromDesktop(aFileURL);
+
+ SfxObjectShell* pFoundShell =
SfxObjectShell::GetShellFromComponent(mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
+ ScDocShellRef xDocSh = dynamic_cast<ScDocShell*>(pFoundShell);
+ CPPUNIT_ASSERT(xDocSh);
+
+ ScDocument& rDocument = xDocSh->GetDocument();
+ {
+ sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(0, 1,
0)); // A2
+ CPPUNIT_ASSERT(pSparkline);
+ }
+ {
+ sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(0, 2,
0)); // A3
+ CPPUNIT_ASSERT(pSparkline);
+ }
+ {
+ sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(1, 0,
1)); //B1
+ CPPUNIT_ASSERT(pSparkline);
+ }
+ {
+ sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(1, 1,
1)); //B2
+ CPPUNIT_ASSERT(pSparkline);
+ }
+ {
+ sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(0, 3, 0));
+ CPPUNIT_ASSERT(!pSparkline);
+ }
+
+ closeDocument(mxComponent);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SparklineTest);
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/qa/extras/testdocuments/Sparklines.xlsx
b/sc/qa/extras/testdocuments/Sparklines.xlsx
new file mode 100644
index 000000000000..0ae84bd3e5be
Binary files /dev/null and b/sc/qa/extras/testdocuments/Sparklines.xlsx differ
commit b0f6cfef95ae18df87439ad5ccbd99f21c0cc683
Author: Tomaž Vajngerl <[email protected]>
AuthorDate: Thu Feb 24 17:43:00 2022 +0900
Commit: Tomaž Vajngerl <[email protected]>
CommitDate: Thu Feb 24 20:32:17 2022 +0900
sc: initial code to draw sparkline into a cell
Change-Id: I82861f4210a24f57573f0ec96489e86ab168677b
diff --git a/sc/source/ui/inc/output.hxx b/sc/source/ui/inc/output.hxx
index 61873156d264..d44f7052589b 100644
--- a/sc/source/ui/inc/output.hxx
+++ b/sc/source/ui/inc/output.hxx
@@ -382,6 +382,7 @@ public:
void DrawNoteMarks(vcl::RenderContext& rRenderContext);
void AddPDFNotes();
+ void DrawSparklines(vcl::RenderContext& rRenderContext);
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx
index 4db0e20ce5a4..ea7db6881755 100644
--- a/sc/source/ui/view/gridwin4.cxx
+++ b/sc/source/ui/view/gridwin4.cxx
@@ -903,6 +903,8 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const
ScTableInfo& rTableI
aOutputData.DrawShadow();
aOutputData.DrawFrame(*pContentDev);
+ aOutputData.DrawSparklines(*pContentDev);
+
// Show Note Mark
if ( rOpts.GetOption( VOPT_NOTES ) )
aOutputData.DrawNoteMarks(*pContentDev);
diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx
index 11a39fb825bf..51535123e208 100644
--- a/sc/source/ui/view/output.cxx
+++ b/sc/source/ui/view/output.cxx
@@ -30,7 +30,6 @@
#include <svx/framelinkarray.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <drawinglayer/processor2d/baseprocessor2d.hxx>
-#include <basegfx/matrix/b2dhommatrix.hxx>
#include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
#include <vcl/lineinfo.hxx>
#include <vcl/gradient.hxx>
@@ -39,6 +38,10 @@
#include <sal/log.hxx>
#include <comphelper/lok.hxx>
#include <o3tl/unit_conversion.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/range/b2drectangle.hxx>
#include <output.hxx>
#include <document.hxx>
@@ -60,6 +63,7 @@
#include <detfunc.hxx>
#include <colorscale.hxx>
+#include <Sparkline.hxx>
#include <math.h>
#include <memory>
@@ -2309,6 +2313,200 @@ void ScOutputData::DrawChangeTrack()
}
}
+namespace
+{
+
+void drawLine(vcl::RenderContext& rRenderContext, tools::Rectangle const &
rRectangle,
+ std::vector<double> const & rValues, double nMin, double nMax)
+{
+ basegfx::B2DPolygon aPolygon;
+ double numebrOfSteps = rValues.size() - 1;
+ double xStep = 0;
+ double nDelta = nMax - nMin;
+
+ for (double aValue : rValues)
+ {
+ double nP = (aValue - nMin) / nDelta;
+ double x = rRectangle.GetWidth() * (xStep / numebrOfSteps);
+ double y = rRectangle.GetHeight() - rRectangle.GetHeight() * nP;
+
+ aPolygon.append({ x, y } );
+ xStep++;
+ }
+
+ basegfx::B2DHomMatrix aMatrix;
+ aMatrix.translate(rRectangle.Left(), rRectangle.Top());
+ aPolygon.transform(aMatrix);
+
+ rRenderContext.DrawPolyLine(aPolygon);
+}
+
+void drawColumn(vcl::RenderContext& rRenderContext, tools::Rectangle const &
rRectangle,
+ std::vector<double> const & rValues, double nMin, double nMax)
+{
+ basegfx::B2DPolygon aPolygon;
+
+ double xStep = 0;
+ double numberOfSteps = rValues.size();
+ double nDelta = nMax - nMin;
+
+ double nColumnSize = rRectangle.GetWidth() / numberOfSteps;
+
+ double nZero = (0 - nMin) / nDelta;
+ double nZeroPosition;
+ if (nZero >= 0)
+ nZeroPosition = rRectangle.GetHeight() - rRectangle.GetHeight() *
nZero;
+ else
+ nZeroPosition = rRectangle.GetHeight();
+
+ for (double aValue : rValues)
+ {
+ if (aValue != 0.0)
+ {
+ double nP = (aValue - nMin) / nDelta;
+ double x = rRectangle.GetWidth() * (xStep / numberOfSteps);
+ double y = rRectangle.GetHeight() - rRectangle.GetHeight() * nP;
+
+ basegfx::B2DRectangle aRectangle(x, y, x + nColumnSize,
nZeroPosition);
+ aPolygon = basegfx::utils::createPolygonFromRect(aRectangle);
+
+ basegfx::B2DHomMatrix aMatrix;
+ aMatrix.translate(rRectangle.Left(), rRectangle.Top());
+ aPolygon.transform(aMatrix);
+ rRenderContext.DrawPolygon(aPolygon);
+ }
+ xStep++;
+ }
+}
+
+void drawSparkline(sc::Sparkline* pSparkline, vcl::RenderContext&
rRenderContext, ScDocument* pDocument,
+ tools::Rectangle const & rRectangle)
+{
+ auto const & rRangeList = pSparkline->getInputRange();
+
+ if (rRangeList.empty())
+ return;
+
+ auto pSparklineGroup = pSparkline->getSparklineGroup();
+
+ rRenderContext.SetAntialiasing(AntialiasingFlags::Enable);
+
+ rRenderContext.SetLineColor(pSparklineGroup->m_aColorSeries);
+ rRenderContext.SetFillColor(pSparklineGroup->m_aColorSeries);
+
+ ScRange aRange = rRangeList[0];
+
+ std::vector<double> aValues;
+
+ double nMin = std::numeric_limits<double>::max();
+ double nMax = std::numeric_limits<double>::min();
+
+ if (aRange.aStart.Row() == aRange.aEnd.Row())
+ {
+ ScAddress aAddress = aRange.aStart;
+
+ while (aAddress.Col() <= aRange.aEnd.Col())
+ {
+ double fCellValue = pDocument->GetValue(aAddress);
+ aValues.push_back(fCellValue);
+ if (fCellValue < nMin)
+ nMin = fCellValue;
+ if (fCellValue > nMax)
+ nMax = fCellValue;
+ aAddress.IncCol();
+ }
+ }
+ else if (aRange.aStart.Col() == aRange.aEnd.Col())
+ {
+ ScAddress aAddress = aRange.aStart;
+
+ while (aAddress.Row() <= aRange.aEnd.Row())
+ {
+ double fCellValue = pDocument->GetValue(aAddress);
+ aValues.push_back(fCellValue);
+ if (fCellValue < nMin)
+ nMin = fCellValue;
+ if (fCellValue > nMax)
+ nMax = fCellValue;
+ aAddress.IncRow();
+ }
+ }
+
+ if (pSparklineGroup->m_sType == "column")
+ {
+ drawColumn(rRenderContext, rRectangle, aValues, nMin, nMax);
+ }
+ else if (pSparklineGroup->m_sType == "stacked")
+ {
+ for (auto & rValue : aValues)
+ {
+ if (rValue != 0.0)
+ rValue = rValue > 0.0 ? 1.0 : -1.0;
+ }
+ drawColumn(rRenderContext, rRectangle, aValues, -1, 1);
+ }
+ else if (pSparklineGroup->m_sType == "line")
+ {
+ drawLine(rRenderContext, rRectangle, aValues, nMin, nMax);
+ }
+}
+} // end anonymous namespace
+
+void ScOutputData::DrawSparklines(vcl::RenderContext& rRenderContext)
+{
+ tools::Long nInitPosX = nScrX;
+ if ( bLayoutRTL )
+ nInitPosX += nMirrorW - 1; // always in pixels
+ tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
+
+ tools::Long nPosY = nScrY;
+ for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
+ {
+ RowInfo* pThisRowInfo = &pRowInfo[nArrY];
+ if ( pThisRowInfo->bChanged )
+ {
+ tools::Long nPosX = nInitPosX;
+ for (SCCOL nX=nX1; nX<=nX2; nX++)
+ {
+ CellInfo* pInfo = &pThisRowInfo->cellInfo(nX);
+ bool bIsMerged = false;
+
+ if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped )
+ {
+ // find start of merged cell
+ bIsMerged = true;
+ SCROW nY = pRowInfo[nArrY].nRowNo;
+ SCCOL nMergeX = nX;
+ SCROW nMergeY = nY;
+ mpDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab );
+ }
+
+ sc::Sparkline* pSparkline = nullptr;
+ ScAddress aCurrentAddress(nX, pRowInfo[nArrY].nRowNo, nTab);
+
+ if (!mpDoc->ColHidden(nX, nTab) && (pSparkline =
mpDoc->GetSparkline(aCurrentAddress))
+ && (bIsMerged || (!pInfo->bHOverlapped &&
!pInfo->bVOverlapped)))
+ {
+ constexpr tools::Long constMarginX = 6;
+ constexpr tools::Long constMarginY = 3;
+
+ const tools::Long nWidth = pRowInfo[0].cellInfo(nX).nWidth;
+ const tools::Long nHeight = pThisRowInfo->nHeight;
+
+ Point aPoint(nPosX + constMarginX , nPosY + constMarginY);
+ Size aSize(nWidth - 2 * constMarginX, nHeight - 2 *
constMarginY);
+
+ drawSparkline(pSparkline, rRenderContext, mpDoc,
tools::Rectangle(aPoint, aSize));
+ }
+
+ nPosX += pRowInfo[0].cellInfo(nX).nWidth * nLayoutSign;
+ }
+ }
+ nPosY += pThisRowInfo->nHeight;
+ }
+
+}
+
//TODO: moggi Need to check if this can't be written simpler
void ScOutputData::DrawNoteMarks(vcl::RenderContext& rRenderContext)
{
commit 50ec87403e7f4d571cadfa05255b5f9d26f2b848
Author: Tomaž Vajngerl <[email protected]>
AuthorDate: Wed Feb 23 10:06:20 2022 +0900
Commit: Tomaž Vajngerl <[email protected]>
CommitDate: Thu Feb 24 20:32:17 2022 +0900
sc: write the OOXML Sparkline props. to the model
Change-Id: I09ecf560f1870624cb984722bdb8ee306d839dfe
diff --git a/sc/inc/SparklineGroup.hxx b/sc/inc/SparklineGroup.hxx
index 250488671190..abc1cc71333c 100644
--- a/sc/inc/SparklineGroup.hxx
+++ b/sc/inc/SparklineGroup.hxx
@@ -11,6 +11,7 @@
#pragma once
#include "scdllapi.h"
+#include <tools/color.hxx>
#include <optional>
namespace sc
@@ -18,6 +19,40 @@ namespace sc
class SC_DLLPUBLIC SparklineGroup
{
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;
+
SparklineGroup() {}
SparklineGroup(const SparklineGroup&) = delete;
diff --git a/sc/source/filter/inc/SparklineFragment.hxx
b/sc/source/filter/inc/SparklineFragment.hxx
index 36a7b5ca9f05..de1f9ae7ebda 100644
--- a/sc/source/filter/inc/SparklineFragment.hxx
+++ b/sc/source/filter/inc/SparklineFragment.hxx
@@ -11,10 +11,10 @@
#include "excelhandlers.hxx"
#include <oox/core/contexthandler.hxx>
+#include <SparklineGroup.hxx>
#include <vector>
#include <memory>
-#include <optional>
namespace oox
{
@@ -36,40 +36,15 @@ 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
+ std::shared_ptr<sc::SparklineGroup> m_pSparklineGroup;
- 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;
+public:
+ SparklineGroup()
+ : m_pSparklineGroup(new sc::SparklineGroup())
+ {
+ }
- std::optional<double> m_aManualMax;
- std::optional<double> m_aManualMin;
- OUString m_sUID;
+ std::shared_ptr<sc::SparklineGroup> getSparklineGroup() { return
m_pSparklineGroup; }
std::vector<Sparkline>& getSparklines() { return m_aSparklines; }
};
@@ -87,6 +62,8 @@ public:
void onStartElement(const AttributeList& rAttribs) override;
void onCharacters(const OUString& rCharacters) override;
void onEndElement() override;
+
+ void insertSparkline(SparklineGroup& rSparklineGroup, Sparkline&
rSparkline);
};
} //namespace oox::xls
diff --git a/sc/source/filter/oox/SparklineFragment.cxx
b/sc/source/filter/oox/SparklineFragment.cxx
index a743b886b7db..bfc5a259a883 100644
--- a/sc/source/filter/oox/SparklineFragment.cxx
+++ b/sc/source/filter/oox/SparklineFragment.cxx
@@ -15,6 +15,8 @@
#include <oox/helper/attributelist.hxx>
#include <document.hxx>
#include <rangeutl.hxx>
+#include <Sparkline.hxx>
+#include <themebuffer.hxx>
using ::oox::core::ContextHandlerRef;
@@ -22,51 +24,74 @@ namespace oox::xls
{
namespace
{
-Color getColor(const AttributeList& rAttribs)
+// TODO: deduplicate with importOOXColor
+::Color getColor(const AttributeList& rAttribs, ThemeBuffer const&
rThemeBuffer)
{
if (rAttribs.hasAttribute(XML_rgb))
{
- return Color(ColorTransparency,
- rAttribs.getIntegerHex(XML_rgb,
sal_Int32(API_RGB_TRANSPARENT)));
+ return ::Color(ColorAlpha, rAttribs.getIntegerHex(XML_rgb,
sal_Int32(API_RGB_TRANSPARENT)));
}
- return Color();
+ else if (rAttribs.hasAttribute(XML_theme))
+ {
+ sal_uInt32 nThemeIndex = rAttribs.getUnsigned(XML_theme, 0);
+
+ // Excel has a bug in the mapping of index 0, 1, 2 and 3.
+ if (nThemeIndex == 0)
+ nThemeIndex = 1;
+ else if (nThemeIndex == 1)
+ nThemeIndex = 0;
+ else if (nThemeIndex == 2)
+ nThemeIndex = 3;
+ else if (nThemeIndex == 3)
+ nThemeIndex = 2;
+
+ ::Color aColor = rThemeBuffer.getColorByIndex(nThemeIndex);
+ double nTint = rAttribs.getDouble(XML_tint, 0.0);
+
+ if (nTint > 0.0)
+ aColor.ApplyTintOrShade(nTint * 10000);
+ return aColor;
+ }
+
+ return ::Color();
}
-void addColorsToSparklineGroup(SparklineGroup& rSparklineGroup, sal_Int32
nElement,
- const AttributeList& rAttribs)
+void addColorsToSparklineGroup(sc::SparklineGroup& rSparklineGroup, sal_Int32
nElement,
+ const AttributeList& rAttribs, ThemeBuffer&
rThemeBuffer)
{
switch (nElement)
{
case XLS14_TOKEN(colorSeries):
- rSparklineGroup.m_aColorSeries = getColor(rAttribs);
+ rSparklineGroup.m_aColorSeries = getColor(rAttribs, rThemeBuffer);
break;
case XLS14_TOKEN(colorNegative):
- rSparklineGroup.m_aColorNegative = getColor(rAttribs);
+ rSparklineGroup.m_aColorNegative = getColor(rAttribs,
rThemeBuffer);
break;
case XLS14_TOKEN(colorAxis):
- rSparklineGroup.m_aColorAxis = getColor(rAttribs);
+ rSparklineGroup.m_aColorAxis = getColor(rAttribs, rThemeBuffer);
break;
case XLS14_TOKEN(colorMarkers):
- rSparklineGroup.m_aColorMarkers = getColor(rAttribs);
+ rSparklineGroup.m_aColorMarkers = getColor(rAttribs, rThemeBuffer);
break;
case XLS14_TOKEN(colorFirst):
- rSparklineGroup.m_aColorFirst = getColor(rAttribs);
+ rSparklineGroup.m_aColorFirst = getColor(rAttribs, rThemeBuffer);
break;
case XLS14_TOKEN(colorLast):
- rSparklineGroup.m_aColorLast = getColor(rAttribs);
+ rSparklineGroup.m_aColorLast = getColor(rAttribs, rThemeBuffer);
break;
case XLS14_TOKEN(colorHigh):
- rSparklineGroup.m_aColorHigh = getColor(rAttribs);
+ rSparklineGroup.m_aColorHigh = getColor(rAttribs, rThemeBuffer);
break;
case XLS14_TOKEN(colorLow):
- rSparklineGroup.m_aColorLow = getColor(rAttribs);
+ rSparklineGroup.m_aColorLow = getColor(rAttribs, rThemeBuffer);
break;
default:
break;
}
}
-void addAttributesToSparklineGroup(SparklineGroup& rSparklineGroup, const
AttributeList& rAttribs)
+void addAttributesToSparklineGroup(sc::SparklineGroup& rSparklineGroup,
+ const AttributeList& rAttribs)
{
auto oManualMax = rAttribs.getDouble(XML_manualMax);
auto oManualMin = rAttribs.getDouble(XML_manualMin);
@@ -116,7 +141,7 @@ ContextHandlerRef
SparklineGroupsContext::onCreateContext(sal_Int32 nElement,
case XLS14_TOKEN(sparklineGroup):
{
auto& rLastGroup = m_aSparklineGroups.emplace_back();
- addAttributesToSparklineGroup(rLastGroup, rAttribs);
+ addAttributesToSparklineGroup(*rLastGroup.getSparklineGroup(),
rAttribs);
return this;
}
case XLS14_TOKEN(colorSeries):
@@ -129,7 +154,8 @@ ContextHandlerRef
SparklineGroupsContext::onCreateContext(sal_Int32 nElement,
case XLS14_TOKEN(colorLow):
{
auto& rLastGroup = m_aSparklineGroups.back();
- addColorsToSparklineGroup(rLastGroup, nElement, rAttribs);
+ addColorsToSparklineGroup(*rLastGroup.getSparklineGroup(),
nElement, rAttribs,
+ getTheme());
return this;
}
case XLS14_TOKEN(sparklines):
@@ -155,7 +181,6 @@ void SparklineGroupsContext::onCharacters(const OUString&
rChars)
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))
@@ -182,7 +207,32 @@ void SparklineGroupsContext::onCharacters(const OUString&
rChars)
}
}
-void SparklineGroupsContext::onEndElement() {}
+void SparklineGroupsContext::onEndElement()
+{
+ if (getCurrentElement() == XLS14_TOKEN(sparklineGroup))
+ {
+ auto& rLastGroup = m_aSparklineGroups.back();
+ for (Sparkline& rSparkline : rLastGroup.getSparklines())
+ {
+ insertSparkline(rLastGroup, rSparkline);
+ }
+ }
+}
+
+void SparklineGroupsContext::insertSparkline(SparklineGroup& rSparklineGroup,
Sparkline& rSparkline)
+{
+ auto& rDocument = getScDocument();
+ if (rSparkline.m_aTargetRange.size() == 1)
+ {
+ auto& rRange = rSparkline.m_aTargetRange[0];
+ if (rRange.aStart == rRange.aEnd)
+ {
+ auto pSparklineGroup = rSparklineGroup.getSparklineGroup();
+ auto* pCreated = rDocument.CreateSparkline(rRange.aStart,
pSparklineGroup);
+ pCreated->setInputRange(rSparkline.m_aInputRange);
+ }
+ }
+}
} //namespace oox::xls
commit f51fc2e05be4c39debb55f33b173e61747b74367
Author: Tomaž Vajngerl <[email protected]>
AuthorDate: Wed Feb 23 09:52:50 2022 +0900
Commit: Tomaž Vajngerl <[email protected]>
CommitDate: Thu Feb 24 20:32:17 2022 +0900
sc: add Sparkline to the model as a column multi_type_vector
Change-Id: Id309ded34bfa7a35c1be43f7c0543d88594e66ff
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 62ab22a797c4..11449217edd9 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -185,6 +185,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/data/sheetevents \
sc/source/core/data/simpleformulacalc \
sc/source/core/data/sortparam \
+ sc/source/core/data/Sparkline \
sc/source/core/data/stlpool \
sc/source/core/data/stlsheet \
sc/source/core/data/subtotalparam \
diff --git a/sc/inc/Sparkline.hxx b/sc/inc/Sparkline.hxx
new file mode 100644
index 000000000000..8969fa3bfd3e
--- /dev/null
+++ b/sc/inc/Sparkline.hxx
@@ -0,0 +1,40 @@
+/* -*- 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 "scdllapi.h"
+#include "SparklineGroup.hxx"
+#include "rangelst.hxx"
+#include <memory>
+
+namespace sc
+{
+class SC_DLLPUBLIC Sparkline
+{
+private:
+ ScRangeList m_aInputRange;
+ std::shared_ptr<SparklineGroup> m_pSparklineGroup;
+
+public:
+ Sparkline(std::shared_ptr<SparklineGroup>& pSparklineGroup);
+
+ Sparkline(const Sparkline&) = delete;
+ Sparkline& operator=(const Sparkline&) = delete;
+
+ void setInputRange(ScRangeList const& rInputRange) { m_aInputRange =
rInputRange; }
+ ScRangeList const& getInputRange() { return m_aInputRange; }
+
+ std::shared_ptr<SparklineGroup> const& getSparklineGroup() { return
m_pSparklineGroup; }
+};
+
+} // end sc
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/SparklineGroup.hxx b/sc/inc/SparklineGroup.hxx
new file mode 100644
index 000000000000..250488671190
--- /dev/null
+++ b/sc/inc/SparklineGroup.hxx
@@ -0,0 +1,29 @@
+/* -*- 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 "scdllapi.h"
+#include <optional>
+
+namespace sc
+{
+class SC_DLLPUBLIC SparklineGroup
+{
+public:
+ SparklineGroup() {}
+
+ SparklineGroup(const SparklineGroup&) = delete;
+ SparklineGroup& operator=(const SparklineGroup&) = delete;
+};
+
+} // end sc
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 2e1f0df49bdb..4c711b9944dc 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -65,6 +65,7 @@ class CompileFormulaContext;
struct SetFormulaDirtyContext;
enum class MatrixEdge;
class ColumnIterator;
+class Sparkline;
}
@@ -99,7 +100,7 @@ struct ScInterpreterContext;
struct ScNeededSizeOptions
{
- const ScPatternAttr* pPattern;
+ const ScPatternAttr* pPattern;
bool bFormula;
bool bSkipMerged;
bool bGetFont;
@@ -126,6 +127,9 @@ class ScColumn
// Cell values.
sc::CellStoreType maCells;
+ // Sparklines
+ sc::SparklineStoreType maSparklines;
+
std::unique_ptr<ScAttrArray> pAttrArray;
size_t mnBlkCountFormula;
@@ -612,6 +616,10 @@ public:
void BroadcastCells( const std::vector<SCROW>& rRows, SfxHintId nHint );
void BroadcastRows( SCROW nStartRow, SCROW nEndRow, SfxHintId nHint );
+ // Spaklines
+ sc::Sparkline* GetSparkline(SCROW nRow);
+ void SetSparkline(SCROW nRow, std::unique_ptr<sc::Sparkline> pSparkline);
+
// cell notes
ScPostIt* GetCellNote( SCROW nRow );
const ScPostIt* GetCellNote( SCROW nRow ) const;
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index a53c9334d47f..d0ef2006846e 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -101,6 +101,8 @@ class UpdatedRangeNames;
class TableColumnBlockPositionSet;
class ColumnIterator;
class ExternalDataMapper;
+class Sparkline;
+class SparklineGroup;
}
@@ -1235,6 +1237,10 @@ public:
*/
sc::MultiDataCellState HasMultipleDataCells( const ScRange& rRange ) const;
+ /** Spaklines */
+ SC_DLLPUBLIC sc::Sparkline* GetSparkline(ScAddress const & rPosition);
+ SC_DLLPUBLIC sc::Sparkline* CreateSparkline(ScAddress const & rPosition,
std::shared_ptr<sc::SparklineGroup> & pSparklineGroup);
+
/** Notes **/
SC_DLLPUBLIC ScPostIt* GetNote(const ScAddress& rPos);
SC_DLLPUBLIC ScPostIt* GetNote(SCCOL nCol, SCROW nRow, SCTAB nTab);
@@ -1266,6 +1272,7 @@ public:
SC_DLLPUBLIC void GetAllNoteEntries( std::vector<sc::NoteEntry>& rNotes )
const;
SC_DLLPUBLIC void GetAllNoteEntries( SCTAB nTab,
std::vector<sc::NoteEntry>& rNotes ) const;
void GetNotesInRange( const ScRangeList& rRange,
std::vector<sc::NoteEntry>& rNotes ) const;
+
bool ContainsNotesInRange( const ScRangeList& rRange ) const;
SC_DLLPUBLIC void SetDrawPageSize(SCTAB nTab);
diff --git a/sc/inc/mtvelements.hxx b/sc/inc/mtvelements.hxx
index 05a0970bd64d..979a09c641db 100644
--- a/sc/inc/mtvelements.hxx
+++ b/sc/inc/mtvelements.hxx
@@ -15,6 +15,7 @@
#include <editeng/editobj.hxx>
#include "calcmacros.hxx"
#include "postit.hxx"
+#include "Sparkline.hxx"
#include "celltextattr.hxx"
#if DEBUG_COLUMN_STORAGE
@@ -49,6 +50,7 @@ const mdds::mtv::element_t element_type_edittext =
mdds::mtv::element_type_user_
const mdds::mtv::element_t element_type_formula =
mdds::mtv::element_type_user_start + 4;
const mdds::mtv::element_t element_type_cellnote =
mdds::mtv::element_type_user_start + 5;
+const mdds::mtv::element_t element_type_sparkline =
mdds::mtv::element_type_user_start + 6;
/// Mapped standard element types (for convenience).
const mdds::mtv::element_t element_type_numeric =
mdds::mtv::element_type_double;
@@ -57,6 +59,7 @@ const mdds::mtv::element_t element_type_uint16 =
mdds::mtv::element_type_uint16;
/// Custom element blocks.
+typedef mdds::mtv::noncopyable_managed_element_block<element_type_sparkline,
sc::Sparkline> sparkline_block;
typedef mdds::mtv::noncopyable_managed_element_block<element_type_cellnote,
ScPostIt> cellnote_block;
typedef mdds::mtv::noncopyable_managed_element_block<element_type_broadcaster,
SvtBroadcaster> broadcaster_block;
typedef mdds::mtv::default_element_block<element_type_celltextattr,
CellTextAttr> celltextattr_block;
@@ -68,8 +71,13 @@ typedef
mdds::mtv::noncopyable_managed_element_block<element_type_formula, ScFor
typedef mdds::mtv::double_element_block numeric_block;
typedef mdds::mtv::uint16_element_block uint16_block;
-/// This needs to be in the same namespace as CellTextAttr.
+} // end sc namespace
+
+/// CAUTION! The following defines must be in the same namespace as the
respective type.
+/// For example sc types like sc::CellTextAttr, ScFormulaCell in global
namespace.
+namespace sc {
MDDS_MTV_DEFINE_ELEMENT_CALLBACKS(CellTextAttr, element_type_celltextattr,
CellTextAttr(), celltextattr_block)
+MDDS_MTV_DEFINE_ELEMENT_CALLBACKS_PTR(Sparkline, sc::element_type_sparkline,
nullptr, sc::sparkline_block)
}
/// These need to be in global namespace just like their respective types are.
@@ -79,9 +87,7 @@ MDDS_MTV_DEFINE_ELEMENT_CALLBACKS_PTR(ScFormulaCell,
sc::element_type_formula, n
MDDS_MTV_DEFINE_ELEMENT_CALLBACKS_PTR(EditTextObject,
sc::element_type_edittext, nullptr, sc::edittext_block)
namespace svl {
-
MDDS_MTV_DEFINE_ELEMENT_CALLBACKS(SharedString, sc::element_type_string,
SharedString(), sc::string_block)
-
}
namespace sc {
@@ -106,6 +112,10 @@ struct CellStoreTrait
static constexpr mdds::mtv::lu_factor_t loop_unrolling =
mdds::mtv::lu_factor_t::lu16;
};
+/// Sparkline container
+typedef mdds::mtv::custom_block_func1<sc::sparkline_block> CSparklineFunction;
+typedef mdds::mtv::soa::multi_type_vector<CSparklineFunction>
SparklineStoreType;
+
/// Cell note container
typedef mdds::mtv::custom_block_func1<sc::cellnote_block> CNoteFunc;
typedef mdds::mtv::soa::multi_type_vector<CNoteFunc> CellNoteStoreType;
diff --git a/sc/source/core/data/Sparkline.cxx
b/sc/source/core/data/Sparkline.cxx
new file mode 100644
index 000000000000..301fda820ff2
--- /dev/null
+++ b/sc/source/core/data/Sparkline.cxx
@@ -0,0 +1,22 @@
+/* -*- 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 <memory>
+#include <Sparkline.hxx>
+
+namespace sc
+{
+Sparkline::Sparkline(std::shared_ptr<SparklineGroup>& pSparklineGroup)
+ : m_pSparklineGroup(pSparklineGroup)
+{
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 167a3541f511..59c251be3d70 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -84,6 +84,7 @@ ScColumn::ScColumn(ScSheetLimits const & rSheetLimits) :
maCellNotes(rSheetLimits.GetMaxRowCount()),
maBroadcasters(rSheetLimits.GetMaxRowCount()),
maCells(sc::CellStoreEvent(this)),
+ maSparklines(rSheetLimits.GetMaxRowCount()),
mnBlkCountFormula(0),
nCol( 0 ),
nTab( 0 ),
@@ -877,6 +878,9 @@ void ScColumn::InsertRow( SCROW nStartRow, SCSIZE nSize )
maCellNotes.insert_empty(nStartRow, nSize);
maCellNotes.resize(GetDoc().GetSheetLimits().GetMaxRowCount());
+ maSparklines.insert_empty(nStartRow, nSize);
+ maSparklines.resize(GetDoc().GetSheetLimits().GetMaxRowCount());
+
maBroadcasters.insert_empty(nStartRow, nSize);
maBroadcasters.resize(GetDoc().GetSheetLimits().GetMaxRowCount());
@@ -1973,6 +1977,7 @@ void ScColumn::SwapCol(ScColumn& rCol)
maCells.swap(rCol.maCells);
maCellTextAttrs.swap(rCol.maCellTextAttrs);
maCellNotes.swap(rCol.maCellNotes);
+ maSparklines.swap(rCol.maSparklines);
// Swap all CellStoreEvent mdds event_func related.
std::swap( mnBlkCountFormula, rCol.mnBlkCountFormula);
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 042b1eafbe25..9eb661e49d9d 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1977,6 +1977,16 @@ void ScColumn::PrepareBroadcastersForDestruction()
}
}
+sc::Sparkline* ScColumn::GetSparkline(SCROW nRow)
+{
+ return maSparklines.get<sc::Sparkline*>(nRow);
+}
+
+void ScColumn::SetSparkline(SCROW nRow, std::unique_ptr<sc::Sparkline>
pSparkline)
+{
+ maSparklines.set(nRow, pSparkline.release());
+}
+
ScPostIt* ScColumn::GetCellNote(SCROW nRow)
{
return maCellNotes.get<ScPostIt*>(nRow);
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index e34aac4d135c..0d07278f7db5 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -148,6 +148,7 @@ void ScColumn::Delete( SCROW nRow )
DeleteContent(nRow, false);
maCellTextAttrs.set_empty(nRow, nRow);
maCellNotes.set_empty(nRow, nRow);
+ maSparklines.set_empty(nRow, nRow);
Broadcast(nRow);
CellStorageModified();
@@ -165,6 +166,8 @@ void ScColumn::FreeAll()
maCellTextAttrs.resize(maxRowCount);
maCellNotes.clear();
maCellNotes.resize(maxRowCount);
+ maSparklines.clear();
+ maSparklines.resize(maxRowCount);
CellStorageModified();
}
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 6e0fc6468457..7f1eeab2d12a 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -6513,6 +6513,33 @@ bool ScDocument::IsInVBAMode() const
return false;
}
+sc::Sparkline* ScDocument::GetSparkline(ScAddress const& rPosition)
+{
+ SCTAB nTab = rPosition.Tab();
+ SCCOL nCol = rPosition.Col();
+
+ if (ValidTab(nTab) && nTab < SCTAB(maTabs.size()) &&
+ nCol < maTabs[nTab]->GetAllocatedColumnsCount())
+ {
+ SCROW nRow = rPosition.Row();
+ return maTabs[nTab]->aCol[nCol].GetSparkline(nRow);
+ }
+ return nullptr;
+}
+
+sc::Sparkline* ScDocument::CreateSparkline(ScAddress const & rPosition,
std::shared_ptr<sc::SparklineGroup> & pSparklineGroup)
+{
+ std::unique_ptr<sc::Sparkline> pSparkline(new
sc::Sparkline(pSparklineGroup));
+ sc::Sparkline* pCreated = pSparkline.get();
+
+ SCTAB nTab = rPosition.Tab();
+ SCCOL nCol = rPosition.Col();
+ SCROW nRow = rPosition.Row();
+ maTabs[nTab]->CreateColumnIfNotExists(nCol).SetSparkline(nRow,
std::move(pSparkline));
+
+ return pCreated;
+}
+
ScPostIt* ScDocument::GetNote(const ScAddress& rPos)
{
return GetNote(rPos.Col(), rPos.Row(), rPos.Tab());
commit 0963873522cd71aecc022ac36a3a532cc384f2f8
Author: Tomaž Vajngerl <[email protected]>
AuthorDate: Thu Feb 17 12:43:34 2022 +0900
Commit: Tomaž Vajngerl <[email protected]>
CommitDate: Thu Feb 24 20:32:04 2022 +0900
sc: support reading sparklines from OOXML document
Change-Id: Id2d34db70300957735571875d6defb3d560fbb26
diff --git a/oox/source/token/tokens.txt b/oox/source/token/tokens.txt
index 328a94a23727..593ef0b23a5d 100644
--- a/oox/source/token/tokens.txt
+++ b/oox/source/token/tokens.txt
@@ -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
@@ -5492,6 +5511,7 @@ ui8
uiCompat97To2003
uiExpand
uiPriority
+uid
uint
ulTrailSpace
un
diff --git a/sc/Library_scfilt.mk b/sc/Library_scfilt.mk
index 79170313b121..8e23db6662fa 100644
--- a/sc/Library_scfilt.mk
+++ b/sc/Library_scfilt.mk
@@ -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 \
diff --git a/sc/source/filter/inc/SparklineFragment.hxx
b/sc/source/filter/inc/SparklineFragment.hxx
new file mode 100644
index 000000000000..36a7b5ca9f05
--- /dev/null
+++ b/sc/source/filter/inc/SparklineFragment.hxx
@@ -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: */
diff --git a/sc/source/filter/inc/extlstcontext.hxx
b/sc/source/filter/inc/extlstcontext.hxx
index 80efe25b78fb..8635c6029523 100644
--- a/sc/source/filter/inc/extlstcontext.hxx
+++ b/sc/source/filter/inc/extlstcontext.hxx
@@ -70,19 +70,6 @@ private:
std::vector<ExtCondFormatRuleModel> maModels;
};
-class ExtSparklineGroupsContext : public WorksheetContextBase
-{
-private:
-
-public:
- explicit ExtSparklineGroupsContext(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;
-};
-
/**
* Handle ExtLst entries in xlsx. These entries are a way to extend the
standard
* without actually changing it
diff --git a/sc/source/filter/oox/SparklineFragment.cxx
b/sc/source/filter/oox/SparklineFragment.cxx
new file mode 100644
index 000000000000..a743b886b7db
--- /dev/null
+++ b/sc/source/filter/oox/SparklineFragment.cxx
@@ -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: */
diff --git a/sc/source/filter/oox/extlstcontext.cxx
b/sc/source/filter/oox/extlstcontext.cxx
index 6cd715229ff5..67d52fc69da9 100644
--- a/sc/source/filter/oox/extlstcontext.cxx
+++ b/sc/source/filter/oox/extlstcontext.cxx
@@ -22,6 +22,7 @@
#include <workbookfragment.hxx>
#include <stylesbuffer.hxx>
#include <stylesfragment.hxx>
+#include <SparklineFragment.hxx>
#include <rangeutl.hxx>
#include <sal/log.hxx>
@@ -298,28 +299,6 @@ void ExtConditionalFormattingContext::onEndElement()
}
}
-ExtSparklineGroupsContext::ExtSparklineGroupsContext(WorksheetContextBase&
rFragment)
- : WorksheetContextBase(rFragment)
-{
-}
-
-ContextHandlerRef ExtSparklineGroupsContext::onCreateContext(sal_Int32
nElement, const AttributeList&)
-{
-
-}
-
-void ExtSparklineGroupsContext::onStartElement(const AttributeList& )
-{
-}
-
-void ExtSparklineGroupsContext::onCharacters(const OUString& rChars)
-{
-}
-
-void ExtSparklineGroupsContext::onEndElement()
-{
-}
-
ExtLstLocalContext::ExtLstLocalContext( WorksheetContextBase& rFragment,
ScDataBarFormatData* pTarget ):
WorksheetContextBase(rFragment),
mpTarget(pTarget)
@@ -372,7 +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
ExtSparklineGroupsContext(*this);
+ case XLS14_TOKEN(sparklineGroups): return new
SparklineGroupsContext(*this);
}
return this;
}