summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2017-06-22 18:10:14 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2017-06-26 10:49:17 +0200
commit47f0e83989c4c03d9690229b6433a5541032a3eb (patch)
tree511e04a9190e9e93663157ff1650eaf42b85b562
parent603a8414454ab963b5907085d6642dcfd432ce34 (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>
-rw-r--r--sc/source/filter/excel/xepivotxml.cxx102
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:
+ ;
+ }
}
}