tdf#140968 tdf#140978 XLSX import: fix lost rounded filters

if the stored filter values are in the visible cell
format (e.g. rounded values) instead of the original
(editing) values.

Now AutoFilter popup window shows the items according
to the visible cell format (e.g. 1.0 instead of 1.01 or
0.99), but still grouping them based on the "editing
format" (e.g. not rounded values which visible during
editing), i.e. there could be repeated values in the
filtering conditions (e.g. two options "1.0" and "1.0"
for 1.01 and 0.99).

Note: Next step will be to group and filter based on the
actual cell format, like MSO does, to simplify filtering
of values rounded by the cell format (e.g. selecting
the single AutoFilter condition "1.0" to filter both
1.01 and 0.99).

Change-Id: I430da5e09794fc4ed8acf79b6485926f46b70277
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112343
Tested-by: Jenkins
Reviewed-by: László Németh <nemeth@numbertext.org>
This commit is contained in:
Balazs Varga
2021-03-25 15:00:31 +01:00
committed by László Németh
parent 8940975262
commit 4fd1333ba4
16 changed files with 79 additions and 32 deletions
+5 -2
View File
@@ -560,9 +560,12 @@ public:
OUString& sOutString, const Color** ppColor, bool bUseStarFormat = false );
/** Format a number according to the standard default format matching
the given format index */
the given format index. rOutString will be the real cell string (e.g.
a number rounded by the cell format, which rounded value is used
in the filtering condition now), instead of the EditFormat string
(e.g a not rounded value, which is visible during editing).*/
void GetInputLineString( const double& fOutNumber,
sal_uInt32 nFIndex, OUString& rOutString );
sal_uInt32 nFIndex, OUString& rOutString, bool bFiltering = false );
/** Format a number according to a format code string to be scanned.
@return
+1 -1
View File
@@ -44,7 +44,7 @@ public:
static void GetInputString(
const ScRefCellValue& rCell, sal_uInt32 nFormat, OUString& rString, SvNumberFormatter& rFormatter,
const ScDocument& rDoc );
const ScDocument& rDoc, bool bFiltering = false );
static OUString GetOutputString(
ScDocument& rDoc, const ScAddress& rPos, const ScRefCellValue& rCell );
+4 -1
View File
@@ -134,6 +134,8 @@ class ScColumn
SCCOL nCol;
SCTAB nTab;
bool mbFiltering; // it is true if there is a filtering in the column
friend class ScDocument; // for FillInfo
friend class ScTable;
friend class ScValueIterator;
@@ -181,6 +183,7 @@ public:
ScDocument& GetDoc() const { return pAttrArray->GetDoc(); }
SCTAB GetTab() const { return nTab; }
SCCOL GetCol() const { return nCol; }
bool HasFiltering() const { return mbFiltering; }
sc::CellStoreType& GetCellStore() { return maCells; }
const sc::CellStoreType& GetCellStore() const { return maCells; }
sc::CellTextAttrStoreType& GetCellAttrStore() { return maCellTextAttrs; }
@@ -534,7 +537,7 @@ public:
void GetFilterEntries(
sc::ColumnBlockConstPosition& rBlockPos, SCROW nStartRow, SCROW nEndRow,
ScFilterEntries& rFilterEntries );
ScFilterEntries& rFilterEntries, bool bFiltering );
bool GetDataEntries( SCROW nRow, std::set<ScTypedStrData>& rStrings, bool bLimit ) const;
+2 -1
View File
@@ -39,8 +39,9 @@ struct SC_DLLPUBLIC ScQueryEntry
double mfVal;
svl::SharedString maString;
bool mbMatchEmpty;
bool mbFormattedValue;
Item() : meType(ByValue), mfVal(0.0), mbMatchEmpty(false) {}
Item() : meType(ByValue), mfVal(0.0), mbMatchEmpty(false), mbFormattedValue(false) {}
bool operator== (const Item& r) const;
};
+1 -1
View File
@@ -953,7 +953,7 @@ public:
bool CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam);
void GetFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, ScFilterEntries& rFilterEntries );
void GetFilteredFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, ScFilterEntries& rFilterEntries );
void GetFilteredFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, ScFilterEntries& rFilterEntries, bool bFiltering );
[[nodiscard]]
bool GetDataEntries(SCCOL nCol, SCROW nRow, std::set<ScTypedStrData>& rStrings, bool bLimit);
+15
View File
@@ -323,5 +323,20 @@ class AutofilterTest(UITestCase):
xOkBtn = xFloatWindow.getChild("cancel")
xOkBtn.executeAction("CLICK", tuple())
self.ui_test.close_doc()
def test_time_value(self):
doc = self.ui_test.load_file(get_url_for_data_file("time_value.xlsx"))
xGridWin = self.xUITest.getTopFocusWindow().getChild("grid_window")
xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "0"}))
xFloatWindow = self.xUITest.getFloatWindow()
xCheckListMenu = xFloatWindow.getChild("check_list_menu")
xTreeList = xCheckListMenu.getChild("check_list_box")
self.assertEqual(2, len(xTreeList.getChildren()))
xOkBtn = xFloatWindow.getChild("cancel")
xOkBtn.executeAction("CLICK", tuple())
self.ui_test.close_doc()
# vim: set shiftwidth=4 softtabstop=4 expandtab:
Binary file not shown.
+2 -1
View File
@@ -85,7 +85,8 @@ ScColumn::ScColumn(ScSheetLimits const & rSheetLimits) :
maCells(maCellsEvent),
mnBlkCountFormula(0),
nCol( 0 ),
nTab( 0 )
nTab( 0 ),
mbFiltering( false )
{
maCells.resize(rSheetLimits.GetMaxRowCount());
}
+3 -2
View File
@@ -2420,7 +2420,7 @@ class FilterEntriesHandler
SvNumberFormatter* pFormatter = mrColumn.GetDoc().GetFormatTable();
OUString aStr;
sal_uLong nFormat = mrColumn.GetNumberFormat(mrColumn.GetDoc().GetNonThreadedContext(), nRow);
ScCellFormat::GetInputString(rCell, nFormat, aStr, *pFormatter, mrColumn.GetDoc());
ScCellFormat::GetInputString(rCell, nFormat, aStr, *pFormatter, mrColumn.GetDoc(), mrColumn.HasFiltering());
if (rCell.hasString())
{
@@ -2532,8 +2532,9 @@ public:
void ScColumn::GetFilterEntries(
sc::ColumnBlockConstPosition& rBlockPos, SCROW nStartRow, SCROW nEndRow,
ScFilterEntries& rFilterEntries )
ScFilterEntries& rFilterEntries, bool bFiltering )
{
mbFiltering = bFiltering;
FilterEntriesHandler aFunc(*this, rFilterEntries);
rBlockPos.miCellPos =
sc::ParseAll(rBlockPos.miCellPos, maCells, nStartRow, nEndRow, aFunc, aFunc);
+1 -1
View File
@@ -1581,7 +1581,7 @@ void ScDocument::GetFilterEntries(
if ( bFilter )
{
maTabs[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rFilterEntries );
maTabs[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rFilterEntries, bFilter );
}
else
{
+8 -5
View File
@@ -2418,7 +2418,7 @@ public:
}
std::pair<bool,bool> compareByString(
ScRefCellValue& rCell, SCROW nRow, const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem,
const ScRefCellValue& rCell, SCROW nRow, const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem,
const ScInterpreterContext* pContext)
{
if (!rCell.isEmpty())
@@ -2439,7 +2439,7 @@ public:
mrTab.GetNumberFormat( static_cast<SCCOL>(rEntry.nField), nRow );
OUString aStr;
SvNumberFormatter* pFormatter = pContext ? pContext->GetFormatTable() : mrDoc.GetFormatTable();
ScCellFormat::GetInputString(rCell, nFormat, aStr, *pFormatter, mrDoc);
ScCellFormat::GetInputString(rCell, nFormat, aStr, *pFormatter, mrDoc, rEntry.bDoQuery);
return compareByStringComparator(rEntry, rItem, nullptr, &aStr);
}
}
@@ -3016,6 +3016,9 @@ public:
if (rItem.meType != ScQueryEntry::ByString && rItem.meType != ScQueryEntry::ByDate)
return;
if (rItem.mbFormattedValue)
return;
sal_uInt32 nIndex = 0;
bool bNumber = mrDoc.GetFormatTable()->
IsNumberFormat(rItem.maString.getString(), nIndex, rItem.mfVal);
@@ -3507,11 +3510,11 @@ void ScTable::GetFilterEntries( SCCOL nCol, SCROW nRow1, SCROW nRow2, ScFilterEn
{
sc::ColumnBlockConstPosition aBlockPos;
aCol[nCol].InitBlockPosition(aBlockPos);
aCol[nCol].GetFilterEntries(aBlockPos, nRow1, nRow2, rFilterEntries);
aCol[nCol].GetFilterEntries(aBlockPos, nRow1, nRow2, rFilterEntries, false);
}
void ScTable::GetFilteredFilterEntries(
SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, ScFilterEntries& rFilterEntries )
SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, ScFilterEntries& rFilterEntries, bool bFiltering )
{
sc::ColumnBlockConstPosition aBlockPos;
aCol[nCol].InitBlockPosition(aBlockPos);
@@ -3525,7 +3528,7 @@ void ScTable::GetFilteredFilterEntries(
{
if (ValidQuery(j, aParam))
{
aCol[nCol].GetFilterEntries(aBlockPos, j, j, rFilterEntries);
aCol[nCol].GetFilterEntries(aBlockPos, j, j, rFilterEntries, bFiltering);
}
}
}
+2 -2
View File
@@ -116,7 +116,7 @@ OUString ScCellFormat::GetString(
}
void ScCellFormat::GetInputString(
const ScRefCellValue& rCell, sal_uInt32 nFormat, OUString& rString, SvNumberFormatter& rFormatter, const ScDocument& rDoc )
const ScRefCellValue& rCell, sal_uInt32 nFormat, OUString& rString, SvNumberFormatter& rFormatter, const ScDocument& rDoc, bool bFiltering )
{
switch (rCell.meType)
{
@@ -125,7 +125,7 @@ void ScCellFormat::GetInputString(
rString = rCell.getString(&rDoc);
break;
case CELLTYPE_VALUE:
rFormatter.GetInputLineString(rCell.mfValue, nFormat, rString );
rFormatter.GetInputLineString(rCell.mfValue, nFormat, rString, bFiltering);
break;
case CELLTYPE_FORMULA:
{
+1 -1
View File
@@ -32,7 +32,7 @@
bool ScQueryEntry::Item::operator== (const Item& r) const
{
return meType == r.meType && mfVal == r.mfVal && maString == r.maString && mbMatchEmpty == r.mbMatchEmpty;
return meType == r.meType && mfVal == r.mfVal && maString == r.maString && mbMatchEmpty == r.mbMatchEmpty && mbFormattedValue == r.mbFormattedValue;
}
ScQueryEntry::ScQueryEntry() :
+13 -1
View File
@@ -1128,7 +1128,19 @@ void fillQueryParam(
aItem.mfVal = rVal.NumericValue;
aItem.maString = rPool.intern(rVal.StringValue);
if (aItem.meType == ScQueryEntry::ByValue)
if (aItem.meType == ScQueryEntry::ByString)
{
sal_uInt32 nIndex = 0;
aItem.mbFormattedValue = true;
bool bNumber = pDoc->GetFormatTable()->IsNumberFormat(rVal.StringValue, nIndex, aItem.mfVal);
if (bNumber)
{
OUString aStr;
pDoc->GetFormatTable()->GetInputLineString(aItem.mfVal, nIndex, aStr);
aItem.maString = rPool.intern(aStr);
}
}
else if (aItem.meType == ScQueryEntry::ByValue)
{
OUString aStr;
pDoc->GetFormatTable()->GetInputLineString(aItem.mfVal, 0, aStr);
+17 -11
View File
@@ -544,14 +544,18 @@ public:
class AddSelectedItemString
{
std::unordered_set<OUString>& mrSet;
std::unordered_set<OUString>& mrSetString;
std::unordered_set<double>& mrSetValue;
public:
explicit AddSelectedItemString(std::unordered_set<OUString>& r) :
mrSet(r) {}
explicit AddSelectedItemString(std::unordered_set<OUString>& rString, std::unordered_set<double>& rValue) :
mrSetString(rString), mrSetValue(rValue) {}
void operator() (const ScQueryEntry::Item& rItem)
{
mrSet.insert(rItem.maString.getString());
if( rItem.meType == ScQueryEntry::QueryType::ByValue )
mrSetValue.insert(rItem.mfVal);
else
mrSetString.insert(rItem.maString.getString());
}
};
@@ -659,13 +663,14 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow)
ScQueryParam aParam;
pDBData->GetQueryParam(aParam);
std::vector<ScQueryEntry*> aEntries = aParam.FindAllEntriesByField(nCol);
std::unordered_set<OUString> aSelected;
std::unordered_set<OUString> aSelectedString;
std::unordered_set<double> aSelectedValue;
for (ScQueryEntry* pEntry : aEntries)
{
if (pEntry && pEntry->bDoQuery && pEntry->eOp == SC_EQUAL)
{
ScQueryEntry::QueryItemsType& rItems = pEntry->GetQueryItems();
std::for_each(rItems.begin(), rItems.end(), AddSelectedItemString(aSelected));
std::for_each(rItems.begin(), rItems.end(), AddSelectedItemString(aSelectedString, aSelectedValue));
}
}
@@ -673,14 +678,15 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow)
rControl.setMemberSize(aFilterEntries.size());
for (const auto& rEntry : aFilterEntries)
{
const OUString& aVal = rEntry.GetString();
const OUString& aStringVal = rEntry.GetString();
const double aDoubleVal = rEntry.GetValue();
bool bSelected = true;
if (!aSelected.empty())
bSelected = aSelected.count(aVal) > 0;
if (!aSelectedValue.empty() || !aSelectedString.empty())
bSelected = aSelectedValue.count(aDoubleVal) > 0 || aSelectedString.count(aStringVal) > 0;
if ( rEntry.IsDate() )
rControl.addDateMember( aVal, rEntry.GetValue(), bSelected );
rControl.addDateMember( aStringVal, rEntry.GetValue(), bSelected );
else
rControl.addMember(aVal, bSelected);
rControl.addMember(aStringVal, bSelected);
}
// Populate the menu.
+4 -2
View File
@@ -1589,7 +1589,8 @@ sal_uInt32 SvNumberFormatter::GetEditFormat( double fNumber, sal_uInt32 nFIndex,
void SvNumberFormatter::GetInputLineString(const double& fOutNumber,
sal_uInt32 nFIndex,
OUString& sOutString)
OUString& sOutString,
bool bFiltering)
{
::osl::MutexGuard aGuard( GetInstanceMutex() );
const Color* pColor;
@@ -1630,7 +1631,8 @@ void SvNumberFormatter::GetInputLineString(const double& fOutNumber,
}
sal_uInt32 nKey = GetEditFormat( fOutNumber, nRealKey, eType, eLang, pFormat);
if ( nKey != nRealKey )
// if bFiltering true keep the nRealKey format
if ( nKey != nRealKey && !bFiltering )
{
pFormat = GetFormatEntry( nKey );
}