diff options
author | Dennis Francis <dennis.francis@collabora.com> | 2019-04-19 23:15:53 +0530 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2019-05-04 10:22:02 +0200 |
commit | c2f1c68ffb6dfa1ce7de09dcc428d6c53549e88d (patch) | |
tree | 15d5df7332e6249922645e58d30c2706df17c659 /sc/source/filter/oox | |
parent | 8c637b47d9de4b3a64c33a9c2ffe7ed220be2467 (diff) |
tdf#122590: follow-up : import x14:cfRule priorities
If there are x:cfRule's and x14:cfRule's with matching
range-list, then insert the conditional-fmt entries into
the document in the order of the priorities. That is
don't just append the x14:cfRule entries to the document
after the x:cfRule entries are inserted.
There was also a off-by-one bug in the priority export
of x14:cfRule entries. This caused the priority numbers
to be duplicated. This is also fixed.
Change-Id: I5b0d11c4456b2966b808f6ee589075a870f43768
Reviewed-on: https://gerrit.libreoffice.org/71311
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Diffstat (limited to 'sc/source/filter/oox')
-rw-r--r-- | sc/source/filter/oox/condformatbuffer.cxx | 87 | ||||
-rw-r--r-- | sc/source/filter/oox/extlstcontext.cxx | 15 |
2 files changed, 96 insertions, 6 deletions
diff --git a/sc/source/filter/oox/condformatbuffer.cxx b/sc/source/filter/oox/condformatbuffer.cxx index 5750cce50592..0d75b4399200 100644 --- a/sc/source/filter/oox/condformatbuffer.cxx +++ b/sc/source/filter/oox/condformatbuffer.cxx @@ -18,6 +18,8 @@ */ #include <memory> +#include <unordered_set> +#include <unordered_map> #include <condformatbuffer.hxx> #include <formulaparser.hxx> @@ -424,7 +426,8 @@ void CondFormatRuleModel::setBiff12TextType( sal_Int32 nOperator ) CondFormatRule::CondFormatRule( const CondFormat& rCondFormat, ScConditionalFormat* pFormat ) : WorksheetHelper( rCondFormat ), mrCondFormat( rCondFormat ), - mpFormat(pFormat) + mpFormat(pFormat), + mpFormatEntry(nullptr) { } @@ -698,8 +701,20 @@ void CondFormatRule::importCfRule( SequenceInputStream& rStrm ) } } +void CondFormatRule::setFormatEntry(sal_Int32 nPriority, ScFormatEntry* pEntry) +{ + maModel.mnPriority = nPriority; + mpFormatEntry = pEntry; +} + void CondFormatRule::finalizeImport() { + if (mpFormatEntry) + { + mpFormat->AddEntry(mpFormatEntry); + return; + } + ScConditionMode eOperator = ScConditionMode::NONE; /* Replacement formula for unsupported rule types (text comparison rules, @@ -1091,10 +1106,63 @@ ScConditionalFormat* findFormatByRange(const ScRangeList& rRange, const ScDocume return nullptr; } +class ScRangeListHasher +{ +public: + size_t operator() (ScRangeList const& rRanges) const + { + size_t nHash = 0; + for (size_t nIdx = 0; nIdx < rRanges.size(); ++nIdx) + nHash += rRanges[nIdx].hashArea(); + return nHash; + } +}; + } void CondFormatBuffer::finalizeImport() { + std::unordered_set<size_t> aDoneExtCFs; + typedef std::unordered_map<ScRangeList, CondFormat*, ScRangeListHasher> RangeMap; + typedef std::vector<std::unique_ptr<ScFormatEntry>> FormatEntries; + RangeMap aRangeMap; + for (auto& rxCondFormat : maCondFormats) + { + if (aRangeMap.find(rxCondFormat->getRanges()) != aRangeMap.end()) + continue; + aRangeMap[rxCondFormat->getRanges()] = rxCondFormat.get(); + } + + size_t nExtCFIndex = 0; + for (const auto& rxExtCondFormat : maExtCondFormats) + { + ScDocument* pDoc = &getScDocument(); + const ScRangeList& rRange = rxExtCondFormat->getRange(); + RangeMap::iterator it = aRangeMap.find(rRange); + if (it != aRangeMap.end()) + { + CondFormat& rCondFormat = *it->second; + const FormatEntries& rEntries = rxExtCondFormat->getEntries(); + const std::vector<sal_Int32>& rPriorities = rxExtCondFormat->getPriorities(); + size_t nEntryIdx = 0; + for (const auto& rxEntry : rEntries) + { + CondFormatRuleRef xRule = rCondFormat.createRule(); + ScFormatEntry* pNewEntry = rxEntry->Clone(pDoc); + sal_Int32 nPriority = rPriorities[nEntryIdx]; + if (nPriority == -1) + nPriority = mnNonPrioritizedRuleNextPriority++; + xRule->setFormatEntry(nPriority, pNewEntry); + rCondFormat.insertRule(xRule); + ++nEntryIdx; + } + + aDoneExtCFs.insert(nExtCFIndex); + } + + ++nExtCFIndex; + } + for( const auto& rxCondFormat : maCondFormats ) { if ( rxCondFormat.get()) @@ -1106,10 +1174,16 @@ void CondFormatBuffer::finalizeImport() rxCfRule.get()->finalizeImport(); } + nExtCFIndex = 0; for (const auto& rxExtCondFormat : maExtCondFormats) { - ScDocument* pDoc = &getScDocument(); + if (aDoneExtCFs.count(nExtCFIndex)) + { + ++nExtCFIndex; + continue; + } + ScDocument* pDoc = &getScDocument(); const ScRangeList& rRange = rxExtCondFormat->getRange(); SCTAB nTab = rRange.front().aStart.Tab(); ScConditionalFormat* pFormat = findFormatByRange(rRange, pDoc, nTab); @@ -1128,6 +1202,8 @@ void CondFormatBuffer::finalizeImport() { pFormat->AddEntry(rxEntry->Clone(pDoc)); } + + ++nExtCFIndex; } rStyleIdx = 0; // Resets <extlst> <cfRule> style index. @@ -1294,10 +1370,15 @@ void ExtCfDataBarRule::importCfvo( const AttributeList& rAttribs ) maModel.maColorScaleType = rAttribs.getString( XML_type, OUString() ); } -ExtCfCondFormat::ExtCfCondFormat(const ScRangeList& rRange, std::vector< std::unique_ptr<ScFormatEntry> >& rEntries): +ExtCfCondFormat::ExtCfCondFormat(const ScRangeList& rRange, std::vector< std::unique_ptr<ScFormatEntry> >& rEntries, + std::vector<sal_Int32>* pPriorities): maRange(rRange) { maEntries.swap(rEntries); + if (pPriorities) + maPriorities = *pPriorities; + else + maPriorities.resize(maEntries.size(), -1); } ExtCfCondFormat::~ExtCfCondFormat() diff --git a/sc/source/filter/oox/extlstcontext.cxx b/sc/source/filter/oox/extlstcontext.cxx index 1d1bc8341fd5..46d268f32ca7 100644 --- a/sc/source/filter/oox/extlstcontext.cxx +++ b/sc/source/filter/oox/extlstcontext.cxx @@ -84,6 +84,7 @@ void ExtCfRuleContext::onStartElement( const AttributeList& rAttribs ) ExtConditionalFormattingContext::ExtConditionalFormattingContext(WorksheetContextBase& rFragment): WorksheetContextBase(rFragment) { + nPriority = -1; isPreviousElementF = false; } @@ -104,6 +105,7 @@ ContextHandlerRef ExtConditionalFormattingContext::onCreateContext(sal_Int32 nEl { OUString aType = rAttribs.getString(XML_type, OUString()); OUString aId = rAttribs.getString(XML_id, OUString()); + nPriority = rAttribs.getInteger( XML_priority, -1 ); if (aType == "dataBar") { @@ -179,6 +181,7 @@ void ExtConditionalFormattingContext::onEndElement() case XM_TOKEN(f): { rFormulas.push_back(aChars); + maPriorities.push_back(nPriority); } break; case XLS14_TOKEN( cfRule ): @@ -201,9 +204,9 @@ void ExtConditionalFormattingContext::onEndElement() aRange[i].aEnd.SetTab(nTab); } - if(isPreviousElementF) // sqref can be alone in some cases. + if (isPreviousElementF) // sqref can be alone in some cases. { - for(const OUString& rFormula : rFormulas) + for (const OUString& rFormula : rFormulas) { ScAddress rPos = aRange.GetTopLeftCorner(); rStyle = getStyles().createExtDxfStyle(rStyleIdx); @@ -215,11 +218,17 @@ void ExtConditionalFormattingContext::onEndElement() maEntries.push_back(std::unique_ptr<ScFormatEntry>(pEntry)); rStyleIdx++; } + + assert(rFormulas.size() == maPriorities.size()); rFormulas.clear(); } std::vector< std::unique_ptr<ExtCfCondFormat> >& rExtFormats = getCondFormats().importExtCondFormat(); - rExtFormats.push_back(std::make_unique<ExtCfCondFormat>(aRange, maEntries)); + rExtFormats.push_back(std::make_unique<ExtCfCondFormat>(aRange, maEntries, &maPriorities)); + + if (isPreviousElementF) + maPriorities.clear(); + isPreviousElementF = false; } break; |