tdf#89139: list all items in pivot table definition, incl. hidden
Change-Id: I14ce935185a6e0e3739fcf01fdefa031d814e821 Reviewed-on: https://gerrit.libreoffice.org/41509 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
This commit is contained in:
BIN
sc/qa/unit/data/xlsx/tdf89139_pivot_table.xlsx
Normal file
BIN
sc/qa/unit/data/xlsx/tdf89139_pivot_table.xlsx
Normal file
Binary file not shown.
@@ -115,6 +115,7 @@ public:
|
|||||||
void testCellNoteExportXLS();
|
void testCellNoteExportXLS();
|
||||||
void testFormatExportODS();
|
void testFormatExportODS();
|
||||||
|
|
||||||
|
void testPivotTableExportXLSX();
|
||||||
void testPivotExportXLSX();
|
void testPivotExportXLSX();
|
||||||
void testCommentExportXLSX();
|
void testCommentExportXLSX();
|
||||||
#if HAVE_MORE_FONTS
|
#if HAVE_MORE_FONTS
|
||||||
@@ -227,6 +228,7 @@ public:
|
|||||||
CPPUNIT_TEST(testCellNoteExportXLS);
|
CPPUNIT_TEST(testCellNoteExportXLS);
|
||||||
CPPUNIT_TEST(testFormatExportODS);
|
CPPUNIT_TEST(testFormatExportODS);
|
||||||
|
|
||||||
|
CPPUNIT_TEST(testPivotTableExportXLSX);
|
||||||
CPPUNIT_TEST(testPivotExportXLSX);
|
CPPUNIT_TEST(testPivotExportXLSX);
|
||||||
CPPUNIT_TEST(testCommentExportXLSX);
|
CPPUNIT_TEST(testCommentExportXLSX);
|
||||||
#if HAVE_MORE_FONTS
|
#if HAVE_MORE_FONTS
|
||||||
@@ -563,6 +565,22 @@ void ScExportTest::testFormatExportODS()
|
|||||||
xDocSh->DoClose();
|
xDocSh->DoClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScExportTest::testPivotTableExportXLSX()
|
||||||
|
{
|
||||||
|
// tdf#89139: pivot table definition needs to list items, including hidden
|
||||||
|
|
||||||
|
ScDocShellRef xShell = loadDoc("tdf89139_pivot_table.", FORMAT_XLSX);
|
||||||
|
CPPUNIT_ASSERT(xShell.is());
|
||||||
|
|
||||||
|
std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(&(*xShell), FORMAT_XLSX);
|
||||||
|
xmlDocPtr pTable = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/pivotTables/pivotTable1.xml");
|
||||||
|
CPPUNIT_ASSERT(pTable);
|
||||||
|
|
||||||
|
assertXPath(pTable, "/x:pivotTableDefinition/x:pivotFields/x:pivotField[3]/x:items", "count", "4");
|
||||||
|
assertXPath(pTable, "/x:pivotTableDefinition/x:pivotFields/x:pivotField[3]/x:items/x:item", 4);
|
||||||
|
assertXPath(pTable, "/x:pivotTableDefinition/x:pivotFields/x:pivotField[3]/x:items/x:item[3]", "h", "1");
|
||||||
|
}
|
||||||
|
|
||||||
void ScExportTest::testPivotExportXLSX()
|
void ScExportTest::testPivotExportXLSX()
|
||||||
{
|
{
|
||||||
// tdf#89139 FILESAVE xlsx pivot table corrupted after save with LO and re-open with MS Office
|
// tdf#89139 FILESAVE xlsx pivot table corrupted after save with LO and re-open with MS Office
|
||||||
|
@@ -701,24 +701,35 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dump field items.
|
// Dump field items.
|
||||||
css::uno::Sequence<OUString> aMemberNames;
|
std::vector<ScDPLabelData::Member> aMembers;
|
||||||
{
|
{
|
||||||
// We need to get the members in actual order, getting which requires non-const reference here
|
// We need to get the members in actual order, getting which requires non-const reference here
|
||||||
auto& dpo = const_cast<ScDPObject&>(rDPObj);
|
auto& dpo = const_cast<ScDPObject&>(rDPObj);
|
||||||
dpo.GetMemberNames(i, aMemberNames);
|
dpo.GetMembers(i, dpo.GetUsedHierarchy(i), aMembers);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ScDPCache::ScDPItemDataVec& rCacheFieldItems = rCache.GetDimMemberValues(i);
|
const ScDPCache::ScDPItemDataVec& rCacheFieldItems = rCache.GetDimMemberValues(i);
|
||||||
std::vector<size_t> aMemberSequence;
|
const auto iCacheFieldItems_begin = rCacheFieldItems.begin(), iCacheFieldItems_end = rCacheFieldItems.end();
|
||||||
for (const OUString& sMemberName : aMemberNames)
|
// The pair contains the member index in cache and if it is hidden
|
||||||
|
std::vector< std::pair<size_t, bool> > aMemberSequence;
|
||||||
|
std::set<size_t> aUsedCachePositions;
|
||||||
|
for (const auto & rMember : aMembers)
|
||||||
{
|
{
|
||||||
auto it = std::find_if(rCacheFieldItems.begin(), rCacheFieldItems.end(),
|
auto it = std::find_if(iCacheFieldItems_begin, iCacheFieldItems_end,
|
||||||
[&sMemberName](const ScDPItemData& arg) -> bool { return arg.GetString() == sMemberName; });
|
[&rMember](const ScDPItemData& arg) -> bool { return arg.GetString() == rMember.maName; });
|
||||||
if (it != rCacheFieldItems.end())
|
if (it != iCacheFieldItems_end)
|
||||||
{
|
{
|
||||||
aMemberSequence.push_back(it - rCacheFieldItems.begin());
|
size_t nCachePos = it - iCacheFieldItems_begin;
|
||||||
|
aMemberSequence.push_back(std::make_pair(nCachePos, !rMember.mbVisible));
|
||||||
|
aUsedCachePositions.insert(nCachePos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Now add all remaining cache items as hidden
|
||||||
|
for (size_t nItem = 0; nItem < rCacheFieldItems.size(); ++nItem)
|
||||||
|
{
|
||||||
|
if (aUsedCachePositions.find(nItem) == aUsedCachePositions.end())
|
||||||
|
aMemberSequence.push_back(std::make_pair(nItem, true));
|
||||||
|
}
|
||||||
|
|
||||||
auto pAttList = sax_fastparser::FastSerializerHelper::createAttrList();
|
auto pAttList = sax_fastparser::FastSerializerHelper::createAttrList();
|
||||||
pAttList->add(XML_axis, toOOXMLAxisType(eOrient));
|
pAttList->add(XML_axis, toOOXMLAxisType(eOrient));
|
||||||
@@ -726,14 +737,20 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP
|
|||||||
|
|
||||||
long nSubTotalCount = pDim->GetSubTotalsCount();
|
long nSubTotalCount = pDim->GetSubTotalsCount();
|
||||||
std::vector<OString> aSubtotalSequence;
|
std::vector<OString> aSubtotalSequence;
|
||||||
|
bool bHasDefaultSubtotal = false;
|
||||||
for (long nSubTotal = 0; nSubTotal < nSubTotalCount; ++nSubTotal)
|
for (long nSubTotal = 0; nSubTotal < nSubTotalCount; ++nSubTotal)
|
||||||
{
|
{
|
||||||
ScGeneralFunction eFunc = pDim->GetSubTotalFunc(nSubTotal);
|
ScGeneralFunction eFunc = pDim->GetSubTotalFunc(nSubTotal);
|
||||||
aSubtotalSequence.push_back(GetSubtotalFuncName(eFunc));
|
aSubtotalSequence.push_back(GetSubtotalFuncName(eFunc));
|
||||||
sal_Int32 nAttToken = GetSubtotalAttrToken(eFunc);
|
sal_Int32 nAttToken = GetSubtotalAttrToken(eFunc);
|
||||||
if (!pAttList->hasAttribute(nAttToken))
|
if (nAttToken == XML_defaultSubtotal)
|
||||||
|
bHasDefaultSubtotal = true;
|
||||||
|
else if (!pAttList->hasAttribute(nAttToken))
|
||||||
pAttList->add(nAttToken, ToPsz10(true));
|
pAttList->add(nAttToken, ToPsz10(true));
|
||||||
}
|
}
|
||||||
|
// XML_defaultSubtotal is true by default; only write it if it's false
|
||||||
|
if (!bHasDefaultSubtotal)
|
||||||
|
pAttList->add(XML_defaultSubtotal, ToPsz10(false));
|
||||||
|
|
||||||
sax_fastparser::XFastAttributeListRef xAttributeList(pAttList);
|
sax_fastparser::XFastAttributeListRef xAttributeList(pAttList);
|
||||||
pPivotStrm->startElement(XML_pivotField, xAttributeList);
|
pPivotStrm->startElement(XML_pivotField, xAttributeList);
|
||||||
@@ -742,11 +759,14 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP
|
|||||||
XML_count, OString::number(static_cast<long>(aMemberSequence.size() + aSubtotalSequence.size())),
|
XML_count, OString::number(static_cast<long>(aMemberSequence.size() + aSubtotalSequence.size())),
|
||||||
FSEND);
|
FSEND);
|
||||||
|
|
||||||
for (size_t nMember : aMemberSequence)
|
for (const auto & nMember : aMemberSequence)
|
||||||
{
|
{
|
||||||
pPivotStrm->singleElement(XML_item,
|
auto pItemAttList = sax_fastparser::FastSerializerHelper::createAttrList();
|
||||||
XML_x, OString::number(static_cast<long>(nMember)),
|
if (nMember.second)
|
||||||
FSEND);
|
pItemAttList->add(XML_h, ToPsz10(true));
|
||||||
|
pItemAttList->add(XML_x, OString::number(static_cast<long>(nMember.first)));
|
||||||
|
sax_fastparser::XFastAttributeListRef xItemAttributeList(pItemAttList);
|
||||||
|
pPivotStrm->singleElement(XML_item, xItemAttributeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const OString& sSubtotal : aSubtotalSequence)
|
for (const OString& sSubtotal : aSubtotalSequence)
|
||||||
|
Reference in New Issue
Block a user