summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2017-06-13 22:00:51 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2017-06-26 16:45:30 +0200
commitf2b846a1fefa0cd7a091204ed3f8aa00515b34fd (patch)
tree346473d44f531a1d281472d20a7302aa1e33eb73 /sc
parent748ebf9573096d31a59cdbf5d1e65340d1d55cfa (diff)
tdf#89139: dump pivotField items
This makes the pivot table exported to XLSX refreshable (does not crash Excel on pivot table refresh). Change-Id: Icc35795cd116e091b75bb1d4a603c52ccc71c44d Reviewed-on: https://gerrit.libreoffice.org/39018 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Kohei Yoshida <libreoffice@kohei.us> (cherry picked from commit 430774c4edcdba3e6a4e383d9ac9345a517e227f) Reviewed-on: https://gerrit.libreoffice.org/39256 Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com> Tested-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'sc')
-rw-r--r--sc/source/filter/excel/xepivotxml.cxx102
1 files changed, 97 insertions, 5 deletions
diff --git a/sc/source/filter/excel/xepivotxml.cxx b/sc/source/filter/excel/xepivotxml.cxx
index 1b340812cc3f..d03403aa230b 100644
--- a/sc/source/filter/excel/xepivotxml.cxx
+++ b/sc/source/filter/excel/xepivotxml.cxx
@@ -413,6 +413,47 @@ struct DataField
DataField( long nPos, const ScDPSaveDimension* pDim ) : mnPos(nPos), mpDim(pDim) {}
};
+/** Returns a OOXML subtotal function name string. See ECMA-376-1:2016 18.18.43 */
+OString GetSubtotalFuncName(sal_uInt16 eFunc)
+{
+ switch (eFunc)
+ {
+ case sheet::GeneralFunction_SUM: return "sum";
+ case sheet::GeneralFunction_COUNT: return "count";
+ case sheet::GeneralFunction_AVERAGE: return "avg";
+ case sheet::GeneralFunction_MAX: return "max";
+ case sheet::GeneralFunction_MIN: return "min";
+ case sheet::GeneralFunction_PRODUCT: return "product";
+ case sheet::GeneralFunction_COUNTNUMS: return "countA";
+ case sheet::GeneralFunction_STDEV: return "stdDev";
+ case sheet::GeneralFunction_STDEVP: return "stdDevP";
+ case sheet::GeneralFunction_VAR: return "var";
+ case sheet::GeneralFunction_VARP: return "varP";
+ default:;
+ }
+ return "default";
+}
+
+sal_Int32 GetSubtotalAttrToken(sal_uInt16 eFunc)
+{
+ switch (eFunc)
+ {
+ case sheet::GeneralFunction_SUM: return XML_sumSubtotal;
+ case sheet::GeneralFunction_COUNT: return XML_countSubtotal;
+ case sheet::GeneralFunction_AVERAGE: return XML_avgSubtotal;
+ case sheet::GeneralFunction_MAX: return XML_maxSubtotal;
+ case sheet::GeneralFunction_MIN: return XML_minSubtotal;
+ case sheet::GeneralFunction_PRODUCT: return XML_productSubtotal;
+ case sheet::GeneralFunction_COUNTNUMS: return XML_countASubtotal;
+ case sheet::GeneralFunction_STDEV: return XML_stdDevSubtotal;
+ case sheet::GeneralFunction_STDEVP: return XML_stdDevPSubtotal;
+ case sheet::GeneralFunction_VAR: return XML_varSubtotal;
+ case sheet::GeneralFunction_VARP: return XML_varPSubtotal;
+ default:;
+ }
+ return XML_defaultSubtotal;
+}
+
}
void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDPObject& rDPObj, sal_Int32 nCacheId )
@@ -554,8 +595,9 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP
XML_count, OString::number(static_cast<long>(aCachedDims.size())).getStr(),
FSEND);
- for (const ScDPSaveDimension* pDim : aCachedDims)
+ for (size_t i = 0; i < nFieldCount; ++i)
{
+ const ScDPSaveDimension* pDim = aCachedDims[i];
if (!pDim)
{
pPivotStrm->singleElement(XML_pivotField,
@@ -585,13 +627,63 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP
continue;
}
- pPivotStrm->startElement(XML_pivotField,
- XML_axis, toOOXMLAxisType(eOrient),
- XML_showAll, BS(false),
+ // Dump field items.
+ css::uno::Sequence<OUString> aMemberNames;
+ {
+ // We need to get the members in actual order, getting which requires non-const reference here
+ auto& dpo = const_cast<ScDPObject&>(rDPObj);
+ dpo.GetMemberNames(i, aMemberNames);
+ }
+
+ const ScDPCache::ScDPItemDataVec& rCacheFieldItems = rCache.GetDimMemberValues(i);
+ std::vector<size_t> aMemberSequence;
+ for (const OUString& sMemberName : aMemberNames)
+ {
+ auto it = std::find_if(rCacheFieldItems.begin(), rCacheFieldItems.end(),
+ [&sMemberName](const ScDPItemData& arg) -> bool { return arg.GetString() == sMemberName; });
+ if (it != rCacheFieldItems.end())
+ {
+ aMemberSequence.push_back(it - rCacheFieldItems.begin());
+ }
+ }
+
+ auto pAttList = sax_fastparser::FastSerializerHelper::createAttrList();
+ pAttList->add(XML_axis, toOOXMLAxisType(eOrient));
+ pAttList->add(XML_showAll, BS(false));
+
+ long nSubTotalCount = pDim->GetSubTotalsCount();
+ std::vector<OString> aSubtotalSequence;
+ for (long nSubTotal = 0; nSubTotal < nSubTotalCount; ++nSubTotal)
+ {
+ sal_uInt16 eFunc = pDim->GetSubTotalFunc(nSubTotal);
+ aSubtotalSequence.push_back(GetSubtotalFuncName(eFunc));
+ sal_Int32 nAttToken = GetSubtotalAttrToken(eFunc);
+ if (!pAttList->hasAttribute(nAttToken))
+ pAttList->add(nAttToken, BS(true));
+ }
+
+ sax_fastparser::XFastAttributeListRef xAttributeList(pAttList);
+ pPivotStrm->startElement(XML_pivotField, xAttributeList);
+
+ pPivotStrm->startElement(XML_items,
+ XML_count, OString::number(static_cast<long>(aMemberSequence.size() + aSubtotalSequence.size())),
FSEND);
- // TODO : Dump field items.
+ for (size_t nMember : aMemberSequence)
+ {
+ pPivotStrm->singleElement(XML_item,
+ XML_x, OString::number(static_cast<long>(nMember)),
+ FSEND);
+ }
+
+ for (const OString& sSubtotal : aSubtotalSequence)
+ {
+ pPivotStrm->singleElement(XML_item,
+ XML_t, sSubtotal,
+ FSEND);
+ }
+ pPivotStrm->endElement(XML_items);
pPivotStrm->endElement(XML_pivotField);
}