xref: /AOO41X/main/sc/inc/dociter.hxx (revision 38d50f7b14e1cf975d8c6468d9633894cd59b523)
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