sc/inc/cellvalue.hxx | 6 ++++++ sc/inc/column.hxx | 3 +++ sc/inc/document.hxx | 15 +++++++++++---- sc/inc/table.hxx | 5 ++++- sc/source/core/data/cellvalue.cxx | 10 ++++++++++ sc/source/core/data/column.cxx | 10 ++++++++++ sc/source/core/data/column2.cxx | 16 ++++++++++++++++ sc/source/core/data/documen2.cxx | 8 ++++++++ sc/source/core/data/documen4.cxx | 11 ++++++++--- sc/source/core/data/documen6.cxx | 13 +++++++++---- sc/source/core/data/table1.cxx | 8 ++++++++ sc/source/core/data/table3.cxx | 29 ++++++++++++++++++++++++----- sc/source/filter/html/htmlexp.cxx | 18 +++++++++++------- sc/source/filter/inc/htmlexp.hxx | 6 +++++- 14 files changed, 133 insertions(+), 25 deletions(-)
New commits: commit 6f810e3d7dafcd7d0101173a501786226f4d8886 Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Wed May 15 13:13:31 2019 +0200 Commit: Luboš Luňák <l.lu...@collabora.com> CommitDate: Thu May 16 12:34:51 2019 +0200 optimize ScHTMLExport::WriteTables() with large columns Again, unless given a hint, mdds always starts a search from the beginning of the container, so iterating over a column becomes quadratic. Shows when selecting (the title of) a large column with different value types, e.g. in tdf#120558, which triggers setting the selection from VclQt5Clipboard::setContents(), which calls this. Change-Id: Ida009c5ddf18ccdc8dff88c15530cc7e33ce80e7 Reviewed-on: https://gerrit.libreoffice.org/72366 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> diff --git a/sc/inc/cellvalue.hxx b/sc/inc/cellvalue.hxx index 7b6e3aad5794..281612d8874e 100644 --- a/sc/inc/cellvalue.hxx +++ b/sc/inc/cellvalue.hxx @@ -18,6 +18,10 @@ class EditTextObject; class ScColumn; struct ScRefCellValue; +namespace sc { +struct ColumnBlockPosition; +} + namespace svl { class SharedString; @@ -117,6 +121,7 @@ struct SC_DLLPUBLIC ScRefCellValue * Take cell value from specified position in specified document. */ ScRefCellValue( ScDocument& rDoc, const ScAddress& rPos ); + ScRefCellValue( ScDocument& rDoc, const ScAddress& rPos, sc::ColumnBlockPosition& rBlockPos ); void clear(); @@ -124,6 +129,7 @@ struct SC_DLLPUBLIC ScRefCellValue * Take cell value from specified position in specified document. */ void assign( ScDocument& rDoc, const ScAddress& rPos ); + void assign( ScDocument& rDoc, const ScAddress& rPos, sc::ColumnBlockPosition& rBlockPos ); /** * Set cell value at specified position in specified document. diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 9a4d22a3e664..340b5628faf6 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -189,6 +189,7 @@ public: const sc::CellNoteStoreType& GetCellNoteStore() const { return maCellNotes; } ScRefCellValue GetCellValue( SCROW nRow ) const; + ScRefCellValue GetCellValue( sc::ColumnBlockPosition& rBlockPos, SCROW nRow ); ScRefCellValue GetCellValue( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow ) const; static ScRefCellValue GetCellValue( const sc::CellStoreType::const_iterator& itPos, size_t nOffset ); diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index dd59a74c44e4..af372c270675 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -1550,7 +1550,7 @@ public: void CopyTabToClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, ScDocument* pClipDoc); - bool InitColumnBlockPosition( sc::ColumnBlockPosition& rBlockPos, SCTAB nTab, SCCOL nCol ); + SC_DLLPUBLIC bool InitColumnBlockPosition( sc::ColumnBlockPosition& rBlockPos, SCTAB nTab, SCCOL nCol ); void DeleteBeforeCopyFromClip( sc::CopyFromClipContext& rCxt, const ScMarkData& rMark, sc::ColumnSpanSet& rBroadcastSpans ); @@ -1692,7 +1692,9 @@ public: void RemoveCondFormatData( const ScRangeList& rRange, SCTAB nTab, sal_uInt32 nIndex ); SC_DLLPUBLIC ScConditionalFormat* GetCondFormat( SCCOL nCol, SCROW nRow, SCTAB nTab ) const; - SC_DLLPUBLIC const SfxItemSet* GetCondResult( SCCOL nCol, SCROW nRow, SCTAB nTab ) const; + // pCell is an optimization, must point to rPos + SC_DLLPUBLIC const SfxItemSet* GetCondResult( SCCOL nCol, SCROW nRow, SCTAB nTab, + ScRefCellValue* pCell = nullptr ) const; const SfxItemSet* GetCondResult( ScRefCellValue& rCell, const ScAddress& rPos, const ScConditionalFormatList& rList, const ScCondFormatIndexes& rIndex ) const; @@ -1705,8 +1707,12 @@ public: SC_DLLPUBLIC const css::uno::Reference< css::i18n::XBreakIterator >& GetBreakIterator(); bool HasStringWeakCharacters( const OUString& rString ); SC_DLLPUBLIC SvtScriptType GetStringScriptType( const OUString& rString ); - SC_DLLPUBLIC SvtScriptType GetCellScriptType( const ScAddress& rPos, sal_uInt32 nNumberFormat ); - SC_DLLPUBLIC SvtScriptType GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab ); + // pCell is an optimization, must point to rPos + SC_DLLPUBLIC SvtScriptType GetCellScriptType( const ScAddress& rPos, sal_uInt32 nNumberFormat, + ScRefCellValue* pCell = nullptr ); + // pCell is an optimization, must point to nCol,nRow,nTab + SC_DLLPUBLIC SvtScriptType GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab, + ScRefCellValue* pCell = nullptr ); SvtScriptType GetRangeScriptType( sc::ColumnBlockPosition& rBlockPos, const ScAddress& rPos, SCROW nLength ); SvtScriptType GetRangeScriptType( const ScRangeList& rRanges ); @@ -2527,6 +2533,7 @@ private: bool HasPartOfMerged( const ScRange& rRange ); ScRefCellValue GetRefCellValue( const ScAddress& rPos ); + ScRefCellValue GetRefCellValue( const ScAddress& rPos, sc::ColumnBlockPosition& rBlockPos ); std::map< SCTAB, ScSortParam > mSheetSortParams; diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 59dc2bbfd7dc..29a7b28fe635 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -998,6 +998,7 @@ public: void RegroupFormulaCells( SCCOL nCol ); ScRefCellValue GetRefCellValue( SCCOL nCol, SCROW nRow ); + ScRefCellValue GetRefCellValue( SCCOL nCol, SCROW nRow, sc::ColumnBlockPosition& rBlockPos ); SvtBroadcaster* GetBroadcaster( SCCOL nCol, SCROW nRow ); const SvtBroadcaster* GetBroadcaster( SCCOL nCol, SCROW nRow ) const; diff --git a/sc/source/core/data/cellvalue.cxx b/sc/source/core/data/cellvalue.cxx index 7fffc669ee6c..ef662c4818f7 100644 --- a/sc/source/core/data/cellvalue.cxx +++ b/sc/source/core/data/cellvalue.cxx @@ -567,6 +567,11 @@ ScRefCellValue::ScRefCellValue( ScDocument& rDoc, const ScAddress& rPos ) assign( rDoc, rPos); } +ScRefCellValue::ScRefCellValue( ScDocument& rDoc, const ScAddress& rPos, sc::ColumnBlockPosition& rBlockPos ) +{ + assign( rDoc, rPos, rBlockPos ); +} + void ScRefCellValue::clear() { // Reset to empty value. @@ -579,6 +584,11 @@ void ScRefCellValue::assign( ScDocument& rDoc, const ScAddress& rPos ) *this = rDoc.GetRefCellValue(rPos); } +void ScRefCellValue::assign( ScDocument& rDoc, const ScAddress& rPos, sc::ColumnBlockPosition& rBlockPos ) +{ + *this = rDoc.GetRefCellValue(rPos, rBlockPos); +} + void ScRefCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const { switch (meType) diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 70ee70b8e1f4..548e6403cc8b 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -726,6 +726,16 @@ ScRefCellValue ScColumn::GetCellValue( SCROW nRow ) const return GetCellValue(aPos.first, aPos.second); } +ScRefCellValue ScColumn::GetCellValue( sc::ColumnBlockPosition& rBlockPos, SCROW nRow ) +{ + std::pair<sc::CellStoreType::iterator,size_t> aPos = maCells.position(rBlockPos.miCellPos, nRow); + if (aPos.first == maCells.end()) + return ScRefCellValue(); + + rBlockPos.miCellPos = aPos.first; // Store this for next call. + return GetCellValue(aPos.first, aPos.second); +} + ScRefCellValue ScColumn::GetCellValue( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow ) const { std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(rBlockPos.miCellPos, nRow); diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index 2ffbd7806549..56506490ec5d 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -529,6 +529,14 @@ ScRefCellValue ScDocument::GetRefCellValue( const ScAddress& rPos ) return maTabs[rPos.Tab()]->GetRefCellValue(rPos.Col(), rPos.Row()); } +ScRefCellValue ScDocument::GetRefCellValue( const ScAddress& rPos, sc::ColumnBlockPosition& rBlockPos ) +{ + if (!TableExists(rPos.Tab())) + return ScRefCellValue(); // empty + + return maTabs[rPos.Tab()]->GetRefCellValue(rPos.Col(), rPos.Row(), rBlockPos); +} + svl::SharedStringPool& ScDocument::GetSharedStringPool() { return *mpCellStringPool; diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx index a1f5a6861db2..1d36d52e3bfb 100644 --- a/sc/source/core/data/documen4.cxx +++ b/sc/source/core/data/documen4.cxx @@ -782,19 +782,24 @@ const SfxPoolItem* ScDocument::GetEffItem( return nullptr; } -const SfxItemSet* ScDocument::GetCondResult( SCCOL nCol, SCROW nRow, SCTAB nTab ) const +const SfxItemSet* ScDocument::GetCondResult( SCCOL nCol, SCROW nRow, SCTAB nTab, ScRefCellValue* pCell ) const { ScConditionalFormatList* pFormatList = GetCondFormList(nTab); if (!pFormatList) return nullptr; ScAddress aPos(nCol, nRow, nTab); - ScRefCellValue aCell(const_cast<ScDocument&>(*this), aPos); + ScRefCellValue aCell; + if( pCell == nullptr ) + { + aCell.assign(const_cast<ScDocument&>(*this), aPos); + pCell = &aCell; + } const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab ); const ScCondFormatIndexes& rIndex = pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData(); - return GetCondResult(aCell, aPos, *pFormatList, rIndex); + return GetCondResult(*pCell, aPos, *pFormatList, rIndex); } const SfxItemSet* ScDocument::GetCondResult( diff --git a/sc/source/core/data/documen6.cxx b/sc/source/core/data/documen6.cxx index 4076cef8a2f4..9dd1f8b523a3 100644 --- a/sc/source/core/data/documen6.cxx +++ b/sc/source/core/data/documen6.cxx @@ -108,14 +108,19 @@ SvtScriptType ScDocument::GetStringScriptType( const OUString& rString ) return nRet; } -SvtScriptType ScDocument::GetCellScriptType( const ScAddress& rPos, sal_uInt32 nNumberFormat ) +SvtScriptType ScDocument::GetCellScriptType( const ScAddress& rPos, sal_uInt32 nNumberFormat, + ScRefCellValue* pCell ) { SvtScriptType nStored = GetScriptType(rPos); if ( nStored != SvtScriptType::UNKNOWN ) // stored value valid? return nStored; // use stored value Color* pColor; - OUString aStr = ScCellFormat::GetString(*this, rPos, nNumberFormat, &pColor, *mxPoolHelper->GetFormTable()); + OUString aStr; + if( pCell ) + ScCellFormat::GetString(*pCell, nNumberFormat, aStr, &pColor, *mxPoolHelper->GetFormTable(), this); + else + ScCellFormat::GetString(*this, rPos, nNumberFormat, &pColor, *mxPoolHelper->GetFormTable()); SvtScriptType nRet = GetStringScriptType( aStr ); @@ -124,7 +129,7 @@ SvtScriptType ScDocument::GetCellScriptType( const ScAddress& rPos, sal_uInt32 n return nRet; } -SvtScriptType ScDocument::GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab ) +SvtScriptType ScDocument::GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab, ScRefCellValue* pCell ) { // if script type is set, don't have to get number formats @@ -143,7 +148,7 @@ SvtScriptType ScDocument::GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab ) sal_uInt32 nFormat = pPattern->GetNumberFormat( mxPoolHelper->GetFormTable(), pCondSet ); - return GetCellScriptType(aPos, nFormat); + return GetCellScriptType(aPos, nFormat, pCell); } namespace { diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index c18c039c46db..be7d12b50150 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -2421,6 +2421,14 @@ ScRefCellValue ScTable::GetRefCellValue( SCCOL nCol, SCROW nRow ) return aCol[nCol].GetCellValue(nRow); } +ScRefCellValue ScTable::GetRefCellValue( SCCOL nCol, SCROW nRow, sc::ColumnBlockPosition& rBlockPos ) +{ + if ( !IsColRowValid( nCol, nRow ) ) + return ScRefCellValue(); + + return aCol[nCol].GetCellValue(rBlockPos, nRow); +} + SvtBroadcaster* ScTable::GetBroadcaster( SCCOL nCol, SCROW nRow ) { if ( !IsColRowValid( nCol, nRow ) ) diff --git a/sc/source/filter/html/htmlexp.cxx b/sc/source/filter/html/htmlexp.cxx index ea7ae4c025da..8b9a5ade838b 100644 --- a/sc/source/filter/html/htmlexp.cxx +++ b/sc/source/filter/html/htmlexp.cxx @@ -59,6 +59,7 @@ #include <editutil.hxx> #include <ftools.hxx> #include <cellvalue.hxx> +#include <mtvelements.hxx> #include <editeng/flditem.hxx> #include <editeng/borderline.hxx> @@ -764,6 +765,10 @@ void ScHTMLExport::WriteTables() // At least old (3.x, 4.x?) Netscape doesn't follow <TABLE COLS=n> and // <COL WIDTH=x> specified, but needs a width at every column. bool bHasHiddenRows = pDoc->HasHiddenRows(nStartRow, nEndRow, nTab); + // We need to cache sc::ColumnBlockPosition per each column. + std::vector< sc::ColumnBlockPosition > blockPos( nEndCol - nStartCol + 1 ); + for( SCCOL i = nStartCol; i <= nEndCol; ++i ) + pDoc->InitColumnBlockPosition( blockPos[ i - nStartCol ], nTab, i ); for ( SCROW nRow=nStartRow; nRow<=nEndRow; nRow++ ) { if ( bHasHiddenRows && pDoc->RowHidden(nRow, nTab) ) @@ -782,7 +787,7 @@ void ScHTMLExport::WriteTables() if ( nCol2 == nEndCol ) IncIndent(-1); - WriteCell( nCol2, nRow, nTab ); + WriteCell( blockPos[ nCol2 - nStartCol ], nCol2, nRow, nTab ); bTableDataHeight = false; } @@ -822,16 +827,17 @@ void ScHTMLExport::WriteTables() } } -void ScHTMLExport::WriteCell( SCCOL nCol, SCROW nRow, SCTAB nTab ) +void ScHTMLExport::WriteCell( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol, SCROW nRow, SCTAB nTab ) { + ScAddress aPos( nCol, nRow, nTab ); + ScRefCellValue aCell(*pDoc, aPos, rBlockPos); const ScPatternAttr* pAttr = pDoc->GetPattern( nCol, nRow, nTab ); - const SfxItemSet* pCondItemSet = pDoc->GetCondResult( nCol, nRow, nTab ); + const SfxItemSet* pCondItemSet = pDoc->GetCondResult( nCol, nRow, nTab, &aCell ); const ScMergeFlagAttr& rMergeFlagAttr = pAttr->GetItem( ATTR_MERGE_FLAG, pCondItemSet ); if ( rMergeFlagAttr.IsOverlapped() ) return ; - ScAddress aPos( nCol, nRow, nTab ); ScHTMLGraphEntry* pGraphEntry = nullptr; if ( bTabHasGraphics && !mbSkipImages ) { @@ -852,13 +858,11 @@ void ScHTMLExport::WriteCell( SCCOL nCol, SCROW nRow, SCTAB nTab ) } } - ScRefCellValue aCell(*pDoc, aPos); - sal_uInt32 nFormat = pAttr->GetNumberFormat( pFormatter ); bool bValueData = aCell.hasNumeric(); SvtScriptType nScriptType = SvtScriptType::NONE; if (!aCell.isEmpty()) - nScriptType = pDoc->GetScriptType(nCol, nRow, nTab); + nScriptType = pDoc->GetScriptType(nCol, nRow, nTab, &aCell); if ( nScriptType == SvtScriptType::NONE ) nScriptType = aHTMLStyle.nDefaultScriptType; diff --git a/sc/source/filter/inc/htmlexp.hxx b/sc/source/filter/inc/htmlexp.hxx index f0507cc1738d..8642795baa8a 100644 --- a/sc/source/filter/inc/htmlexp.hxx +++ b/sc/source/filter/inc/htmlexp.hxx @@ -42,6 +42,10 @@ class EditTextObject; enum class SvtScriptType; namespace editeng { class SvxBorderLine; } +namespace sc { +struct ColumnBlockPosition; +} + struct ScHTMLStyle { // Defaults from stylesheet Color aBackgroundColor; @@ -133,7 +137,7 @@ class ScHTMLExport : public ScExportBase void WriteHeader(); void WriteOverview(); void WriteTables(); - void WriteCell( SCCOL nCol, SCROW nRow, SCTAB nTab ); + void WriteCell( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol, SCROW nRow, SCTAB nTab ); void WriteGraphEntry( ScHTMLGraphEntry* ); void WriteImage( OUString& rLinkName, const Graphic&, const OString& rImgOptions, commit ace16e500c92797bb47ad580cf535de0702137bd Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Wed May 15 15:58:46 2019 +0200 Commit: Luboš Luňák <l.lu...@collabora.com> CommitDate: Thu May 16 12:34:42 2019 +0200 cache mdds access in ScTable::ValidQuery() (tdf#80853) Once more, mdds always searches from the start of the container, so iterating is quadratic. Change-Id: I8f8f3b5aad5c3342a10c21df3ad2d0d3fcaea8ad Reviewed-on: https://gerrit.libreoffice.org/72368 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index f55bc63b9541..9a4d22a3e664 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -218,6 +218,8 @@ public: bool bConsiderCellDrawObjects=false) const; bool HasDataAt(sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow, bool bConsiderCellNotes=false, bool bConsiderCellDrawObjects=false) const; + bool HasDataAt(sc::ColumnBlockPosition& rBlockPos, SCROW nRow, bool bConsiderCellNotes=false, + bool bConsiderCellDrawObjects=false); bool HasVisibleDataAt(SCROW nRow) const; SCROW GetFirstDataPos() const; SCROW GetLastDataPos() const; diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 547d9936e44b..59dc2bbfd7dc 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -64,6 +64,7 @@ class ColumnSpanSet; class RangeColumnSpanSet; class ColumnSet; struct ColumnBlockPosition; +class TableColumnBlockPositionSet; struct RefUpdateContext; struct RefUpdateInsertTabContext; struct RefUpdateDeleteTabContext; @@ -930,7 +931,8 @@ public: bool ValidQuery( SCROW nRow, const ScQueryParam& rQueryParam, const ScRefCellValue* pCell = nullptr, - bool* pbTestEqualCondition = nullptr, const ScInterpreterContext* pContext = nullptr); + bool* pbTestEqualCondition = nullptr, const ScInterpreterContext* pContext = nullptr, + sc::TableColumnBlockPositionSet* pBlockPos = nullptr ); void TopTenQuery( ScQueryParam& ); SCSIZE Query(const ScQueryParam& rQueryParam, bool bKeepSub); bool CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam); diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 25680418ca39..d8e2646d99f5 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -3100,6 +3100,22 @@ bool ScColumn::HasDataAt(sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow, return aPos.first->type != sc::element_type_empty; } +bool ScColumn::HasDataAt(sc::ColumnBlockPosition& rBlockPos, SCROW nRow, + bool bConsiderCellNotes, bool bConsiderCellDrawObjects) +{ + if (bConsiderCellNotes && !IsNotesEmptyBlock(nRow, nRow)) + return true; + + if (bConsiderCellDrawObjects && !IsDrawObjectsEmptyBlock(nRow, nRow)) + return true; + + std::pair<sc::CellStoreType::iterator,size_t> aPos = maCells.position(rBlockPos.miCellPos, nRow); + if (aPos.first == maCells.end()) + return false; + rBlockPos.miCellPos = aPos.first; // Store this for next call. + return aPos.first->type != sc::element_type_empty; +} + bool ScColumn::IsAllAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const { if (pAttrArray && rCol.pAttrArray) diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index d04d704937d2..da1e5e981753 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -2729,7 +2729,7 @@ public: bool ScTable::ValidQuery( SCROW nRow, const ScQueryParam& rParam, const ScRefCellValue* pCell, bool* pbTestEqualCondition, - const ScInterpreterContext* pContext) + const ScInterpreterContext* pContext, sc::TableColumnBlockPositionSet* pBlockPos) { if (!rParam.GetEntry(0).bDoQuery) return true; @@ -2753,19 +2753,36 @@ bool ScTable::ValidQuery( // We can only handle one single direct query passed as a known pCell, // subsequent queries have to obtain the cell. - ScRefCellValue aCell( (pCell && it == itBeg) ? *pCell : GetCellValue(nCol, nRow)); + ScRefCellValue aCell; + if(pCell && it == itBeg) + aCell = *pCell; + else if( pBlockPos ) + { // hinted mdds access + ScColumn* column = FetchColumn(nCol); + aCell = column->GetCellValue(*pBlockPos->getBlockPosition( nCol ), nRow); + } + else + aCell = GetCellValue(nCol, nRow); std::pair<bool,bool> aRes(false, false); const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems(); if (rItems.size() == 1 && rItems.front().meType == ScQueryEntry::ByEmpty) { + bool hasData; + if( pBlockPos ) + { + ScColumn* column = FetchColumn(rEntry.nField); + hasData = column->HasDataAt(*pBlockPos->getBlockPosition(rEntry.nField), nRow); + } + else + hasData = aCol[rEntry.nField].HasDataAt(nRow); if (rEntry.IsQueryByEmpty()) - aRes.first = !aCol[rEntry.nField].HasDataAt(nRow); + aRes.first = !hasData; else { assert(rEntry.IsQueryByNonEmpty()); - aRes.first = aCol[rEntry.nField].HasDataAt(nRow); + aRes.first = hasData; } } else @@ -3056,11 +3073,13 @@ SCSIZE ScTable::Query(const ScQueryParam& rParamOrg, bool bKeepSub) aParam.nDestCol, aParam.nDestRow, aParam.nDestTab ); } + sc::TableColumnBlockPositionSet blockPos( GetDoc(), nTab ); // cache mdds access + SCROW nRealRow2 = aParam.nRow2; for (SCROW j = aParam.nRow1 + nHeader; j <= nRealRow2; ++j) { bool bResult; // Filter result - bool bValid = ValidQuery(j, aParam); + bool bValid = ValidQuery(j, aParam, nullptr, nullptr, nullptr, &blockPos); if (!bValid && bKeepSub) // Keep subtotals { for (SCCOL nCol=aParam.nCol1; nCol<=aParam.nCol2 && !bValid; nCol++) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits