Rebased ref, commits from common ancestor:
commit ff5ca3c47e4bca3ed669655540adfeb9385a5dbd
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Fri Mar 4 20:40:14 2022 +0900
Commit:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
CommitDate: Fri Mar 4 20:40:14 2022 +0900

    sc: Sparkline export for OOXML documents + roundtrip test
    
    Change-Id: I4ab93d7ad33867ae817aa98d13ea9bc724b7d710

diff --git a/sc/CppunitTest_sc_sparkline_test.mk 
b/sc/CppunitTest_sc_sparkline_test.mk
index edf7a3cac7da..00db7396cdb0 100644
--- a/sc/CppunitTest_sc_sparkline_test.mk
+++ b/sc/CppunitTest_sc_sparkline_test.mk
@@ -32,6 +32,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sc_sparkline_test, 
\
     test \
     tl \
     unotest \
+    utl \
     vcl \
 ))
 
diff --git a/sc/Library_scfilt.mk b/sc/Library_scfilt.mk
index 8e23db6662fa..84b6e5fd5edd 100644
--- a/sc/Library_scfilt.mk
+++ b/sc/Library_scfilt.mk
@@ -130,6 +130,7 @@ $(eval $(call gb_Library_add_exception_objects,scfilt,\
        sc/source/filter/excel/xltools \
        sc/source/filter/excel/xltracer \
        sc/source/filter/excel/xlview \
+       sc/source/filter/excel/export/SparklineExt \
        sc/source/filter/ftools/fapihelper \
        sc/source/filter/ftools/fprogressbar \
        sc/source/filter/ftools/ftools \
diff --git a/sc/qa/extras/SparklineTest.cxx b/sc/qa/extras/SparklineTest.cxx
index 122a6b23f5be..a217747899d2 100644
--- a/sc/qa/extras/SparklineTest.cxx
+++ b/sc/qa/extras/SparklineTest.cxx
@@ -10,19 +10,36 @@
 #include <test/calc_unoapi_test.hxx>
 
 #include <com/sun/star/lang/XComponent.hpp>
+#include <unotools/tempfile.hxx>
+#include <comphelper/propertyvalue.hxx>
 #include <docsh.hxx>
 #include <Sparkline.hxx>
 
 using namespace css;
 
-namespace sc_apitest
-{
 class SparklineTest : public CalcUnoApiTest
 {
     uno::Reference<lang::XComponent> mxComponent;
 
 public:
-    SparklineTest();
+    SparklineTest()
+        : CalcUnoApiTest("sc/qa/extras/testdocuments")
+    {
+    }
+
+    void saveAndReload(uno::Reference<lang::XComponent>& xComponent, const 
OUString& rFilter)
+    {
+        utl::TempFile aTempFile;
+        aTempFile.EnableKillingFile();
+        // "calc8", "Calc Office Open XML", ...
+        uno::Sequence aArgs{ comphelper::makePropertyValue("FilterName", 
rFilter) };
+        uno::Reference<frame::XStorable> xStorable(xComponent, 
uno::UNO_QUERY_THROW);
+        xStorable->storeAsURL(aTempFile.GetURL(), aArgs);
+        uno::Reference<util::XCloseable> xCloseable(xComponent, 
uno::UNO_QUERY_THROW);
+        xCloseable->close(true);
+
+        xComponent = loadFromDesktop(aTempFile.GetURL(), 
"com.sun.star.sheet.SpreadsheetDocument");
+    }
 
     void testSparklines();
 
@@ -31,121 +48,224 @@ public:
     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();
-    // Sparkline at Sheet1:A2
-    {
-        sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(0, 1, 
0)); // A2
-        CPPUNIT_ASSERT(pSparkline);
-        auto pSparklineGroup = pSparkline->getSparklineGroup();
-        CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Line, 
pSparklineGroup->m_eType);
-
-        CPPUNIT_ASSERT_EQUAL(Color(0x376092), pSparklineGroup->m_aColorSeries);
-        CPPUNIT_ASSERT_EQUAL(Color(0x00b050), 
pSparklineGroup->m_aColorNegative);
-        CPPUNIT_ASSERT_EQUAL(Color(0x000000), pSparklineGroup->m_aColorAxis);
-        CPPUNIT_ASSERT_EQUAL(Color(0x000000), 
pSparklineGroup->m_aColorMarkers);
-        CPPUNIT_ASSERT_EQUAL(Color(0x7030a0), pSparklineGroup->m_aColorFirst);
-        CPPUNIT_ASSERT_EQUAL(Color(0xff0000), pSparklineGroup->m_aColorLast);
-        CPPUNIT_ASSERT_EQUAL(Color(0x92d050), pSparklineGroup->m_aColorHigh);
-        CPPUNIT_ASSERT_EQUAL(Color(0x00b0f0), pSparklineGroup->m_aColorLow);
-
-        CPPUNIT_ASSERT_EQUAL(1.0, pSparklineGroup->m_fLineWeight);
-        CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bDateAxis);
-        CPPUNIT_ASSERT_EQUAL(sc::DisplayEmptyCellAs::Gap, 
pSparklineGroup->m_eDisplayEmptyCellsAs);
-
-        CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bMarkers);
-        CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bHigh);
-        CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bLow);
-        CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bFirst);
-        CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bLast);
-        CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bNegative);
-        CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bDisplayXAxis);
-        CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bDisplayHidden);
-        CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bRightToLeft);
-
-        CPPUNIT_ASSERT_EQUAL(false, bool(pSparklineGroup->m_aManualMax));
-        CPPUNIT_ASSERT_EQUAL(false, bool(pSparklineGroup->m_aManualMin));
-    }
-    // Sparkline at Sheet1:A3
-    {
-        sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(0, 2, 
0)); // A3
-        CPPUNIT_ASSERT(pSparkline);
-        auto pSparklineGroup = pSparkline->getSparklineGroup();
-        CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Column, 
pSparklineGroup->m_eType);
-
-        CPPUNIT_ASSERT_EQUAL(Color(0x376092), pSparklineGroup->m_aColorSeries);
-        CPPUNIT_ASSERT_EQUAL(Color(0xff0000), 
pSparklineGroup->m_aColorNegative);
-        CPPUNIT_ASSERT_EQUAL(Color(0x000000), pSparklineGroup->m_aColorAxis);
-        CPPUNIT_ASSERT_EQUAL(Color(0xd00000), 
pSparklineGroup->m_aColorMarkers);
-        CPPUNIT_ASSERT_EQUAL(Color(0x92d050), pSparklineGroup->m_aColorFirst);
-        CPPUNIT_ASSERT_EQUAL(Color(0x00b0f0), pSparklineGroup->m_aColorLast);
-        CPPUNIT_ASSERT_EQUAL(Color(0x7030a0), pSparklineGroup->m_aColorHigh);
-        CPPUNIT_ASSERT_EQUAL(Color(0xffc000), pSparklineGroup->m_aColorLow);
-
-        CPPUNIT_ASSERT_EQUAL(0.75, pSparklineGroup->m_fLineWeight);
-        CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bDateAxis);
-        CPPUNIT_ASSERT_EQUAL(sc::DisplayEmptyCellAs::Gap, 
pSparklineGroup->m_eDisplayEmptyCellsAs);
-
-        CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bMarkers);
-        CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bHigh);
-        CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bLow);
-        CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bFirst);
-        CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bLast);
-        CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bNegative);
-        CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bDisplayXAxis);
-        CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bDisplayHidden);
-        CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bRightToLeft);
-
-        CPPUNIT_ASSERT_EQUAL(false, bool(pSparklineGroup->m_aManualMax));
-        CPPUNIT_ASSERT_EQUAL(false, bool(pSparklineGroup->m_aManualMin));
-    }
-    // Sparkline at Sheet2:B1
     {
-        sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(1, 0, 
1)); //B1
-        CPPUNIT_ASSERT(pSparkline);
-        auto pSparklineGroup = pSparkline->getSparklineGroup();
-        CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Column, 
pSparklineGroup->m_eType);
-    }
-    // Sparkline at Sheet2:B2
-    {
-        sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(1, 1, 
1)); //B2
-        CPPUNIT_ASSERT(pSparkline);
-        auto pSparklineGroup = pSparkline->getSparklineGroup();
-        CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Line, 
pSparklineGroup->m_eType);
-    }
-    // Sparkline at Sheet2:B2
-    {
-        sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(1, 1, 
1)); //B2
-        CPPUNIT_ASSERT(pSparkline);
-        auto pSparklineGroup = pSparkline->getSparklineGroup();
-        CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Line, 
pSparklineGroup->m_eType);
+        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();
+        // Sparkline at Sheet1:A2
+        {
+            sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(0, 1, 
0)); // A2
+            CPPUNIT_ASSERT(pSparkline);
+            auto pSparklineGroup = pSparkline->getSparklineGroup();
+            CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Line, 
pSparklineGroup->m_eType);
+
+            CPPUNIT_ASSERT_EQUAL(Color(0x376092), 
pSparklineGroup->m_aColorSeries);
+            CPPUNIT_ASSERT_EQUAL(Color(0x00b050), 
pSparklineGroup->m_aColorNegative);
+            CPPUNIT_ASSERT_EQUAL(Color(0x000000), 
pSparklineGroup->m_aColorAxis);
+            CPPUNIT_ASSERT_EQUAL(Color(0x000000), 
pSparklineGroup->m_aColorMarkers);
+            CPPUNIT_ASSERT_EQUAL(Color(0x7030a0), 
pSparklineGroup->m_aColorFirst);
+            CPPUNIT_ASSERT_EQUAL(Color(0xff0000), 
pSparklineGroup->m_aColorLast);
+            CPPUNIT_ASSERT_EQUAL(Color(0x92d050), 
pSparklineGroup->m_aColorHigh);
+            CPPUNIT_ASSERT_EQUAL(Color(0x00b0f0), 
pSparklineGroup->m_aColorLow);
+
+            CPPUNIT_ASSERT_EQUAL(1.0, pSparklineGroup->m_fLineWeight);
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bDateAxis);
+            CPPUNIT_ASSERT_EQUAL(sc::DisplayEmptyCellAs::Gap,
+                                 pSparklineGroup->m_eDisplayEmptyCellsAs);
+
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bMarkers);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bHigh);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bLow);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bFirst);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bLast);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bNegative);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bDisplayXAxis);
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bDisplayHidden);
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bRightToLeft);
+
+            CPPUNIT_ASSERT_EQUAL(false, bool(pSparklineGroup->m_aManualMax));
+            CPPUNIT_ASSERT_EQUAL(false, bool(pSparklineGroup->m_aManualMin));
+        }
+        // Sparkline at Sheet1:A3
+        {
+            sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(0, 2, 
0)); // A3
+            CPPUNIT_ASSERT(pSparkline);
+            auto pSparklineGroup = pSparkline->getSparklineGroup();
+            CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Column, 
pSparklineGroup->m_eType);
+
+            CPPUNIT_ASSERT_EQUAL(Color(0x376092), 
pSparklineGroup->m_aColorSeries);
+            CPPUNIT_ASSERT_EQUAL(Color(0xff0000), 
pSparklineGroup->m_aColorNegative);
+            CPPUNIT_ASSERT_EQUAL(Color(0x000000), 
pSparklineGroup->m_aColorAxis);
+            CPPUNIT_ASSERT_EQUAL(Color(0xd00000), 
pSparklineGroup->m_aColorMarkers);
+            CPPUNIT_ASSERT_EQUAL(Color(0x92d050), 
pSparklineGroup->m_aColorFirst);
+            CPPUNIT_ASSERT_EQUAL(Color(0x00b0f0), 
pSparklineGroup->m_aColorLast);
+            CPPUNIT_ASSERT_EQUAL(Color(0x7030a0), 
pSparklineGroup->m_aColorHigh);
+            CPPUNIT_ASSERT_EQUAL(Color(0xffc000), 
pSparklineGroup->m_aColorLow);
+
+            CPPUNIT_ASSERT_EQUAL(0.75, pSparklineGroup->m_fLineWeight);
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bDateAxis);
+            CPPUNIT_ASSERT_EQUAL(sc::DisplayEmptyCellAs::Gap,
+                                 pSparklineGroup->m_eDisplayEmptyCellsAs);
+
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bMarkers);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bHigh);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bLow);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bFirst);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bLast);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bNegative);
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bDisplayXAxis);
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bDisplayHidden);
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bRightToLeft);
+
+            CPPUNIT_ASSERT_EQUAL(false, bool(pSparklineGroup->m_aManualMax));
+            CPPUNIT_ASSERT_EQUAL(false, bool(pSparklineGroup->m_aManualMin));
+        }
+        // Sparkline at Sheet2:B1
+        {
+            sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(1, 0, 
1)); //B1
+            CPPUNIT_ASSERT(pSparkline);
+            auto pSparklineGroup = pSparkline->getSparklineGroup();
+            CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Column, 
pSparklineGroup->m_eType);
+        }
+        // Sparkline at Sheet2:B2
+        {
+            sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(1, 1, 
1)); //B2
+            CPPUNIT_ASSERT(pSparkline);
+            auto pSparklineGroup = pSparkline->getSparklineGroup();
+            CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Line, 
pSparklineGroup->m_eType);
+        }
+        // Sparkline at Sheet2:B2
+        {
+            sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(1, 1, 
1)); //B2
+            CPPUNIT_ASSERT(pSparkline);
+            auto pSparklineGroup = pSparkline->getSparklineGroup();
+            CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Line, 
pSparklineGroup->m_eType);
+        }
+        // Sparkline doesn't exists at A4
+        {
+            sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(0, 3, 
0)); //A4
+            CPPUNIT_ASSERT(!pSparkline);
+        }
     }
-    // Sparkline doesn't exists at A4
+
+    saveAndReload(mxComponent, "Calc Office Open XML");
+
     {
-        sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(0, 3, 
0)); //A4
-        CPPUNIT_ASSERT(!pSparkline);
+        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();
+        // Sparkline at Sheet1:A2
+        {
+            sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(0, 1, 
0)); // A2
+            CPPUNIT_ASSERT(pSparkline);
+            auto pSparklineGroup = pSparkline->getSparklineGroup();
+            CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Line, 
pSparklineGroup->m_eType);
+
+            CPPUNIT_ASSERT_EQUAL(Color(0x376092), 
pSparklineGroup->m_aColorSeries);
+            CPPUNIT_ASSERT_EQUAL(Color(0x00b050), 
pSparklineGroup->m_aColorNegative);
+            CPPUNIT_ASSERT_EQUAL(Color(0x000000), 
pSparklineGroup->m_aColorAxis);
+            CPPUNIT_ASSERT_EQUAL(Color(0x000000), 
pSparklineGroup->m_aColorMarkers);
+            CPPUNIT_ASSERT_EQUAL(Color(0x7030a0), 
pSparklineGroup->m_aColorFirst);
+            CPPUNIT_ASSERT_EQUAL(Color(0xff0000), 
pSparklineGroup->m_aColorLast);
+            CPPUNIT_ASSERT_EQUAL(Color(0x92d050), 
pSparklineGroup->m_aColorHigh);
+            CPPUNIT_ASSERT_EQUAL(Color(0x00b0f0), 
pSparklineGroup->m_aColorLow);
+
+            CPPUNIT_ASSERT_EQUAL(1.0, pSparklineGroup->m_fLineWeight);
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bDateAxis);
+            CPPUNIT_ASSERT_EQUAL(sc::DisplayEmptyCellAs::Gap,
+                                 pSparklineGroup->m_eDisplayEmptyCellsAs);
+
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bMarkers);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bHigh);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bLow);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bFirst);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bLast);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bNegative);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bDisplayXAxis);
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bDisplayHidden);
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bRightToLeft);
+
+            CPPUNIT_ASSERT_EQUAL(false, bool(pSparklineGroup->m_aManualMax));
+            CPPUNIT_ASSERT_EQUAL(false, bool(pSparklineGroup->m_aManualMin));
+        }
+        // Sparkline at Sheet1:A3
+        {
+            sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(0, 2, 
0)); // A3
+            CPPUNIT_ASSERT(pSparkline);
+            auto pSparklineGroup = pSparkline->getSparklineGroup();
+            CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Column, 
pSparklineGroup->m_eType);
+
+            CPPUNIT_ASSERT_EQUAL(Color(0x376092), 
pSparklineGroup->m_aColorSeries);
+            CPPUNIT_ASSERT_EQUAL(Color(0xff0000), 
pSparklineGroup->m_aColorNegative);
+            CPPUNIT_ASSERT_EQUAL(Color(0x000000), 
pSparklineGroup->m_aColorAxis);
+            CPPUNIT_ASSERT_EQUAL(Color(0xd00000), 
pSparklineGroup->m_aColorMarkers);
+            CPPUNIT_ASSERT_EQUAL(Color(0x92d050), 
pSparklineGroup->m_aColorFirst);
+            CPPUNIT_ASSERT_EQUAL(Color(0x00b0f0), 
pSparklineGroup->m_aColorLast);
+            CPPUNIT_ASSERT_EQUAL(Color(0x7030a0), 
pSparklineGroup->m_aColorHigh);
+            CPPUNIT_ASSERT_EQUAL(Color(0xffc000), 
pSparklineGroup->m_aColorLow);
+
+            CPPUNIT_ASSERT_EQUAL(0.75, pSparklineGroup->m_fLineWeight);
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bDateAxis);
+            CPPUNIT_ASSERT_EQUAL(sc::DisplayEmptyCellAs::Gap,
+                                 pSparklineGroup->m_eDisplayEmptyCellsAs);
+
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bMarkers);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bHigh);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bLow);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bFirst);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bLast);
+            CPPUNIT_ASSERT_EQUAL(true, pSparklineGroup->m_bNegative);
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bDisplayXAxis);
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bDisplayHidden);
+            CPPUNIT_ASSERT_EQUAL(false, pSparklineGroup->m_bRightToLeft);
+
+            CPPUNIT_ASSERT_EQUAL(false, bool(pSparklineGroup->m_aManualMax));
+            CPPUNIT_ASSERT_EQUAL(false, bool(pSparklineGroup->m_aManualMin));
+        }
+        // Sparkline at Sheet2:B1
+        {
+            sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(1, 0, 
1)); //B1
+            CPPUNIT_ASSERT(pSparkline);
+            auto pSparklineGroup = pSparkline->getSparklineGroup();
+            CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Column, 
pSparklineGroup->m_eType);
+        }
+        // Sparkline at Sheet2:B2
+        {
+            sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(1, 1, 
1)); //B2
+            CPPUNIT_ASSERT(pSparkline);
+            auto pSparklineGroup = pSparkline->getSparklineGroup();
+            CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Line, 
pSparklineGroup->m_eType);
+        }
+        // Sparkline at Sheet2:B2
+        {
+            sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(1, 1, 
1)); //B2
+            CPPUNIT_ASSERT(pSparkline);
+            auto pSparklineGroup = pSparkline->getSparklineGroup();
+            CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Line, 
pSparklineGroup->m_eType);
+        }
+        // Sparkline doesn't exists at A4
+        {
+            sc::Sparkline* pSparkline = rDocument.GetSparkline(ScAddress(0, 3, 
0)); //A4
+            CPPUNIT_ASSERT(!pSparkline);
+        }
     }
 
     closeDocument(mxComponent);
 }
 
 CPPUNIT_TEST_SUITE_REGISTRATION(SparklineTest);
-}
 
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sc/source/filter/excel/excdoc.cxx 
b/sc/source/filter/excel/excdoc.cxx
index 6b02457f70f6..529e76971cbc 100644
--- a/sc/source/filter/excel/excdoc.cxx
+++ b/sc/source/filter/excel/excdoc.cxx
@@ -39,6 +39,7 @@
 #include <xecontent.hxx>
 #include <xeescher.hxx>
 #include <xepivot.hxx>
+#include <export/SparklineExt.hxx>
 #include <XclExpChangeTrack.hxx>
 #include <xepivotxml.hxx>
 #include <xedbdata.hxx>
@@ -611,6 +612,8 @@ void ExcTable::FillAsTableXml()
     // conditional formats
     Add( new XclExpCondFormatBuffer( GetRoot(), xExtLst ) );
 
+    Add(new xcl::exp::SparklineBuffer(GetRoot(), xExtLst));
+
     // data validation (DVAL and list of DV records), generated by the cell 
table
     aRecList.AppendRecord( mxCellTable->CreateRecord( EXC_ID_DVAL ) );
 
diff --git a/sc/source/filter/excel/export/SparklineExt.cxx 
b/sc/source/filter/excel/export/SparklineExt.cxx
new file mode 100644
index 000000000000..f1e97b2c62ed
--- /dev/null
+++ b/sc/source/filter/excel/export/SparklineExt.cxx
@@ -0,0 +1,246 @@
+/* -*- 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 "export/SparklineExt.hxx"
+
+#include <oox/export/utils.hxx>
+#include <oox/token/namespaces.hxx>
+#include <oox/token/tokens.hxx>
+
+using namespace oox;
+
+namespace xcl::exp
+{
+SparklineExt::SparklineExt(const XclExpRoot& rRoot,
+                           std::vector<std::shared_ptr<sc::Sparkline>> const& 
pSparklines)
+    : XclExpExt(rRoot)
+{
+    maURI = "{05C60535-1F16-4fd2-B633-F4F36F0B64E0}";
+
+    for (auto const& pSparkline : pSparklines)
+    {
+        auto* pGroupPointer = pSparkline->getSparklineGroup().get();
+
+        auto aIterator = m_aSparklineGroupMap.find(pGroupPointer);
+        if (aIterator == m_aSparklineGroupMap.end())
+        {
+            std::vector<std::shared_ptr<sc::Sparkline>> aSparklineVector;
+            aSparklineVector.push_back(pSparkline);
+            m_aSparklineGroupMap.emplace(pGroupPointer, aSparklineVector);
+        }
+        else
+        {
+            aIterator->second.push_back(pSparkline);
+        }
+    }
+}
+
+void SparklineExt::SaveXml(XclExpXmlStream& rStream)
+{
+    sax_fastparser::FSHelperPtr& rWorksheet = rStream.GetCurrentStream();
+    rWorksheet->startElement(XML_ext, FSNS(XML_xmlns, XML_x14),
+                             rStream.getNamespaceURL(OOX_NS(xls14Lst)), 
XML_uri, maURI);
+
+    rWorksheet->startElementNS(XML_x14, XML_sparklineGroups, FSNS(XML_xmlns, 
XML_xm),
+                               rStream.getNamespaceURL(OOX_NS(xm)));
+
+    for (auto const & [ pSparklineGroup, rSparklineVector ] : 
m_aSparklineGroupMap)
+    {
+        addSparklineGroup(rStream, *pSparklineGroup, rSparklineVector);
+    }
+
+    rWorksheet->endElementNS(XML_x14, XML_sparklineGroups);
+    rWorksheet->endElement(XML_ext);
+}
+
+void SparklineExt::addSparklineGroupAttributes(
+    rtl::Reference<sax_fastparser::FastAttributeList>& pAttrList,
+    sc::SparklineGroup& rSparklineGroup)
+{
+    if (rSparklineGroup.m_fLineWeight != 0.75)
+        pAttrList->add(XML_lineWeight, 
OString::number(rSparklineGroup.m_fLineWeight));
+
+    if (rSparklineGroup.m_eType != sc::SparklineType::Line)
+    {
+        if (rSparklineGroup.m_eType == sc::SparklineType::Column)
+            pAttrList->add(XML_type, "column");
+        else if (rSparklineGroup.m_eType == sc::SparklineType::Stacked)
+            pAttrList->add(XML_type, "stacked");
+    }
+
+    if (rSparklineGroup.m_bDateAxis)
+        pAttrList->add(XML_dateAxis, "1");
+
+    if (rSparklineGroup.m_eDisplayEmptyCellsAs != sc::DisplayEmptyCellAs::Zero)
+    {
+        if (rSparklineGroup.m_eDisplayEmptyCellsAs == 
sc::DisplayEmptyCellAs::Gap)
+            pAttrList->add(XML_displayEmptyCellsAs, "gap");
+        else if (rSparklineGroup.m_eDisplayEmptyCellsAs == 
sc::DisplayEmptyCellAs::Span)
+            pAttrList->add(XML_displayEmptyCellsAs, "span");
+    }
+
+    if (rSparklineGroup.m_bMarkers)
+        pAttrList->add(XML_markers, "1");
+    if (rSparklineGroup.m_bHigh)
+        pAttrList->add(XML_high, "1");
+    if (rSparklineGroup.m_bLow)
+        pAttrList->add(XML_low, "1");
+    if (rSparklineGroup.m_bFirst)
+        pAttrList->add(XML_first, "1");
+    if (rSparklineGroup.m_bLast)
+        pAttrList->add(XML_last, "1");
+    if (rSparklineGroup.m_bNegative)
+        pAttrList->add(XML_negative, "1");
+    if (rSparklineGroup.m_bDisplayXAxis)
+        pAttrList->add(XML_displayXAxis, "1");
+    if (rSparklineGroup.m_bDisplayHidden)
+        pAttrList->add(XML_displayHidden, "1");
+
+    if (rSparklineGroup.m_eMinAxisType != sc::AxisType::Individual)
+    {
+        if (rSparklineGroup.m_eMinAxisType == sc::AxisType::Group)
+            pAttrList->add(XML_minAxisType, "group");
+        else if (rSparklineGroup.m_eMinAxisType == sc::AxisType::Custom)
+            pAttrList->add(XML_minAxisType, "custom");
+    }
+
+    if (rSparklineGroup.m_eMaxAxisType != sc::AxisType::Individual)
+    {
+        if (rSparklineGroup.m_eMaxAxisType == sc::AxisType::Group)
+            pAttrList->add(XML_maxAxisType, "group");
+        else if (rSparklineGroup.m_eMaxAxisType == sc::AxisType::Custom)
+            pAttrList->add(XML_maxAxisType, "custom");
+    }
+
+    if (rSparklineGroup.m_bRightToLeft)
+        pAttrList->add(XML_rightToLeft, "1");
+
+    if (rSparklineGroup.m_aManualMax && rSparklineGroup.m_eMaxAxisType == 
sc::AxisType::Custom)
+        pAttrList->add(XML_manualMax, 
OString::number(*rSparklineGroup.m_aManualMax));
+
+    if (rSparklineGroup.m_aManualMin && rSparklineGroup.m_eMinAxisType == 
sc::AxisType::Custom)
+        pAttrList->add(XML_manualMin, 
OString::number(*rSparklineGroup.m_aManualMin));
+}
+
+void SparklineExt::addSparklineGroupColors(XclExpXmlStream& rStream,
+                                           sc::SparklineGroup& rSparklineGroup)
+{
+    sax_fastparser::FSHelperPtr& rWorksheet = rStream.GetCurrentStream();
+
+    rWorksheet->singleElementNS(XML_x14, XML_colorSeries, XML_rgb,
+                                
XclXmlUtils::ToOString(rSparklineGroup.m_aColorSeries));
+
+    if (rSparklineGroup.m_aColorSeries != COL_TRANSPARENT)
+    {
+        rWorksheet->singleElementNS(XML_x14, XML_colorNegative, XML_rgb,
+                                    
XclXmlUtils::ToOString(rSparklineGroup.m_aColorNegative));
+    }
+
+    if (rSparklineGroup.m_aColorAxis != COL_TRANSPARENT)
+    {
+        rWorksheet->singleElementNS(XML_x14, XML_colorAxis, XML_rgb,
+                                    
XclXmlUtils::ToOString(rSparklineGroup.m_aColorAxis));
+    }
+
+    if (rSparklineGroup.m_aColorMarkers != COL_TRANSPARENT)
+    {
+        rWorksheet->singleElementNS(XML_x14, XML_colorMarkers, XML_rgb,
+                                    
XclXmlUtils::ToOString(rSparklineGroup.m_aColorMarkers));
+    }
+
+    if (rSparklineGroup.m_aColorFirst != COL_TRANSPARENT)
+    {
+        rWorksheet->singleElementNS(XML_x14, XML_colorFirst, XML_rgb,
+                                    
XclXmlUtils::ToOString(rSparklineGroup.m_aColorFirst));
+    }
+
+    if (rSparklineGroup.m_aColorLast != COL_TRANSPARENT)
+    {
+        rWorksheet->singleElementNS(XML_x14, XML_colorLast, XML_rgb,
+                                    
XclXmlUtils::ToOString(rSparklineGroup.m_aColorLast));
+    }
+
+    if (rSparklineGroup.m_aColorHigh != COL_TRANSPARENT)
+    {
+        rWorksheet->singleElementNS(XML_x14, XML_colorHigh, XML_rgb,
+                                    
XclXmlUtils::ToOString(rSparklineGroup.m_aColorHigh));
+    }
+
+    if (rSparklineGroup.m_aColorLow != COL_TRANSPARENT)
+    {
+        rWorksheet->singleElementNS(XML_x14, XML_colorLow, XML_rgb,
+                                    
XclXmlUtils::ToOString(rSparklineGroup.m_aColorLow));
+    }
+}
+
+void SparklineExt::addSparklineGroup(XclExpXmlStream& rStream, 
sc::SparklineGroup& rSparklineGroup,
+                                     
std::vector<std::shared_ptr<sc::Sparkline>> const& rSparklines)
+{
+    sax_fastparser::FSHelperPtr& rWorksheet = rStream.GetCurrentStream();
+
+    // Sparkline Group Attributes
+    auto pAttrList = sax_fastparser::FastSerializerHelper::createAttrList();
+    addSparklineGroupAttributes(pAttrList, rSparklineGroup);
+
+    rWorksheet->startElementNS(XML_x14, XML_sparklineGroup, pAttrList);
+
+    addSparklineGroupColors(rStream, rSparklineGroup);
+
+    // Sparklines
+
+    rWorksheet->startElementNS(XML_x14, XML_sparklines);
+    for (auto const& rSparkline : rSparklines)
+    {
+        rWorksheet->startElementNS(XML_x14, XML_sparkline);
+
+        {
+            rWorksheet->startElementNS(XML_xm, XML_f);
+
+            OUString sRangeFormula;
+            ScRefFlags eFlags = ScRefFlags::VALID | ScRefFlags::TAB_3D;
+            rSparkline->getInputRange().Format(sRangeFormula, eFlags, GetDoc(),
+                                               
formula::FormulaGrammar::CONV_XL_OOX, ' ', true);
+
+            rWorksheet->writeEscaped(sRangeFormula);
+            rWorksheet->endElementNS(XML_xm, XML_f);
+        }
+
+        {
+            rWorksheet->startElementNS(XML_xm, XML_sqref);
+
+            ScAddress::Details detailsXL(formula::FormulaGrammar::CONV_XL_OOX);
+            ScAddress aAddress(rSparkline->getColumn(), rSparkline->getRow(), 
GetCurrScTab());
+            OUString sLocation = aAddress.Format(ScRefFlags::VALID, &GetDoc(), 
detailsXL);
+
+            rWorksheet->writeEscaped(sLocation);
+            rWorksheet->endElementNS(XML_xm, XML_sqref);
+        }
+
+        rWorksheet->endElementNS(XML_x14, XML_sparkline);
+    }
+    rWorksheet->endElementNS(XML_x14, XML_sparklines);
+    rWorksheet->endElementNS(XML_x14, XML_sparklineGroup);
+}
+
+SparklineBuffer::SparklineBuffer(const XclExpRoot& rRoot, XclExtLstRef const& 
xExtLst)
+    : XclExpRoot(rRoot)
+{
+    if (sc::SparklineList* pSparklineList = 
GetDoc().GetSparklineList(GetCurrScTab()))
+    {
+        auto pSparklines = pSparklineList->getSparklines();
+        if (!pSparklines.empty())
+        {
+            xExtLst->AddRecord(new xcl::exp::SparklineExt(GetRoot(), 
pSparklines));
+        }
+    }
+}
+
+} // end namespace xcl::exp
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/inc/export/SparklineExt.hxx 
b/sc/source/filter/inc/export/SparklineExt.hxx
new file mode 100644
index 000000000000..116462c5f3c4
--- /dev/null
+++ b/sc/source/filter/inc/export/SparklineExt.hxx
@@ -0,0 +1,52 @@
+/* -*- 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 <vector>
+#include <map>
+#include <rangelst.hxx>
+#include <Sparkline.hxx>
+
+#include <sax/fastattribs.hxx>
+
+#include "xerecord.hxx"
+#include "xeroot.hxx"
+#include "xeextlst.hxx"
+
+namespace xcl::exp
+{
+class SparklineExt : public XclExpExt
+{
+    std::map<sc::SparklineGroup*, std::vector<std::shared_ptr<sc::Sparkline>>> 
m_aSparklineGroupMap;
+
+public:
+    SparklineExt(const XclExpRoot& rRoot,
+                 std::vector<std::shared_ptr<sc::Sparkline>> const& 
pSparklines);
+
+    void SaveXml(XclExpXmlStream& rStream) override;
+    void addSparklineGroup(XclExpXmlStream& rStream, sc::SparklineGroup& 
rSparklineGroup,
+                           std::vector<std::shared_ptr<sc::Sparkline>> const& 
rSparklines);
+    void 
addSparklineGroupAttributes(rtl::Reference<sax_fastparser::FastAttributeList>& 
pAttrList,
+                                     sc::SparklineGroup& rSparklineGroup);
+    void addSparklineGroupColors(XclExpXmlStream& rStream, sc::SparklineGroup& 
rSparklineGroup);
+
+    XclExpExtType GetType() override { return XclExpExtSparklineType; }
+};
+
+class SparklineBuffer : public XclExpRecordBase, protected XclExpRoot
+{
+public:
+    explicit SparklineBuffer(const XclExpRoot& rRoot, const XclExtLstRef& 
xExtLst);
+};
+
+} // end namespace xcl::exp
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/inc/xeextlst.hxx 
b/sc/source/filter/inc/xeextlst.hxx
index c5db5fcaff99..1770f9af191d 100644
--- a/sc/source/filter/inc/xeextlst.hxx
+++ b/sc/source/filter/inc/xeextlst.hxx
@@ -19,7 +19,8 @@
 enum XclExpExtType
 {
     XclExpExtDataBarType,
-    XclExpExtDataFooType
+    XclExpExtDataFooType,
+    XclExpExtSparklineType,
 };
 
 struct XclExpExtCondFormatData
commit 2c5a429b2deb52c40340a59292079987336a5523
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Fri Mar 4 17:26:34 2022 +0900
Commit:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
CommitDate: Fri Mar 4 17:26:34 2022 +0900

    sc: set colors in SparklineGroup construction to COL_TRANSPARENT
    
    Change-Id: I67ceab2ffd723511fbf0616cca661992f0a8cf69

diff --git a/sc/inc/SparklineGroup.hxx b/sc/inc/SparklineGroup.hxx
index 32e4b757378f..170ccee51539 100644
--- a/sc/inc/SparklineGroup.hxx
+++ b/sc/inc/SparklineGroup.hxx
@@ -74,7 +74,17 @@ public:
     std::optional<double> m_aManualMin;
     OUString m_sUID;
 
-    SparklineGroup() {}
+    SparklineGroup()
+        : m_aColorSeries(COL_TRANSPARENT)
+        , m_aColorNegative(COL_TRANSPARENT)
+        , m_aColorAxis(COL_TRANSPARENT)
+        , m_aColorMarkers(COL_TRANSPARENT)
+        , m_aColorFirst(COL_TRANSPARENT)
+        , m_aColorLast(COL_TRANSPARENT)
+        , m_aColorHigh(COL_TRANSPARENT)
+        , m_aColorLow(COL_TRANSPARENT)
+    {
+    }
 
     SparklineGroup(const SparklineGroup&) = delete;
     SparklineGroup& operator=(const SparklineGroup&) = delete;
commit 3d357d5d4205cee25354f12c09d124e067c2d050
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Wed Mar 2 17:44:08 2022 +0900
Commit:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
CommitDate: Fri Mar 4 12:45:25 2022 +0900

    sc: refactor sparkline struture to store a list of sparklines
    
    We need to access a list of sparklines and sparkline groups for
    a sheet. To preven going through all the columns of a sheet, we
    need to store all the created sparklines in a list. For this it
    is necessary to change the model structrue a bit. A cell now has
    a container that stores a shared_ptr to the sparkline instead of
    storing the sparkline directly. With this we can store a list
    of weak_ptr to the sparklines in a list (vector), which can be
    accessed at any time and is quite fast.
    
    This is needed by the OOXML export.
    
    Change-Id: Iaca0a41e20912775f072ea6e8cab9c44367d6f30

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 11449217edd9..62ab22a797c4 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -185,7 +185,6 @@ $(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
index 8969fa3bfd3e..ad4688f33a5e 100644
--- a/sc/inc/Sparkline.hxx
+++ b/sc/inc/Sparkline.hxx
@@ -19,20 +19,67 @@ namespace sc
 {
 class SC_DLLPUBLIC Sparkline
 {
-private:
+    SCCOL m_nColumn;
+    SCROW m_nRow;
+
     ScRangeList m_aInputRange;
     std::shared_ptr<SparklineGroup> m_pSparklineGroup;
 
 public:
-    Sparkline(std::shared_ptr<SparklineGroup>& pSparklineGroup);
+    Sparkline(SCCOL nColumn, SCROW nRow, std::shared_ptr<SparklineGroup> 
const& pSparklineGroup)
+        : m_nColumn(nColumn)
+        , m_nRow(nRow)
+        , m_pSparklineGroup(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; }
+
+    SCCOL getColumn() { return m_nColumn; }
+
+    SCROW getRow() { return m_nRow; }
+};
+
+class SC_DLLPUBLIC SparklineList
+{
+private:
+    std::vector<std::weak_ptr<Sparkline>> m_pSparklines;
+
+public:
+    SparklineList() {}
+
+    void addSparkline(std::shared_ptr<Sparkline> const& pSparkline)
+    {
+        m_pSparklines.push_back(pSparkline);
+    }
+
+    std::vector<std::shared_ptr<Sparkline>> getSparklines()
+    {
+        std::vector<std::shared_ptr<Sparkline>> toReturn;
+
+        std::vector<std::weak_ptr<Sparkline>>::iterator aIter;
+        for (aIter = m_pSparklines.begin(); aIter != m_pSparklines.end();)
+        {
+            if (auto aSparkline = aIter->lock())
+            {
+                toReturn.push_back(aSparkline);
+                aIter++;
+            }
+            else
+            {
+                aIter = m_pSparklines.erase(aIter);
+            }
+        }
+
+        return toReturn;
+    }
 };
 
 } // end sc
diff --git a/sc/inc/SparklineCell.hxx b/sc/inc/SparklineCell.hxx
new file mode 100644
index 000000000000..0aca857170c9
--- /dev/null
+++ b/sc/inc/SparklineCell.hxx
@@ -0,0 +1,47 @@
+/* -*- 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 "Sparkline.hxx"
+#include <memory>
+
+namespace sc
+{
+class SC_DLLPUBLIC SparklineCell
+{
+private:
+    std::shared_ptr<Sparkline> m_pSparkline;
+
+public:
+    SparklineCell(std::shared_ptr<Sparkline> const& pSparkline)
+        : m_pSparkline(pSparkline)
+    {
+    }
+
+    SparklineCell(const SparklineCell&) = delete;
+    SparklineCell& operator=(const SparklineCell&) = delete;
+
+    void setInputRange(ScRangeList const& rInputRange) { 
m_pSparkline->setInputRange(rInputRange); }
+
+    ScRangeList const& getInputRange() { return m_pSparkline->getInputRange(); 
}
+
+    std::shared_ptr<SparklineGroup> const& getSparklineGroup()
+    {
+        return m_pSparkline->getSparklineGroup();
+    }
+
+    std::shared_ptr<Sparkline> const& getSparkline() { return m_pSparkline; }
+};
+
+} // end sc
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 4c711b9944dc..17e0d61f79c4 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -617,8 +617,8 @@ public:
     void BroadcastRows( SCROW nStartRow, SCROW nEndRow, SfxHintId nHint );
 
     // Spaklines
-    sc::Sparkline* GetSparkline(SCROW nRow);
-    void SetSparkline(SCROW nRow, std::unique_ptr<sc::Sparkline> pSparkline);
+    sc::SparklineCell* GetSparklineCell(SCROW nRow);
+    void CreateSparklineCell(SCROW nRow, std::shared_ptr<sc::Sparkline> const& 
pSparkline);
 
     // cell notes
     ScPostIt* GetCellNote( SCROW nRow );
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index d0ef2006846e..84ee8184d2e9 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -103,6 +103,7 @@ class ColumnIterator;
 class ExternalDataMapper;
 class Sparkline;
 class SparklineGroup;
+class SparklineList;
 
 }
 
@@ -1240,6 +1241,7 @@ public:
     /** Spaklines */
     SC_DLLPUBLIC sc::Sparkline* GetSparkline(ScAddress const & rPosition);
     SC_DLLPUBLIC sc::Sparkline* CreateSparkline(ScAddress const & rPosition, 
std::shared_ptr<sc::SparklineGroup> & pSparklineGroup);
+    SC_DLLPUBLIC sc::SparklineList* GetSparklineList(SCTAB nTab);
 
     /** Notes **/
     SC_DLLPUBLIC ScPostIt*       GetNote(const ScAddress& rPos);
diff --git a/sc/inc/mtvelements.hxx b/sc/inc/mtvelements.hxx
index 979a09c641db..c60a8832c8df 100644
--- a/sc/inc/mtvelements.hxx
+++ b/sc/inc/mtvelements.hxx
@@ -15,7 +15,7 @@
 #include <editeng/editobj.hxx>
 #include "calcmacros.hxx"
 #include "postit.hxx"
-#include "Sparkline.hxx"
+#include "SparklineCell.hxx"
 #include "celltextattr.hxx"
 
 #if DEBUG_COLUMN_STORAGE
@@ -59,7 +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_sparkline, 
sc::SparklineCell> 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;
@@ -77,7 +77,7 @@ typedef mdds::mtv::uint16_element_block uint16_block;
 /// 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)
+MDDS_MTV_DEFINE_ELEMENT_CALLBACKS_PTR(SparklineCell, 
sc::element_type_sparkline, nullptr, sc::sparkline_block)
 }
 
 /// These need to be in global namespace just like their respective types are.
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 30c92cd87520..534da038bf54 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -227,6 +227,7 @@ private:
     mutable std::unique_ptr<ScRangeName> mpRangeName;
 
     std::unique_ptr<ScConditionalFormatList> mpCondFormatList;
+    sc::SparklineList maSparklineList;
 
     ScAddress       maLOKFreezeCell;
 
@@ -472,6 +473,14 @@ public:
     void        GetFirstDataPos(SCCOL& rCol, SCROW& rRow) const;
     void        GetLastDataPos(SCCOL& rCol, SCROW& rRow) const;
 
+    // Sparklines
+
+    sc::Sparkline* GetSparkline(SCCOL nCol, SCROW nRow);
+    sc::Sparkline* CreateSparkline(SCCOL nCol, SCROW nRow, 
std::shared_ptr<sc::SparklineGroup> & pSparklineGroup);
+
+    sc::SparklineList& GetSparklineList();
+
+    // Notes / Comments
     std::unique_ptr<ScPostIt> ReleaseNote( SCCOL nCol, SCROW nRow );
     ScPostIt*                 GetNote( SCCOL nCol, SCROW nRow );
     void                      SetNote( SCCOL nCol, SCROW nRow, 
std::unique_ptr<ScPostIt> pNote );
diff --git a/sc/source/core/data/Sparkline.cxx 
b/sc/source/core/data/Sparkline.cxx
deleted file mode 100644
index 301fda820ff2..000000000000
--- a/sc/source/core/data/Sparkline.cxx
+++ /dev/null
@@ -1,22 +0,0 @@
-/* -*- 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/column2.cxx b/sc/source/core/data/column2.cxx
index 9eb661e49d9d..d391c4baaeae 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1977,14 +1977,14 @@ void ScColumn::PrepareBroadcastersForDestruction()
     }
 }
 
-sc::Sparkline* ScColumn::GetSparkline(SCROW nRow)
+sc::SparklineCell* ScColumn::GetSparklineCell(SCROW nRow)
 {
-    return maSparklines.get<sc::Sparkline*>(nRow);
+    return maSparklines.get<sc::SparklineCell*>(nRow);
 }
 
-void ScColumn::SetSparkline(SCROW nRow, std::unique_ptr<sc::Sparkline> 
pSparkline)
+void ScColumn::CreateSparklineCell(SCROW nRow, std::shared_ptr<sc::Sparkline> 
const& pSparkline)
 {
-    maSparklines.set(nRow, pSparkline.release());
+    maSparklines.set(nRow, new sc::SparklineCell(pSparkline));
 }
 
 ScPostIt* ScColumn::GetCellNote(SCROW nRow)
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 7f1eeab2d12a..88b1d7ce12b9 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -6513,33 +6513,41 @@ bool ScDocument::IsInVBAMode() const
     return false;
 }
 
+// Sparklines
 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())
+    if (ValidTab(nTab) && nTab < SCTAB(maTabs.size()))
     {
-        SCROW nRow = rPosition.Row();
-        return maTabs[nTab]->aCol[nCol].GetSparkline(nRow);
+        return maTabs[nTab]->GetSparkline(rPosition.Col(), rPosition.Row());
     }
     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;
+    if (ValidTab(nTab) && nTab < SCTAB(maTabs.size()))
+    {
+        return maTabs[nTab]->CreateSparkline(rPosition.Col(), rPosition.Row(), 
pSparklineGroup);
+    }
+
+    return nullptr;
+}
+
+sc::SparklineList* ScDocument::GetSparklineList(SCTAB nTab)
+{
+    if (ValidTab(nTab) && nTab < SCTAB(maTabs.size()))
+    {
+        return &maTabs[nTab]->GetSparklineList();
+    }
+    return nullptr;
 }
 
+// Notes
+
 ScPostIt* ScDocument::GetNote(const ScAddress& rPos)
 {
     return GetNote(rPos.Col(), rPos.Row(), rPos.Tab());
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index e0753b15d252..d79b3a910d28 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1809,6 +1809,43 @@ ScFormulaCell* ScTable::GetFormulaCell( SCCOL nCol, 
SCROW nRow )
     return aCol[nCol].GetFormulaCell(nRow);
 }
 
+// Sparklines
+
+sc::Sparkline* ScTable::GetSparkline(SCCOL nCol, SCROW nRow)
+{
+    if (!ValidCol(nCol) || nCol >= GetAllocatedColumnsCount())
+        return nullptr;
+
+    sc::SparklineCell* pSparklineCell = aCol[nCol].GetSparklineCell(nRow);
+    if (!pSparklineCell)
+        return nullptr;
+
+    std::shared_ptr<sc::Sparkline> pSparkline(pSparklineCell->getSparkline());
+    assert(pSparkline);
+
+    return pSparkline.get();
+}
+
+sc::Sparkline* ScTable::CreateSparkline(SCCOL nCol, SCROW nRow, 
std::shared_ptr<sc::SparklineGroup>& pSparklineGroup)
+{
+    if (!ValidCol(nCol))
+        return nullptr;
+
+    ScColumn& rColumn = CreateColumnIfNotExists(nCol);
+
+    std::shared_ptr<sc::Sparkline> pSparkline(new sc::Sparkline(nCol, nRow, 
pSparklineGroup));
+    maSparklineList.addSparkline(pSparkline);
+    rColumn.CreateSparklineCell(nRow, pSparkline);
+    return pSparkline.get();
+}
+
+sc::SparklineList& ScTable::GetSparklineList()
+{
+    return maSparklineList;
+}
+
+// Notes
+
 std::unique_ptr<ScPostIt> ScTable::ReleaseNote( SCCOL nCol, SCROW nRow )
 {
     if (!ValidCol(nCol) || nCol >= GetAllocatedColumnsCount())

Reply via email to