xlsx: Don't add cell data to chart data sequence if in totalsRow

When importing data from a cell range to use in a chart, if a cell is in
the totalsRow it is now ignored if it's the last row in the range.

Change-Id: Ie8c79b995c4d46b361492e8f7687894e2640392f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143488
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
diff --git a/chart2/qa/extras/chart2import.cxx b/chart2/qa/extras/chart2import.cxx
index 68791e3..a9c301a 100644
--- a/chart2/qa/extras/chart2import.cxx
+++ b/chart2/qa/extras/chart2import.cxx
@@ -137,6 +137,7 @@ public:
    void testTdf121205();
    void testFixedSizeBarChartVeryLongLabel();
    void testAutomaticSizeBarChartVeryLongLabel();
    void testTotalsRowIgnored();

    CPPUNIT_TEST_SUITE(Chart2ImportTest);
    CPPUNIT_TEST(Fdo60083);
@@ -223,6 +224,7 @@ public:
    CPPUNIT_TEST(testTdf121205);
    CPPUNIT_TEST(testFixedSizeBarChartVeryLongLabel);
    CPPUNIT_TEST(testAutomaticSizeBarChartVeryLongLabel);
    CPPUNIT_TEST(testTotalsRowIgnored);

    CPPUNIT_TEST_SUITE_END();
};
@@ -2274,6 +2276,33 @@ void Chart2ImportTest::testAutomaticSizeBarChartVeryLongLabel()
    CPPUNIT_ASSERT_DOUBLES_EQUAL(1192, xXAxis->getSize().Height, 100);
}

void Chart2ImportTest::testTotalsRowIgnored()
{
    loadFromURL(u"xlsx/barchart_totalsrow.xlsx");
    {
        uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
        CPPUNIT_ASSERT(xChartDoc.is());

        Reference<chart2::data::XDataSequence> xDataSeq =
            getDataSequenceFromDocByRole(xChartDoc, u"values-y");
        CPPUNIT_ASSERT(xDataSeq.is());

        // Table data range is D2:D9 (8 rows) but because last row is totals row it is ignored
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(7u), xDataSeq->getData().size());
    }
    {
        uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(1, mxComponent);
        CPPUNIT_ASSERT(xChartDoc.is());

        Reference<chart2::data::XDataSequence> xDataSeq =
            getDataSequenceFromDocByRole(xChartDoc, u"values-y");
        CPPUNIT_ASSERT(xDataSeq.is());

        // Table data range is D2:D10 (9 rows) and totals row isn't the last row so it's not ignored
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(9u), xDataSeq->getData().size());
    }
}

CPPUNIT_TEST_SUITE_REGISTRATION(Chart2ImportTest);

CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/chart2/qa/extras/data/xlsx/barchart_totalsrow.xlsx b/chart2/qa/extras/data/xlsx/barchart_totalsrow.xlsx
new file mode 100644
index 0000000..c87b2b3
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/barchart_totalsrow.xlsx
Binary files differ
diff --git a/sc/source/ui/unoobj/chart2uno.cxx b/sc/source/ui/unoobj/chart2uno.cxx
index f92b1d4..18378bdf 100644
--- a/sc/source/ui/unoobj/chart2uno.cxx
+++ b/sc/source/ui/unoobj/chart2uno.cxx
@@ -2571,6 +2571,26 @@ void ScChart2DataSequence::BuildDataCache()
                    m_pDocument->InitColumnBlockPosition( hint, nTab, nCol );
                    for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow)
                    {
                        if (nRow == aRange.aEnd.Row())
                        {
                            // Excel behavior: if the last row is the totals row, the data
                            // is not added to the chart. If it's not the last row, the data
                            // is added like normal.
                            const auto* rData = m_pDocument->GetDBAtCursor(
                                nCol, nRow, nTab,
                                ScDBDataPortion::AREA
                            );
                            if (rData && rData->HasTotals())
                            {
                                ScRange aTempRange;
                                rData->GetArea(aTempRange);
                                if (aTempRange.aEnd.Row() == nRow)
                                {
                                    // Current row is totals row, skip
                                    break;
                                }
                            }
                        }
                        bool bColHidden = m_pDocument->ColHidden(nCol, nTab, nullptr, &nLastCol);
                        bool bRowHidden = m_pDocument->RowHidden(nRow, nTab, nullptr, &nLastRow);