diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2020-06-17 09:13:56 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2020-06-22 14:28:28 +0200 |
commit | d1f613399d9c188ff4d5f41a57fbea6b02b536d9 (patch) | |
tree | 3f02d2e31044ed8c9a5c0d248de13bd05c017d53 | |
parent | 70d5151739dd29402294082268b31ab00d47fa03 (diff) |
tdf#97177 speedup loading of large ODS file
drop ScSimpleRangeList and just use ScRangeList, which saves us a
conversion step.
Then teach ScRangeList to do a simple merge, since we are loading in row
order, and can just check the last few entries.
Then fix a case of optimisation doing the wrong thing in
ScAttrArray::SetPatternAreaImpl where std::vector::reserve repeatedly
resizes the data array and breaks the normal doubling-resizing inside
vector.
On my machine the time goes from 5.4s to 4.8s
Change-Id: I68a2204e0c02b673bbfe8aa0fdbe126e53ddbb41
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96516
Tested-by: Noel Grandin <noel.grandin@collabora.co.uk>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
(cherry picked from commit aabcf90da9a90240bddc140485f210dcab66724c)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96800
Tested-by: Jenkins
-rw-r--r-- | sc/Library_sc.mk | 1 | ||||
-rw-r--r-- | sc/inc/rangelst.hxx | 3 | ||||
-rw-r--r-- | sc/inc/simplerangelist.hxx | 65 | ||||
-rw-r--r-- | sc/source/core/data/attarray.cxx | 7 | ||||
-rw-r--r-- | sc/source/core/tool/rangelst.cxx | 71 | ||||
-rw-r--r-- | sc/source/core/tool/simplerangelist.cxx | 188 | ||||
-rw-r--r-- | sc/source/filter/xml/XMLStylesImportHelper.cxx | 97 | ||||
-rw-r--r-- | sc/source/filter/xml/XMLStylesImportHelper.hxx | 22 | ||||
-rw-r--r-- | sc/source/filter/xml/xmlimprt.cxx | 46 | ||||
-rw-r--r-- | sc/source/filter/xml/xmlimprt.hxx | 2 |
10 files changed, 173 insertions, 329 deletions
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk index 997b14c0add9..668a5fa6c63e 100644 --- a/sc/Library_sc.mk +++ b/sc/Library_sc.mk @@ -283,7 +283,6 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/core/tool/scmatrix \ sc/source/core/tool/scopetools \ sc/source/core/tool/sharedformula \ - sc/source/core/tool/simplerangelist \ sc/source/core/tool/stringutil \ sc/source/core/tool/stylehelper \ sc/source/core/tool/subtotal \ diff --git a/sc/inc/rangelst.hxx b/sc/inc/rangelst.hxx index 6558c9539020..6a74662d7572 100644 --- a/sc/inc/rangelst.hxx +++ b/sc/inc/rangelst.hxx @@ -60,6 +60,7 @@ public: void InsertRow( SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW nRowPos, SCSIZE nSize ); void InsertCol( SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL nColPos, SCSIZE nSize ); + void InsertCol( SCTAB nTab, SCCOL nColPos ); /** For now this method assumes that nTab1 == nTab2 * The algorithm will be much more complicated if nTab1 != nTab2 @@ -82,6 +83,8 @@ public: void RemoveAll(); ScRange Combine() const; + // Add new range, and do a partial combine up till one row back + void AddAndPartialCombine(const ScRange&); bool empty() const { return maRanges.empty(); } size_t size() const { return maRanges.size(); } diff --git a/sc/inc/simplerangelist.hxx b/sc/inc/simplerangelist.hxx deleted file mode 100644 index bb4ae9a02a3f..000000000000 --- a/sc/inc/simplerangelist.hxx +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_SC_INC_SIMPLERANGELIST_HXX -#define INCLUDED_SC_INC_SIMPLERANGELIST_HXX - -#include "address.hxx" - -#include <list> -#include <map> -#include <memory> - -/** - * This container is optimized for use in the ods import filter, to store - * ranges for cell styles. We may change the name of this class once we - * have a better name for what it does. Using this is way more efficient - * than ScRangeList. - */ -class ScSimpleRangeList -{ -public: - struct Range - { - SCROW mnRow1; - SCROW mnRow2; - SCCOL mnCol1; - SCCOL mnCol2; - explicit Range(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2); - }; - typedef std::shared_ptr<::std::list<Range>> RangeListRef; - typedef ::std::map<SCTAB, RangeListRef> TabType; - - ScSimpleRangeList(); - - void addRange(const ScRange& rRange); - void insertCol(SCCOL nCol, SCTAB nTab); - void getRangeList(::std::list<ScRange>& rList) const; - void clear(); - -private: - RangeListRef findTab(SCTAB nTab); - -private: - TabType maTabs; -}; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/attarray.cxx b/sc/source/core/data/attarray.cxx index 1f174b5b2a0a..a4c57ca4f0b0 100644 --- a/sc/source/core/data/attarray.cxx +++ b/sc/source/core/data/attarray.cxx @@ -469,13 +469,6 @@ const ScPatternAttr* ScAttrArray::SetPatternAreaImpl(SCROW nStartRow, SCROW nEnd { SCSIZE nNeeded = mvData.size() + 2; SetDefaultIfNotInit( nNeeded ); - if ( mvData.capacity() < nNeeded ) - { - size_t nLimit = mvData.capacity() + SC_ATTRARRAY_DELTA; - if ( nLimit < nNeeded ) - nLimit = nNeeded; - mvData.reserve(nLimit); - } ScAddress aAdrStart( nCol, 0, nTab ); ScAddress aAdrEnd ( nCol, 0, nTab ); diff --git a/sc/source/core/tool/rangelst.cxx b/sc/source/core/tool/rangelst.cxx index c4efb37f29b5..4810566e5fc2 100644 --- a/sc/source/core/tool/rangelst.cxx +++ b/sc/source/core/tool/rangelst.cxx @@ -310,6 +310,51 @@ Label_Range_Join: push_back( rNewRange ); } +void ScRangeList::AddAndPartialCombine( const ScRange& rNewRange ) +{ + if ( maRanges.empty() ) + { + push_back( rNewRange ); + return ; + } + + // One common usage is to join ranges that actually are top to bottom + // appends but the caller doesn't exactly know about it, e.g. when invoked + // by ScMarkData::FillRangeListWithMarks(), check for this special case + // first and speed up things by not looping over all ranges for each range + // to be joined. We don't remember the exact encompassing range that would + // have to be updated on refupdates and insertions and deletions, instead + // remember just the maximum row used, even independently of the sheet. + // This satisfies most use cases. + + const SCROW nRow1 = rNewRange.aStart.Row(); + if (nRow1 > mnMaxRowUsed + 1) + { + push_back( rNewRange ); + return; + } + + // scan backwards 2 rows to see if we can merge with anything + auto it = maRanges.rbegin(); + while (it != maRanges.rend() && it->aStart.Row() >= (rNewRange.aStart.Row() - 2)) + { + // Check if we can simply enlarge this range. + ScRange & rLast = *it; + if (rLast.aEnd.Row() + 1 == nRow1 && + rLast.aStart.Col() == rNewRange.aStart.Col() && rLast.aEnd.Col() == rNewRange.aEnd.Col() && + rLast.aStart.Tab() == rNewRange.aStart.Tab() && rLast.aEnd.Tab() == rNewRange.aEnd.Tab()) + { + const SCROW nRow2 = rNewRange.aEnd.Row(); + rLast.aEnd.SetRow( nRow2 ); + mnMaxRowUsed = std::max(mnMaxRowUsed, nRow2); + return; + } + ++it; + } + + push_back( rNewRange ); +} + bool ScRangeList::operator==( const ScRangeList& r ) const { if ( this == &r ) @@ -458,6 +503,32 @@ void ScRangeList::InsertCol( SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL n } } +void ScRangeList::InsertCol( SCTAB nTab, SCCOL nCol ) +{ + std::vector<ScRange> aNewRanges; + for(const auto & rRange : maRanges) + { + if(rRange.aStart.Tab() <= nTab && rRange.aEnd.Tab() >= nTab) + { + if(rRange.aEnd.Col() == nCol - 1) + { + SCCOL nNewRangeStartCol = rRange.aEnd.Col() + 1; + SCCOL nNewRangeEndCol = nCol; + aNewRanges.emplace_back(nNewRangeStartCol, rRange.aStart.Row(), nTab, nNewRangeEndCol, + rRange.aEnd.Row(), nTab); + } + } + } + + for(const auto & rRange : aNewRanges) + { + if(!rRange.IsValid()) + continue; + + Join(rRange); + } +} + namespace { /** diff --git a/sc/source/core/tool/simplerangelist.cxx b/sc/source/core/tool/simplerangelist.cxx deleted file mode 100644 index 671f91f5669a..000000000000 --- a/sc/source/core/tool/simplerangelist.cxx +++ /dev/null @@ -1,188 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include <sal/config.h> - -#include <algorithm> - -#include <simplerangelist.hxx> -#include <rangelst.hxx> - -using ::std::list; -using ::std::pair; -using ::std::max; - -ScSimpleRangeList::Range::Range(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) : - mnRow1(nRow1), mnRow2(nRow2), mnCol1(nCol1), mnCol2(nCol2) {} - -ScSimpleRangeList::ScSimpleRangeList() -{ -} - -namespace { - -bool maybeJoin(ScSimpleRangeList::Range& rOld, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) -{ - if (rOld.mnRow1 == nRow1 && rOld.mnRow2 == nRow2) - { - // Check their column spans to see if they overlap. - if (rOld.mnCol1 == nCol1) - { - // Their share the start column position. - rOld.mnCol2 = max(rOld.mnCol2, nCol2); - return true; - } - else if (rOld.mnCol1 < nCol1) - { - // Old range sits on the left. - if (nCol1 - rOld.mnCol2 <= 1) - { - rOld.mnCol2 = max(rOld.mnCol2, nCol2); - return true; - } - } - else if (nCol1 < rOld.mnCol1) - { - // New range sits on the left. - if (nCol1 - rOld.mnCol2 <= 1) - { - rOld.mnCol1 = nCol1; - rOld.mnCol2 = max(rOld.mnCol2, nCol2); - return true; - } - } - } - - if (rOld.mnCol1 == nCol1 && rOld.mnCol2 == nCol2) - { - if (rOld.mnRow1 == nRow1) - { - // Their share the start row position. - rOld.mnRow2 = max(rOld.mnRow2, nRow2); - return true; - } - else if (rOld.mnRow1 < nRow1) - { - // Old range sits above. - if (nRow1 - rOld.mnRow2 <= 1) - { - rOld.mnRow2 = max(rOld.mnRow2, nRow2); - return true; - } - } - else if (nRow1 < rOld.mnRow1) - { - // New range sits above. - if (nRow1 - rOld.mnRow2 <= 1) - { - rOld.mnRow1 = nRow1; - rOld.mnRow2 = max(rOld.mnRow2, nRow2); - return true; - } - } - } - - return false; -} - -} - -void ScSimpleRangeList::addRange(const ScRange& rRange) -{ - SCCOL nCol1 = rRange.aStart.Col(); - SCROW nRow1 = rRange.aStart.Row(); - SCTAB nTab1 = rRange.aStart.Tab(); - SCCOL nCol2 = rRange.aEnd.Col(); - SCROW nRow2 = rRange.aEnd.Row(); - SCTAB nTab2 = rRange.aEnd.Tab(); - - for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab) - { - RangeListRef pRef = findTab(nTab); - if (!pRef) - // This should never happen! - return; - - if (pRef->empty() || !maybeJoin(pRef->back(), nCol1, nRow1, nCol2, nRow2)) - // Not joinable. Append it to the list. - pRef->push_back(Range(nCol1, nRow1, nCol2, nRow2)); - } -} - -void ScSimpleRangeList::insertCol(SCCOL nCol, SCTAB nTab) -{ - RangeListRef pRef = findTab(nTab); - if (!pRef) - // This should never happen! - return; - - for (Range& r : *pRef) - { - if (r.mnCol2 < nCol) - // insertion point to the right of the range. - continue; - - if (nCol <= r.mnCol1) - { - // insertion point to the left of the range. - ++r.mnCol1; - ++r.mnCol2; - } - else if (nCol <= r.mnCol2) - { - // insertion point cuts through the range. - ++r.mnCol2; - } - } -} - -void ScSimpleRangeList::getRangeList(list<ScRange>& rList) const -{ - list<ScRange> aList; - for (const auto& [nTab, pRanges] : maTabs) - { - for (const Range& r : *pRanges) - { - aList.emplace_back(r.mnCol1, r.mnRow1, nTab, r.mnCol2, r.mnRow2, nTab); - } - } - rList.swap(aList); -} - -void ScSimpleRangeList::clear() -{ - maTabs.clear(); -} - -ScSimpleRangeList::RangeListRef ScSimpleRangeList::findTab(SCTAB nTab) -{ - TabType::iterator itr = maTabs.find(nTab); - if (itr == maTabs.end()) - { - RangeListRef p = std::make_shared<list<Range>>(); - pair<TabType::iterator, bool> r = maTabs.emplace(nTab, p); - if (!r.second) - return RangeListRef(); - itr = r.first; - } - - return itr->second; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/xml/XMLStylesImportHelper.cxx b/sc/source/filter/xml/XMLStylesImportHelper.cxx index be004af973a6..e52466a54c4c 100644 --- a/sc/source/filter/xml/XMLStylesImportHelper.cxx +++ b/sc/source/filter/xml/XMLStylesImportHelper.cxx @@ -55,50 +55,50 @@ void ScMyStyleRanges::AddRange(const ScRange& rRange, const sal_Int16 nType) case util::NumberFormat::NUMBER: { if (!mpNumberList) - mpNumberList = std::make_shared<ScSimpleRangeList>(); - mpNumberList->addRange(rRange); + mpNumberList = std::make_shared<ScRangeList>(); + mpNumberList->AddAndPartialCombine(rRange); } break; case util::NumberFormat::TEXT: { if (!mpTextList) - mpTextList = std::make_shared<ScSimpleRangeList>(); - mpTextList->addRange(rRange); + mpTextList = std::make_shared<ScRangeList>(); + mpTextList->AddAndPartialCombine(rRange); } break; case util::NumberFormat::TIME: { if (!mpTimeList) - mpTimeList = std::make_shared<ScSimpleRangeList>(); - mpTimeList->addRange(rRange); + mpTimeList = std::make_shared<ScRangeList>(); + mpTimeList->AddAndPartialCombine(rRange); } break; case util::NumberFormat::DATETIME: { if (!mpDateTimeList) - mpDateTimeList = std::make_shared<ScSimpleRangeList>(); - mpDateTimeList->addRange(rRange); + mpDateTimeList = std::make_shared<ScRangeList>(); + mpDateTimeList->AddAndPartialCombine(rRange); } break; case util::NumberFormat::PERCENT: { if (!mpPercentList) - mpPercentList = std::make_shared<ScSimpleRangeList>(); - mpPercentList->addRange(rRange); + mpPercentList = std::make_shared<ScRangeList>(); + mpPercentList->AddAndPartialCombine(rRange); } break; case util::NumberFormat::LOGICAL: { if (!mpLogicalList) - mpLogicalList = std::make_shared<ScSimpleRangeList>(); - mpLogicalList->addRange(rRange); + mpLogicalList = std::make_shared<ScRangeList>(); + mpLogicalList->AddAndPartialCombine(rRange); } break; case util::NumberFormat::UNDEFINED: { if (!mpUndefinedList) - mpUndefinedList = std::make_shared<ScSimpleRangeList>(); - mpUndefinedList->addRange(rRange); + mpUndefinedList = std::make_shared<ScRangeList>(); + mpUndefinedList->AddAndPartialCombine(rRange); } break; default: @@ -117,101 +117,84 @@ void ScMyStyleRanges::AddCurrencyRange(const ScRange& rRange, const std::optiona if (pCurrency) aStyle.sCurrency = *pCurrency; auto itPair = pCurrencyList->insert(aStyle); - itPair.first->mpRanges->addRange(rRange); + itPair.first->mpRanges->AddAndPartialCombine(rRange); } void ScMyStyleRanges::InsertCol(const sal_Int32 nCol, const sal_Int32 nTab) { if (mpTextList) - mpTextList->insertCol(static_cast<SCCOL>(nCol), static_cast<SCTAB>(nTab)); + mpTextList->InsertCol(static_cast<SCCOL>(nTab), static_cast<SCTAB>(nCol)); if (mpNumberList) - mpNumberList->insertCol(static_cast<SCCOL>(nCol), static_cast<SCTAB>(nTab)); + mpNumberList->InsertCol(static_cast<SCCOL>(nTab), static_cast<SCTAB>(nCol)); if (mpTimeList) - mpTimeList->insertCol(static_cast<SCCOL>(nCol), static_cast<SCTAB>(nTab)); + mpTimeList->InsertCol(static_cast<SCCOL>(nTab), static_cast<SCTAB>(nCol)); if (mpDateTimeList) - mpDateTimeList->insertCol(static_cast<SCCOL>(nCol), static_cast<SCTAB>(nTab)); + mpDateTimeList->InsertCol(static_cast<SCCOL>(nTab), static_cast<SCTAB>(nCol)); if (mpPercentList) - mpPercentList->insertCol(static_cast<SCCOL>(nCol), static_cast<SCTAB>(nTab)); + mpPercentList->InsertCol(static_cast<SCCOL>(nTab), static_cast<SCTAB>(nCol)); if (mpLogicalList) - mpLogicalList->insertCol(static_cast<SCCOL>(nCol), static_cast<SCTAB>(nTab)); + mpLogicalList->InsertCol(static_cast<SCCOL>(nTab), static_cast<SCTAB>(nCol)); if (mpUndefinedList) - mpUndefinedList->insertCol(static_cast<SCCOL>(nCol), static_cast<SCTAB>(nTab)); + mpUndefinedList->InsertCol(static_cast<SCCOL>(nTab), static_cast<SCTAB>(nCol)); if (pCurrencyList) { for (auto& rCurrency : *pCurrencyList) { - rCurrency.mpRanges->insertCol(static_cast<SCCOL>(nCol), static_cast<SCTAB>(nTab)); + rCurrency.mpRanges->InsertCol(static_cast<SCCOL>(nCol), static_cast<SCTAB>(nTab)); } } } -void ScMyStyleRanges::SetStylesToRanges(const list<ScRange>& rRanges, +void ScMyStyleRanges::SetStylesToRanges(const ScRangeList& rRanges, const OUString* pStyleName, const sal_Int16 nCellType, const OUString* pCurrency, ScXMLImport& rImport) { - for (const auto& rRange : rRanges) - rImport.SetStyleToRange(rRange, pStyleName, nCellType, pCurrency); + rImport.SetStyleToRanges(rRanges, pStyleName, nCellType, pCurrency); } void ScMyStyleRanges::SetStylesToRanges(const OUString* pStyleName, ScXMLImport& rImport) { if (mpNumberList) { - list<ScRange> aList; - mpNumberList->getRangeList(aList); - SetStylesToRanges(aList, pStyleName, util::NumberFormat::NUMBER, nullptr, rImport); - mpNumberList->clear(); + SetStylesToRanges(*mpNumberList, pStyleName, util::NumberFormat::NUMBER, nullptr, rImport); + mpNumberList.reset(); } if (mpTextList) { - list<ScRange> aList; - mpTextList->getRangeList(aList); - SetStylesToRanges(aList, pStyleName, util::NumberFormat::TEXT, nullptr, rImport); - mpTextList->clear(); + SetStylesToRanges(*mpTextList, pStyleName, util::NumberFormat::TEXT, nullptr, rImport); + mpTextList.reset(); } if (mpTimeList) { - list<ScRange> aList; - mpTimeList->getRangeList(aList); - SetStylesToRanges(aList, pStyleName, util::NumberFormat::TIME, nullptr, rImport); - mpTimeList->clear(); + SetStylesToRanges(*mpTimeList, pStyleName, util::NumberFormat::TIME, nullptr, rImport); + mpTimeList.reset(); } if (mpDateTimeList) { - list<ScRange> aList; - mpDateTimeList->getRangeList(aList); - SetStylesToRanges(aList, pStyleName, util::NumberFormat::DATETIME, nullptr, rImport); - mpDateTimeList->clear(); + SetStylesToRanges(*mpDateTimeList, pStyleName, util::NumberFormat::DATETIME, nullptr, rImport); + mpDateTimeList.reset(); } if (mpPercentList) { - list<ScRange> aList; - mpPercentList->getRangeList(aList); - SetStylesToRanges(aList, pStyleName, util::NumberFormat::PERCENT, nullptr, rImport); - mpPercentList->clear(); + SetStylesToRanges(*mpPercentList, pStyleName, util::NumberFormat::PERCENT, nullptr, rImport); + mpPercentList.reset(); } if (mpLogicalList) { - list<ScRange> aList; - mpLogicalList->getRangeList(aList); - SetStylesToRanges(aList, pStyleName, util::NumberFormat::LOGICAL, nullptr, rImport); - mpLogicalList->clear(); + SetStylesToRanges(*mpLogicalList, pStyleName, util::NumberFormat::LOGICAL, nullptr, rImport); + mpLogicalList.reset(); } if (mpUndefinedList) { - list<ScRange> aList; - mpUndefinedList->getRangeList(aList); - SetStylesToRanges(aList, pStyleName, util::NumberFormat::UNDEFINED, nullptr, rImport); - mpUndefinedList->clear(); + SetStylesToRanges(*mpUndefinedList, pStyleName, util::NumberFormat::UNDEFINED, nullptr, rImport); + mpUndefinedList.reset(); } if (pCurrencyList) { for (const auto& rCurrency : *pCurrencyList) { - list<ScRange> aList; - rCurrency.mpRanges->getRangeList(aList); - SetStylesToRanges(aList, pStyleName, util::NumberFormat::CURRENCY, &rCurrency.sCurrency, rImport); + SetStylesToRanges(*rCurrency.mpRanges, pStyleName, util::NumberFormat::CURRENCY, &rCurrency.sCurrency, rImport); } } } diff --git a/sc/source/filter/xml/XMLStylesImportHelper.hxx b/sc/source/filter/xml/XMLStylesImportHelper.hxx index 2d390979a5fd..e0d5bedc79f9 100644 --- a/sc/source/filter/xml/XMLStylesImportHelper.hxx +++ b/sc/source/filter/xml/XMLStylesImportHelper.hxx @@ -20,7 +20,7 @@ #ifndef INCLUDED_SC_SOURCE_FILTER_XML_XMLSTYLESIMPORTHELPER_HXX #define INCLUDED_SC_SOURCE_FILTER_XML_XMLSTYLESIMPORTHELPER_HXX -#include <simplerangelist.hxx> +#include <rangelst.hxx> #include <rtl/ustring.hxx> #include <tools/ref.hxx> @@ -66,10 +66,10 @@ public: struct ScMyCurrencyStyle { OUString sCurrency; - std::shared_ptr<ScSimpleRangeList> mpRanges; + std::shared_ptr<ScRangeList> mpRanges; ScMyCurrencyStyle() : - mpRanges(std::make_shared<ScSimpleRangeList>()) + mpRanges(std::make_shared<ScRangeList>()) {} }; @@ -85,16 +85,16 @@ typedef std::set<ScMyCurrencyStyle, LessCurrencyStyle> ScMyCurrencyStylesSet; class ScMyStyleRanges { - std::shared_ptr<ScSimpleRangeList> mpTextList; - std::shared_ptr<ScSimpleRangeList> mpNumberList; - std::shared_ptr<ScSimpleRangeList> mpTimeList; - std::shared_ptr<ScSimpleRangeList> mpDateTimeList; - std::shared_ptr<ScSimpleRangeList> mpPercentList; - std::shared_ptr<ScSimpleRangeList> mpLogicalList; - std::shared_ptr<ScSimpleRangeList> mpUndefinedList; + std::shared_ptr<ScRangeList> mpTextList; + std::shared_ptr<ScRangeList> mpNumberList; + std::shared_ptr<ScRangeList> mpTimeList; + std::shared_ptr<ScRangeList> mpDateTimeList; + std::shared_ptr<ScRangeList> mpPercentList; + std::shared_ptr<ScRangeList> mpLogicalList; + std::shared_ptr<ScRangeList> mpUndefinedList; std::unique_ptr<ScMyCurrencyStylesSet> pCurrencyList; - static void SetStylesToRanges(const ::std::list<ScRange>& rList, + static void SetStylesToRanges(const ScRangeList& rList, const OUString* pStyleName, const sal_Int16 nCellType, const OUString* pCurrency, ScXMLImport& rImport); public: diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx index 02310a524091..84931b6de44f 100644 --- a/sc/source/filter/xml/xmlimprt.cxx +++ b/sc/source/filter/xml/xmlimprt.cxx @@ -95,6 +95,7 @@ #include <com/sun/star/io/XSeekable.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/sheet/XSheetCellRangeContainer.hpp> +#include <cellsuno.hxx> #include <memory> #include <utility> @@ -1345,6 +1346,51 @@ void ScXMLImport::SetStyleToRange(const ScRange& rRange, const OUString* pStyleN AddStyleRange(aCellRange); } +void ScXMLImport::SetStyleToRanges(const ScRangeList& rRanges, const OUString* pStyleName, + const sal_Int16 nCellType, const OUString* pCurrency) +{ + if (!mbImportStyles) + return; + + if (sPrevStyleName.isEmpty()) + { + nPrevCellType = nCellType; + if (pStyleName) + sPrevStyleName = *pStyleName; + if (pCurrency) + sPrevCurrency = *pCurrency; + else if (!sPrevCurrency.isEmpty()) + sPrevCurrency.clear(); + } + else if ((nCellType != nPrevCellType) || + ((pStyleName && *pStyleName != sPrevStyleName) || + (!pStyleName && !sPrevStyleName.isEmpty())) || + ((pCurrency && *pCurrency != sPrevCurrency) || + (!pCurrency && !sPrevCurrency.isEmpty()))) + { + SetStyleToRanges(); + nPrevCellType = nCellType; + if (pStyleName) + sPrevStyleName = *pStyleName; + else if(!sPrevStyleName.isEmpty()) + sPrevStyleName.clear(); + if (pCurrency) + sPrevCurrency = *pCurrency; + else if(!sPrevCurrency.isEmpty()) + sPrevCurrency.clear(); + } + + if (!xSheetCellRanges.is() && GetModel().is()) + { + uno::Reference <lang::XMultiServiceFactory> xMultiServiceFactory(GetModel(), uno::UNO_QUERY); + if (xMultiServiceFactory.is()) + xSheetCellRanges.set(uno::Reference <sheet::XSheetCellRangeContainer>(xMultiServiceFactory->createInstance("com.sun.star.sheet.SheetCellRanges"), uno::UNO_QUERY)); + OSL_ENSURE(xSheetCellRanges.is(), "didn't get SheetCellRanges"); + + } + static_cast<ScCellRangesObj*>(xSheetCellRanges.get())->SetNewRanges(rRanges); +} + bool ScXMLImport::SetNullDateOnUnitConverter() { if (!bNullDateSetted) diff --git a/sc/source/filter/xml/xmlimprt.hxx b/sc/source/filter/xml/xmlimprt.hxx index 843a4376b158..0523d437cfd6 100644 --- a/sc/source/filter/xml/xmlimprt.hxx +++ b/sc/source/filter/xml/xmlimprt.hxx @@ -371,6 +371,8 @@ private: public: void SetStyleToRange(const ScRange& rRange, const OUString* pStyleName, const sal_Int16 nCellType, const OUString* pCurrency); + void SetStyleToRanges(const ScRangeList& rRanges, const OUString* pStyleName, + const sal_Int16 nCellType, const OUString* pCurrency); bool SetNullDateOnUnitConverter(); XMLNumberFormatAttributesExportHelper* GetNumberFormatAttributesExportHelper(); ScMyStyleNumberFormats* GetStyleNumberFormats(); |