LibreOffice Module sc (master) 1
queryparam.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <memory>
21#include <queryparam.hxx>
22#include <queryentry.hxx>
23#include <scmatrix.hxx>
24
26#include <svl/numformat.hxx>
27#include <o3tl/safeint.hxx>
28#include <osl/diagnose.h>
29
30#include <algorithm>
31
32namespace {
33
34const size_t MAXQUERY = 8;
35
36class FindByField
37{
38 SCCOLROW mnField;
39public:
40 explicit FindByField(SCCOLROW nField) : mnField(nField) {}
41 bool operator() (const ScQueryEntry& rpEntry) const
42 {
43 return rpEntry.bDoQuery && rpEntry.nField == mnField;
44 }
45};
46
47struct FindUnused
48{
49 bool operator() (const ScQueryEntry& rpEntry) const
50 {
51 return !rpEntry.bDoQuery;
52 }
53};
54
55}
56
58{
59 return m_Entries.begin();
60}
61
63{
64 return m_Entries.end();
65}
66
68 eSearchType(utl::SearchParam::SearchType::Normal),
69 bHasHeader(true),
70 bByRow(true),
71 bInplace(true),
72 bCaseSens(false),
73 bDuplicate(false),
74 mbRangeLookup(false)
75{
76 m_Entries.resize(MAXQUERY);
77}
78
80 eSearchType(r.eSearchType), bHasHeader(r.bHasHeader), bByRow(r.bByRow), bInplace(r.bInplace),
81 bCaseSens(r.bCaseSens), bDuplicate(r.bDuplicate), mbRangeLookup(r.mbRangeLookup),
82 m_Entries(r.m_Entries)
83{
84}
85
87{
88 if (this != &r)
89 {
92 bByRow = r.bByRow;
98 }
99 return *this;
100}
101
103{
104}
105
107{
108 return true;
109}
110
112{
113 return m_Entries.size();
114}
115
117{
118 return m_Entries[n];
119}
120
122{
123 return m_Entries[n];
124}
125
127{
128 // Find the first unused entry.
129 EntriesType::iterator itr = std::find_if(
130 m_Entries.begin(), m_Entries.end(), FindUnused());
131
132 if (itr != m_Entries.end())
133 // Found!
134 return *itr;
135
136 // Add a new entry to the end.
137 m_Entries.push_back(ScQueryEntry());
138 return m_Entries.back();
139}
140
142{
143 EntriesType::iterator itr = std::find_if(
144 m_Entries.begin(), m_Entries.end(), FindByField(nField));
145
146 if (itr != m_Entries.end())
147 {
148 // existing entry found!
149 return &*itr;
150 }
151
152 if (!bNew)
153 // no existing entry found, and we are not creating a new one.
154 return nullptr;
155
156 return &AppendEntry();
157}
158
159std::vector<ScQueryEntry*> ScQueryParamBase::FindAllEntriesByField(SCCOLROW nField)
160{
161 std::vector<ScQueryEntry*> aEntries;
162
163 auto fFind = FindByField(nField);
164
165 for (auto& rxEntry : m_Entries)
166 if (fFind(rxEntry))
167 aEntries.push_back(&rxEntry);
168
169 return aEntries;
170}
171
173{
174 EntriesType::iterator itr = std::find_if(
175 m_Entries.begin(), m_Entries.end(), FindByField(nField));
176 bool bRet = false;
177
178 if (itr != m_Entries.end())
179 {
180 m_Entries.erase(itr);
181 if (m_Entries.size() < MAXQUERY)
182 // Make sure that we have at least MAXQUERY number of entries at
183 // all times.
184 m_Entries.resize(MAXQUERY);
185 bRet = true;
186 }
187
188 return bRet;
189}
190
192{
193 while( RemoveEntryByField( nField ) ) {}
194}
195
197{
198 if (nNew < MAXQUERY)
199 nNew = MAXQUERY; // never less than MAXQUERY
200
201 m_Entries.resize(nNew);
202}
203
205 svl::SharedStringPool& rPool, const OUString& rCellStr, SCSIZE nIndex, SvNumberFormatter* pFormatter )
206{
207 if (nIndex >= m_Entries.size())
208 Resize(nIndex+1);
209
210 ScQueryEntry& rEntry = GetEntry(nIndex);
211 ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
212 bool bByEmpty = false;
213 bool bByNonEmpty = false;
214
215 if (rCellStr.isEmpty())
217 else
218 {
219 rEntry.bDoQuery = true;
220 // Operatoren herausfiltern
221 if (rCellStr[0] == '<')
222 {
223 if (rCellStr.getLength() > 1 && rCellStr[1] == '>')
224 {
225 rItem.maString = rPool.intern(rCellStr.copy(2));
226 rEntry.eOp = SC_NOT_EQUAL;
227 if (rCellStr.getLength() == 2)
228 bByNonEmpty = true;
229 }
230 else if (rCellStr.getLength() > 1 && rCellStr[1] == '=')
231 {
232 rItem.maString = rPool.intern(rCellStr.copy(2));
233 rEntry.eOp = SC_LESS_EQUAL;
234 }
235 else
236 {
237 rItem.maString = rPool.intern(rCellStr.copy(1));
238 rEntry.eOp = SC_LESS;
239 }
240 }
241 else if (rCellStr[0]== '>')
242 {
243 if (rCellStr.getLength() > 1 && rCellStr[1] == '=')
244 {
245 rItem.maString = rPool.intern(rCellStr.copy(2));
246 rEntry.eOp = SC_GREATER_EQUAL;
247 }
248 else
249 {
250 rItem.maString = rPool.intern(rCellStr.copy(1));
251 rEntry.eOp = SC_GREATER;
252 }
253 }
254 else
255 {
256 if (rCellStr[0] == '=')
257 {
258 rItem.maString = rPool.intern(rCellStr.copy(1));
259 if (rCellStr.getLength() == 1)
260 bByEmpty = true;
261 }
262 else
263 rItem.maString = rPool.intern(rCellStr);
264 rEntry.eOp = SC_EQUAL;
265 }
266 }
267
268 if (!pFormatter)
269 return;
270
271 /* TODO: pFormatter currently is also used as a flag whether matching
272 * empty cells with an empty string is triggered from the interpreter.
273 * This could be handled independently if all queries should support
274 * it, needs to be evaluated if that actually is desired. */
275
276 // Interpreter queries have only one query, also QueryByEmpty and
277 // QueryByNonEmpty rely on that.
278 if (nIndex != 0)
279 return;
280
281 // (empty = empty) is a match, and (empty <> not-empty) also is a
282 // match. (empty = 0) is not a match.
283 rItem.mbMatchEmpty = ((rEntry.eOp == SC_EQUAL && rItem.maString.isEmpty())
284 || (rEntry.eOp == SC_NOT_EQUAL && !rItem.maString.isEmpty()));
285
286 // SetQueryBy override item members with special values, so do this last.
287 if (bByEmpty)
288 rEntry.SetQueryByEmpty();
289 else if (bByNonEmpty)
290 rEntry.SetQueryByNonEmpty();
291 else
292 {
293 sal_uInt32 nFormat = 0;
294 bool bNumber = pFormatter->IsNumberFormat( rItem.maString.getString(), nFormat, rItem.mfVal);
296 }
297}
298
300 nCol1(0),nRow1(0),nCol2(0),nRow2(0),nTab(0)
301{
302}
303
305{
306}
307
309 bDestPers(true),
310 nDestTab(0),
311 nDestCol(0),
312 nDestRow(0)
313{
314 Clear();
315}
316
317ScQueryParam::ScQueryParam( const ScQueryParam& ) = default;
318
322 bDestPers(true),
323 nDestTab(0),
324 nDestCol(0),
325 nDestRow(0)
326{
327}
328
330{
331}
332
334{
335 nCol1=nCol2 = 0;
336 nRow1=nRow2 = 0;
337 nTab = SCTAB_MAX;
339 bHasHeader = bCaseSens = false;
340 bInplace = bByRow = bDuplicate = true;
341
342 for (auto & itr : m_Entries)
343 {
344 itr.Clear();
345 }
346
348}
349
351{
352 bDestPers = true;
353 nDestTab = 0;
354 nDestCol = 0;
355 nDestRow = 0;
356}
357
359
360bool ScQueryParam::operator==( const ScQueryParam& rOther ) const
361{
362 bool bEqual = false;
363
364 // Are the number of queries equal?
365 SCSIZE nUsed = 0;
366 SCSIZE nOtherUsed = 0;
367 SCSIZE nEntryCount = GetEntryCount();
368 SCSIZE nOtherEntryCount = rOther.GetEntryCount();
369
370 while (nUsed<nEntryCount && m_Entries[nUsed].bDoQuery) ++nUsed;
371 while (nOtherUsed<nOtherEntryCount && rOther.m_Entries[nOtherUsed].bDoQuery)
372 ++nOtherUsed;
373
374 if ( (nUsed == nOtherUsed)
375 && (nCol1 == rOther.nCol1)
376 && (nRow1 == rOther.nRow1)
377 && (nCol2 == rOther.nCol2)
378 && (nRow2 == rOther.nRow2)
379 && (nTab == rOther.nTab)
380 && (bHasHeader == rOther.bHasHeader)
381 && (bByRow == rOther.bByRow)
382 && (bInplace == rOther.bInplace)
383 && (bCaseSens == rOther.bCaseSens)
384 && (eSearchType == rOther.eSearchType)
385 && (bDuplicate == rOther.bDuplicate)
386 && (bDestPers == rOther.bDestPers)
387 && (nDestTab == rOther.nDestTab)
388 && (nDestCol == rOther.nDestCol)
389 && (nDestRow == rOther.nDestRow) )
390 {
391 bEqual = true;
392 for ( SCSIZE i=0; i<nUsed && bEqual; i++ )
393 bEqual = m_Entries[i] == rOther.m_Entries[i];
394 }
395 return bEqual;
396}
397
399{
400 if (!bInplace)
401 {
402 SCCOL nDifX = nDestCol - nCol1;
403 SCROW nDifY = nDestRow - nRow1;
404 SCTAB nDifZ = nDestTab - nTab;
405
406 nCol1 = sal::static_int_cast<SCCOL>( nCol1 + nDifX );
407 nRow1 = sal::static_int_cast<SCROW>( nRow1 + nDifY );
408 nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nDifX );
409 nRow2 = sal::static_int_cast<SCROW>( nRow2 + nDifY );
410 nTab = sal::static_int_cast<SCTAB>( nTab + nDifZ );
411 size_t n = m_Entries.size();
412 for (size_t i=0; i<n; i++)
413 m_Entries[i].nField += nDifX;
414
415 bInplace = true;
416 }
417 else
418 {
419 OSL_FAIL("MoveToDest, bInplace == TRUE");
420 }
421}
422
424 mnField(-1),
425 mbSkipString(true),
427{
428}
429
431{
432}
433
436{
437}
438
440{
441}
442
444{
445 return nCol1 <= mnField && mnField <= nCol2;
446}
447
450{
451}
452
454{
455 SCSIZE nC, nR;
456 mpMatrix->GetDimensions(nC, nR);
457 return 0 <= mnField && o3tl::make_unsigned(mnField) <= nC;
458}
459
461{
462}
463
464/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
Definition: address.hxx:44
const SCTAB SCTAB_MAX
Definition: address.hxx:57
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber, SvNumInputOptions eInputOptions=SvNumInputOptions::NONE)
SharedString intern(const OUString &rStr)
const OUString & getString() const
bool isEmpty() const
static const SharedString & getEmptyString()
ScXMLEditAttributeMap::Entry const aEntries[]
DocumentType eType
@ SC_LESS_EQUAL
Definition: global.hxx:838
@ SC_LESS
Definition: global.hxx:836
@ SC_GREATER_EQUAL
Definition: global.hxx:839
@ SC_GREATER
Definition: global.hxx:837
@ SC_EQUAL
Definition: global.hxx:835
@ SC_NOT_EQUAL
Definition: global.hxx:840
sal_Int32 nIndex
sal_Int64 n
int i
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
ScDBQueryParamBase()=delete
virtual ~ScDBQueryParamBase() override
Definition: queryparam.cxx:430
virtual ~ScDBQueryParamInternal() override
Definition: queryparam.cxx:439
virtual bool IsValidFieldIndex() const override
Definition: queryparam.cxx:443
virtual bool IsValidFieldIndex() const override
Definition: queryparam.cxx:453
virtual ~ScDBQueryParamMatrix() override
Definition: queryparam.cxx:460
ScMatrixRef mpMatrix
Definition: queryparam.hxx:197
svl::SharedString maString
Definition: queryentry.hxx:49
Each instance of this struct represents a single filtering criteria.
Definition: queryentry.hxx:34
SCCOLROW nField
Definition: queryentry.hxx:61
const Item & GetQueryItem() const
Definition: queryentry.hxx:85
void SetQueryByNonEmpty()
Definition: queryentry.cxx:99
ScQueryOp eOp
Definition: queryentry.hxx:62
void SetQueryByEmpty()
Definition: queryentry.cxx:77
EntriesType m_Entries
Definition: queryparam.hxx:81
void FillInExcelSyntax(svl::SharedStringPool &rPool, const OUString &aCellStr, SCSIZE nIndex, SvNumberFormatter *pFormatter)
Definition: queryparam.cxx:204
virtual bool IsValidFieldIndex() const
Definition: queryparam.cxx:106
ScQueryEntry * FindEntryByField(SCCOLROW nField, bool bNew)
Definition: queryparam.cxx:141
const_iterator begin() const
Definition: queryparam.cxx:57
EntriesType::const_iterator const_iterator
Definition: queryparam.hxx:71
std::vector< ScQueryEntry * > FindAllEntriesByField(SCCOLROW nField)
Definition: queryparam.cxx:159
ScQueryParamBase & operator=(const ScQueryParamBase &r)
Definition: queryparam.cxx:86
SC_DLLPUBLIC const ScQueryEntry & GetEntry(SCSIZE n) const
Definition: queryparam.cxx:116
utl::SearchParam::SearchType eSearchType
Definition: queryparam.hxx:43
void Resize(size_t nNew)
Definition: queryparam.cxx:196
const_iterator end() const
Definition: queryparam.cxx:62
bool mbRangeLookup
for spreadsheet functions like MATCH, LOOKUP, HLOOKUP, VLOOKUP
Definition: queryparam.hxx:49
SC_DLLPUBLIC void RemoveAllEntriesByField(SCCOLROW nField)
Definition: queryparam.cxx:191
virtual ~ScQueryParamBase()
Definition: queryparam.cxx:102
SC_DLLPUBLIC SCSIZE GetEntryCount() const
Definition: queryparam.cxx:111
SC_DLLPUBLIC bool RemoveEntryByField(SCCOLROW nField)
Definition: queryparam.cxx:172
SC_DLLPUBLIC ScQueryEntry & AppendEntry()
Definition: queryparam.cxx:126
virtual ~ScQueryParamTable()
Definition: queryparam.cxx:304
ScQueryParam & operator=(const ScQueryParam &)
virtual ~ScQueryParam() override
Definition: queryparam.cxx:329
void MoveToDest()
Definition: queryparam.cxx:398
bool operator==(const ScQueryParam &rOther) const
Definition: queryparam.cxx:360
void ClearDestParams()
Definition: queryparam.cxx:350
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
Definition: types.hxx:23
sal_Int16 SCTAB
Definition: types.hxx:22
sal_Int16 SCCOL
Definition: types.hxx:21
sal_Int32 SCROW
Definition: types.hxx:17
RedlineType meType