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