sc/qa/unit/data/ods/tdf123225_pivotTable_empty_row_col_items.ods |binary sc/qa/unit/pivottable_filters_test.cxx | 23 ++++++++++ sc/source/filter/excel/xepivotxml.cxx | 20 +++++--- 3 files changed, 35 insertions(+), 8 deletions(-)
New commits: commit a4460b67b7c5273b62cf8597dedbbb2850c97489 Author: Bayram Çiçek <bayram.ci...@collabora.com> AuthorDate: Wed Mar 5 13:40:08 2025 +0300 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Tue Mar 18 11:39:07 2025 +0100 tdf#123225 - calculate count attribute correctly in xl/pivotTables/pivotTable*.xml we have e.g. <location ref="A3:B6" firstHeaderRow="1" firstDataRow="1" firstDataCol="1" rowPageCount="1" colPageCount="1"/> - the 'ref' attribute indicates the cell range of a pivot table. - 'firstDataRow' specifies the first row of the PivotTable data, relative to the top left cell in the ref value. - 'firstDataCol' specifies the first column of the PivotTable data, relative to the top left cell in the ref value. if we get the number of rows and cols in the pivot table (using <location ref="..."), and substract 'firstDataRow' & 'firstDataCol' from it, we get the correct count attr. value of <row/colItems> during export from ODS -> XLSX. - added testTdf123225PivotTableEmptyRowColItems Cppunit test to make sure that export works with empty row/col items. Signed-off-by: Bayram Çiçek <bayram.ci...@collabora.com> Change-Id: Ia85a89e429d95492f0f753af3fbf46771d1a2a0f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182529 Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> (cherry picked from commit 765bf4bff2b8d4ed9569e735dc663ac55ae7a424) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183063 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> diff --git a/sc/qa/unit/data/ods/tdf123225_pivotTable_empty_row_col_items.ods b/sc/qa/unit/data/ods/tdf123225_pivotTable_empty_row_col_items.ods new file mode 100644 index 000000000000..fba4bc00d3ab Binary files /dev/null and b/sc/qa/unit/data/ods/tdf123225_pivotTable_empty_row_col_items.ods differ diff --git a/sc/qa/unit/pivottable_filters_test.cxx b/sc/qa/unit/pivottable_filters_test.cxx index 9c710bcd5324..1baaca95568e 100644 --- a/sc/qa/unit/pivottable_filters_test.cxx +++ b/sc/qa/unit/pivottable_filters_test.cxx @@ -234,6 +234,29 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testTdf123225PivotTableNoColItems) assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i/x:x"_ostr, "v"_ostr, "0"); } +CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testTdf123225PivotTableEmptyRowColItems) +{ + // this doc contains blank row/col items + // <sharedItems containsBlank="1" count="..."> (xl/pivotCache/pivotCacheDefinition1.xml) + createScDoc("ods/tdf123225_pivotTable_empty_row_col_items.ods"); + save(u"Calc Office Open XML"_ustr); + + xmlDocUniquePtr pSheet = parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + + // Row items <rowItems> + + assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems"_ostr, 1); + // check if <rowItems count="4"> + assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems"_ostr, "count"_ostr, "4"); + + // Column items <colItems> + + assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems"_ostr, 1); + // check if <colItems count="5"> + assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems"_ostr, "count"_ostr, "5"); +} + CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testPivotTableNamedRangeSourceODS) { createScDoc("ods/pivot-table-named-range-source.ods"); diff --git a/sc/source/filter/excel/xepivotxml.cxx b/sc/source/filter/excel/xepivotxml.cxx index 66bebb04865a..41ec742a7fa1 100644 --- a/sc/source/filter/excel/xepivotxml.cxx +++ b/sc/source/filter/excel/xepivotxml.cxx @@ -861,6 +861,12 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP // NB: Excel's range does not include page field area (if any). ScRange aOutRange = rDPObj.GetOutputRangeByType(sheet::DataPilotOutputRangeType::TABLE); + // normalize the order to prevent negative row/col counts - just in case. + aOutRange.PutInOrder(); + // both start and end cells are included. subtraction excludes the start cells, therefore add +1. + SCROW pivotTableRowCount = aOutRange.aEnd.Row() - aOutRange.aStart.Row() + 1; + SCCOL pivotTableColCount = aOutRange.aEnd.Col() - aOutRange.aStart.Col() + 1; + sal_Int32 nFirstHeaderRow = rDPObj.GetHideHeader() ? 0 : (rDPObj.GetHeaderLayout() ? 2 : 1); sal_Int32 nFirstDataRow = rDPObj.GetHideHeader() ? 1 : 2; sal_Int32 nFirstDataCol = 1; @@ -1058,15 +1064,8 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP pAttList->add( XML_outline, ToPsz10(false)); pPivotStrm->startElement(XML_pivotField, pAttList); - tools::Long nItemsCount - = static_cast<tools::Long>(aMemberSequence.size() + aSubtotalSequence.size()); pPivotStrm->startElement(XML_items, - XML_count, OString::number(nItemsCount)); - - if (strcmp(toOOXMLAxisType(eOrient), "axisCol") == 0) - nColItemsCount = nItemsCount; - else if (strcmp(toOOXMLAxisType(eOrient), "axisRow") == 0) - nRowItemsCount = nItemsCount; + XML_count, OString::number(static_cast<tools::Long>(aMemberSequence.size() + aSubtotalSequence.size()))); for (const auto & nMember : aMemberSequence) { @@ -1077,6 +1076,11 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP pPivotStrm->singleElement(XML_item, pItemAttList); } + if (strcmp(toOOXMLAxisType(eOrient), "axisCol") == 0) + nColItemsCount = pivotTableColCount - nFirstDataCol; + else if (strcmp(toOOXMLAxisType(eOrient), "axisRow") == 0) + nRowItemsCount = pivotTableRowCount - nFirstDataRow; + for (const OString& sSubtotal : aSubtotalSequence) { pPivotStrm->singleElement(XML_item, XML_t, sSubtotal);