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