sc/inc/attarray.hxx | 1 sc/inc/column.hxx | 16 ++++++-- sc/inc/document.hxx | 9 +++++ sc/inc/table.hxx | 9 +++-- sc/qa/unit/subsequent_export_test2.cxx | 33 ++++++++++++++++++ sc/qa/unit/ucalc.cxx | 54 ++++++++++++++++++++++++++++++ sc/source/core/data/attarray.cxx | 20 +++++++++++ sc/source/core/data/column3.cxx | 2 - sc/source/core/data/dociter.cxx | 59 +++++++++++++++++---------------- sc/source/core/data/table1.cxx | 15 ++++++++ 10 files changed, 181 insertions(+), 37 deletions(-)
New commits: commit 7a9e60c4b7d6c28f5b3e084e3db9ab2445c94bfd Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Wed Mar 9 15:12:43 2022 +0100 Commit: Luboš Luňák <l.lu...@collabora.com> CommitDate: Thu Mar 10 08:34:58 2022 +0100 fix attr iterators to walk even unallocated columns if needed Things like applying bold to an entire row no longer allocates all rows after my recent changes, but the attribute change is done in ScTable to the default attribute of unallocated columns. That means that clamping column positions to the end of allocated columns is no longer valid when handling attributes. Add functions that clamp depending on whether unallocated columns have a non-default attribute set. Change-Id: I879d0a034c0b336064361d0f8cb12e5a8da22b9c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131265 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> diff --git a/sc/inc/attarray.hxx b/sc/inc/attarray.hxx index 34d1403bcc91..c08da494c142 100644 --- a/sc/inc/attarray.hxx +++ b/sc/inc/attarray.hxx @@ -221,6 +221,7 @@ public: bool Reserve( SCSIZE nReserve ); SCSIZE Count() const { return mvData.size(); } SCSIZE Count( SCROW nRow1, SCROW nRow2 ) const; + bool HasNonDefPattern( SCROW nStartRow, SCROW nEndRow ) const; private: const ScPatternAttr* SetPatternAreaImpl( SCROW nStartRow, SCROW nEndRow, const ScPatternAttr* pPattern, diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 0b5fb0aa8ff2..2cf4bdd66573 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -161,6 +161,11 @@ public: bool HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) const; bool HasAttrib( SCROW nRow, HasAttrFlags nMask, SCROW* nStartRow = nullptr, SCROW* nEndRow = nullptr ) const; + std::unique_ptr<ScAttrIterator> CreateAttrIterator( SCROW nStartRow, SCROW nEndRow ) const; + + bool IsAllAttrEqual( const ScColumnData& rCol, SCROW nStartRow, SCROW nEndRow ) const; + bool HasNonDefPattern( SCROW nStartRow, SCROW nEndRow ) const; + void ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark, SCCOL nCol ); void ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark, SCCOL nCol ); }; @@ -207,7 +212,6 @@ friend class ScCountIfCellIterator; friend class ScFormulaGroupIterator; friend class ScCellIterator; friend class ScHorizontalCellIterator; -friend class ScHorizontalAttrIterator; friend class ScColumnTextWidthIterator; friend class ScDocumentImport; friend class sc::DocumentStreamAccess; @@ -299,7 +303,6 @@ public: bool GetLastVisibleAttr( SCROW& rLastRow ) const; bool HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const; bool IsVisibleAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const; - bool IsAllAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const; bool TestInsertCol( SCROW nStartRow, SCROW nEndRow) const; bool TestInsertRow( SCROW nStartRow, SCSIZE nSize ) const; @@ -348,8 +351,6 @@ public: sc::MixDocContext& rCxt, SCROW nRow1, SCROW nRow2, ScPasteFunc nFunction, bool bSkipEmpty, const ScColumn& rSrcCol ); - std::unique_ptr<ScAttrIterator> CreateAttrIterator( SCROW nStartRow, SCROW nEndRow ) const; - void UpdateSelectionFunction( const ScRangeList& rRanges, ScFunctionData& rData, const ScFlatBoolRowSegments& rHiddenRows ); @@ -835,11 +836,16 @@ inline bool ScColumn::IsEmptyAttr() const return pAttrArray->IsEmpty(); } -inline bool ScColumn::IsAllAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const +inline bool ScColumnData::IsAllAttrEqual( const ScColumnData& rCol, SCROW nStartRow, SCROW nEndRow ) const { return pAttrArray->IsAllEqual( *rCol.pAttrArray, nStartRow, nEndRow ); } +inline bool ScColumnData::HasNonDefPattern( SCROW nStartRow, SCROW nEndRow ) const +{ + return pAttrArray->HasNonDefPattern( nStartRow, nEndRow ); +} + inline bool ScColumn::IsVisibleAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const { return pAttrArray->IsVisibleEqual( *rCol.pAttrArray, nStartRow, nEndRow ); diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index f9640ab74c6d..734e2d0dcd75 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -821,6 +821,15 @@ public: SC_DLLPUBLIC SCCOL ClampToAllocatedColumns(SCTAB nTab, SCCOL nCol) const; SC_DLLPUBLIC SCCOL GetAllocatedColumnsCount(SCTAB nTab) const; + // Limits nCol to the last column that can possibly have a non-default pattern. The purpose + // is to avoid checking unallocated columns if they don't have attributes set, so this is + // never less than ClampToAllocatedColumns(). + SCCOL ClampToMaxNonDefPatternColumn(SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2) const; + SCCOL ClampToMaxNonDefPatternColumn(SCTAB nTab, SCCOL nCol) const + { return ClampToMaxNonDefPatternColumn(nTab, nCol, 0, MaxRow()); } + SCCOL GetMaxNonDefPatternColumnsCount(SCTAB nTab, SCROW nRow1, SCROW nRow2) const; + SCCOL GetMaxNonDefPatternColumnsCount(SCTAB nTab) const + { return GetMaxNonDefPatternColumnsCount(nTab, 0, MaxRow()); } SC_DLLPUBLIC ScDBCollection* GetDBCollection() const { return pDBCollection.get();} void SetDBCollection( std::unique_ptr<ScDBCollection> pNewDBCollection, diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 7fe49f2722b7..0ad96d4319fd 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -260,9 +260,6 @@ friend class ScCellIterator; friend class ScQueryCellIterator; friend class ScCountIfCellIterator; friend class ScHorizontalCellIterator; -friend class ScHorizontalAttrIterator; -friend class ScDocAttrIterator; -friend class ScAttrRectIterator; friend class ScColumnTextWidthIterator; friend class ScDocumentImport; friend class sc::DocumentStreamAccess; @@ -1106,6 +1103,12 @@ public: ScColumnsRange GetColumnsRange(SCCOL begin, SCCOL end) const; SCCOL ClampToAllocatedColumns(SCCOL nCol) const { return std::min(nCol, static_cast<SCCOL>(aCol.size() - 1)); } SCCOL GetAllocatedColumnsCount() const { return aCol.size(); } + SCCOL ClampToMaxNonDefPatternColumn(SCCOL nCol, SCROW nRow1, SCROW nRow2) const; + SCCOL ClampToMaxNonDefPatternColumn(SCCOL nCol) const + { return ClampToMaxNonDefPatternColumn(nCol, 0, rDocument.MaxRow()); } + SCCOL GetMaxNonDefPatternColumnsCount(SCROW nRow1, SCROW nRow2) const; + SCCOL GetMaxNonDefPatternColumnsCount() const + { return GetMaxNonDefPatternColumnsCount(0, rDocument.MaxRow()); } /** * Serializes the sheet's geometry data. diff --git a/sc/qa/unit/subsequent_export_test2.cxx b/sc/qa/unit/subsequent_export_test2.cxx index eff1f3b07963..be7469523e67 100644 --- a/sc/qa/unit/subsequent_export_test2.cxx +++ b/sc/qa/unit/subsequent_export_test2.cxx @@ -184,6 +184,7 @@ public: void testTdf142578(); void testTdf145059(); void testTdf130104_XLSXIndent(); + void testWholeRowBold(); CPPUNIT_TEST_SUITE(ScExportTest2); @@ -301,6 +302,7 @@ public: CPPUNIT_TEST(testTdf142578); CPPUNIT_TEST(testTdf145059); CPPUNIT_TEST(testTdf130104_XLSXIndent); + CPPUNIT_TEST(testWholeRowBold); CPPUNIT_TEST_SUITE_END(); @@ -3066,6 +3068,37 @@ void ScExportTest2::testTdf130104_XLSXIndent() xDocSh->DoClose(); } +void ScExportTest2::testWholeRowBold() +{ + ScDocShellRef xDocSh1 = loadDoc(u"blank.", FORMAT_ODS); + CPPUNIT_ASSERT_MESSAGE("Failed to open empty doc", xDocSh1.is()); + ScDocument* pDoc = &xDocSh1->GetDocument(); + + // Make entire second row row bold. + ScPatternAttr boldAttr(pDoc->GetPool()); + boldAttr.GetItemSet().Put(SvxWeightItem(WEIGHT_BOLD, ATTR_FONT_WEIGHT)); + pDoc->ApplyPatternAreaTab(0, 1, pDoc->MaxCol(), 1, 0, boldAttr); + + ScDocShellRef xDocSh2 = saveAndReload(*xDocSh1, FORMAT_ODS); + CPPUNIT_ASSERT(xDocSh2.is()); + pDoc = &xDocSh2->GetDocument(); + // TODO CPPUNIT_ASSERT_EQUAL(SCCOL(INITIALCOLCOUNT), pDoc->GetAllocatedColumnsCount(0)); + vcl::Font aFont; + pDoc->GetPattern(pDoc->MaxCol(), 1, 0)->GetFont(aFont, SC_AUTOCOL_RAW); + CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be bold", WEIGHT_BOLD, aFont.GetWeight()); + + ScDocShellRef xDocSh3 = saveAndReload(*xDocSh2, FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh3.is()); + pDoc = &xDocSh3->GetDocument(); + // TODO CPPUNIT_ASSERT_EQUAL(SCCOL(INITIALCOLCOUNT), pDoc->GetAllocatedColumnsCount(0)); + pDoc->GetPattern(pDoc->MaxCol(), 1, 0)->GetFont(aFont, SC_AUTOCOL_RAW); + CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be bold", WEIGHT_BOLD, aFont.GetWeight()); + + xDocSh1->DoClose(); + xDocSh2->DoClose(); + xDocSh3->DoClose(); +} + CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest2); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 980fd23d783d..a3066631aa47 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -114,6 +114,7 @@ public: void testHorizontalIterator(); void testValueIterator(); void testHorizontalAttrIterator(); + void testIteratorsUnallocatedColumnsAttributes(); /** * More direct test for cell broadcaster management, used to track formula @@ -244,6 +245,7 @@ public: CPPUNIT_TEST(testHorizontalIterator); CPPUNIT_TEST(testValueIterator); CPPUNIT_TEST(testHorizontalAttrIterator); + CPPUNIT_TEST(testIteratorsUnallocatedColumnsAttributes); CPPUNIT_TEST(testCellBroadcaster); CPPUNIT_TEST(testFuncParam); CPPUNIT_TEST(testNamedRange); @@ -1366,6 +1368,58 @@ void Test::testHorizontalAttrIterator() m_pDoc->DeleteTab(0); } +void Test::testIteratorsUnallocatedColumnsAttributes() +{ + m_pDoc->InsertTab(0, "Tab1"); + + // Make entire second row and third row bold. + ScPatternAttr boldAttr(m_pDoc->GetPool()); + boldAttr.GetItemSet().Put(SvxWeightItem(WEIGHT_BOLD, ATTR_FONT_WEIGHT)); + m_pDoc->ApplyPatternAreaTab(0, 1, m_pDoc->MaxCol(), 2, 0, boldAttr); + + // That shouldn't need allocating more columns, just changing the default attribute. + CPPUNIT_ASSERT_EQUAL(SCCOL(INITIALCOLCOUNT), m_pDoc->GetAllocatedColumnsCount(0)); + vcl::Font aFont; + const ScPatternAttr* pattern = m_pDoc->GetPattern(m_pDoc->MaxCol(), 1, 0); + pattern->GetFont(aFont, SC_AUTOCOL_RAW); + CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be bold", WEIGHT_BOLD, aFont.GetWeight()); + + // Test iterators. + ScDocAttrIterator docit( *m_pDoc, 0, INITIALCOLCOUNT - 1, 1, INITIALCOLCOUNT, 2 ); + SCCOL col1, col2; + SCROW row1, row2; + CPPUNIT_ASSERT_EQUAL( pattern, docit.GetNext( col1, row1, row2 )); + CPPUNIT_ASSERT_EQUAL( SCCOL(INITIALCOLCOUNT - 1), col1 ); + CPPUNIT_ASSERT_EQUAL( SCROW(1), row1 ); + CPPUNIT_ASSERT_EQUAL( SCROW(2), row2 ); + CPPUNIT_ASSERT_EQUAL( pattern, docit.GetNext( col1, row1, row2 )); + CPPUNIT_ASSERT_EQUAL( INITIALCOLCOUNT, col1 ); + CPPUNIT_ASSERT_EQUAL( SCROW(1), row1 ); + CPPUNIT_ASSERT_EQUAL( SCROW(2), row2 ); + CPPUNIT_ASSERT( docit.GetNext( col1, row1, row2 ) == nullptr ); + + ScAttrRectIterator rectit( *m_pDoc, 0, INITIALCOLCOUNT - 1, 1, INITIALCOLCOUNT, 2 ); + CPPUNIT_ASSERT_EQUAL( pattern, rectit.GetNext( col1, col2, row1, row2 )); + CPPUNIT_ASSERT_EQUAL( SCCOL(INITIALCOLCOUNT - 1), col1 ); + CPPUNIT_ASSERT_EQUAL( INITIALCOLCOUNT, col2 ); + CPPUNIT_ASSERT_EQUAL( SCROW(1), row1 ); + CPPUNIT_ASSERT_EQUAL( SCROW(2), row2 ); + CPPUNIT_ASSERT( rectit.GetNext( col1, col2, row1, row2 ) == nullptr ); + + ScHorizontalAttrIterator horit( *m_pDoc, 0, INITIALCOLCOUNT - 1, 1, INITIALCOLCOUNT, 2 ); + CPPUNIT_ASSERT_EQUAL( pattern, horit.GetNext( col1, col2, row1 )); + CPPUNIT_ASSERT_EQUAL( SCCOL(INITIALCOLCOUNT - 1), col1 ); + CPPUNIT_ASSERT_EQUAL( INITIALCOLCOUNT, col2 ); + CPPUNIT_ASSERT_EQUAL( SCROW(1), row1 ); + CPPUNIT_ASSERT_EQUAL( pattern, horit.GetNext( col1, col2, row1 )); + CPPUNIT_ASSERT_EQUAL( SCCOL(INITIALCOLCOUNT - 1), col1 ); + CPPUNIT_ASSERT_EQUAL( INITIALCOLCOUNT, col2 ); + CPPUNIT_ASSERT_EQUAL( SCROW(2), row1 ); + CPPUNIT_ASSERT( horit.GetNext( col1, col2, row1 ) == nullptr ); + + m_pDoc->DeleteTab(0); +} + namespace { bool broadcasterShifted(const ScDocument& rDoc, const ScAddress& rFrom, const ScAddress& rTo) diff --git a/sc/source/core/data/attarray.cxx b/sc/source/core/data/attarray.cxx index f2b4fff835d5..a7ee5ff2276e 100644 --- a/sc/source/core/data/attarray.cxx +++ b/sc/source/core/data/attarray.cxx @@ -2681,4 +2681,24 @@ SCSIZE ScAttrArray::Count( SCROW nStartRow, SCROW nEndRow ) const return nIndex2 - nIndex1 + 1; } +bool ScAttrArray::HasNonDefPattern( SCROW nStartRow, SCROW nEndRow ) const +{ + if ( mvData.empty() ) + return false; + + SCSIZE nIndex1, nIndex2; + + if( !Search( nStartRow, nIndex1 ) ) + return false; + + if( !Search( nEndRow, nIndex2 ) ) + nIndex2 = mvData.size() - 1; + + const ScPatternAttr* defPattern = rDocument.GetDefPattern(); + for( SCSIZE index = nIndex1; index <= nIndex2; ++index ) + if( mvData[index].pPattern != defPattern ) + return true; + return false; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index 8d38fa54ea45..9e12ad32cacf 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -1919,7 +1919,7 @@ void ScColumn::MixData( CellStorageModified(); } -std::unique_ptr<ScAttrIterator> ScColumn::CreateAttrIterator( SCROW nStartRow, SCROW nEndRow ) const +std::unique_ptr<ScAttrIterator> ScColumnData::CreateAttrIterator( SCROW nStartRow, SCROW nEndRow ) const { return std::make_unique<ScAttrIterator>( pAttrArray.get(), nStartRow, nEndRow, GetDoc().GetDefPattern() ); } diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx index 28543f720c16..35148072f387 100644 --- a/sc/source/core/data/dociter.cxx +++ b/sc/source/core/data/dociter.cxx @@ -2394,7 +2394,7 @@ ScHorizontalAttrIterator::ScHorizontalAttrIterator( ScDocument& rDocument, SCTAB assert(nTab < rDoc.GetTableCount() && "index out of bounds, FIX IT"); assert(rDoc.maTabs[nTab]); - nEndCol = rDoc.maTabs[nTab]->ClampToAllocatedColumns(nEndCol); + nEndCol = rDoc.maTabs[nTab]->ClampToMaxNonDefPatternColumn(nEndCol); nRow = nStartRow; nCol = nStartCol; @@ -2423,14 +2423,13 @@ void ScHorizontalAttrIterator::InitForNextRow(bool bInitialization) SCCOL nPos = i - nStartCol; if ( bInitialization || pNextEnd[nPos] < nRow ) { - const ScAttrArray* pArray = rDoc.maTabs[nTab]->aCol[i].pAttrArray.get(); - assert(pArray); + const ScAttrArray& pArray = rDoc.maTabs[nTab]->ColumnData(i).AttrArray(); SCSIZE nIndex; if (bInitialization) { - if ( pArray->Count() ) - pArray->Search( nStartRow, nIndex ); + if ( pArray.Count() ) + pArray.Search( nStartRow, nIndex ); else nIndex = 0; pIndices[nPos] = nIndex; @@ -2439,16 +2438,16 @@ void ScHorizontalAttrIterator::InitForNextRow(bool bInitialization) else nIndex = ++pIndices[nPos]; - if ( !nIndex && !pArray->Count() ) + if ( !nIndex && !pArray.Count() ) { pNextEnd[nPos] = rDoc.MaxRow(); assert( pNextEnd[nPos] >= nRow && "Sequence out of order" ); ppPatterns[nPos] = nullptr; } - else if ( nIndex < pArray->Count() ) + else if ( nIndex < pArray.Count() ) { - const ScPatternAttr* pPattern = pArray->mvData[nIndex].pPattern; - SCROW nThisEnd = pArray->mvData[nIndex].nEndRow; + const ScPatternAttr* pPattern = pArray.mvData[nIndex].pPattern; + SCROW nThisEnd = pArray.mvData[nIndex].nEndRow; if ( IsDefaultItem( pPattern ) ) pPattern = nullptr; @@ -2644,11 +2643,14 @@ ScDocAttrIterator::ScDocAttrIterator(ScDocument& rDocument, SCTAB nTable, nEndRow( nRow2 ), nCol( nCol1 ) { - if ( ValidTab(nTab) && nTab < rDoc.GetTableCount() && rDoc.maTabs[nTab] - && nCol < rDoc.maTabs[nTab]->GetAllocatedColumnsCount()) + if ( ValidTab(nTab) && nTab < rDoc.GetTableCount() && rDoc.maTabs[nTab] ) { - nEndCol = rDoc.maTabs[nTab]->ClampToAllocatedColumns(nEndCol); - pColIter = rDoc.maTabs[nTab]->aCol[nCol].CreateAttrIterator( nStartRow, nEndRow ); + SCCOL attrColCount = rDoc.maTabs[nTab]->GetMaxNonDefPatternColumnsCount(nStartRow, nEndRow); + if( nCol < attrColCount ) + { + nEndCol = std::min<SCCOL>(nEndCol,attrColCount - 1); + pColIter = rDoc.maTabs[nTab]->ColumnData(nCol).CreateAttrIterator( nStartRow, nEndRow ); + } } } @@ -2669,7 +2671,7 @@ const ScPatternAttr* ScDocAttrIterator::GetNext( SCCOL& rCol, SCROW& rRow1, SCRO ++nCol; if ( nCol <= nEndCol ) - pColIter = rDoc.maTabs[nTab]->aCol[nCol].CreateAttrIterator( nStartRow, nEndRow ); + pColIter = rDoc.maTabs[nTab]->ColumnData(nCol).CreateAttrIterator( nStartRow, nEndRow ); else pColIter.reset(); } @@ -2776,18 +2778,19 @@ ScAttrRectIterator::ScAttrRectIterator(ScDocument& rDocument, SCTAB nTable, nIterStartCol( nCol1 ), nIterEndCol( nCol1 ) { - if ( ValidTab(nTab) && nTab < rDoc.GetTableCount() && rDoc.maTabs[nTab] - && nCol1 < rDoc.maTabs[nTab]->GetAllocatedColumnsCount()) + if ( ValidTab(nTab) && nTab < rDoc.GetTableCount() && rDoc.maTabs[nTab] ) { - nEndCol = rDoc.maTabs[nTab]->ClampToAllocatedColumns(nEndCol); - pColIter = rDoc.maTabs[nTab]->aCol[nIterStartCol].CreateAttrIterator( nStartRow, nEndRow ); - while ( nIterEndCol < nEndCol && - rDoc.maTabs[nTab]->aCol[nIterEndCol].IsAllAttrEqual( - rDoc.maTabs[nTab]->aCol[nIterEndCol+1], nStartRow, nEndRow ) ) - ++nIterEndCol; + SCCOL attrColCount = rDoc.maTabs[nTab]->GetMaxNonDefPatternColumnsCount(nStartRow, nEndRow); + if( nCol1 < attrColCount ) + { + nEndCol = std::min<SCCOL>(nEndCol,attrColCount - 1); + pColIter = rDoc.maTabs[nTab]->ColumnData(nIterStartCol).CreateAttrIterator( nStartRow, nEndRow ); + while ( nIterEndCol < nEndCol && + rDoc.maTabs[nTab]->ColumnData(nIterEndCol).IsAllAttrEqual( + rDoc.maTabs[nTab]->ColumnData(nIterEndCol+1), nStartRow, nEndRow ) ) + ++nIterEndCol; + } } - else - pColIter = nullptr; } ScAttrRectIterator::~ScAttrRectIterator() @@ -2799,7 +2802,7 @@ void ScAttrRectIterator::DataChanged() if (pColIter) { SCROW nNextRow = pColIter->GetNextRow(); - pColIter = rDoc.maTabs[nTab]->aCol[nIterStartCol].CreateAttrIterator( nNextRow, nEndRow ); + pColIter = rDoc.maTabs[nTab]->ColumnData(nIterStartCol).CreateAttrIterator( nNextRow, nEndRow ); } } @@ -2820,10 +2823,10 @@ const ScPatternAttr* ScAttrRectIterator::GetNext( SCCOL& rCol1, SCCOL& rCol2, if ( nIterStartCol <= nEndCol ) { nIterEndCol = nIterStartCol; - pColIter = rDoc.maTabs[nTab]->aCol[nIterStartCol].CreateAttrIterator( nStartRow, nEndRow ); + pColIter = rDoc.maTabs[nTab]->ColumnData(nIterStartCol).CreateAttrIterator( nStartRow, nEndRow ); while ( nIterEndCol < nEndCol && - rDoc.maTabs[nTab]->aCol[nIterEndCol].IsAllAttrEqual( - rDoc.maTabs[nTab]->aCol[nIterEndCol+1], nStartRow, nEndRow ) ) + rDoc.maTabs[nTab]->ColumnData(nIterEndCol).IsAllAttrEqual( + rDoc.maTabs[nTab]->ColumnData(nIterEndCol+1), nStartRow, nEndRow ) ) ++nIterEndCol; } else diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index 6d9e966eb39a..f48f47ca8a16 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -2644,6 +2644,21 @@ ScColumnsRange ScTable::GetColumnsRange(SCCOL nColBegin, SCCOL nColEnd) const return ScColumnsRange(ScColumnsRange::Iterator(beginIter), ScColumnsRange::Iterator(endIter)); } +SCCOL ScTable::ClampToMaxNonDefPatternColumn(SCCOL nCol, SCROW nRow1, SCROW nRow2) const +{ + // The purpose so to avoid unallocated columns if possible, so don't check allocated ones. + if( nCol < GetAllocatedColumnsCount()) + return nCol; + return std::min<SCCOL>(nCol, GetMaxNonDefPatternColumnsCount( nRow1, nRow2 ) - 1 ); +} + +SCCOL ScTable::GetMaxNonDefPatternColumnsCount(SCROW nRow1, SCROW nRow2) const +{ + if( aDefaultColData.HasNonDefPattern(nRow1, nRow2)) + return GetDoc().GetMaxColCount(); + return GetAllocatedColumnsCount(); +} + // out-of-line the cold part of the CreateColumnIfNotExists function void ScTable::CreateColumnIfNotExistsImpl( const SCCOL nScCol ) const {