diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2017-06-22 18:10:14 +0300 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2017-06-26 10:49:17 +0200 |
commit | 47f0e83989c4c03d9690229b6433a5541032a3eb (patch) | |
tree | 511e04a9190e9e93663157ff1650eaf42b85b562 /sc/source | |
parent | 603a8414454ab963b5907085d6642dcfd432ce34 (diff) |
tdf#89139: pivotCache: output sharedItems children only for string fields
... to avoid "corrupted" warning from Excel.
In case of string fields, Excel expects the item list to be present,
and containsXXX attributes of sharedItems to be absent, otherwise
it shows a warning about file corruption.
For numeric fields, it doesn't expect item list, othervise it also
warns about file corruption.
Change-Id: I5ded5b836587bed3177eb0a6b6c418e459e6be8b
Reviewed-on: https://gerrit.libreoffice.org/39114
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'sc/source')
-rw-r--r-- | sc/source/filter/excel/xepivotxml.cxx | 102 |
1 files changed, 65 insertions, 37 deletions
diff --git a/sc/source/filter/excel/xepivotxml.cxx b/sc/source/filter/excel/xepivotxml.cxx index bf820838e0ee..a8ce9f886588 100644 --- a/sc/source/filter/excel/xepivotxml.cxx +++ b/sc/source/filter/excel/xepivotxml.cxx @@ -235,52 +235,80 @@ void XclExpXmlPivotCaches::SavePivotCacheXml( XclExpXmlStream& rStrm, const Entr ScDPCache::ScDPItemDataVec::const_iterator it = rFieldItems.begin(), itEnd = rFieldItems.end(); std::set<ScDPItemData::Type> aDPTypes; + double fMin = std::numeric_limits<double>::infinity(), fMax = -std::numeric_limits<double>::infinity(); for (; it != itEnd; ++it) { - aDPTypes.insert(it->GetType()); + ScDPItemData::Type eType = it->GetType(); + aDPTypes.insert(eType); + if (eType == ScDPItemData::Value) + { + double fVal = it->GetValue(); + fMin = std::min(fMin, fVal); + fMax = std::max(fMax, fVal); + } } auto aDPTypeEnd = aDPTypes.cend(); - pDefStrm->startElement(XML_sharedItems, - XML_count, OString::number(static_cast<long>(rFieldItems.size())).getStr(), - XML_containsMixedTypes, XclXmlUtils::ToPsz10(aDPTypes.size() > 1), - XML_containsSemiMixedTypes, XclXmlUtils::ToPsz10(aDPTypes.size() > 1), - XML_containsString, XclXmlUtils::ToPsz10(aDPTypes.find(ScDPItemData::String) != aDPTypeEnd), - XML_containsNumber, XclXmlUtils::ToPsz10(aDPTypes.find(ScDPItemData::Value) != aDPTypeEnd), - FSEND); + auto pAttList = sax_fastparser::FastSerializerHelper::createAttrList(); + // tdf#89139: Only create item list for string-only fields. + // Using containsXXX attributes in this case makes Excel think the file is corrupted. + // OTOH listing items for e.g. number fields also triggers "corrupted" warning in Excel. + bool bListItems = aDPTypes.size() == 1 && aDPTypes.find(ScDPItemData::String) != aDPTypeEnd; + if (bListItems) + { + pAttList->add(XML_count, OString::number(static_cast<long>(rFieldItems.size()))); + } + else + { + pAttList->add(XML_containsMixedTypes, XclXmlUtils::ToPsz10(aDPTypes.size() > 1)); + pAttList->add(XML_containsSemiMixedTypes, XclXmlUtils::ToPsz10(aDPTypes.size() > 1)); + pAttList->add(XML_containsString, XclXmlUtils::ToPsz10(aDPTypes.find(ScDPItemData::String) != aDPTypeEnd)); + if (aDPTypes.find(ScDPItemData::Value) != aDPTypeEnd) + { + pAttList->add(XML_containsNumber, XclXmlUtils::ToPsz10(true)); + pAttList->add(XML_minValue, OString::number(fMin)); + pAttList->add(XML_maxValue, OString::number(fMax)); + } + } + sax_fastparser::XFastAttributeListRef xAttributeList(pAttList); - it = rFieldItems.begin(); - for (; it != itEnd; ++it) + pDefStrm->startElement(XML_sharedItems, xAttributeList); + + if (bListItems) { - const ScDPItemData& rItem = *it; - switch (rItem.GetType()) + it = rFieldItems.begin(); + for (; it != itEnd; ++it) { - case ScDPItemData::String: - pDefStrm->singleElement(XML_s, - XML_v, XclXmlUtils::ToOString(rItem.GetString()).getStr(), - FSEND); - break; - case ScDPItemData::Value: - pDefStrm->singleElement(XML_n, - XML_v, OString::number(rItem.GetValue()).getStr(), - FSEND); - break; - case ScDPItemData::Empty: - pDefStrm->singleElement(XML_m, FSEND); - break; - case ScDPItemData::Error: - pDefStrm->singleElement(XML_e, - XML_v, XclXmlUtils::ToOString(rItem.GetString()).getStr(), - FSEND); - break; - case ScDPItemData::GroupValue: - case ScDPItemData::RangeStart: - // TODO : What do we do with these types? - pDefStrm->singleElement(XML_m, FSEND); - break; - default: - ; + const ScDPItemData& rItem = *it; + switch (rItem.GetType()) + { + case ScDPItemData::String: + pDefStrm->singleElement(XML_s, + XML_v, XclXmlUtils::ToOString(rItem.GetString()), + FSEND); + break; + case ScDPItemData::Value: + pDefStrm->singleElement(XML_n, + XML_v, OString::number(rItem.GetValue()), + FSEND); + break; + case ScDPItemData::Empty: + pDefStrm->singleElement(XML_m, FSEND); + break; + case ScDPItemData::Error: + pDefStrm->singleElement(XML_e, + XML_v, XclXmlUtils::ToOString(rItem.GetString()), + FSEND); + break; + case ScDPItemData::GroupValue: + case ScDPItemData::RangeStart: + // TODO : What do we do with these types? + pDefStrm->singleElement(XML_m, FSEND); + break; + default: + ; + } } } |