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