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 SC_DOCITER_HXX
21 : #define SC_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 : short nNumFmtType;
64 : bool bNumValid:1;
65 : bool bSubTotal:1;
66 : bool bCalcAsShown:1;
67 : bool bTextAsZero:1;
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, bool bSTotal = false,
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 0 : class ScDBQueryDataIterator
99 : {
100 : public:
101 0 : 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::auto_ptr<ScDBQueryParamBase> mpParam;
176 : ::std::auto_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 no hidden and no
188 : * sub-total lines.
189 : **/
190 0 : class ScCellIterator
191 : {
192 : typedef std::pair<sc::CellStoreType::const_iterator, size_t> PositionType;
193 :
194 : ScDocument* mpDoc;
195 : ScAddress maStartPos;
196 : ScAddress maEndPos;
197 : ScAddress maCurPos;
198 :
199 : PositionType maCurColPos;
200 : bool mbSubTotal;
201 :
202 : ScRefCellValue maCurCell;
203 :
204 : void incBlock();
205 : void incPos();
206 : void setPos(size_t nPos);
207 :
208 : const ScColumn* getColumn() const;
209 :
210 : void init();
211 : bool getCurrent();
212 :
213 : public:
214 : ScCellIterator( ScDocument* pDoc, const ScRange& rRange, bool bSTotal = false );
215 :
216 0 : const ScAddress& GetPos() const { return maCurPos; }
217 :
218 : CellType getType() const;
219 : OUString getString();
220 : const EditTextObject* getEditText() const;
221 : ScFormulaCell* getFormulaCell();
222 : const ScFormulaCell* getFormulaCell() const;
223 : ScCellValue getCellValue() const;
224 : const ScRefCellValue& getRefCellValue() const;
225 :
226 : bool hasString() const;
227 : bool hasEmptyData() const;
228 : bool isEmpty() const;
229 : bool equalsWithoutFormat( const ScAddress& rPos ) const;
230 :
231 : bool first();
232 : bool next();
233 : };
234 :
235 0 : class ScQueryCellIterator // walk through all non-empty cells in an area
236 : {
237 : enum StopOnMismatchBits
238 : {
239 : nStopOnMismatchDisabled = 0x00,
240 : nStopOnMismatchEnabled = 0x01,
241 : nStopOnMismatchOccurred = 0x02,
242 : nStopOnMismatchExecuted = nStopOnMismatchEnabled | nStopOnMismatchOccurred
243 : };
244 :
245 : enum TestEqualConditionBits
246 : {
247 : nTestEqualConditionDisabled = 0x00,
248 : nTestEqualConditionEnabled = 0x01,
249 : nTestEqualConditionMatched = 0x02,
250 : nTestEqualConditionFulfilled = nTestEqualConditionEnabled | nTestEqualConditionMatched
251 : };
252 :
253 : typedef sc::CellStoreType::const_position_type PositionType;
254 : PositionType maCurPos;
255 :
256 : boost::scoped_ptr<ScQueryParam> mpParam;
257 : ScDocument* pDoc;
258 : const ScAttrArray* pAttrArray;
259 : sal_uLong nNumFormat;
260 : SCTAB nTab;
261 : SCCOL nCol;
262 : SCROW nRow;
263 : SCROW nAttrEndRow;
264 : sal_uInt8 nStopOnMismatch;
265 : sal_uInt8 nTestEqualCondition;
266 : bool bAdvanceQuery;
267 : bool bIgnoreMismatchOnLeadingStrings;
268 :
269 : /** Initialize position for new column. */
270 : void InitPos();
271 : void IncPos();
272 : void IncBlock();
273 : bool GetThis();
274 :
275 : /* Only works if no regular expression is involved, only
276 : searches for rows in one column, and only the first
277 : query entry is considered with simple conditions
278 : SC_LESS_EQUAL (sorted ascending) or SC_GREATER_EQUAL
279 : (sorted descending). Check these things before
280 : invocation! Delivers a starting point, continue with
281 : GetThis() and GetNext() afterwards. Introduced for
282 : FindEqualOrSortedLastInRange()
283 : */
284 : bool BinarySearch();
285 :
286 : public:
287 : ScQueryCellIterator(ScDocument* pDocument, SCTAB nTable,
288 : const ScQueryParam& aParam, bool bMod = true);
289 : // for bMod = FALSE the QueryParam has to be filled
290 : // (bIsString)
291 : bool GetFirst();
292 : bool GetNext();
293 0 : SCCOL GetCol() { return nCol; }
294 0 : SCROW GetRow() { return nRow; }
295 :
296 : // increments all Entry.nField, if column
297 : // changes, for ScInterpreter ScHLookup()
298 0 : void SetAdvanceQueryParamEntryField( bool bVal )
299 0 : { bAdvanceQuery = bVal; }
300 : void AdvanceQueryParamEntryField();
301 :
302 : /** If set, iterator stops on first non-matching cell
303 : content. May be used in SC_LESS_EQUAL queries where a
304 : cell range is assumed to be sorted; stops on first
305 : value being greater than the queried value and
306 : GetFirst()/GetNext() return NULL. StoppedOnMismatch()
307 : returns true then.
308 : However, the iterator's conditions are not set to end
309 : all queries, GetCol() and GetRow() return values for
310 : the non-matching cell, further GetNext() calls may be
311 : executed. */
312 0 : void SetStopOnMismatch( bool bVal )
313 : {
314 : nStopOnMismatch = sal::static_int_cast<sal_uInt8>(bVal ? nStopOnMismatchEnabled :
315 0 : nStopOnMismatchDisabled);
316 0 : }
317 0 : bool StoppedOnMismatch() const
318 0 : { return nStopOnMismatch == nStopOnMismatchExecuted; }
319 :
320 : /** If set, an additional test for SC_EQUAL condition is
321 : executed in ScTable::ValidQuery() if SC_LESS_EQUAL or
322 : SC_GREATER_EQUAL conditions are to be tested. May be
323 : used where a cell range is assumed to be sorted to stop
324 : if an equal match is found. */
325 0 : void SetTestEqualCondition( bool bVal )
326 : {
327 : nTestEqualCondition = sal::static_int_cast<sal_uInt8>(bVal ?
328 : nTestEqualConditionEnabled :
329 0 : nTestEqualConditionDisabled);
330 0 : }
331 0 : bool IsEqualConditionFulfilled() const
332 0 : { return nTestEqualCondition == nTestEqualConditionFulfilled; }
333 :
334 : /** In a range assumed to be sorted find either the last of
335 : a sequence of equal entries or the last being less than
336 : (or greater than) the queried value. Used by the
337 : interpreter for [HV]?LOOKUP() and MATCH(). Column and
338 : row position of the found entry are returned, otherwise
339 : invalid.
340 :
341 : @param bSearchForEqualAfterMismatch
342 : Continue searching for an equal entry even if the
343 : last entry matching the range was found, in case
344 : the data is not sorted. Is always done if regular
345 : expressions are involved.
346 :
347 : @param bIgnoreMismatchOnLeadingStrings
348 : Normally strings are sorted behind numerical
349 : values. If this parameter is true, the search does
350 : not stop when encountering a string and does not
351 : assume that no values follow anymore.
352 : If querying for a string a mismatch on the first
353 : entry, e.g. column header, is ignored.
354 :
355 : @ATTENTION! StopOnMismatch, TestEqualCondition and
356 : the internal IgnoreMismatchOnLeadingStrings and query
357 : params are in an undefined state upon return! The
358 : iterator is not usable anymore except for obtaining the
359 : number format!
360 : */
361 : bool FindEqualOrSortedLastInRange( SCCOL& nFoundCol,
362 : SCROW& nFoundRow, bool bSearchForEqualAfterMismatch = false,
363 : bool bIgnoreMismatchOnLeadingStrings = true );
364 : };
365 :
366 : class ScDocAttrIterator // all attribute areas
367 : {
368 : private:
369 : ScDocument* pDoc;
370 : SCTAB nTab;
371 : SCCOL nEndCol;
372 : SCROW nStartRow;
373 : SCROW nEndRow;
374 : SCCOL nCol;
375 : ScAttrIterator* pColIter;
376 :
377 : public:
378 : ScDocAttrIterator(ScDocument* pDocument, SCTAB nTable,
379 : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2);
380 : ~ScDocAttrIterator();
381 :
382 : const ScPatternAttr* GetNext( SCCOL& rCol, SCROW& rRow1, SCROW& rRow2 );
383 : };
384 :
385 : class ScAttrRectIterator // all attribute areas, including areas stretching
386 : // across more then one column
387 : {
388 : private:
389 : ScDocument* pDoc;
390 : SCTAB nTab;
391 : SCCOL nEndCol;
392 : SCROW nStartRow;
393 : SCROW nEndRow;
394 : SCCOL nIterStartCol;
395 : SCCOL nIterEndCol;
396 : ScAttrIterator* pColIter;
397 :
398 : public:
399 : ScAttrRectIterator(ScDocument* pDocument, SCTAB nTable,
400 : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2);
401 : ~ScAttrRectIterator();
402 :
403 : void DataChanged();
404 : const ScPatternAttr* GetNext( SCCOL& rCol1, SCCOL& rCol2, SCROW& rRow1, SCROW& rRow2 );
405 : };
406 :
407 : class ScHorizontalCellIterator // walk through all non empty cells in an area
408 : { // row by row
409 0 : struct ColParam
410 : {
411 : sc::CellStoreType::const_iterator maPos;
412 : sc::CellStoreType::const_iterator maEnd;
413 : SCCOL mnCol;
414 : };
415 :
416 : std::vector<ColParam>::iterator maColPos;
417 : std::vector<ColParam> maColPositions;
418 :
419 : ScDocument* pDoc;
420 : SCTAB mnTab;
421 : SCCOL nStartCol;
422 : SCCOL nEndCol;
423 : SCROW nStartRow;
424 : SCROW nEndRow;
425 : SCROW* pNextRows;
426 : SCSIZE* pNextIndices;
427 : SCCOL mnCol;
428 : SCROW mnRow;
429 : ScRefCellValue maCurCell;
430 : bool mbMore;
431 :
432 : public:
433 : ScHorizontalCellIterator(ScDocument* pDocument, SCTAB nTable,
434 : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2);
435 : ~ScHorizontalCellIterator();
436 :
437 : ScRefCellValue* GetNext( SCCOL& rCol, SCROW& rRow );
438 : bool GetPos( SCCOL& rCol, SCROW& rRow );
439 : /// Set a(nother) sheet and (re)init.
440 : void SetTab( SCTAB nTab );
441 :
442 : private:
443 : void Advance();
444 : void SkipInvalid();
445 : bool SkipInvalidInRow();
446 : SCROW FindNextNonEmptyRow();
447 : };
448 :
449 :
450 : /** Row-wise value iterator. */
451 : class ScHorizontalValueIterator
452 : {
453 : private:
454 : ScDocument *pDoc;
455 : const ScAttrArray *pAttrArray;
456 : ScHorizontalCellIterator *pCellIter;
457 : sal_uLong nNumFormat; // for CalcAsShown
458 : sal_uLong nNumFmtIndex;
459 : SCTAB nEndTab;
460 : SCCOL nCurCol;
461 : SCROW nCurRow;
462 : SCTAB nCurTab;
463 : SCROW nAttrEndRow;
464 : short nNumFmtType;
465 : bool bNumValid;
466 : bool bSubTotal;
467 : bool bCalcAsShown;
468 : bool bTextAsZero;
469 :
470 : public:
471 :
472 : ScHorizontalValueIterator( ScDocument* pDocument,
473 : const ScRange& rRange,
474 : bool bSTotal = false,
475 : bool bTextAsZero = false );
476 : ~ScHorizontalValueIterator();
477 : /// Does NOT reset rValue if no value found!
478 : bool GetNext( double& rValue, sal_uInt16& rErr );
479 : };
480 :
481 : // returns all areas with non-default formatting (horizontal)
482 :
483 :
484 : class ScHorizontalAttrIterator
485 : {
486 : private:
487 : ScDocument* pDoc;
488 : SCTAB nTab;
489 : SCCOL nStartCol;
490 : SCROW nStartRow;
491 : SCCOL nEndCol;
492 : SCROW nEndRow;
493 :
494 : SCROW* pNextEnd;
495 : SCSIZE* pIndices;
496 : const ScPatternAttr** ppPatterns;
497 : SCCOL nCol;
498 : SCROW nRow;
499 : bool bRowEmpty;
500 :
501 : public:
502 : ScHorizontalAttrIterator( ScDocument* pDocument, SCTAB nTable,
503 : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
504 : ~ScHorizontalAttrIterator();
505 :
506 : const ScPatternAttr* GetNext( SCCOL& rCol1, SCCOL& rCol2, SCROW& rRow );
507 : };
508 :
509 :
510 : // returns non-empty cells and areas with formatting (horizontal)
511 :
512 :
513 : class SC_DLLPUBLIC ScUsedAreaIterator
514 : {
515 : private:
516 : ScHorizontalCellIterator aCellIter;
517 : ScHorizontalAttrIterator aAttrIter;
518 :
519 : SCCOL nNextCol;
520 : SCROW nNextRow;
521 :
522 : SCCOL nCellCol;
523 : SCROW nCellRow;
524 : ScRefCellValue* pCell;
525 : SCCOL nAttrCol1;
526 : SCCOL nAttrCol2;
527 : SCROW nAttrRow;
528 : const ScPatternAttr* pPattern;
529 :
530 : SCCOL nFoundStartCol; // results after GetNext
531 : SCCOL nFoundEndCol;
532 : SCROW nFoundRow;
533 : const ScPatternAttr* pFoundPattern;
534 :
535 : ScRefCellValue maFoundCell;
536 :
537 : public:
538 : ScUsedAreaIterator( ScDocument* pDocument, SCTAB nTable,
539 : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
540 : ~ScUsedAreaIterator();
541 :
542 : bool GetNext();
543 :
544 0 : SCCOL GetStartCol() const { return nFoundStartCol; }
545 0 : SCCOL GetEndCol() const { return nFoundEndCol; }
546 0 : SCROW GetRow() const { return nFoundRow; }
547 0 : const ScPatternAttr* GetPattern() const { return pFoundPattern; }
548 : const ScRefCellValue& GetCell() const;
549 : };
550 :
551 : class ScRowBreakIterator
552 : {
553 : public:
554 : static SCROW NOT_FOUND;
555 :
556 : explicit ScRowBreakIterator(::std::set<SCROW>& rBreaks);
557 : SCROW first();
558 : SCROW next();
559 :
560 : private:
561 : ::std::set<SCROW>& mrBreaks;
562 : ::std::set<SCROW>::const_iterator maItr;
563 : ::std::set<SCROW>::const_iterator maEnd;
564 : };
565 :
566 : class ScDocRowHeightUpdater
567 : {
568 : public:
569 0 : struct TabRanges
570 : {
571 : SCTAB mnTab;
572 : ::boost::shared_ptr<ScFlatBoolRowSegments> mpRanges;
573 :
574 : TabRanges(SCTAB nTab);
575 : };
576 :
577 : /**
578 : * Passing a NULL pointer to pTabRangesArray forces the heights of all
579 : * rows in all tables to be updated.
580 : */
581 : explicit ScDocRowHeightUpdater(
582 : ScDocument& rDoc, OutputDevice* pOutDev, double fPPTX, double fPPTY,
583 : const ::std::vector<TabRanges>* pTabRangesArray = NULL);
584 :
585 : void update();
586 :
587 : private:
588 : void updateAll();
589 :
590 : private:
591 : ScDocument& mrDoc;
592 : OutputDevice* mpOutDev;
593 : double mfPPTX;
594 : double mfPPTY;
595 : const ::std::vector<TabRanges>* mpTabRangesArray;
596 : };
597 :
598 :
599 : #endif
600 :
601 :
602 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|