diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2017-06-13 22:00:51 +0300 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2017-06-26 16:45:30 +0200 |
commit | f2b846a1fefa0cd7a091204ed3f8aa00515b34fd (patch) | |
tree | 346473d44f531a1d281472d20a7302aa1e33eb73 /sc | |
parent | 748ebf9573096d31a59cdbf5d1e65340d1d55cfa (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.cxx | 102 |
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); } |