xref: /aoo41x/main/sc/inc/dociter.hxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #ifndef SC_DOCITER_HXX
29 #define SC_DOCITER_HXX
30 
31 #include "address.hxx"
32 #include <tools/solar.h>
33 #include "global.hxx"
34 #include "scdllapi.h"
35 #include "queryparam.hxx"
36 
37 #include <memory>
38 
39 #include <set>
40 
41 class ScDocument;
42 class ScBaseCell;
43 class ScPatternAttr;
44 class ScAttrArray;
45 class ScAttrIterator;
46 class ScRange;
47 
48 class ScDocumentIterator				// alle nichtleeren Zellen durchgehen
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 	sal_Bool					GetThis();
68 	sal_Bool					GetThisCol();
69 
70 public:
71 			ScDocumentIterator( ScDocument* pDocument, SCTAB nStartTable, SCTAB nEndTable );
72 			~ScDocumentIterator();
73 
74 	sal_Bool					GetFirst();
75 	sal_Bool					GetNext();
76 
77 	ScBaseCell*				GetCell();
78 	const ScPatternAttr*	GetPattern();
79 	void					GetPos( SCCOL& rCol, SCROW& rRow, SCTAB& rTab );
80 };
81 
82 class ScValueIterator            // alle Zahlenwerte in einem Bereich durchgehen
83 {
84 private:
85 	double			fNextValue;
86 	ScDocument*		pDoc;
87 	const ScAttrArray*	pAttrArray;
88 	sal_uLong			nNumFormat;		// fuer 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 	sal_Bool			bNumValid;
104 	sal_Bool			bSubTotal;
105 	sal_Bool			bNextValid;
106 	sal_Bool			bCalcAsShown;
107 	sal_Bool			bTextAsZero;
108 
109 	sal_Bool			GetThis(double& rValue, sal_uInt16& rErr);
110 public:
111 //UNUSED2008-05  ScValueIterator(ScDocument* pDocument,
112 //UNUSED2008-05                  SCCOL nSCol, SCROW nSRow, SCTAB nSTab,
113 //UNUSED2008-05                  SCCOL nECol, SCROW nERow, SCTAB nETab,
114 //UNUSED2008-05                  sal_Bool bSTotal = sal_False, sal_Bool bTextAsZero = sal_False);
115 
116 					ScValueIterator(ScDocument* pDocument,
117 									const ScRange& rRange, sal_Bool bSTotal = sal_False,
118 									sal_Bool bTextAsZero = sal_False );
119 	void			GetCurNumFmtInfo( short& nType, sal_uLong& nIndex );
120     /// Does NOT reset rValue if no value found!
121 	sal_Bool			GetFirst(double& rValue, sal_uInt16& rErr);
122     /// Does NOT reset rValue if no value found!
123 	sal_Bool			GetNext(double& rValue, sal_uInt16& rErr)
124 					{
125 						return bNextValid ? ( bNextValid = sal_False, rValue = fNextValue,
126 												rErr = 0, nRow = nNextRow,
127 												++nColRow, bNumValid = sal_False, sal_True )
128 										  : ( ++nRow, GetThis(rValue, rErr) );
129 					}
130 };
131 
132 // ============================================================================
133 
134 class ScDBQueryDataIterator
135 {
136 public:
137     struct Value
138     {
139         ::rtl::OUString maString;
140         double          mfValue;
141         sal_uInt16      mnError;
142         bool            mbIsNumber;
143 
144         Value();
145     };
146 
147 private:
148     static SCROW        GetRowByColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCSIZE nColRow);
149     static ScBaseCell*  GetCellByColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCSIZE nColRow);
150     static ScAttrArray* GetAttrArrayByCol(ScDocument& rDoc, SCTAB nTab, SCCOL nCol);
151     static bool         IsQueryValid(ScDocument& rDoc, const ScQueryParam& rParam, SCTAB nTab, SCROW nRow, ScBaseCell* pCell);
152     static SCSIZE       SearchColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCROW nRow, SCCOL nCol);
153 
154     class DataAccess
155     {
156     public:
157         DataAccess(const ScDBQueryDataIterator* pParent);
158         virtual ~DataAccess() = 0;
159         virtual bool getCurrent(Value& rValue) = 0;
160         virtual bool getFirst(Value& rValue) = 0;
161         virtual bool getNext(Value& rValue) = 0;
162     protected:
163         const ScDBQueryDataIterator* mpParent;
164     };
165 
166     class DataAccessInternal : public DataAccess
167     {
168     public:
169         DataAccessInternal(const ScDBQueryDataIterator* pParent, ScDBQueryParamInternal* pParam, ScDocument* pDoc);
170         virtual ~DataAccessInternal();
171         virtual bool getCurrent(Value& rValue);
172         virtual bool getFirst(Value& rValue);
173         virtual bool getNext(Value& rValue);
174 
175     private:
176         ScDBQueryParamInternal* mpParam;
177         ScDocument*         mpDoc;
178         const ScAttrArray*  pAttrArray;
179         sal_uLong               nNumFormat;     // for CalcAsShown
180         sal_uLong               nNumFmtIndex;
181         SCCOL               nCol;
182         SCROW               nRow;
183         SCSIZE              nColRow;
184         SCROW               nAttrEndRow;
185         SCTAB               nTab;
186         short               nNumFmtType;
187         bool                bCalcAsShown;
188     };
189 
190     class DataAccessMatrix : public DataAccess
191     {
192     public:
193         DataAccessMatrix(const ScDBQueryDataIterator* pParent, ScDBQueryParamMatrix* pParam);
194         virtual ~DataAccessMatrix();
195         virtual bool getCurrent(Value& rValue);
196         virtual bool getFirst(Value& rValue);
197         virtual bool getNext(Value& rValue);
198 
199     private:
200         bool isValidQuery(SCROW mnRow, const ScMatrix& rMat) const;
201 
202         ScDBQueryParamMatrix* mpParam;
203         SCROW mnCurRow;
204         SCROW mnRows;
205         SCCOL mnCols;
206     };
207 
208     ::std::auto_ptr<ScDBQueryParamBase> mpParam;
209     ::std::auto_ptr<DataAccess>         mpData;
210 
211 public:
212                     ScDBQueryDataIterator(ScDocument* pDocument, ScDBQueryParamBase* pParam);
213     /// Does NOT reset rValue if no value found!
214     bool            GetFirst(Value& rValue);
215     /// Does NOT reset rValue if no value found!
216     bool            GetNext(Value& rValue);
217 };
218 
219 // ============================================================================
220 
221 class ScCellIterator            // alle Zellen in einem Bereich durchgehen
222 {								// bei SubTotal aber keine ausgeblendeten und
223 private:						// SubTotalZeilen
224 	ScDocument*		pDoc;
225 	SCCOL			nStartCol;
226 	SCROW			nStartRow;
227 	SCTAB			nStartTab;
228 	SCCOL			nEndCol;
229 	SCROW			nEndRow;
230 	SCTAB			nEndTab;
231 	SCCOL 			nCol;
232 	SCROW			nRow;
233 	SCTAB			nTab;
234 	SCSIZE			nColRow;
235 	sal_Bool			bSubTotal;
236 
237 	ScBaseCell*		GetThis();
238 public:
239 					ScCellIterator(ScDocument* pDocument,
240 								   SCCOL nSCol, SCROW nSRow, SCTAB nSTab,
241 								   SCCOL nECol, SCROW nERow, SCTAB nETab,
242 								   sal_Bool bSTotal = sal_False);
243 					ScCellIterator(ScDocument* pDocument,
244 								   const ScRange& rRange, sal_Bool bSTotal = sal_False);
245 	ScBaseCell*		GetFirst();
246 	ScBaseCell*		GetNext();
247     SCCOL           GetCol() const { return nCol; }
248     SCROW           GetRow() const { return nRow; }
249     SCTAB           GetTab() const { return nTab; }
250     ScAddress       GetPos() const { return ScAddress( nCol, nRow, nTab ); }
251 };
252 
253 class ScQueryCellIterator           // alle nichtleeren Zellen in einem Bereich
254 {									// durchgehen
255     enum StopOnMismatchBits
256     {
257         nStopOnMismatchDisabled = 0x00,
258         nStopOnMismatchEnabled  = 0x01,
259         nStopOnMismatchOccured  = 0x02,
260         nStopOnMismatchExecuted = nStopOnMismatchEnabled | nStopOnMismatchOccured
261     };
262 
263     enum TestEqualConditionBits
264     {
265         nTestEqualConditionDisabled = 0x00,
266         nTestEqualConditionEnabled  = 0x01,
267         nTestEqualConditionMatched  = 0x02,
268         nTestEqualConditionFulfilled = nTestEqualConditionEnabled | nTestEqualConditionMatched
269     };
270 
271 private:
272 	ScQueryParam	aParam;
273 	ScDocument*		pDoc;
274 	const ScAttrArray*	pAttrArray;
275 	sal_uLong			nNumFormat;
276 	SCTAB			nTab;
277 	SCCOL 			nCol;
278 	SCROW			nRow;
279 	SCSIZE			nColRow;
280 	SCROW			nAttrEndRow;
281     sal_uInt8            nStopOnMismatch;
282     sal_uInt8            nTestEqualCondition;
283 	sal_Bool			bAdvanceQuery;
284     sal_Bool            bIgnoreMismatchOnLeadingStrings;
285 
286 	ScBaseCell*		GetThis();
287 
288                     /* Only works if no regular expression is involved, only
289                        searches for rows in one column, and only the first
290                        query entry is considered with simple conditions
291                        SC_LESS_EQUAL (sorted ascending) or SC_GREATER_EQUAL
292                        (sorted descending). Check these things before
293                        invocation! Delivers a starting point, continue with
294                        GetThis() and GetNext() afterwards. Introduced for
295                        FindEqualOrSortedLastInRange()
296                      */
297     ScBaseCell*     BinarySearch();
298 
299 public:
300 					ScQueryCellIterator(ScDocument* pDocument, SCTAB nTable,
301 										const ScQueryParam& aParam, sal_Bool bMod = sal_True);
302 										// fuer bMod = sal_False muss der QueryParam
303 										// weiter aufgefuellt sein (bIsString)
304 	ScBaseCell*		GetFirst();
305 	ScBaseCell*		GetNext();
306 	SCCOL           GetCol() { return nCol; }
307 	SCROW           GetRow() { return nRow; }
308 
309 					// setzt alle Entry.nField einen weiter, wenn Spalte
310 					// wechselt, fuer ScInterpreter ScHLookup()
311 	void			SetAdvanceQueryParamEntryField( sal_Bool bVal )
312 						{ bAdvanceQuery = bVal; }
313 	void			AdvanceQueryParamEntryField();
314 
315                     /** If set, iterator stops on first non-matching cell
316                         content. May be used in SC_LESS_EQUAL queries where a
317                         cell range is assumed to be sorted; stops on first
318                         value being greater than the queried value and
319                         GetFirst()/GetNext() return NULL. StoppedOnMismatch()
320                         returns sal_True then.
321                         However, the iterator's conditions are not set to end
322                         all queries, GetCol() and GetRow() return values for
323                         the non-matching cell, further GetNext() calls may be
324                         executed. */
325     void            SetStopOnMismatch( sal_Bool bVal )
326                         {
327                             nStopOnMismatch = sal::static_int_cast<sal_uInt8>(bVal ? nStopOnMismatchEnabled :
328                                 nStopOnMismatchDisabled);
329                         }
330     sal_Bool            StoppedOnMismatch() const
331                         { return nStopOnMismatch == nStopOnMismatchExecuted; }
332 
333                     /** If set, an additional test for SC_EQUAL condition is
334                         executed in ScTable::ValidQuery() if SC_LESS_EQUAL or
335                         SC_GREATER_EQUAL conditions are to be tested. May be
336                         used where a cell range is assumed to be sorted to stop
337                         if an equal match is found. */
338     void            SetTestEqualCondition( sal_Bool bVal )
339                         {
340                             nTestEqualCondition = sal::static_int_cast<sal_uInt8>(bVal ?
341                                 nTestEqualConditionEnabled :
342                                 nTestEqualConditionDisabled);
343                         }
344     sal_Bool            IsEqualConditionFulfilled() const
345                         { return nTestEqualCondition == nTestEqualConditionFulfilled; }
346 
347                     /** In a range assumed to be sorted find either the last of
348                         a sequence of equal entries or the last being less than
349                         (or greater than) the queried value. Used by the
350                         interpreter for [HV]?LOOKUP() and MATCH(). Column and
351                         row position of the found entry are returned, otherwise
352                         invalid.
353 
354                         @param bSearchForEqualAfterMismatch
355                             Continue searching for an equal entry even if the
356                             last entry matching the range was found, in case
357                             the data is not sorted. Is always done if regular
358                             expressions are involved.
359 
360                         @param bIgnoreMismatchOnLeadingStrings
361                             Normally strings are sorted behind numerical
362                             values. If this parameter is sal_True, the search does
363                             not stop when encountering a string and does not
364                             assume that no values follow anymore.
365                             If querying for a string a mismatch on the first
366                             entry, e.g. column header, is ignored.
367 
368                         @ATTENTION! StopOnMismatch, TestEqualCondition and
369                         the internal IgnoreMismatchOnLeadingStrings and query
370                         params are in an undefined state upon return! The
371                         iterator is not usable anymore except for obtaining the
372                         number format!
373                       */
374     sal_Bool            FindEqualOrSortedLastInRange( SCCOL& nFoundCol,
375                         SCROW& nFoundRow, sal_Bool bSearchForEqualAfterMismatch = sal_False,
376                         sal_Bool bIgnoreMismatchOnLeadingStrings = sal_True );
377 };
378 
379 class ScDocAttrIterator				// alle Attribut-Bereiche
380 {
381 private:
382 	ScDocument*		pDoc;
383 	SCTAB			nTab;
384 	SCCOL			nEndCol;
385 	SCROW			nStartRow;
386 	SCROW			nEndRow;
387 	SCCOL			nCol;
388 	ScAttrIterator*	pColIter;
389 
390 public:
391 					ScDocAttrIterator(ScDocument* pDocument, SCTAB nTable,
392 									SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2);
393 					~ScDocAttrIterator();
394 
395 	const ScPatternAttr*	GetNext( SCCOL& rCol, SCROW& rRow1, SCROW& rRow2 );
396 };
397 
398 class ScAttrRectIterator			// alle Attribut-Bereiche, auch Bereiche ueber mehrere Spalten
399 {
400 private:
401 	ScDocument*		pDoc;
402 	SCTAB			nTab;
403 	SCCOL			nEndCol;
404 	SCROW			nStartRow;
405 	SCROW			nEndRow;
406 	SCCOL			nIterStartCol;
407 	SCCOL			nIterEndCol;
408 	ScAttrIterator*	pColIter;
409 
410 public:
411 					ScAttrRectIterator(ScDocument* pDocument, SCTAB nTable,
412 									SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2);
413 					~ScAttrRectIterator();
414 
415 	void 					DataChanged();
416 	const ScPatternAttr*	GetNext( SCCOL& rCol1, SCCOL& rCol2, SCROW& rRow1, SCROW& rRow2 );
417 };
418 
419 class ScHorizontalCellIterator		// alle nichtleeren Zellen in einem Bereich
420 {									// zeilenweise durchgehen
421 private:
422 	ScDocument*		pDoc;
423 	SCTAB			nTab;
424 	SCCOL			nStartCol;
425 	SCCOL			nEndCol;
426 	SCROW			nStartRow;
427 	SCROW			nEndRow;
428 	SCROW*			pNextRows;
429 	SCSIZE*			pNextIndices;
430 	SCCOL			nCol;
431 	SCROW			nRow;
432 	sal_Bool			bMore;
433 
434 public:
435 					ScHorizontalCellIterator(ScDocument* pDocument, SCTAB nTable,
436 									SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2);
437 					~ScHorizontalCellIterator();
438 
439 	ScBaseCell*		GetNext( SCCOL& rCol, SCROW& rRow );
440 	sal_Bool			ReturnNext( SCCOL& rCol, SCROW& rRow );
441     /// Set a(nother) sheet and (re)init.
442     void            SetTab( SCTAB nTab );
443 
444 private:
445 	void			Advance();
446 };
447 
448 
449 /** Row-wise value iterator. */
450 class ScHorizontalValueIterator
451 {
452 private:
453     ScDocument               *pDoc;
454     const ScAttrArray        *pAttrArray;
455     ScHorizontalCellIterator *pCellIter;
456     sal_uLong                 nNumFormat;     // for CalcAsShown
457     sal_uLong                 nNumFmtIndex;
458     SCTAB                     nEndTab;
459     SCCOL                     nCurCol;
460     SCROW                     nCurRow;
461     SCTAB                     nCurTab;
462     SCROW                     nAttrEndRow;
463     short                     nNumFmtType;
464     bool                      bNumValid;
465     bool                      bSubTotal;
466     bool                      bCalcAsShown;
467     bool                      bTextAsZero;
468 
469 public:
470 
471                     ScHorizontalValueIterator( ScDocument* pDocument,
472                                                const ScRange& rRange,
473                                                bool bSTotal = false,
474                                                bool bTextAsZero = false );
475                     ~ScHorizontalValueIterator();
476     void            GetCurNumFmtInfo( short& nType, sal_uLong& nIndex );
477     /// Does NOT reset rValue if no value found!
478     bool            GetNext( double& rValue, sal_uInt16& rErr );
479 };
480 
481 
482 //
483 //	gibt alle Bereiche mit nicht-Default-Formatierung zurueck (horizontal)
484 //
485 
486 class ScHorizontalAttrIterator
487 {
488 private:
489 	ScDocument* 			pDoc;
490 	SCTAB					nTab;
491 	SCCOL					nStartCol;
492 	SCROW					nStartRow;
493 	SCCOL					nEndCol;
494 	SCROW					nEndRow;
495 
496 	SCROW*					pNextEnd;
497 	SCSIZE*					pIndices;
498 	const ScPatternAttr**	ppPatterns;
499 	SCCOL					nCol;
500 	SCROW					nRow;
501 	sal_Bool					bRowEmpty;
502 
503 public:
504 			ScHorizontalAttrIterator( ScDocument* pDocument, SCTAB nTable,
505 									SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
506 			~ScHorizontalAttrIterator();
507 
508 	const ScPatternAttr*	GetNext( SCCOL& rCol1, SCCOL& rCol2, SCROW& rRow );
509 };
510 
511 //
512 //	gibt nichtleere Zellen und Bereiche mit Formatierung zurueck (horizontal)
513 //
514 
515 class SC_DLLPUBLIC ScUsedAreaIterator
516 {
517 private:
518 	ScHorizontalCellIterator	aCellIter;
519 	ScHorizontalAttrIterator	aAttrIter;
520 
521 	SCCOL					nNextCol;
522 	SCROW					nNextRow;
523 
524 	SCCOL					nCellCol;
525 	SCROW					nCellRow;
526 	const ScBaseCell*		pCell;
527 	SCCOL					nAttrCol1;
528 	SCCOL					nAttrCol2;
529 	SCROW					nAttrRow;
530 	const ScPatternAttr*	pPattern;
531 
532 	SCCOL					nFoundStartCol;			// Ergebnisse nach GetNext
533 	SCCOL					nFoundEndCol;
534 	SCROW					nFoundRow;
535 	const ScPatternAttr*	pFoundPattern;
536 	const ScBaseCell*		pFoundCell;
537 
538 public:
539 			ScUsedAreaIterator( ScDocument* pDocument, SCTAB nTable,
540 								SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
541 			~ScUsedAreaIterator();
542 
543 	sal_Bool	GetNext();
544 
545 	SCCOL					GetStartCol() const		{ return nFoundStartCol; }
546 	SCCOL					GetEndCol() const		{ return nFoundEndCol; }
547 	SCROW					GetRow() const			{ return nFoundRow; }
548 	const ScPatternAttr*	GetPattern() const		{ return pFoundPattern; }
549 	const ScBaseCell*		GetCell() const			{ return pFoundCell; }
550 };
551 
552 // ============================================================================
553 
554 class ScRowBreakIterator
555 {
556 public:
557     static SCROW NOT_FOUND;
558 
559     explicit ScRowBreakIterator(::std::set<SCROW>& rBreaks);
560     SCROW first();
561     SCROW next();
562 
563 private:
564     ::std::set<SCROW>& mrBreaks;
565     ::std::set<SCROW>::const_iterator maItr;
566     ::std::set<SCROW>::const_iterator maEnd;
567 };
568 
569 #endif
570 
571 
572