34 lines
1.9 KiB
Diff
34 lines
1.9 KiB
Diff
# UNDF: UNDF-2026-000001119
|
|
--- a/sc/source/filter/excel/xepivotxml.cxx
|
|
+++ b/sc/source/filter/excel/xepivotxml.cxx
|
|
@@ -1404,16 +1404,22 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScD
|
|
if (eOrient == sheet::DataPilotFieldOrientation_ROW)
|
|
aRowMemberResultData.initLookupFor(pDim->GetName());
|
|
else if (eOrient == sheet::DataPilotFieldOrientation_COLUMN)
|
|
aColumnMemberResultData.initLookupFor(pDim->GetName());
|
|
|
|
+ // Build O(1) name-to-index lookup to replace O(C) std::find in the loop below.
|
|
+ // Without this map, the loop is O(M * C) where M = aMembers.size() and
|
|
+ // C = aCacheFieldItems.size(). Large pivot tables with many distinct values
|
|
+ // (e.g. 5000-row data with a text dimension) exhibit quadratic save times.
|
|
+ std::unordered_map<OUString, size_t> aCacheItemIndex;
|
|
+ aCacheItemIndex.reserve(aCacheFieldItems.size());
|
|
+ for (size_t k = 0; k < aCacheFieldItems.size(); ++k)
|
|
+ aCacheItemIndex.emplace(aCacheFieldItems[k], k);
|
|
+
|
|
// 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;
|
|
sal_Int32 nIndex = 0;
|
|
for (const auto & rMember : aMembers)
|
|
{
|
|
- auto it = std::find(aCacheFieldItems.begin(), aCacheFieldItems.end(), rMember.maName);
|
|
- if (it != aCacheFieldItems.end())
|
|
+ auto mapIt = aCacheItemIndex.find(rMember.maName);
|
|
+ if (mapIt != aCacheItemIndex.end())
|
|
{
|
|
- size_t nCachePos = static_cast<size_t>(std::distance(aCacheFieldItems.begin(), it));
|
|
+ size_t nCachePos = mapIt->second;
|
|
auto aInserted = aUsedCachePositions.insert(nCachePos);
|
|
if (aInserted.second)
|
|
{
|