summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Francis <dennisfrancis.in@gmail.com>2015-11-24 01:34:47 +0530
committerEike Rathke <erack@redhat.com>2016-01-21 20:48:07 +0000
commit3536fe8f4cdbacf5702e743407f34d918b6f4d38 (patch)
tree24ae7b9048003baadd5408db08662cbcd8782895
parenteb3ee586e420ee4e38f9ef8c579e1a37d2dc0c10 (diff)
tdf#34873 : Show autofilter row count in status bar
Change-Id: I91aa637d654c1f4d828832f2e43ad21f03036ad0 Reviewed-on: https://gerrit.libreoffice.org/20134 Reviewed-by: Eike Rathke <erack@redhat.com> Tested-by: Eike Rathke <erack@redhat.com>
-rw-r--r--sc/inc/document.hxx1
-rw-r--r--sc/inc/globstr.hrc4
-rw-r--r--sc/inc/table.hxx11
-rw-r--r--sc/source/core/data/documen3.cxx40
-rw-r--r--sc/source/core/data/table1.cxx1
-rw-r--r--sc/source/core/data/table2.cxx54
-rw-r--r--sc/source/core/data/table5.cxx31
-rw-r--r--sc/source/ui/src/globstr.src4
-rw-r--r--sc/source/ui/view/cellsh.cxx12
9 files changed, 157 insertions, 1 deletions
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index f334e3fdab53..ce1017e40729 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1759,6 +1759,7 @@ public:
void GetFormulaEntries( ScTypedCaseStrSet& rStrings );
bool HasAutoFilter( SCCOL nCol, SCROW nRow, SCTAB nTab );
+ void GetFilterSelCount( SCCOL nCol, SCROW nRow, SCTAB nTab, SCSIZE& nSelected, SCSIZE& nTotal );
SC_DLLPUBLIC bool HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
SCTAB nTab );
diff --git a/sc/inc/globstr.hrc b/sc/inc/globstr.hrc
index b51897e999a5..9c98402c130a 100644
--- a/sc/inc/globstr.hrc
+++ b/sc/inc/globstr.hrc
@@ -705,7 +705,9 @@
#define STR_FUNCTIONS_FOUND 531
-#define SC_GLOBSTR_STR_COUNT 532 /**< the count of permanently resident strings */
+#define STR_FILTER_SELCOUNT 532
+
+#define SC_GLOBSTR_STR_COUNT 533 /**< the count of permanently resident strings */
#endif
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index d2672fe3ff36..d6111dda7526 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -117,6 +117,16 @@ class ScHint;
class ScTable : private boost::noncopyable
{
private:
+ // To store an Autofilter's filtered row count
+ struct FilteredRowCountData {
+ SCROW nStartRow;
+ SCROW nEndRow;
+ SCSIZE nCount;
+ FilteredRowCountData(SCROW nRow1, SCROW nRow2, SCSIZE nVal) :
+ nStartRow(nRow1), nEndRow(nRow2), nCount(nVal)
+ {}
+ };
+
typedef ::std::vector< ScRange > ScRangeVec;
ScColumn aCol[MAXCOLCOUNT];
@@ -151,6 +161,7 @@ private:
std::unique_ptr<ScFlatBoolRowSegments> mpHiddenRows;
std::unique_ptr<ScFlatBoolColSegments> mpFilteredCols;
std::unique_ptr<ScFlatBoolRowSegments> mpFilteredRows;
+ FilteredRowCountData maFilteredRowCount;
::std::set<SCROW> maRowPageBreaks;
::std::set<SCROW> maRowManualBreaks;
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
index 48f01cf2c401..5f632d922049 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -1464,6 +1464,46 @@ bool ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol,
return ValidTab(nTab) && maTabs[nTab] && maTabs[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
}
+void ScDocument::GetFilterSelCount( SCCOL nCol, SCROW nRow, SCTAB nTab, SCSIZE& nSelected, SCSIZE& nTotal )
+{
+ nSelected = 0;
+ nTotal = 0;
+ if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
+ {
+ const ScDBData* pDBData = GetDBAtCursor( nCol, nRow, nTab, ScDBDataPortion::AREA );
+ if( pDBData && pDBData->HasAutoFilter() )
+ {
+ SCTAB nAreaTab;
+ SCCOL nStartCol;
+ SCROW nStartRow;
+ SCCOL nEndCol;
+ SCROW nEndRow;
+ pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
+
+ if( pDBData->HasHeader() )
+ ++nStartRow;
+
+ nTotal = nEndRow - nStartRow + 1;
+
+ ScTable::FilteredRowCountData* pFilteredRowCount = &(maTabs[nTab]->maFilteredRowCount);
+ // Exact range match, cache hit, early exit
+ if( ( pFilteredRowCount->nStartRow == nStartRow ) && ( pFilteredRowCount->nEndRow == nEndRow ) &&
+ ( pFilteredRowCount->nCount != SCSIZE_MAX ) )
+ {
+ nSelected = nTotal - pFilteredRowCount->nCount;
+ return;
+ }
+
+ // Compute the count
+ nSelected = CountNonFilteredRows( nStartRow, nEndRow, nTab );
+ // and store it in the cache
+ pFilteredRowCount->nStartRow = nStartRow;
+ pFilteredRowCount->nEndRow = nEndRow;
+ pFilteredRowCount->nCount = nTotal - nSelected;
+ }
+ }
+}
+
/**
* Entries for AutoFilter listbox
*/
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index 2bc27053d964..e09018d6d6fa 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -245,6 +245,7 @@ ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const OUString& rNewName,
mpHiddenRows(new ScFlatBoolRowSegments),
mpFilteredCols(new ScFlatBoolColSegments),
mpFilteredRows(new ScFlatBoolRowSegments),
+ maFilteredRowCount(0, MAXROW, SCSIZE_MAX),
pOutlineTable( nullptr ),
pSheetEvents( nullptr ),
nTableAreaX( 0 ),
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 11c0d58c7bd9..23121cbac275 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -171,6 +171,13 @@ void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE
mpFilteredRows->insertSegment(nStartRow, nSize, true);
mpHiddenRows->insertSegment(nStartRow, nSize, true);
+ if( ( nStartRow <= maFilteredRowCount.nEndRow ) && ( maFilteredRowCount.nCount != SCSIZE_MAX ) )
+ {
+ if( nStartRow < maFilteredRowCount.nStartRow )
+ maFilteredRowCount.nStartRow += nSize;
+ maFilteredRowCount.nEndRow += nSize;
+ }
+
if (!maRowManualBreaks.empty())
{
// Copy all breaks up to nStartRow (non-inclusive).
@@ -217,6 +224,53 @@ void ScTable::DeleteRow(
if (pUndoOutline)
*pUndoOutline = true;
+ if( ( maFilteredRowCount.nCount != SCSIZE_MAX ) && ( nStartRow <= maFilteredRowCount.nEndRow ) )
+ {
+ SCROW nEndRow = nStartRow + nSize - 1;
+ // rows to be deleted has some overlap with autofilter
+ if( nEndRow >= maFilteredRowCount.nStartRow )
+ {
+ SCROW nStartRowInside = ( nStartRow >= maFilteredRowCount.nStartRow ) ? nStartRow : maFilteredRowCount.nStartRow;
+ SCROW nEndRowInside = ( nEndRow <= maFilteredRowCount.nEndRow ) ? nEndRow : maFilteredRowCount.nEndRow;
+
+ // All rows inside the autofilter are to be deleted, so set dirty flag.
+ if( ( nStartRowInside == maFilteredRowCount.nStartRow ) && ( nEndRowInside == maFilteredRowCount.nEndRow ) )
+ maFilteredRowCount.nCount = SCSIZE_MAX;
+ else
+ {
+ SCSIZE nChange = 0;
+ ScFlatBoolRowSegments::RangeData aData;
+ SCROW nRowItr = nStartRowInside;
+ while( nRowItr <= nEndRowInside )
+ {
+ if( !mpFilteredRows->getRangeData( nRowItr, aData ) )
+ break;
+ if( aData.mnRow2 > nEndRowInside )
+ aData.mnRow2 = nEndRowInside;
+
+ if( aData.mbValue )
+ nChange += aData.mnRow2 - nRowItr + 1;
+
+ nRowItr = aData.mnRow2 + 1;
+ }
+ if( nStartRowInside == maFilteredRowCount.nStartRow )
+ maFilteredRowCount.nStartRow = ( nEndRowInside + 1 - nSize );
+
+ if( nEndRowInside == maFilteredRowCount.nEndRow )
+ maFilteredRowCount.nEndRow = ( nStartRowInside - 1 );
+ else
+ maFilteredRowCount.nEndRow -= nSize;
+ maFilteredRowCount.nCount -= nChange;
+ }
+ }
+ // No overlap but the rows to be deleted are above the autofilter area.
+ else
+ {
+ maFilteredRowCount.nStartRow -= nSize;
+ maFilteredRowCount.nEndRow -= nSize;
+ }
+ }
+
mpFilteredRows->removeSegment(nStartRow, nStartRow+nSize);
mpHiddenRows->removeSegment(nStartRow, nStartRow+nSize);
diff --git a/sc/source/core/data/table5.cxx b/sc/source/core/data/table5.cxx
index 8ba078cb4e84..f35338353b37 100644
--- a/sc/source/core/data/table5.cxx
+++ b/sc/source/core/data/table5.cxx
@@ -859,6 +859,37 @@ void ScTable::CopyRowFiltered(ScTable& rTable, SCROW nStartRow, SCROW nEndRow)
void ScTable::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, bool bFiltered)
{
+ // First adjust the maFilteredRowCount cache
+ if( ( nStartRow >= maFilteredRowCount.nStartRow ) || ( nEndRow <= maFilteredRowCount.nEndRow ) )
+ {
+ if( ( nStartRow >= maFilteredRowCount.nStartRow ) && ( nEndRow <= maFilteredRowCount.nEndRow ) &&
+ ( maFilteredRowCount.nCount != SCSIZE_MAX ) )
+ {
+ SCSIZE nChange = 0;
+ ScFlatBoolRowSegments::RangeData aData;
+ SCROW nRowItr = nStartRow;
+ while( nRowItr <= nEndRow )
+ {
+ if( !mpFilteredRows->getRangeData( nRowItr, aData ) )
+ break;
+ if( aData.mnRow2 > nEndRow )
+ aData.mnRow2 = nEndRow;
+ // rows not filtered and going to be filtered
+ if( bFiltered && !aData.mbValue )
+ nChange += aData.mnRow2 - nRowItr + 1;
+ // rows filtered and not going to be filtered any more
+ else if( !bFiltered && aData.mbValue )
+ nChange -= aData.mnRow2 - nRowItr + 1;
+
+ nRowItr = aData.mnRow2 + 1;
+ }
+
+ maFilteredRowCount.nCount += nChange;
+ }
+ else
+ maFilteredRowCount.nCount = SCSIZE_MAX;
+ }
+
if (bFiltered)
mpFilteredRows->setTrue(nStartRow, nEndRow);
else
diff --git a/sc/source/ui/src/globstr.src b/sc/source/ui/src/globstr.src
index 073c5f917a3b..b1d72d36992e 100644
--- a/sc/source/ui/src/globstr.src
+++ b/sc/source/ui/src/globstr.src
@@ -589,6 +589,10 @@ Resource RID_GLOBSTR
{
Text [ en-US ] = "$1 rows, $2 columns selected";
};
+ String STR_FILTER_SELCOUNT
+ {
+ Text [ en-US ] = "$1 of $2 records found";
+ };
String STR_COLUMN
{
Text [ en-US ] = "Column" ;
diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx
index 60a92b6b7b16..f381267368c9 100644
--- a/sc/source/ui/view/cellsh.cxx
+++ b/sc/source/ui/view/cellsh.cxx
@@ -723,6 +723,18 @@ void ScCellShell::GetState(SfxItemSet &rSet)
aStr = aStr.replaceAll( "$2", OUString::number( nCol2 - nCol1 + 1 ));
rSet.Put( SfxStringItem( nWhich, aStr ) );
}
+ else
+ {
+ SCSIZE nSelected, nTotal;
+ pDoc->GetFilterSelCount( nPosX, nPosY, nTab, nSelected, nTotal );
+ if( nTotal )
+ {
+ OUString aStr = ScGlobal::GetRscString( STR_FILTER_SELCOUNT );
+ aStr = aStr.replaceAll( "$1", OUString::number( nSelected ) );
+ aStr = aStr.replaceAll( "$2", OUString::number( nTotal ) );
+ rSet.Put( SfxStringItem( nWhich, aStr ) );
+ }
+ }
}
break;