Line data Source code
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 : #ifndef INCLUDED_SC_INC_DOCITER_HXX
21 : #define INCLUDED_SC_INC_DOCITER_HXX
22 :
23 : #include "address.hxx"
24 : #include <tools/solar.h>
25 : #include "global.hxx"
26 : #include "scdllapi.h"
27 : #include "cellvalue.hxx"
28 : #include "mtvelements.hxx"
29 :
30 : #include <memory>
31 :
32 : #include <set>
33 : #include <vector>
34 : #include <boost/shared_ptr.hpp>
35 : #include <boost/scoped_ptr.hpp>
36 :
37 : class ScDocument;
38 : class ScPatternAttr;
39 : class ScAttrArray;
40 : class ScAttrIterator;
41 : class ScRange;
42 : class ScFlatBoolRowSegments;
43 : class ScMatrix;
44 : struct ScDBQueryParamBase;
45 : struct ScQueryParam;
46 : struct ScDBQueryParamInternal;
47 : struct ScDBQueryParamMatrix;
48 : class ScFormulaCell;
49 :
50 : class ScValueIterator // walk through all values in an area
51 : {
52 : typedef sc::CellStoreType::const_position_type PositionType;
53 :
54 : ScDocument* pDoc;
55 : const ScAttrArray* pAttrArray;
56 : sal_uLong nNumFormat; // for CalcAsShown
57 : sal_uLong nNumFmtIndex;
58 : ScAddress maStartPos;
59 : ScAddress maEndPos;
60 : SCCOL mnCol;
61 : SCTAB mnTab;
62 : SCROW nAttrEndRow;
63 : sal_uInt16 mnSubTotalFlags;
64 : short nNumFmtType;
65 : bool bNumValid;
66 : bool bCalcAsShown;
67 : bool bTextAsZero;
68 :
69 : const sc::CellStoreType* mpCells;
70 : PositionType maCurPos;
71 :
72 : SCROW GetRow() const;
73 : void IncBlock();
74 : void IncPos();
75 : void SetPos(size_t nPos);
76 :
77 : /**
78 : * See if the cell at the current position is a non-empty cell. If not,
79 : * move to the next non-empty cell position.
80 : */
81 : bool GetThis( double& rValue, sal_uInt16& rErr );
82 :
83 : public:
84 :
85 : ScValueIterator(
86 : ScDocument* pDocument, const ScRange& rRange, sal_uInt16 nSubTotalFlags = 0x00,
87 : bool bTextAsZero = false );
88 :
89 : void GetCurNumFmtInfo( short& nType, sal_uLong& nIndex );
90 :
91 : /// Does NOT reset rValue if no value found!
92 : bool GetFirst( double& rValue, sal_uInt16& rErr );
93 :
94 : /// Does NOT reset rValue if no value found!
95 : bool GetNext( double& rValue, sal_uInt16& rErr );
96 : };
97 :
98 30 : class ScDBQueryDataIterator
99 : {
100 : public:
101 32 : struct Value
102 : {
103 : OUString maString;
104 : double mfValue;
105 : sal_uInt16 mnError;
106 : bool mbIsNumber;
107 :
108 : Value();
109 : };
110 :
111 : private:
112 : static const sc::CellStoreType* GetColumnCellStore(ScDocument& rDoc, SCTAB nTab, SCCOL nCol);
113 : static const ScAttrArray* GetAttrArrayByCol(ScDocument& rDoc, SCTAB nTab, SCCOL nCol);
114 : static bool IsQueryValid(ScDocument& rDoc, const ScQueryParam& rParam, SCTAB nTab, SCROW nRow, ScRefCellValue* pCell);
115 :
116 : class DataAccess
117 : {
118 : public:
119 : DataAccess(const ScDBQueryDataIterator* pParent);
120 : virtual ~DataAccess() = 0;
121 : virtual bool getCurrent(Value& rValue) = 0;
122 : virtual bool getFirst(Value& rValue) = 0;
123 : virtual bool getNext(Value& rValue) = 0;
124 : protected:
125 : const ScDBQueryDataIterator* mpParent;
126 : };
127 :
128 : class DataAccessInternal : public DataAccess
129 : {
130 : typedef std::pair<sc::CellStoreType::const_iterator,size_t> PositionType;
131 : public:
132 : DataAccessInternal(const ScDBQueryDataIterator* pParent, ScDBQueryParamInternal* pParam, ScDocument* pDoc);
133 : virtual ~DataAccessInternal();
134 : virtual bool getCurrent(Value& rValue) SAL_OVERRIDE;
135 : virtual bool getFirst(Value& rValue) SAL_OVERRIDE;
136 : virtual bool getNext(Value& rValue) SAL_OVERRIDE;
137 :
138 : private:
139 : void incBlock();
140 : void incPos();
141 :
142 : const sc::CellStoreType* mpCells;
143 : PositionType maCurPos;
144 : ScDBQueryParamInternal* mpParam;
145 : ScDocument* mpDoc;
146 : const ScAttrArray* pAttrArray;
147 : sal_uLong nNumFormat; // for CalcAsShown
148 : sal_uLong nNumFmtIndex;
149 : SCCOL nCol;
150 : SCROW nRow;
151 : SCROW nAttrEndRow;
152 : SCTAB nTab;
153 : short nNumFmtType;
154 : bool bCalcAsShown;
155 : };
156 :
157 : class DataAccessMatrix : public DataAccess
158 : {
159 : public:
160 : DataAccessMatrix(const ScDBQueryDataIterator* pParent, ScDBQueryParamMatrix* pParam);
161 : virtual ~DataAccessMatrix();
162 : virtual bool getCurrent(Value& rValue) SAL_OVERRIDE;
163 : virtual bool getFirst(Value& rValue) SAL_OVERRIDE;
164 : virtual bool getNext(Value& rValue) SAL_OVERRIDE;
165 :
166 : private:
167 : bool isValidQuery(SCROW mnRow, const ScMatrix& rMat) const;
168 :
169 : ScDBQueryParamMatrix* mpParam;
170 : SCROW mnCurRow;
171 : SCROW mnRows;
172 : SCCOL mnCols;
173 : };
174 :
175 : ::std::unique_ptr<ScDBQueryParamBase> mpParam;
176 : ::std::unique_ptr<DataAccess> mpData;
177 :
178 : public:
179 : ScDBQueryDataIterator(ScDocument* pDocument, ScDBQueryParamBase* pParam);
180 : /// Does NOT reset rValue if no value found!
181 : bool GetFirst(Value& rValue);
182 : /// Does NOT reset rValue if no value found!
183 : bool GetNext(Value& rValue);
184 : };
185 :
186 : /**
187 : * Walk through all cells in an area. For SubTotal and Aggregate depending on mnSubTotalFlags.
188 : **/
189 434 : class ScCellIterator
190 : {
191 : typedef std::pair<sc::CellStoreType::const_iterator, size_t> PositionType;
192 :
193 : ScDocument* mpDoc;
194 : ScAddress maStartPos;
195 : ScAddress maEndPos;
196 : ScAddress maCurPos;
197 :
198 : PositionType maCurColPos;
199 : sal_uInt16 mnSubTotalFlags;
200 :
201 : ScRefCellValue maCurCell;
202 :
203 : void incBlock();
204 : void incPos();
205 : void setPos(size_t nPos);
206 :
207 : const ScColumn* getColumn() const;
208 :
209 : void init();
210 : bool getCurrent();
211 :
212 : public:
213 : ScCellIterator( ScDocument* pDoc, const ScRange& rRange, sal_uInt16 nSubTotalFlags = 0x00 );
214 :
215 1136 : const ScAddress& GetPos() const { return maCurPos; }
216 :
217 1586 : CellType getType() const { return maCurCell.meType;}
218 : OUString getString();
219 0 : const EditTextObject* getEditText() const { return maCurCell.mpEditText;}
220 692 : ScFormulaCell* getFormulaCell() { return maCurCell.mpFormula;}
221 : const ScFormulaCell* getFormulaCell() const { return maCurCell.mpFormula;}
222 : ScCellValue getCellValue() const;
223 152 : const ScRefCellValue& getRefCellValue() const { return maCurCell;}
224 :
225 : bool hasString() const;
226 : bool hasEmptyData() const;
227 : bool isEmpty() const;
228 : bool equalsWithoutFormat( const ScAddress& rPos ) const;
229 :
230 : bool first();
231 : bool next();
232 : };
233 :
234 236 : class ScQueryCellIterator // walk through all non-empty cells in an area
235 : {
236 : enum StopOnMismatchBits
237 : {
238 : nStopOnMismatchDisabled = 0x00,
239 : nStopOnMismatchEnabled = 0x01,
240 : nStopOnMismatchOccurred = 0x02,
241 : nStopOnMismatchExecuted = nStopOnMismatchEnabled | nStopOnMismatchOccurred
242 : };
243 :
244 : enum TestEqualConditionBits
245 : {
246 : nTestEqualConditionDisabled = 0x00,
247 : nTestEqualConditionEnabled = 0x01,
248 : nTestEqualConditionMatched = 0x02,
249 : nTestEqualConditionFulfilled = nTestEqualConditionEnabled | nTestEqualConditionMatched
250 : };
251 :
252 : typedef sc::CellStoreType::const_position_type PositionType;
253 : PositionType maCurPos;
254 :
255 : boost::scoped_ptr<ScQueryParam> mpParam;
256 : ScDocument* pDoc;
257 : const ScAttrArray* pAttrArray;
258 : sal_uLong nNumFormat;
259 : SCTAB nTab;
260 : SCCOL nCol;
261 : SCROW nRow;
262 : SCROW nAttrEndRow;
263 : sal_uInt8 nStopOnMismatch;
264 : sal_uInt8 nTestEqualCondition;
265 : bool bAdvanceQuery;
266 : bool bIgnoreMismatchOnLeadingStrings;
267 :
268 : /** Initialize position for new column. */
269 : void InitPos();
270 : void IncPos();
271 : void IncBlock();
272 : bool GetThis();
273 :
274 : /* Only works if no regular expression is involved, only
275 : searches for rows in one column, and only the first
276 : query entry is considered with simple conditions
277 : SC_LESS_EQUAL (sorted ascending) or SC_GREATER_EQUAL
278 : (sorted descending). Check these things before
279 : invocation! Delivers a starting point, continue with
280 : GetThis() and GetNext() afterwards. Introduced for
281 : FindEqualOrSortedLastInRange()
282 : */
283 : bool BinarySearch();
284 :
285 : public:
286 : ScQueryCellIterator(ScDocument* pDocument, SCTAB nTable,
287 : const ScQueryParam& aParam, bool bMod = true);
288 : // for bMod = FALSE the QueryParam has to be filled
289 : // (bIsString)
290 : bool GetFirst();
291 : bool GetNext();
292 510 : SCCOL GetCol() { return nCol; }
293 510 : SCROW GetRow() { return nRow; }
294 :
295 : // increments all Entry.nField, if column
296 : // changes, for ScInterpreter ScHLookup()
297 100 : void SetAdvanceQueryParamEntryField( bool bVal )
298 100 : { bAdvanceQuery = bVal; }
299 : void AdvanceQueryParamEntryField();
300 :
301 : /** If set, iterator stops on first non-matching cell
302 : content. May be used in SC_LESS_EQUAL queries where a
303 : cell range is assumed to be sorted; stops on first
304 : value being greater than the queried value and
305 : GetFirst()/GetNext() return NULL. StoppedOnMismatch()
306 : returns true then.
307 : However, the iterator's conditions are not set to end
308 : all queries, GetCol() and GetRow() return values for
309 : the non-matching cell, further GetNext() calls may be
310 : executed. */
311 180 : void SetStopOnMismatch( bool bVal )
312 : {
313 : nStopOnMismatch = sal::static_int_cast<sal_uInt8>(bVal ? nStopOnMismatchEnabled :
314 180 : nStopOnMismatchDisabled);
315 180 : }
316 0 : bool StoppedOnMismatch() const
317 0 : { return nStopOnMismatch == nStopOnMismatchExecuted; }
318 :
319 : /** If set, an additional test for SC_EQUAL condition is
320 : executed in ScTable::ValidQuery() if SC_LESS_EQUAL or
321 : SC_GREATER_EQUAL conditions are to be tested. May be
322 : used where a cell range is assumed to be sorted to stop
323 : if an equal match is found. */
324 198 : void SetTestEqualCondition( bool bVal )
325 : {
326 : nTestEqualCondition = sal::static_int_cast<sal_uInt8>(bVal ?
327 : nTestEqualConditionEnabled :
328 198 : nTestEqualConditionDisabled);
329 198 : }
330 782 : bool IsEqualConditionFulfilled() const
331 782 : { return nTestEqualCondition == nTestEqualConditionFulfilled; }
332 :
333 : /** In a range assumed to be sorted find either the last of
334 : a sequence of equal entries or the last being less than
335 : (or greater than) the queried value. Used by the
336 : interpreter for [HV]?LOOKUP() and MATCH(). Column and
337 : row position of the found entry are returned, otherwise
338 : invalid.
339 :
340 : @param bSearchForEqualAfterMismatch
341 : Continue searching for an equal entry even if the
342 : last entry matching the range was found, in case
343 : the data is not sorted. Is always done if regular
344 : expressions are involved.
345 :
346 : @param bIgnoreMismatchOnLeadingStrings
347 : Normally strings are sorted behind numerical
348 : values. If this parameter is true, the search does
349 : not stop when encountering a string and does not
350 : assume that no values follow anymore.
351 : If querying for a string a mismatch on the first
352 : entry, e.g. column header, is ignored.
353 :
354 : @ATTENTION! StopOnMismatch, TestEqualCondition and
355 : the internal IgnoreMismatchOnLeadingStrings and query
356 : params are in an undefined state upon return! The
357 : iterator is not usable anymore except for obtaining the
358 : number format!
359 : */
360 : bool FindEqualOrSortedLastInRange( SCCOL& nFoundCol,
361 : SCROW& nFoundRow, bool bSearchForEqualAfterMismatch = false,
362 : bool bIgnoreMismatchOnLeadingStrings = true );
363 : };
364 :
365 : class ScDocAttrIterator // all attribute areas
366 : {
367 : private:
368 : ScDocument* pDoc;
369 : SCTAB nTab;
370 : SCCOL nEndCol;
371 : SCROW nStartRow;
372 : SCROW nEndRow;
373 : SCCOL nCol;
374 : ScAttrIterator* pColIter;
375 :
376 : public:
377 : ScDocAttrIterator(ScDocument* pDocument, SCTAB nTable,
378 : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2);
379 : ~ScDocAttrIterator();
380 :
381 : const ScPatternAttr* GetNext( SCCOL& rCol, SCROW& rRow1, SCROW& rRow2 );
382 : };
383 :
384 : class ScAttrRectIterator // all attribute areas, including areas stretching
385 : // across more than one column
386 : {
387 : private:
388 : ScDocument* pDoc;
389 : SCTAB nTab;
390 : SCCOL nEndCol;
391 : SCROW nStartRow;
392 : SCROW nEndRow;
393 : SCCOL nIterStartCol;
394 : SCCOL nIterEndCol;
395 : ScAttrIterator* pColIter;
396 :
397 : public:
398 : ScAttrRectIterator(ScDocument* pDocument, SCTAB nTable,
399 : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2);
400 : ~ScAttrRectIterator();
401 :
402 : void DataChanged();
403 : const ScPatternAttr* GetNext( SCCOL& rCol1, SCCOL& rCol2, SCROW& rRow1, SCROW& rRow2 );
404 : };
405 :
406 : class ScHorizontalCellIterator // walk through all non empty cells in an area
407 : { // row by row
408 117386 : struct ColParam
409 : {
410 : sc::CellStoreType::const_iterator maPos;
411 : sc::CellStoreType::const_iterator maEnd;
412 : SCCOL mnCol;
413 : };
414 :
415 : std::vector<ColParam>::iterator maColPos;
416 : std::vector<ColParam> maColPositions;
417 :
418 : ScDocument* pDoc;
419 : SCTAB mnTab;
420 : SCCOL nStartCol;
421 : SCCOL nEndCol;
422 : SCROW nStartRow;
423 : SCROW nEndRow;
424 : SCROW* pNextRows;
425 : SCSIZE* pNextIndices;
426 : SCCOL mnCol;
427 : SCROW mnRow;
428 : ScRefCellValue maCurCell;
429 : bool mbMore;
430 :
431 : public:
432 : ScHorizontalCellIterator(ScDocument* pDocument, SCTAB nTable,
433 : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2);
434 : ~ScHorizontalCellIterator();
435 :
436 : ScRefCellValue* GetNext( SCCOL& rCol, SCROW& rRow );
437 : bool GetPos( SCCOL& rCol, SCROW& rRow );
438 : /// Set a(nother) sheet and (re)init.
439 : void SetTab( SCTAB nTab );
440 :
441 : private:
442 : void Advance();
443 : void SkipInvalid();
444 : bool SkipInvalidInRow();
445 : SCROW FindNextNonEmptyRow();
446 : };
447 :
448 : /** Row-wise value iterator. */
449 : class ScHorizontalValueIterator
450 : {
451 : private:
452 : ScDocument *pDoc;
453 : const ScAttrArray *pAttrArray;
454 : ScHorizontalCellIterator *pCellIter;
455 : sal_uLong nNumFormat; // for CalcAsShown
456 : sal_uLong nNumFmtIndex;
457 : SCTAB nEndTab;
458 : SCCOL nCurCol;
459 : SCROW nCurRow;
460 : SCTAB nCurTab;
461 : SCROW nAttrEndRow;
462 : short nNumFmtType;
463 : bool bNumValid;
464 : bool bCalcAsShown;
465 : bool bTextAsZero;
466 :
467 : public:
468 :
469 : ScHorizontalValueIterator( ScDocument* pDocument,
470 : const ScRange& rRange,
471 : bool bTextAsZero = false );
472 : ~ScHorizontalValueIterator();
473 : /// Does NOT reset rValue if no value found!
474 : bool GetNext( double& rValue, sal_uInt16& rErr );
475 : };
476 :
477 : // returns all areas with non-default formatting (horizontal)
478 :
479 : class ScHorizontalAttrIterator
480 : {
481 : private:
482 : ScDocument* pDoc;
483 : SCTAB nTab;
484 : SCCOL nStartCol;
485 : SCROW nStartRow;
486 : SCCOL nEndCol;
487 : SCROW nEndRow;
488 :
489 : SCROW* pNextEnd;
490 : SCSIZE* pIndices;
491 : const ScPatternAttr** ppPatterns;
492 : SCCOL nCol;
493 : SCROW nRow;
494 : bool bRowEmpty;
495 :
496 : public:
497 : ScHorizontalAttrIterator( ScDocument* pDocument, SCTAB nTable,
498 : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
499 : ~ScHorizontalAttrIterator();
500 :
501 : const ScPatternAttr* GetNext( SCCOL& rCol1, SCCOL& rCol2, SCROW& rRow );
502 : };
503 :
504 : // returns non-empty cells and areas with formatting (horizontal)
505 :
506 : class SC_DLLPUBLIC ScUsedAreaIterator
507 : {
508 : private:
509 : ScHorizontalCellIterator aCellIter;
510 : ScHorizontalAttrIterator aAttrIter;
511 :
512 : SCCOL nNextCol;
513 : SCROW nNextRow;
514 :
515 : SCCOL nCellCol;
516 : SCROW nCellRow;
517 : ScRefCellValue* pCell;
518 : SCCOL nAttrCol1;
519 : SCCOL nAttrCol2;
520 : SCROW nAttrRow;
521 : const ScPatternAttr* pPattern;
522 :
523 : SCCOL nFoundStartCol; // results after GetNext
524 : SCCOL nFoundEndCol;
525 : SCROW nFoundRow;
526 : const ScPatternAttr* pFoundPattern;
527 :
528 : ScRefCellValue maFoundCell;
529 :
530 : public:
531 : ScUsedAreaIterator( ScDocument* pDocument, SCTAB nTable,
532 : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
533 : ~ScUsedAreaIterator();
534 :
535 : bool GetNext();
536 :
537 6252 : SCCOL GetStartCol() const { return nFoundStartCol; }
538 6252 : SCCOL GetEndCol() const { return nFoundEndCol; }
539 6252 : SCROW GetRow() const { return nFoundRow; }
540 6252 : const ScPatternAttr* GetPattern() const { return pFoundPattern; }
541 6252 : const ScRefCellValue& GetCell() const { return maFoundCell;}
542 : };
543 :
544 : class ScRowBreakIterator
545 : {
546 : public:
547 : static SCROW NOT_FOUND;
548 :
549 : explicit ScRowBreakIterator(::std::set<SCROW>& rBreaks);
550 : SCROW first();
551 : SCROW next();
552 :
553 : private:
554 : ::std::set<SCROW>& mrBreaks;
555 : ::std::set<SCROW>::const_iterator maItr;
556 : ::std::set<SCROW>::const_iterator maEnd;
557 : };
558 :
559 : class ScDocRowHeightUpdater
560 : {
561 : public:
562 6 : struct TabRanges
563 : {
564 : SCTAB mnTab;
565 : ::boost::shared_ptr<ScFlatBoolRowSegments> mpRanges;
566 :
567 : TabRanges(SCTAB nTab);
568 : };
569 :
570 : /**
571 : * Passing a NULL pointer to pTabRangesArray forces the heights of all
572 : * rows in all tables to be updated.
573 : */
574 : explicit ScDocRowHeightUpdater(
575 : ScDocument& rDoc, OutputDevice* pOutDev, double fPPTX, double fPPTY,
576 : const ::std::vector<TabRanges>* pTabRangesArray = NULL);
577 :
578 : void update();
579 :
580 : private:
581 : void updateAll();
582 :
583 : private:
584 : ScDocument& mrDoc;
585 : OutputDevice* mpOutDev;
586 : double mfPPTX;
587 : double mfPPTY;
588 : const ::std::vector<TabRanges>* mpTabRangesArray;
589 : };
590 :
591 : #endif
592 :
593 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|