/* -*- 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 .
*/
staticbool needsDescending(ScQueryOp op)
{
assert(op == SC_GREATER || op == SC_GREATER_EQUAL || op == SC_LESS || op == SC_LESS_EQUAL
|| op == SC_EQUAL); // We want all matching values to start in the sort order, // since the data is searched from start until the last matching one. return op == SC_GREATER || op == SC_GREATER_EQUAL;
}
SCROW startRow = maRange.aStart.Row();
SCROW endRow = maRange.aEnd.Row();
SCCOL startCol = maRange.aStart.Col();
SCCOL endCol = maRange.aEnd.Col(); if (!item.mbMatchEmpty) if (!rDoc.ShrinkToDataArea(nTab, startCol, startRow, endCol, endRow)) return; // no data cells, no need for a cache
std::vector<ColRowData> colrowData; for (SCCOL nCol = startCol; nCol <= endCol; ++nCol)
{ for (SCROW nRow = startRow; nRow <= endRow; ++nRow)
{
ScRefCellValue cell(rDoc.GetRefCellValue(ScAddress(nCol, nRow, nTab))); if (ScQueryEvaluator::isQueryByValue(mQueryOp, mQueryType, cell))
colrowData.push_back(ColRowData{ mRowSearch ? nRow : nCol, cell.getValue() }); elseif (ScQueryEvaluator::isQueryByString(mQueryOp, mQueryType, cell))
{ // Make sure that other possibilities in the generic handling // in ScQueryEvaluator::processEntry() do not alter the results. // (ByTextColor/ByBackgroundColor are blocked by CanBeUsedForSorterCache(), // but isQueryByString() is possible if the cell content is a string. // And including strings here would be tricky, as the string comparison // may possibly(?) be different than a numeric one. So check if the string // may possibly match a number, by converting it to one. If it can't match, // then it's fine to ignore it (and it can happen e.g. if the query uses // the whole column which includes a textual header). But if it can possibly // match, then bail out and leave it to the unoptimized case. // TODO Maybe it would actually work to use the numeric value obtained here? if (!bNewSearchFunction && !ScQueryEvaluator::isMatchWholeCell(rDoc, mQueryOp)) return; // substring matching cannot be sorted, but new search functions are sorted
sal_uInt32 format = 0; double value; if (context->NFIsNumberFormat(cell.getString(rDoc), format, value)) return;
}
}
}
if (nSortedBinarySearch == 0x00) //nBinarySearchDisabled = 0x00
{
std::stable_sort(
colrowData.begin(), colrowData.end(),
[](const ColRowData& d1, const ColRowData& d2) { return d1.value < d2.value; });
} elseif (nSortedBinarySearch == 0x01) //nSearchbAscd
{ // expected it is already sorted properly in Ascd mode.
} else/*(nSortedBinarySearch == 0x02) nSearchbDesc*/
{ // expected it is already sorted properly in Desc mode, just need to reverse.
std::reverse(colrowData.begin(), colrowData.end());
}
if (needsDescending(entry.eOp))
{ for (auto it = colrowData.rbegin(); it != colrowData.rend(); ++it)
{ if (mRowSearch)
mSortedRows.emplace_back(it->col_row); else
mSortedCols.emplace_back(it->col_row);
}
} else
{ for (const ColRowData& d : colrowData)
{ if (mRowSearch)
mSortedRows.emplace_back(d.col_row); else
mSortedCols.emplace_back(d.col_row);
}
}
} else
{ struct ColRowData
{
SCCOLROW col_row;
OUString string;
};
std::vector<ColRowData> colrowData; // Try to reuse as much ScQueryEvaluator code as possible, this should // basically do the same comparisons.
assert(rDoc.FetchTable(nTab) != nullptr);
ScQueryEvaluator evaluator(rDoc, *rDoc.FetchTable(nTab), param, context, nullptr,
bNewSearchFunction); for (SCCOL nCol = startCol; nCol <= endCol; ++nCol)
{ for (SCROW nRow = startRow; nRow <= endRow; ++nRow)
{
ScRefCellValue cell(rDoc.GetRefCellValue(ScAddress(nCol, nRow, nTab))); // This should be used only with ScQueryEntry::ByString, and that // means that ScQueryEvaluator::isQueryByString() should be the only // possibility in the generic handling in ScQueryEvaluator::processEntry() // (ByTextColor/ByBackgroundColor are blocked by CanBeUsedForSorterCache(), // and isQueryByValue() is blocked by ScQueryEntry::ByString).
assert(mQueryType == ScQueryEntry::ByString);
assert(!ScQueryEvaluator::isQueryByValue(mQueryOp, mQueryType, cell)); if (ScQueryEvaluator::isQueryByString(mQueryOp, mQueryType, cell))
{
OUString string = evaluator.getCellString(cell, nRow, nCol);
colrowData.push_back(ColRowData{ mRowSearch ? nRow : nCol, string });
}
}
}
CollatorWrapper& collator
= ScGlobal::GetCollator(mValueType == ValueType::StringsCaseSensitive);
if (nSortedBinarySearch == 0x00) //nBinarySearchDisabled = 0x00
{
std::stable_sort(colrowData.begin(), colrowData.end(),
[&collator](const ColRowData& d1, const ColRowData& d2) { return collator.compareString(d1.string, d2.string) < 0;
});
} elseif (nSortedBinarySearch == 0x01) //nSearchbAscd
{ // expected it is already sorted properly in Asc mode.
} else/*(nSortedBinarySearch == 0x02) nSearchbDesc*/
{ // expected it is already sorted properly in Desc mode, just need to reverse.
std::reverse(colrowData.begin(), colrowData.end());
}
if (needsDescending(entry.eOp))
{ for (auto it = colrowData.rbegin(); it != colrowData.rend(); ++it)
{ if (mRowSearch)
mSortedRows.emplace_back(it->col_row); else
mSortedCols.emplace_back(it->col_row);
}
} else
{ for (const ColRowData& d : colrowData)
{ if (mRowSearch)
mSortedRows.emplace_back(d.col_row); else
mSortedCols.emplace_back(d.col_row);
}
}
}
if (mRowSearch)
{
mRowToIndex.resize(maRange.aEnd.Row() - maRange.aStart.Row() + 1, mSortedRows.max_size()); for (size_t i = 0; i < mSortedRows.size(); ++i)
mRowToIndex[mSortedRows[i] - maRange.aStart.Row()] = i;
} else
{
mColToIndex.resize(maRange.aEnd.Col() - maRange.aStart.Col() + 1, mSortedCols.max_size()); for (size_t i = 0; i < mSortedCols.size(); ++i)
mColToIndex[mSortedCols[i] - maRange.aStart.Col()] = i;
}
mValid = true;
}
void ScSortedRangeCache::Notify(const SfxHint& rHint)
{ if (!mrDoc.IsInDtorClear())
{ if (rHint.GetId() == SfxHintId::ScDataChanged || rHint.GetId() == SfxHintId::ScAreaChanged)
{
mrDoc.RemoveSortedRangeCache(*this); // this ScSortedRangeCache is deleted by RemoveSortedRangeCache
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.