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