xref: /trunk/main/sc/source/core/data/dociter.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 // INCLUDE ---------------------------------------------------------------
32 
33 #include <svl/zforlist.hxx>
34 
35 #include "scitems.hxx"
36 #include "global.hxx"
37 #include "dociter.hxx"
38 #include "document.hxx"
39 #include "table.hxx"
40 #include "column.hxx"
41 #include "cell.hxx"
42 #include "attarray.hxx"
43 #include "patattr.hxx"
44 #include "docoptio.hxx"
45 #include "cellform.hxx"
46 
47 #include <vector>
48 
49 using ::rtl::math::approxEqual;
50 using ::std::vector;
51 using ::rtl::OUString;
52 using ::std::set;
53 
54 // STATIC DATA -----------------------------------------------------------
55 
56 namespace {
57 
58 void lcl_toUpper(OUString& rStr)
59 {
60     rStr = ScGlobal::pCharClass->toUpper(rStr.trim(), 0, static_cast<sal_uInt16>(rStr.getLength()));
61 }
62 
63 }
64 
65 ScDocumentIterator::ScDocumentIterator( ScDocument* pDocument,
66                             SCTAB nStartTable, SCTAB nEndTable ) :
67     pDoc( pDocument ),
68     nStartTab( nStartTable ),
69     nEndTab( nEndTable )
70 {
71     PutInOrder( nStartTab, nEndTab );
72     if (!ValidTab(nStartTab)) nStartTab = MAXTAB;
73     if (!ValidTab(nEndTab)) nEndTab = MAXTAB;
74 
75     pDefPattern = pDoc->GetDefPattern();
76 
77     nCol = 0;
78     nRow = 0;
79     nTab = nStartTab;
80 
81     nColPos = 0;
82     nAttrPos = 0;
83 }
84 
85 ScDocumentIterator::~ScDocumentIterator()
86 {
87 }
88 
89 sal_Bool ScDocumentIterator::GetThisCol()
90 {
91     ScTable*        pTab;
92     while ( (pTab = pDoc->pTab[nTab]) == NULL )
93     {
94         if ( nTab == nEndTab )
95         {
96             nCol = MAXCOL;
97             nRow = MAXROW;
98             return sal_False;
99         }
100         ++nTab;
101     }
102     ScColumn*       pCol = &pTab->aCol[nCol];
103     ScAttrArray*    pAtt = pCol->pAttrArray;
104 
105     sal_Bool bFound = sal_False;
106     do
107     {
108         SCROW nColRow;
109         SCROW nAttrEnd;
110 
111         do
112         {
113             nAttrEnd = pAtt->pData[nAttrPos].nRow;
114             if (nAttrEnd < nRow)
115                 ++nAttrPos;
116         }
117         while (nAttrEnd < nRow);
118 
119         do
120         {
121             nColRow = (nColPos < pCol->nCount) ? pCol->pItems[nColPos].nRow : MAXROW+1;
122             if (nColRow < nRow)
123                 ++nColPos;
124         }
125         while (nColRow < nRow);
126 
127         if (nColRow == nRow)
128         {
129             bFound   = sal_True;
130             pCell    = pCol->pItems[nColPos].pCell;
131             pPattern = pAtt->pData[nAttrPos].pPattern;
132         }
133         else if ( pAtt->pData[nAttrPos].pPattern != pDefPattern )
134         {
135             bFound = sal_True;
136             pCell = NULL;
137             pPattern = pAtt->pData[nAttrPos].pPattern;
138         }
139         else
140         {
141             nRow = Min( (SCROW)nColRow, (SCROW)(nAttrEnd+1) );
142         }
143     }
144     while (!bFound && nRow <= MAXROW);
145 
146     return bFound;
147 }
148 
149 sal_Bool ScDocumentIterator::GetThis()
150 {
151     sal_Bool bEnd = sal_False;
152     sal_Bool bSuccess = sal_False;
153 
154     while ( !bSuccess && !bEnd )
155     {
156         if ( nRow > MAXROW )
157             bSuccess = sal_False;
158         else
159             bSuccess = GetThisCol();
160 
161         if ( !bSuccess )
162         {
163             ++nCol;
164             if (nCol > MAXCOL)
165             {
166                 nCol = 0;
167                 ++nTab;
168                 if (nTab > nEndTab)
169                     bEnd = sal_True;
170             }
171             nRow = 0;
172             nColPos = 0;
173             nAttrPos = 0;
174         }
175     }
176 
177     return !bEnd;
178 }
179 
180 sal_Bool ScDocumentIterator::GetFirst()
181 {
182     nCol = 0;
183     nTab = nStartTab;
184 
185     nRow = 0;
186     nColPos = 0;
187     nAttrPos = 0;
188 
189     return GetThis();
190 }
191 
192 sal_Bool ScDocumentIterator::GetNext()
193 {
194     ++nRow;
195 
196     return GetThis();
197 }
198 
199 //------------------------------------------------------------------------
200 
201 ScBaseCell* ScDocumentIterator::GetCell()
202 {
203     return pCell;
204 }
205 
206 const ScPatternAttr* ScDocumentIterator::GetPattern()
207 {
208     return pPattern;
209 }
210 
211 void ScDocumentIterator::GetPos( SCCOL& rCol, SCROW& rRow, SCTAB& rTab )
212 {
213     rCol = nCol;
214     rRow = nRow;
215     rTab = nTab;
216 }
217 
218 
219 //------------------------------------------------------------------------
220 //------------------------------------------------------------------------
221 void lcl_IterGetNumberFormat( sal_uLong& nFormat, const ScAttrArray*& rpArr,
222         SCROW& nAttrEndRow, const ScAttrArray* pNewArr, SCROW nRow,
223         ScDocument* pDoc )
224 {
225     if ( rpArr != pNewArr || nAttrEndRow < nRow )
226     {
227         SCSIZE nPos;
228         pNewArr->Search( nRow, nPos );  // nPos 0 gueltig wenn nicht gefunden
229         const ScPatternAttr* pPattern = pNewArr->pData[nPos].pPattern;
230         nFormat = pPattern->GetNumberFormat( pDoc->GetFormatTable() );
231         rpArr = pNewArr;
232         nAttrEndRow = pNewArr->pData[nPos].nRow;
233     }
234 }
235 
236 //UNUSED2008-05  ScValueIterator::ScValueIterator( ScDocument* pDocument,
237 //UNUSED2008-05                                    SCCOL nSCol, SCROW nSRow, SCTAB nSTab,
238 //UNUSED2008-05                                    SCCOL nECol, SCROW nERow, SCTAB nETab,
239 //UNUSED2008-05                                    sal_Bool bSTotal, sal_Bool bTextZero ) :
240 //UNUSED2008-05  pDoc( pDocument ),
241 //UNUSED2008-05  nNumFmtIndex(0),
242 //UNUSED2008-05  nStartCol( nSCol),
243 //UNUSED2008-05  nStartRow( nSRow),
244 //UNUSED2008-05  nStartTab( nSTab ),
245 //UNUSED2008-05  nEndCol( nECol ),
246 //UNUSED2008-05  nEndRow( nERow),
247 //UNUSED2008-05  nEndTab( nETab ),
248 //UNUSED2008-05  nNumFmtType( NUMBERFORMAT_UNDEFINED ),
249 //UNUSED2008-05  bNumValid( sal_False ),
250 //UNUSED2008-05  bSubTotal(bSTotal),
251 //UNUSED2008-05  bNextValid( sal_False ),
252 //UNUSED2008-05  bCalcAsShown( pDocument->GetDocOptions().IsCalcAsShown() ),
253 //UNUSED2008-05  bTextAsZero( bTextZero )
254 //UNUSED2008-05  {
255 //UNUSED2008-05      PutInOrder( nStartCol, nEndCol);
256 //UNUSED2008-05      PutInOrder( nStartRow, nEndRow);
257 //UNUSED2008-05      PutInOrder( nStartTab, nEndTab );
258 //UNUSED2008-05
259 //UNUSED2008-05      if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
260 //UNUSED2008-05      if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
261 //UNUSED2008-05      if (!ValidRow(nStartRow)) nStartRow = MAXROW;
262 //UNUSED2008-05      if (!ValidRow(nEndRow)) nEndRow = MAXROW;
263 //UNUSED2008-05      if (!ValidTab(nStartTab)) nStartTab = MAXTAB;
264 //UNUSED2008-05      if (!ValidTab(nEndTab)) nEndTab = MAXTAB;
265 //UNUSED2008-05
266 //UNUSED2008-05      nCol = nStartCol;
267 //UNUSED2008-05      nRow = nStartRow;
268 //UNUSED2008-05      nTab = nStartTab;
269 //UNUSED2008-05
270 //UNUSED2008-05      nColRow = 0;                    // wird bei GetFirst initialisiert
271 //UNUSED2008-05
272 //UNUSED2008-05      nNumFormat = 0;                 // werden bei GetNumberFormat initialisiert
273 //UNUSED2008-05      pAttrArray = 0;
274 //UNUSED2008-05      nAttrEndRow = 0;
275 //UNUSED2008-05  }
276 
277 ScValueIterator::ScValueIterator( ScDocument* pDocument, const ScRange& rRange,
278             sal_Bool bSTotal, sal_Bool bTextZero ) :
279     pDoc( pDocument ),
280     nNumFmtIndex(0),
281     nStartCol( rRange.aStart.Col() ),
282     nStartRow( rRange.aStart.Row() ),
283     nStartTab( rRange.aStart.Tab() ),
284     nEndCol( rRange.aEnd.Col() ),
285     nEndRow( rRange.aEnd.Row() ),
286     nEndTab( rRange.aEnd.Tab() ),
287     nNumFmtType( NUMBERFORMAT_UNDEFINED ),
288     bNumValid( sal_False ),
289     bSubTotal(bSTotal),
290     bNextValid( sal_False ),
291     bCalcAsShown( pDocument->GetDocOptions().IsCalcAsShown() ),
292     bTextAsZero( bTextZero )
293 {
294     PutInOrder( nStartCol, nEndCol);
295     PutInOrder( nStartRow, nEndRow);
296     PutInOrder( nStartTab, nEndTab );
297 
298     if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
299     if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
300     if (!ValidRow(nStartRow)) nStartRow = MAXROW;
301     if (!ValidRow(nEndRow)) nEndRow = MAXROW;
302     if (!ValidTab(nStartTab)) nStartTab = MAXTAB;
303     if (!ValidTab(nEndTab)) nEndTab = MAXTAB;
304 
305     nCol = nStartCol;
306     nRow = nStartRow;
307     nTab = nStartTab;
308 
309     nColRow = 0;                    // wird bei GetFirst initialisiert
310 
311     nNumFormat = 0;                 // werden bei GetNumberFormat initialisiert
312     pAttrArray = 0;
313     nAttrEndRow = 0;
314 }
315 
316 sal_Bool ScValueIterator::GetThis(double& rValue, sal_uInt16& rErr)
317 {
318     ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
319     for (;;)
320     {
321         if ( nRow > nEndRow )
322         {
323             nRow = nStartRow;
324             do
325             {
326                 nCol++;
327                 if ( nCol > nEndCol )
328                 {
329                     nCol = nStartCol;
330                     nTab++;
331                     if ( nTab > nEndTab )
332                     {
333                         // rValue = 0.0;    //! do not change caller's value!
334                         rErr = 0;
335                         return sal_False;               // Ende und Aus
336                     }
337                 }
338                 pCol = &(pDoc->pTab[nTab])->aCol[nCol];
339             } while ( pCol->nCount == 0 );
340             pCol->Search( nRow, nColRow );
341         }
342 
343         while (( nColRow < pCol->nCount ) && ( pCol->pItems[nColRow].nRow < nRow ))
344             nColRow++;
345 
346         if ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow <= nEndRow )
347         {
348             nRow = pCol->pItems[nColRow].nRow + 1;
349             if ( !bSubTotal || !pDoc->pTab[nTab]->RowFiltered( nRow-1 ) )
350             {
351                 ScBaseCell* pCell = pCol->pItems[nColRow].pCell;
352                 ++nColRow;
353                 switch (pCell->GetCellType())
354                 {
355                     case CELLTYPE_VALUE:
356                     {
357                         bNumValid = sal_False;
358                         rValue = ((ScValueCell*)pCell)->GetValue();
359                         rErr = 0;
360                         --nRow;
361                         if ( bCalcAsShown )
362                         {
363                             lcl_IterGetNumberFormat( nNumFormat, pAttrArray,
364                                 nAttrEndRow, pCol->pAttrArray, nRow, pDoc );
365                             rValue = pDoc->RoundValueAsShown( rValue, nNumFormat );
366                         }
367                         //
368                         //  wenn in der selben Spalte gleich noch eine Value-Cell folgt, die
369                         //  auch noch im Block liegt, den Wert jetzt schon holen
370                         //
371                         if ( nColRow < pCol->nCount &&
372                              pCol->pItems[nColRow].nRow <= nEndRow &&
373                              pCol->pItems[nColRow].pCell->GetCellType() == CELLTYPE_VALUE &&
374                              !bSubTotal )
375                         {
376                             fNextValue = ((ScValueCell*)pCol->pItems[nColRow].pCell)->GetValue();
377                             nNextRow = pCol->pItems[nColRow].nRow;
378                             bNextValid = sal_True;
379                             if ( bCalcAsShown )
380                             {
381                                 lcl_IterGetNumberFormat( nNumFormat, pAttrArray,
382                                     nAttrEndRow, pCol->pAttrArray, nNextRow, pDoc );
383                                 fNextValue = pDoc->RoundValueAsShown( fNextValue, nNumFormat );
384                             }
385                         }
386 
387                         return sal_True;                                    // gefunden
388                     }
389 //                    break;
390                     case CELLTYPE_FORMULA:
391                     {
392                         if (!bSubTotal || !((ScFormulaCell*)pCell)->IsSubTotal())
393                         {
394                             rErr = ((ScFormulaCell*)pCell)->GetErrCode();
395                             if ( rErr || ((ScFormulaCell*)pCell)->IsValue() )
396                             {
397                                 rValue = ((ScFormulaCell*)pCell)->GetValue();
398                                 nRow--;
399                                 bNumValid = sal_False;
400                                 return sal_True;                            // gefunden
401                             }
402                             else if ( bTextAsZero )
403                             {
404                                 rValue = 0.0;
405                                 nRow--;
406                                 bNumValid = sal_False;
407                                 return sal_True;
408                             }
409                         }
410                     }
411                     break;
412                     case CELLTYPE_STRING :
413                     case CELLTYPE_EDIT :
414                     {
415                         if ( bTextAsZero )
416                         {
417                             rErr = 0;
418                             rValue = 0.0;
419                             nNumFmtType = NUMBERFORMAT_NUMBER;
420                             nNumFmtIndex = 0;
421                             bNumValid = sal_True;
422                             --nRow;
423                             return sal_True;
424                         }
425                     }
426                     break;
427                     default:
428                     {
429                         // added to avoid warnings
430                     }
431                 }
432             }
433         }
434         else
435             nRow = nEndRow + 1;         // naechste Spalte
436     }
437 }
438 
439 void ScValueIterator::GetCurNumFmtInfo( short& nType, sal_uLong& nIndex )
440 {
441     if (!bNumValid)
442     {
443         const ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
444         nNumFmtIndex = pCol->GetNumberFormat( nRow );
445         if ( (nNumFmtIndex % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
446         {
447             const ScBaseCell* pCell;
448             SCSIZE nIdx = nColRow - 1;
449             // there might be rearranged something, so be on the safe side
450             if ( nIdx < pCol->nCount && pCol->pItems[nIdx].nRow == nRow )
451                 pCell = pCol->pItems[nIdx].pCell;
452             else
453             {
454                 if ( pCol->Search( nRow, nIdx ) )
455                     pCell = pCol->pItems[nIdx].pCell;
456                 else
457                     pCell = NULL;
458             }
459             if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
460                 ((const ScFormulaCell*)pCell)->GetFormatInfo( nNumFmtType, nNumFmtIndex );
461             else
462                 nNumFmtType = pDoc->GetFormatTable()->GetType( nNumFmtIndex );
463         }
464         else
465             nNumFmtType = pDoc->GetFormatTable()->GetType( nNumFmtIndex );
466         bNumValid = sal_True;
467     }
468     nType = nNumFmtType;
469     nIndex = nNumFmtIndex;
470 }
471 
472 sal_Bool ScValueIterator::GetFirst(double& rValue, sal_uInt16& rErr)
473 {
474     nCol = nStartCol;
475     nRow = nStartRow;
476     nTab = nStartTab;
477 
478 //  nColRow = 0;
479     ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
480     pCol->Search( nRow, nColRow );
481 
482     nNumFormat = 0;                 // werden bei GetNumberFormat initialisiert
483     pAttrArray = 0;
484     nAttrEndRow = 0;
485 
486     return GetThis(rValue, rErr);
487 }
488 
489 /*  ist inline:
490 sal_Bool ScValueIterator::GetNext(double& rValue, sal_uInt16& rErr)
491 {
492     ++nRow;
493     return GetThis(rValue, rErr);
494 }
495 */
496 
497 // ============================================================================
498 
499 ScDBQueryDataIterator::DataAccess::DataAccess(const ScDBQueryDataIterator* pParent) :
500     mpParent(pParent)
501 {
502 }
503 
504 ScDBQueryDataIterator::DataAccess::~DataAccess()
505 {
506 }
507 
508 SCROW ScDBQueryDataIterator::GetRowByColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCSIZE nColRow)
509 {
510     ScColumn* pCol = &rDoc.pTab[nTab]->aCol[nCol];
511     return pCol->pItems[nColRow].nRow;
512 }
513 
514 ScBaseCell* ScDBQueryDataIterator::GetCellByColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCSIZE nColRow)
515 {
516     ScColumn* pCol = &rDoc.pTab[nTab]->aCol[nCol];
517     return pCol->pItems[nColRow].pCell;
518 }
519 
520 ScAttrArray* ScDBQueryDataIterator::GetAttrArrayByCol(ScDocument& rDoc, SCTAB nTab, SCCOL nCol)
521 {
522     ScColumn* pCol = &rDoc.pTab[nTab]->aCol[nCol];
523     return pCol->pAttrArray;
524 }
525 
526 bool ScDBQueryDataIterator::IsQueryValid(ScDocument& rDoc, const ScQueryParam& rParam, SCTAB nTab, SCROW nRow, ScBaseCell* pCell)
527 {
528     return rDoc.pTab[nTab]->ValidQuery(nRow, rParam, NULL, pCell);
529 }
530 
531 SCSIZE ScDBQueryDataIterator::SearchColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCROW nRow, SCCOL nCol)
532 {
533     ScColumn* pCol = &rDoc.pTab[nTab]->aCol[nCol];
534     SCSIZE nColRow;
535     pCol->Search(nRow, nColRow);
536     return nColRow;
537 }
538 
539 // ----------------------------------------------------------------------------
540 
541 ScDBQueryDataIterator::DataAccessInternal::DataAccessInternal(const ScDBQueryDataIterator* pParent, ScDBQueryParamInternal* pParam, ScDocument* pDoc) :
542     DataAccess(pParent),
543     mpParam(pParam),
544     mpDoc(pDoc),
545     bCalcAsShown( pDoc->GetDocOptions().IsCalcAsShown() )
546 {
547     nCol = mpParam->mnField;
548     nRow = mpParam->nRow1;
549     nTab = mpParam->nTab;
550 
551     nColRow = 0;                    // wird bei GetFirst initialisiert
552     SCSIZE i;
553     SCSIZE nCount = mpParam->GetEntryCount();
554     for (i=0; (i<nCount) && (mpParam->GetEntry(i).bDoQuery); i++)
555     {
556         ScQueryEntry& rEntry = mpParam->GetEntry(i);
557         sal_uInt32 nIndex = 0;
558         rEntry.bQueryByString =
559             !(mpDoc->GetFormatTable()->IsNumberFormat(*rEntry.pStr, nIndex, rEntry.nVal));
560     }
561     nNumFormat = 0;                 // werden bei GetNumberFormat initialisiert
562     pAttrArray = 0;
563     nAttrEndRow = 0;
564 }
565 
566 ScDBQueryDataIterator::DataAccessInternal::~DataAccessInternal()
567 {
568 }
569 
570 bool ScDBQueryDataIterator::DataAccessInternal::getCurrent(Value& rValue)
571 {
572     SCCOLROW nFirstQueryField = mpParam->GetEntry(0).nField;
573     for ( ;; )
574     {
575         if (nRow > mpParam->nRow2)
576         {
577             // Bottom of the range reached.  Bail out.
578             rValue.mnError = 0;
579             return false;
580         }
581 
582         SCSIZE nCellCount = mpDoc->GetCellCount(nTab, nCol);
583         SCROW nThisRow = ScDBQueryDataIterator::GetRowByColEntryIndex(*mpDoc, nTab, nCol, nColRow);
584         while ( (nColRow < nCellCount) && (nThisRow < nRow) )
585             nThisRow = ScDBQueryDataIterator::GetRowByColEntryIndex(*mpDoc, nTab, nCol, ++nColRow);
586 
587         if ( nColRow < nCellCount && nThisRow <= mpParam->nRow2 )
588         {
589             nRow = nThisRow;
590             ScBaseCell* pCell = NULL;
591             if (nCol == static_cast<SCCOL>(nFirstQueryField))
592                 pCell = ScDBQueryDataIterator::GetCellByColEntryIndex(*mpDoc, nTab, nCol, nColRow);
593 
594             if (ScDBQueryDataIterator::IsQueryValid(*mpDoc, *mpParam, nTab, nRow, pCell))
595             {
596                 // #i109812# get cell here if it wasn't done above
597                 if (nCol != static_cast<SCCOL>(nFirstQueryField))
598                     pCell = ScDBQueryDataIterator::GetCellByColEntryIndex(*mpDoc, nTab, nCol, nColRow);
599 
600                 switch (pCell ? pCell->GetCellType() : CELLTYPE_NONE)
601                 {
602                     case CELLTYPE_VALUE:
603                         {
604                             rValue.mfValue = ((ScValueCell*)pCell)->GetValue();
605                             rValue.mbIsNumber = true;
606                             if ( bCalcAsShown )
607                             {
608                                 const ScAttrArray* pNewAttrArray =
609                                     ScDBQueryDataIterator::GetAttrArrayByCol(*mpDoc, nTab, nCol);
610                                 lcl_IterGetNumberFormat( nNumFormat, pAttrArray,
611                                     nAttrEndRow, pNewAttrArray, nRow, mpDoc );
612                                 rValue.mfValue = mpDoc->RoundValueAsShown( rValue.mfValue, nNumFormat );
613                             }
614                             nNumFmtType = NUMBERFORMAT_NUMBER;
615                             nNumFmtIndex = 0;
616                             rValue.mnError = 0;
617                             return sal_True;        // gefunden
618                         }
619 //                        break;
620                     case CELLTYPE_FORMULA:
621                         {
622                             if (((ScFormulaCell*)pCell)->IsValue())
623                             {
624                                 rValue.mfValue = ((ScFormulaCell*)pCell)->GetValue();
625                                 rValue.mbIsNumber = true;
626                                 mpDoc->GetNumberFormatInfo( nNumFmtType,
627                                     nNumFmtIndex, ScAddress( nCol, nRow, nTab ),
628                                     pCell );
629                                 rValue.mnError = ((ScFormulaCell*)pCell)->GetErrCode();
630                                 return sal_True;    // gefunden
631                             }
632                             else
633                                 nRow++;
634                         }
635                         break;
636                     case CELLTYPE_STRING:
637                     case CELLTYPE_EDIT:
638                         if (mpParam->mbSkipString)
639                             ++nRow;
640                         else
641                         {
642                             rValue.maString = pCell->GetStringData();
643                             rValue.mfValue = 0.0;
644                             rValue.mnError = 0;
645                             rValue.mbIsNumber = false;
646                             return true;
647                         }
648                         break;
649                     default:
650                         nRow++;
651                         break;
652                 }
653             }
654             else
655                 nRow++;
656         }
657         else
658             nRow = mpParam->nRow2 + 1; // Naechste Spalte
659     }
660 // statement unreachable
661 //    return false;
662 }
663 
664 bool ScDBQueryDataIterator::DataAccessInternal::getFirst(Value& rValue)
665 {
666     if (mpParam->bHasHeader)
667         nRow++;
668 
669     nColRow = ScDBQueryDataIterator::SearchColEntryIndex(*mpDoc, nTab, nRow, nCol);
670     return getCurrent(rValue);
671 }
672 
673 bool ScDBQueryDataIterator::DataAccessInternal::getNext(Value& rValue)
674 {
675     ++nRow;
676     return getCurrent(rValue);
677 }
678 
679 // ----------------------------------------------------------------------------
680 
681 ScDBQueryDataIterator::DataAccessMatrix::DataAccessMatrix(const ScDBQueryDataIterator* pParent, ScDBQueryParamMatrix* pParam) :
682     DataAccess(pParent),
683     mpParam(pParam)
684 {
685     SCSIZE nC, nR;
686     mpParam->mpMatrix->GetDimensions(nC, nR);
687     mnRows = static_cast<SCROW>(nR);
688     mnCols = static_cast<SCCOL>(nC);
689 }
690 
691 ScDBQueryDataIterator::DataAccessMatrix::~DataAccessMatrix()
692 {
693 }
694 
695 bool ScDBQueryDataIterator::DataAccessMatrix::getCurrent(Value& rValue)
696 {
697     // Starting from row == mnCurRow, get the first row that satisfies all the
698     // query parameters.
699     for ( ;mnCurRow < mnRows; ++mnCurRow)
700     {
701         const ScMatrix& rMat = *mpParam->mpMatrix;
702         if (rMat.IsEmpty(mpParam->mnField, mnCurRow))
703             // Don't take empty values into account.
704             continue;
705 
706         bool bIsStrVal = rMat.IsString(mpParam->mnField, mnCurRow);
707         if (bIsStrVal && mpParam->mbSkipString)
708             continue;
709 
710         if (isValidQuery(mnCurRow, rMat))
711         {
712             rValue.maString = rMat.GetString(mpParam->mnField, mnCurRow);
713             rValue.mfValue = rMat.GetDouble(mpParam->mnField, mnCurRow);
714             rValue.mbIsNumber = !bIsStrVal;
715             rValue.mnError = 0;
716             return true;
717         }
718     }
719     return false;
720 }
721 
722 bool ScDBQueryDataIterator::DataAccessMatrix::getFirst(Value& rValue)
723 {
724     mnCurRow = mpParam->bHasHeader ? 1 : 0;
725     return getCurrent(rValue);
726 }
727 
728 bool ScDBQueryDataIterator::DataAccessMatrix::getNext(Value& rValue)
729 {
730     ++mnCurRow;
731     return getCurrent(rValue);
732 }
733 
734 namespace {
735 
736 bool lcl_isQueryByValue(const ScQueryEntry& rEntry, const ScMatrix& rMat, SCSIZE nCol, SCSIZE nRow)
737 {
738     if (rEntry.bQueryByString)
739         return false;
740 
741     if (!rMat.IsValueOrEmpty(nCol, nRow))
742         return false;
743 
744     return true;
745 }
746 
747 bool lcl_isQueryByString(const ScQueryEntry& rEntry, const ScMatrix& rMat, SCSIZE nCol, SCSIZE nRow)
748 {
749     switch (rEntry.eOp)
750     {
751         case SC_EQUAL:
752         case SC_NOT_EQUAL:
753         case SC_CONTAINS:
754         case SC_DOES_NOT_CONTAIN:
755         case SC_BEGINS_WITH:
756         case SC_ENDS_WITH:
757         case SC_DOES_NOT_BEGIN_WITH:
758         case SC_DOES_NOT_END_WITH:
759             return true;
760         default:
761             ;
762     }
763 
764     if (rEntry.bQueryByString && rMat.IsString(nCol, nRow))
765         return true;
766 
767     return false;
768 }
769 
770 }
771 
772 bool ScDBQueryDataIterator::DataAccessMatrix::isValidQuery(SCROW nRow, const ScMatrix& rMat) const
773 {
774     SCSIZE nEntryCount = mpParam->GetEntryCount();
775     vector<bool> aResults;
776     aResults.reserve(nEntryCount);
777 
778     const CollatorWrapper& rCollator =
779         mpParam->bCaseSens ? *ScGlobal::GetCaseCollator() : *ScGlobal::GetCollator();
780 
781     for (SCSIZE i = 0; i < nEntryCount; ++i)
782     {
783         const ScQueryEntry& rEntry = mpParam->GetEntry(i);
784         if (!rEntry.bDoQuery)
785             continue;
786 
787         switch (rEntry.eOp)
788         {
789             case SC_EQUAL:
790             case SC_LESS:
791             case SC_GREATER:
792             case SC_LESS_EQUAL:
793             case SC_GREATER_EQUAL:
794             case SC_NOT_EQUAL:
795                 break;
796             default:
797                 // Only the above operators are supported.
798                 continue;
799         }
800 
801         bool bValid = false;
802 
803         SCSIZE nField = static_cast<SCSIZE>(rEntry.nField);
804         if (lcl_isQueryByValue(rEntry, rMat, nField, nRow))
805         {
806             // By value
807             double fMatVal = rMat.GetDouble(nField, nRow);
808             bool bEqual = approxEqual(fMatVal, rEntry.nVal);
809             switch (rEntry.eOp)
810             {
811                 case SC_EQUAL:
812                     bValid = bEqual;
813                 break;
814                 case SC_LESS:
815                     bValid = (fMatVal < rEntry.nVal) && !bEqual;
816                 break;
817                 case SC_GREATER:
818                     bValid = (fMatVal > rEntry.nVal) && !bEqual;
819                 break;
820                 case SC_LESS_EQUAL:
821                     bValid = (fMatVal < rEntry.nVal) || bEqual;
822                 break;
823                 case SC_GREATER_EQUAL:
824                     bValid = (fMatVal > rEntry.nVal) || bEqual;
825                 break;
826                 case SC_NOT_EQUAL:
827                     bValid = !bEqual;
828                 break;
829                 default:
830                     ;
831             }
832         }
833         else if (lcl_isQueryByString(rEntry, rMat, nField, nRow))
834         {
835             // By string
836             do
837             {
838                 if (!rEntry.pStr)
839                     break;
840 
841                 // Equality check first.
842 
843                 OUString aMatStr = rMat.GetString(nField, nRow);
844                 lcl_toUpper(aMatStr);
845                 OUString aQueryStr = *rEntry.pStr;
846                 lcl_toUpper(aQueryStr);
847                 bool bDone = false;
848                 switch (rEntry.eOp)
849                 {
850                     case SC_EQUAL:
851                         bValid = aMatStr.equals(aQueryStr);
852                         bDone = true;
853                     break;
854                     case SC_NOT_EQUAL:
855                         bValid = !aMatStr.equals(aQueryStr);
856                         bDone = true;
857                     break;
858                     default:
859                         ;
860                 }
861 
862                 if (bDone)
863                     break;
864 
865                 // Unequality check using collator.
866 
867                 sal_Int32 nCompare = rCollator.compareString(aMatStr, aQueryStr);
868                 switch (rEntry.eOp)
869                 {
870                     case SC_LESS :
871                         bValid = (nCompare < 0);
872                     break;
873                     case SC_GREATER :
874                         bValid = (nCompare > 0);
875                     break;
876                     case SC_LESS_EQUAL :
877                         bValid = (nCompare <= 0);
878                     break;
879                     case SC_GREATER_EQUAL :
880                         bValid = (nCompare >= 0);
881                     break;
882                     default:
883                         ;
884                 }
885             }
886             while (false);
887         }
888         else if (mpParam->bMixedComparison)
889         {
890             // Not used at the moment.
891         }
892 
893         if (aResults.empty())
894             // First query entry.
895             aResults.push_back(bValid);
896         else if (rEntry.eConnect == SC_AND)
897         {
898             // For AND op, tuck the result into the last result value.
899             size_t n = aResults.size();
900             aResults[n-1] = aResults[n-1] && bValid;
901         }
902         else
903             // For OR op, store its own result.
904             aResults.push_back(bValid);
905     }
906 
907     // Row is valid as long as there is at least one result being true.
908     vector<bool>::const_iterator itr = aResults.begin(), itrEnd = aResults.end();
909     for (; itr != itrEnd; ++itr)
910         if (*itr)
911             return true;
912 
913     return false;
914 }
915 
916 // ----------------------------------------------------------------------------
917 
918 ScDBQueryDataIterator::Value::Value() :
919     mnError(0), mbIsNumber(true)
920 {
921     ::rtl::math::setNan(&mfValue);
922 }
923 
924 // ----------------------------------------------------------------------------
925 
926 ScDBQueryDataIterator::ScDBQueryDataIterator(ScDocument* pDocument, ScDBQueryParamBase* pParam) :
927     mpParam (pParam)
928 {
929     switch (mpParam->GetType())
930     {
931         case ScDBQueryParamBase::INTERNAL:
932         {
933             ScDBQueryParamInternal* p = static_cast<ScDBQueryParamInternal*>(pParam);
934             mpData.reset(new DataAccessInternal(this, p, pDocument));
935         }
936         break;
937         case ScDBQueryParamBase::MATRIX:
938         {
939             ScDBQueryParamMatrix* p = static_cast<ScDBQueryParamMatrix*>(pParam);
940             mpData.reset(new DataAccessMatrix(this, p));
941         }
942     }
943 }
944 
945 bool ScDBQueryDataIterator::GetFirst(Value& rValue)
946 {
947     return mpData->getFirst(rValue);
948 }
949 
950 bool ScDBQueryDataIterator::GetNext(Value& rValue)
951 {
952     return mpData->getNext(rValue);
953 }
954 
955 // ============================================================================
956 
957 ScCellIterator::ScCellIterator( ScDocument* pDocument,
958                                 SCCOL nSCol, SCROW nSRow, SCTAB nSTab,
959                                 SCCOL nECol, SCROW nERow, SCTAB nETab, sal_Bool bSTotal ) :
960     pDoc( pDocument ),
961     nStartCol( nSCol),
962     nStartRow( nSRow),
963     nStartTab( nSTab ),
964     nEndCol( nECol ),
965     nEndRow( nERow),
966     nEndTab( nETab ),
967     bSubTotal(bSTotal)
968 
969 {
970     PutInOrder( nStartCol, nEndCol);
971     PutInOrder( nStartRow, nEndRow);
972     PutInOrder( nStartTab, nEndTab );
973 
974     if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
975     if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
976     if (!ValidRow(nStartRow)) nStartRow = MAXROW;
977     if (!ValidRow(nEndRow)) nEndRow = MAXROW;
978     if (!ValidTab(nStartTab)) nStartTab = MAXTAB;
979     if (!ValidTab(nEndTab)) nEndTab = MAXTAB;
980 
981     while (nEndTab>0 && !pDoc->pTab[nEndTab])
982         --nEndTab;                                      // nur benutzte Tabellen
983     if (nStartTab>nEndTab)
984         nStartTab = nEndTab;
985 
986     nCol = nStartCol;
987     nRow = nStartRow;
988     nTab = nStartTab;
989     nColRow = 0;                    // wird bei GetFirst initialisiert
990 
991     if (!pDoc->pTab[nTab])
992     {
993         DBG_ERROR("Tabelle nicht gefunden");
994         nStartCol = nCol = MAXCOL+1;
995         nStartRow = nRow = MAXROW+1;
996         nStartTab = nTab = MAXTAB+1;    // -> Abbruch bei GetFirst
997     }
998 }
999 
1000 ScCellIterator::ScCellIterator
1001     ( ScDocument* pDocument, const ScRange& rRange, sal_Bool bSTotal ) :
1002     pDoc( pDocument ),
1003     nStartCol( rRange.aStart.Col() ),
1004     nStartRow( rRange.aStart.Row() ),
1005     nStartTab( rRange.aStart.Tab() ),
1006     nEndCol( rRange.aEnd.Col() ),
1007     nEndRow( rRange.aEnd.Row() ),
1008     nEndTab( rRange.aEnd.Tab() ),
1009     bSubTotal(bSTotal)
1010 
1011 {
1012     PutInOrder( nStartCol, nEndCol);
1013     PutInOrder( nStartRow, nEndRow);
1014     PutInOrder( nStartTab, nEndTab );
1015 
1016     if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
1017     if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
1018     if (!ValidRow(nStartRow)) nStartRow = MAXROW;
1019     if (!ValidRow(nEndRow)) nEndRow = MAXROW;
1020     if (!ValidTab(nStartTab)) nStartTab = MAXTAB;
1021     if (!ValidTab(nEndTab)) nEndTab = MAXTAB;
1022 
1023     while (nEndTab>0 && !pDoc->pTab[nEndTab])
1024         --nEndTab;                                      // nur benutzte Tabellen
1025     if (nStartTab>nEndTab)
1026         nStartTab = nEndTab;
1027 
1028     nCol = nStartCol;
1029     nRow = nStartRow;
1030     nTab = nStartTab;
1031     nColRow = 0;                    // wird bei GetFirst initialisiert
1032 
1033     if (!pDoc->pTab[nTab])
1034     {
1035         DBG_ERROR("Tabelle nicht gefunden");
1036         nStartCol = nCol = MAXCOL+1;
1037         nStartRow = nRow = MAXROW+1;
1038         nStartTab = nTab = MAXTAB+1;    // -> Abbruch bei GetFirst
1039     }
1040 }
1041 
1042 ScBaseCell* ScCellIterator::GetThis()
1043 {
1044     ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
1045     for ( ;; )
1046     {
1047         if ( nRow > nEndRow )
1048         {
1049             nRow = nStartRow;
1050             do
1051             {
1052                 nCol++;
1053                 if ( nCol > nEndCol )
1054                 {
1055                     nCol = nStartCol;
1056                     nTab++;
1057                     if ( nTab > nEndTab )
1058                         return NULL;                // Ende und Aus
1059                 }
1060                 pCol = &(pDoc->pTab[nTab])->aCol[nCol];
1061             } while ( pCol->nCount == 0 );
1062             pCol->Search( nRow, nColRow );
1063         }
1064 
1065         while ( (nColRow < pCol->nCount) && (pCol->pItems[nColRow].nRow < nRow) )
1066             nColRow++;
1067 
1068         if ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow <= nEndRow )
1069         {
1070             nRow = pCol->pItems[nColRow].nRow;
1071             if ( !bSubTotal || !pDoc->pTab[nTab]->RowFiltered( nRow ) )
1072             {
1073                 ScBaseCell* pCell = pCol->pItems[nColRow].pCell;
1074 
1075                 if ( bSubTotal && pCell->GetCellType() == CELLTYPE_FORMULA
1076                                 && ((ScFormulaCell*)pCell)->IsSubTotal() )
1077                     nRow++;             // Sub-Total-Zeilen nicht
1078                 else
1079                     return pCell;       // gefunden
1080             }
1081             else
1082                 nRow++;
1083         }
1084         else
1085             nRow = nEndRow + 1; // Naechste Spalte
1086     }
1087 }
1088 
1089 ScBaseCell* ScCellIterator::GetFirst()
1090 {
1091     if ( !ValidTab(nTab) )
1092         return NULL;
1093     nCol = nStartCol;
1094     nRow = nStartRow;
1095     nTab = nStartTab;
1096 //  nColRow = 0;
1097     ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
1098     pCol->Search( nRow, nColRow );
1099     return GetThis();
1100 }
1101 
1102 ScBaseCell* ScCellIterator::GetNext()
1103 {
1104     ++nRow;
1105     return GetThis();
1106 }
1107 
1108 //-------------------------------------------------------------------------------
1109 
1110 ScQueryCellIterator::ScQueryCellIterator(ScDocument* pDocument, SCTAB nTable,
1111              const ScQueryParam& rParam, sal_Bool bMod ) :
1112     aParam (rParam),
1113     pDoc( pDocument ),
1114     nTab( nTable),
1115     nStopOnMismatch( nStopOnMismatchDisabled ),
1116     nTestEqualCondition( nTestEqualConditionDisabled ),
1117     bAdvanceQuery( sal_False ),
1118     bIgnoreMismatchOnLeadingStrings( sal_False )
1119 {
1120     nCol = aParam.nCol1;
1121     nRow = aParam.nRow1;
1122     nColRow = 0;                    // wird bei GetFirst initialisiert
1123     SCSIZE i;
1124     if (bMod)                               // sonst schon eingetragen
1125     {
1126         for (i=0; (i<MAXQUERY) && (aParam.GetEntry(i).bDoQuery); i++)
1127         {
1128             ScQueryEntry& rEntry = aParam.GetEntry(i);
1129             sal_uInt32 nIndex = 0;
1130             rEntry.bQueryByString =
1131                      !(pDoc->GetFormatTable()->IsNumberFormat(*rEntry.pStr,
1132                                                               nIndex, rEntry.nVal));
1133         }
1134     }
1135     nNumFormat = 0;                 // werden bei GetNumberFormat initialisiert
1136     pAttrArray = 0;
1137     nAttrEndRow = 0;
1138 }
1139 
1140 ScBaseCell* ScQueryCellIterator::GetThis()
1141 {
1142     ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
1143     const ScQueryEntry& rEntry = aParam.GetEntry(0);
1144     SCCOLROW nFirstQueryField = rEntry.nField;
1145     bool bAllStringIgnore = bIgnoreMismatchOnLeadingStrings &&
1146         !rEntry.bQueryByString;
1147     bool bFirstStringIgnore = bIgnoreMismatchOnLeadingStrings &&
1148         !aParam.bHasHeader && rEntry.bQueryByString &&
1149         ((aParam.bByRow && nRow == aParam.nRow1) ||
1150          (!aParam.bByRow && nCol == aParam.nCol1));
1151     for ( ;; )
1152     {
1153         if ( nRow > aParam.nRow2 )
1154         {
1155             nRow = aParam.nRow1;
1156             if (aParam.bHasHeader && aParam.bByRow)
1157                 nRow++;
1158             do
1159             {
1160                 if ( ++nCol > aParam.nCol2 )
1161                     return NULL;                // Ende und Aus
1162                 if ( bAdvanceQuery )
1163                 {
1164                     AdvanceQueryParamEntryField();
1165                     nFirstQueryField = rEntry.nField;
1166                 }
1167                 pCol = &(pDoc->pTab[nTab])->aCol[nCol];
1168             } while ( pCol->nCount == 0 );
1169             pCol->Search( nRow, nColRow );
1170             bFirstStringIgnore = bIgnoreMismatchOnLeadingStrings &&
1171                 !aParam.bHasHeader && rEntry.bQueryByString &&
1172                 aParam.bByRow;
1173         }
1174 
1175         while ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow < nRow )
1176             nColRow++;
1177 
1178         if ( nColRow < pCol->nCount &&
1179                 (nRow = pCol->pItems[nColRow].nRow) <= aParam.nRow2 )
1180         {
1181             ScBaseCell* pCell = pCol->pItems[nColRow].pCell;
1182             if ( pCell->GetCellType() == CELLTYPE_NOTE )
1183                 ++nRow;
1184             else if (bAllStringIgnore && pCell->HasStringData())
1185                 ++nRow;
1186             else
1187             {
1188                 sal_Bool bTestEqualCondition;
1189                 if ( (pDoc->pTab[nTab])->ValidQuery( nRow, aParam, NULL,
1190                         (nCol == static_cast<SCCOL>(nFirstQueryField) ? pCell : NULL),
1191                         (nTestEqualCondition ? &bTestEqualCondition : NULL) ) )
1192                 {
1193                     if ( nTestEqualCondition && bTestEqualCondition )
1194                         nTestEqualCondition |= nTestEqualConditionMatched;
1195                     return pCell;     // found
1196                 }
1197                 else if ( nStopOnMismatch )
1198                 {
1199                     // Yes, even a mismatch may have a fulfilled equal
1200                     // condition if regular expressions were involved and
1201                     // SC_LESS_EQUAL or SC_GREATER_EQUAL were queried.
1202                     if ( nTestEqualCondition && bTestEqualCondition )
1203                     {
1204                         nTestEqualCondition |= nTestEqualConditionMatched;
1205                         nStopOnMismatch |= nStopOnMismatchOccured;
1206                         return NULL;
1207                     }
1208                     bool bStop;
1209                     if (bFirstStringIgnore)
1210                     {
1211                         if (pCell->HasStringData())
1212                         {
1213                             ++nRow;
1214                             bStop = false;
1215                         }
1216                         else
1217                             bStop = true;
1218                     }
1219                     else
1220                         bStop = true;
1221                     if (bStop)
1222                     {
1223                         nStopOnMismatch |= nStopOnMismatchOccured;
1224                         return NULL;
1225                     }
1226                 }
1227                 else
1228                     nRow++;
1229             }
1230         }
1231         else
1232             nRow = aParam.nRow2 + 1; // Naechste Spalte
1233         bFirstStringIgnore = false;
1234     }
1235 }
1236 
1237 ScBaseCell* ScQueryCellIterator::GetFirst()
1238 {
1239     nCol = aParam.nCol1;
1240     nRow = aParam.nRow1;
1241     if (aParam.bHasHeader)
1242         nRow++;
1243 //  nColRow = 0;
1244     ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
1245     pCol->Search( nRow, nColRow );
1246     return GetThis();
1247 }
1248 
1249 ScBaseCell* ScQueryCellIterator::GetNext()
1250 {
1251     ++nRow;
1252     if ( nStopOnMismatch )
1253         nStopOnMismatch = nStopOnMismatchEnabled;
1254     if ( nTestEqualCondition )
1255         nTestEqualCondition = nTestEqualConditionEnabled;
1256     return GetThis();
1257 }
1258 
1259 void ScQueryCellIterator::AdvanceQueryParamEntryField()
1260 {
1261     SCSIZE nEntries = aParam.GetEntryCount();
1262     for ( SCSIZE j = 0; j < nEntries; j++  )
1263     {
1264         ScQueryEntry& rEntry = aParam.GetEntry( j );
1265         if ( rEntry.bDoQuery )
1266         {
1267             if ( rEntry.nField < MAXCOL )
1268                 rEntry.nField++;
1269             else
1270             {
1271                 DBG_ERRORFILE( "AdvanceQueryParamEntryField: ++rEntry.nField > MAXCOL" );
1272             }
1273         }
1274         else
1275             break;  // for
1276     }
1277 }
1278 
1279 
1280 sal_Bool ScQueryCellIterator::FindEqualOrSortedLastInRange( SCCOL& nFoundCol,
1281         SCROW& nFoundRow, sal_Bool bSearchForEqualAfterMismatch,
1282         sal_Bool bIgnoreMismatchOnLeadingStringsP )
1283 {
1284     nFoundCol = MAXCOL+1;
1285     nFoundRow = MAXROW+1;
1286     SetStopOnMismatch( sal_True );      // assume sorted keys
1287     SetTestEqualCondition( sal_True );
1288     bIgnoreMismatchOnLeadingStrings = bIgnoreMismatchOnLeadingStringsP;
1289     bool bRegExp = aParam.bRegExp && aParam.GetEntry(0).bQueryByString;
1290     bool bBinary = !bRegExp && aParam.bByRow && (aParam.GetEntry(0).eOp ==
1291             SC_LESS_EQUAL || aParam.GetEntry(0).eOp == SC_GREATER_EQUAL);
1292     if (bBinary ? (BinarySearch() ? GetThis() : 0) : GetFirst())
1293     {
1294         // First equal entry or last smaller than (greater than) entry.
1295         SCSIZE nColRowSave;
1296         ScBaseCell* pNext = 0;
1297         do
1298         {
1299             nFoundCol = GetCol();
1300             nFoundRow = GetRow();
1301             nColRowSave = nColRow;
1302         } while ( !IsEqualConditionFulfilled() && (pNext = GetNext()) != NULL );
1303         // There may be no pNext but equal condition fulfilled if regular
1304         // expressions are involved. Keep the found entry and proceed.
1305         if (!pNext && !IsEqualConditionFulfilled())
1306         {
1307             // Step back to last in range and adjust position markers for
1308             // GetNumberFormat() or similar.
1309             nCol = nFoundCol;
1310             nRow = nFoundRow;
1311             nColRow = nColRowSave;
1312         }
1313     }
1314     if ( IsEqualConditionFulfilled() )
1315     {
1316         // Position on last equal entry.
1317         SCSIZE nEntries = aParam.GetEntryCount();
1318         for ( SCSIZE j = 0; j < nEntries; j++  )
1319         {
1320             ScQueryEntry& rEntry = aParam.GetEntry( j );
1321             if ( rEntry.bDoQuery )
1322             {
1323                 switch ( rEntry.eOp )
1324                 {
1325                     case SC_LESS_EQUAL :
1326                     case SC_GREATER_EQUAL :
1327                         rEntry.eOp = SC_EQUAL;
1328                     break;
1329                     default:
1330                     {
1331                         // added to avoid warnings
1332                     }
1333                 }
1334             }
1335             else
1336                 break;  // for
1337         }
1338         SCSIZE nColRowSave;
1339         bIgnoreMismatchOnLeadingStrings = sal_False;
1340         SetTestEqualCondition( sal_False );
1341         do
1342         {
1343             nFoundCol = GetCol();
1344             nFoundRow = GetRow();
1345             nColRowSave = nColRow;
1346         } while (GetNext());
1347         // Step back conditions same as above
1348         nCol = nFoundCol;
1349         nRow = nFoundRow;
1350         nColRow = nColRowSave;
1351         return sal_True;
1352     }
1353     if ( (bSearchForEqualAfterMismatch || aParam.bRegExp) &&
1354             StoppedOnMismatch() )
1355     {
1356         // Assume found entry to be the last value less than respectively
1357         // greater than the query. But keep on searching for an equal match.
1358         SCSIZE nEntries = aParam.GetEntryCount();
1359         for ( SCSIZE j = 0; j < nEntries; j++  )
1360         {
1361             ScQueryEntry& rEntry = aParam.GetEntry( j );
1362             if ( rEntry.bDoQuery )
1363             {
1364                 switch ( rEntry.eOp )
1365                 {
1366                     case SC_LESS_EQUAL :
1367                     case SC_GREATER_EQUAL :
1368                         rEntry.eOp = SC_EQUAL;
1369                     break;
1370                     default:
1371                     {
1372                         // added to avoid warnings
1373                     }
1374                 }
1375             }
1376             else
1377                 break;  // for
1378         }
1379         SetStopOnMismatch( sal_False );
1380         SetTestEqualCondition( sal_False );
1381         if (GetNext())
1382         {
1383             // Last of a consecutive area, avoid searching the entire parameter
1384             // range as it is a real performance bottleneck in case of regular
1385             // expressions.
1386             SCSIZE nColRowSave;
1387             do
1388             {
1389                 nFoundCol = GetCol();
1390                 nFoundRow = GetRow();
1391                 nColRowSave = nColRow;
1392                 SetStopOnMismatch( sal_True );
1393             } while (GetNext());
1394             nCol = nFoundCol;
1395             nRow = nFoundRow;
1396             nColRow = nColRowSave;
1397         }
1398     }
1399     return (nFoundCol <= MAXCOL) && (nFoundRow <= MAXROW);
1400 }
1401 
1402 
1403 ScBaseCell* ScQueryCellIterator::BinarySearch()
1404 {
1405     nCol = aParam.nCol1;
1406     ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
1407     if (!pCol->nCount)
1408         return 0;
1409 
1410     ScBaseCell* pCell;
1411     SCSIZE nHi, nLo;
1412     CollatorWrapper* pCollator = (aParam.bCaseSens ? ScGlobal::GetCaseCollator() :
1413         ScGlobal::GetCollator());
1414     SvNumberFormatter& rFormatter = *(pDoc->GetFormatTable());
1415     const ScQueryEntry& rEntry = aParam.GetEntry(0);
1416     bool bLessEqual = rEntry.eOp == SC_LESS_EQUAL;
1417     bool bByString = rEntry.bQueryByString;
1418     bool bAllStringIgnore = bIgnoreMismatchOnLeadingStrings && !bByString;
1419     bool bFirstStringIgnore = bIgnoreMismatchOnLeadingStrings &&
1420         !aParam.bHasHeader && bByString;
1421 
1422     nRow = aParam.nRow1;
1423     if (aParam.bHasHeader)
1424         nRow++;
1425     const ColEntry* pItems = pCol->pItems;
1426     if (pCol->Search( nRow, nLo ) && bFirstStringIgnore &&
1427             pItems[nLo].pCell->HasStringData())
1428     {
1429         String aCellStr;
1430         sal_uLong nFormat = pCol->GetNumberFormat( pItems[nLo].nRow);
1431         ScCellFormat::GetInputString( pItems[nLo].pCell, nFormat, aCellStr,
1432                 rFormatter);
1433         sal_Int32 nTmp = pCollator->compareString( aCellStr, *rEntry.pStr);
1434         if ((rEntry.eOp == SC_LESS_EQUAL && nTmp > 0) ||
1435                 (rEntry.eOp == SC_GREATER_EQUAL && nTmp < 0) ||
1436                 (rEntry.eOp == SC_EQUAL && nTmp != 0))
1437             ++nLo;
1438     }
1439     if (!pCol->Search( aParam.nRow2, nHi ) && nHi>0)
1440         --nHi;
1441     while (bAllStringIgnore && nLo <= nHi && nLo < pCol->nCount &&
1442             pItems[nLo].pCell->HasStringData())
1443         ++nLo;
1444 
1445     // Bookkeeping values for breaking up the binary search in case the data
1446     // range isn't strictly sorted.
1447     SCSIZE nLastInRange = nLo;
1448     SCSIZE nFirstLastInRange = nLastInRange;
1449     double fLastInRangeValue = bLessEqual ?
1450         -(::std::numeric_limits<double>::max()) :
1451             ::std::numeric_limits<double>::max();
1452     String aLastInRangeString;
1453     if (!bLessEqual)
1454         aLastInRangeString.Assign( sal_Unicode(0xFFFF));
1455     if (nLastInRange < pCol->nCount)
1456     {
1457         pCell = pItems[nLastInRange].pCell;
1458         if (pCell->HasStringData())
1459         {
1460             sal_uLong nFormat = pCol->GetNumberFormat( pItems[nLastInRange].nRow);
1461             ScCellFormat::GetInputString( pCell, nFormat, aLastInRangeString,
1462                     rFormatter);
1463         }
1464         else
1465         {
1466             switch ( pCell->GetCellType() )
1467             {
1468                 case CELLTYPE_VALUE :
1469                     fLastInRangeValue =
1470                         static_cast<ScValueCell*>(pCell)->GetValue();
1471                     break;
1472                 case CELLTYPE_FORMULA :
1473                     fLastInRangeValue =
1474                         static_cast<ScFormulaCell*>(pCell)->GetValue();
1475                     break;
1476                 default:
1477                 {
1478                     // added to avoid warnings
1479                 }
1480             }
1481         }
1482     }
1483 
1484     sal_Int32 nRes = 0;
1485     bool bFound = false;
1486     bool bDone = false;
1487     while (nLo <= nHi && !bDone)
1488     {
1489         SCSIZE nMid = (nLo+nHi)/2;
1490         SCSIZE i = nMid;
1491         while (i <= nHi && pItems[i].pCell->GetCellType() == CELLTYPE_NOTE)
1492             ++i;
1493         if (i > nHi)
1494         {
1495             if (nMid > 0)
1496                 nHi = nMid - 1;
1497             else
1498                 bDone = true;
1499             continue;   // while
1500         }
1501         sal_Bool bStr = pItems[i].pCell->HasStringData();
1502         nRes = 0;
1503         // compares are content<query:-1, content>query:1
1504         // Cell value comparison similar to ScTable::ValidQuery()
1505         if (!bStr && !bByString)
1506         {
1507             double nCellVal;
1508             pCell = pItems[i].pCell;
1509             switch ( pCell->GetCellType() )
1510             {
1511                 case CELLTYPE_VALUE :
1512                     nCellVal = static_cast<ScValueCell*>(pCell)->GetValue();
1513                     break;
1514                 case CELLTYPE_FORMULA :
1515                     nCellVal = static_cast<ScFormulaCell*>(pCell)->GetValue();
1516                     break;
1517                 default:
1518                     nCellVal = 0.0;
1519             }
1520             if ((nCellVal < rEntry.nVal) && !::rtl::math::approxEqual(
1521                         nCellVal, rEntry.nVal))
1522             {
1523                 nRes = -1;
1524                 if (bLessEqual)
1525                 {
1526                     if (fLastInRangeValue < nCellVal)
1527                     {
1528                         fLastInRangeValue = nCellVal;
1529                         nLastInRange = i;
1530                     }
1531                     else if (fLastInRangeValue > nCellVal)
1532                     {
1533                         // not strictly sorted, continue with GetThis()
1534                         nLastInRange = nFirstLastInRange;
1535                         bDone = true;
1536                     }
1537                 }
1538             }
1539             else if ((nCellVal > rEntry.nVal) && !::rtl::math::approxEqual(
1540                         nCellVal, rEntry.nVal))
1541             {
1542                 nRes = 1;
1543                 if (!bLessEqual)
1544                 {
1545                     if (fLastInRangeValue > nCellVal)
1546                     {
1547                         fLastInRangeValue = nCellVal;
1548                         nLastInRange = i;
1549                     }
1550                     else if (fLastInRangeValue < nCellVal)
1551                     {
1552                         // not strictly sorted, continue with GetThis()
1553                         nLastInRange = nFirstLastInRange;
1554                         bDone = true;
1555                     }
1556                 }
1557             }
1558         }
1559         else if (bStr && bByString)
1560         {
1561             String aCellStr;
1562             sal_uLong nFormat = pCol->GetNumberFormat( pItems[i].nRow);
1563             ScCellFormat::GetInputString( pItems[i].pCell, nFormat, aCellStr,
1564                     rFormatter);
1565             nRes = pCollator->compareString( aCellStr, *rEntry.pStr);
1566             if (nRes < 0 && bLessEqual)
1567             {
1568                 sal_Int32 nTmp = pCollator->compareString( aLastInRangeString,
1569                         aCellStr);
1570                 if (nTmp < 0)
1571                 {
1572                     aLastInRangeString = aCellStr;
1573                     nLastInRange = i;
1574                 }
1575                 else if (nTmp > 0)
1576                 {
1577                     // not strictly sorted, continue with GetThis()
1578                     nLastInRange = nFirstLastInRange;
1579                     bDone = true;
1580                 }
1581             }
1582             else if (nRes > 0 && !bLessEqual)
1583             {
1584                 sal_Int32 nTmp = pCollator->compareString( aLastInRangeString,
1585                         aCellStr);
1586                 if (nTmp > 0)
1587                 {
1588                     aLastInRangeString = aCellStr;
1589                     nLastInRange = i;
1590                 }
1591                 else if (nTmp < 0)
1592                 {
1593                     // not strictly sorted, continue with GetThis()
1594                     nLastInRange = nFirstLastInRange;
1595                     bDone = true;
1596                 }
1597             }
1598         }
1599         else if (!bStr && bByString)
1600         {
1601             nRes = -1;  // numeric < string
1602             if (bLessEqual)
1603                 nLastInRange = i;
1604         }
1605         else // if (bStr && !bByString)
1606         {
1607             nRes = 1;   // string > numeric
1608             if (!bLessEqual)
1609                 nLastInRange = i;
1610         }
1611         if (nRes < 0)
1612         {
1613             if (bLessEqual)
1614                 nLo = nMid + 1;
1615             else    // assumed to be SC_GREATER_EQUAL
1616             {
1617                 if (nMid > 0)
1618                     nHi = nMid - 1;
1619                 else
1620                     bDone = true;
1621             }
1622         }
1623         else if (nRes > 0)
1624         {
1625             if (bLessEqual)
1626             {
1627                 if (nMid > 0)
1628                     nHi = nMid - 1;
1629                 else
1630                     bDone = true;
1631             }
1632             else    // assumed to be SC_GREATER_EQUAL
1633                 nLo = nMid + 1;
1634         }
1635         else
1636         {
1637             nLo = i;
1638             bDone = bFound = true;
1639         }
1640     }
1641     if (!bFound)
1642     {
1643         // If all hits didn't result in a moving limit there's something
1644         // strange, e.g. data range not properly sorted, or only identical
1645         // values encountered, which doesn't mean there aren't any others in
1646         // between.. leave it to GetThis(). The condition for this would be
1647         // if (nLastInRange == nFirstLastInRange) nLo = nFirstLastInRange;
1648         // Else, in case no exact match was found, we step back for a
1649         // subsequent GetThis() to find the last in range. Effectively this is
1650         // --nLo with nLastInRange == nLo-1. Both conditions combined yield:
1651         nLo = nLastInRange;
1652     }
1653     if (nLo < pCol->nCount && pCol->pItems[nLo].nRow <= aParam.nRow2)
1654     {
1655         nRow = pItems[nLo].nRow;
1656         pCell = pItems[nLo].pCell;
1657         nColRow = nLo;
1658     }
1659     else
1660     {
1661         nRow = aParam.nRow2 + 1;
1662         pCell = 0;
1663         nColRow = pCol->nCount - 1;
1664     }
1665     return pCell;
1666 }
1667 
1668 
1669 //-------------------------------------------------------------------------------
1670 
1671 ScHorizontalCellIterator::ScHorizontalCellIterator(ScDocument* pDocument, SCTAB nTable,
1672                                     SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) :
1673     pDoc( pDocument ),
1674     nTab( nTable ),
1675     nStartCol( nCol1 ),
1676     nEndCol( nCol2 ),
1677     nStartRow( nRow1 ),
1678     nEndRow( nRow2 ),
1679     nCol( nCol1 ),
1680     nRow( nRow1 ),
1681     bMore( sal_True )
1682 {
1683 
1684     pNextRows = new SCROW[ nCol2-nCol1+1 ];
1685     pNextIndices = new SCSIZE[ nCol2-nCol1+1 ];
1686 
1687     SetTab( nTab );
1688 }
1689 
1690 ScHorizontalCellIterator::~ScHorizontalCellIterator()
1691 {
1692     delete [] pNextRows;
1693     delete [] pNextIndices;
1694 }
1695 
1696 void ScHorizontalCellIterator::SetTab( SCTAB nTabP )
1697 {
1698     nTab = nTabP;
1699     nRow = nStartRow;
1700     nCol = nStartCol;
1701     bMore = sal_True;
1702 
1703     for (SCCOL i=nStartCol; i<=nEndCol; i++)
1704     {
1705         ScColumn* pCol = &pDoc->pTab[nTab]->aCol[i];
1706 
1707         SCSIZE nIndex;
1708         pCol->Search( nStartRow, nIndex );
1709         if ( nIndex < pCol->nCount )
1710         {
1711             pNextRows[i-nStartCol] = pCol->pItems[nIndex].nRow;
1712             pNextIndices[i-nStartCol] = nIndex;
1713         }
1714         else
1715         {
1716             pNextRows[i-nStartCol] = MAXROWCOUNT;       // nichts gefunden
1717             pNextIndices[i-nStartCol] = MAXROWCOUNT;
1718         }
1719     }
1720 
1721     if (pNextRows[0] != nStartRow)
1722         Advance();
1723 }
1724 
1725 ScBaseCell* ScHorizontalCellIterator::GetNext( SCCOL& rCol, SCROW& rRow )
1726 {
1727     if ( bMore )
1728     {
1729         rCol = nCol;
1730         rRow = nRow;
1731 
1732         ScColumn* pCol = &pDoc->pTab[nTab]->aCol[nCol];
1733         SCSIZE nIndex = pNextIndices[nCol-nStartCol];
1734         DBG_ASSERT( nIndex < pCol->nCount, "ScHorizontalCellIterator::GetNext: nIndex out of range" );
1735         ScBaseCell* pCell = pCol->pItems[nIndex].pCell;
1736         if ( ++nIndex < pCol->nCount )
1737         {
1738             pNextRows[nCol-nStartCol] = pCol->pItems[nIndex].nRow;
1739             pNextIndices[nCol-nStartCol] = nIndex;
1740         }
1741         else
1742         {
1743             pNextRows[nCol-nStartCol] = MAXROWCOUNT;        // nichts gefunden
1744             pNextIndices[nCol-nStartCol] = MAXROWCOUNT;
1745         }
1746 
1747         Advance();
1748         return pCell;
1749     }
1750     else
1751         return NULL;
1752 }
1753 
1754 sal_Bool ScHorizontalCellIterator::ReturnNext( SCCOL& rCol, SCROW& rRow )
1755 {
1756     rCol = nCol;
1757     rRow = nRow;
1758     return bMore;
1759 }
1760 
1761 void ScHorizontalCellIterator::Advance()
1762 {
1763     sal_Bool bFound = sal_False;
1764     SCCOL i;
1765 
1766     for (i=nCol+1; i<=nEndCol && !bFound; i++)
1767         if (pNextRows[i-nStartCol] == nRow)
1768         {
1769             nCol = i;
1770             bFound = sal_True;
1771         }
1772 
1773     if (!bFound)
1774     {
1775         SCROW nMinRow = MAXROW+1;
1776         for (i=nStartCol; i<=nEndCol; i++)
1777             if (pNextRows[i-nStartCol] < nMinRow)
1778             {
1779                 nCol = i;
1780                 nMinRow = pNextRows[i-nStartCol];
1781             }
1782 
1783         if (nMinRow <= nEndRow)
1784         {
1785             nRow = nMinRow;
1786             bFound = sal_True;
1787         }
1788     }
1789 
1790     if ( !bFound )
1791         bMore = sal_False;
1792 }
1793 
1794 //------------------------------------------------------------------------
1795 
1796 ScHorizontalValueIterator::ScHorizontalValueIterator( ScDocument* pDocument,
1797         const ScRange& rRange, bool bSTotal, bool bTextZero ) :
1798     pDoc( pDocument ),
1799     nNumFmtIndex(0),
1800     nEndTab( rRange.aEnd.Tab() ),
1801     nNumFmtType( NUMBERFORMAT_UNDEFINED ),
1802     bNumValid( false ),
1803     bSubTotal( bSTotal ),
1804     bCalcAsShown( pDocument->GetDocOptions().IsCalcAsShown() ),
1805     bTextAsZero( bTextZero )
1806 {
1807     SCCOL nStartCol = rRange.aStart.Col();
1808     SCROW nStartRow = rRange.aStart.Row();
1809     SCTAB nStartTab = rRange.aStart.Tab();
1810     SCCOL nEndCol = rRange.aEnd.Col();
1811     SCROW nEndRow = rRange.aEnd.Row();
1812     PutInOrder( nStartCol, nEndCol);
1813     PutInOrder( nStartRow, nEndRow);
1814     PutInOrder( nStartTab, nEndTab );
1815 
1816     if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
1817     if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
1818     if (!ValidRow(nStartRow)) nStartRow = MAXROW;
1819     if (!ValidRow(nEndRow)) nEndRow = MAXROW;
1820     if (!ValidTab(nStartTab)) nStartTab = MAXTAB;
1821     if (!ValidTab(nEndTab)) nEndTab = MAXTAB;
1822 
1823     nCurCol = nStartCol;
1824     nCurRow = nStartRow;
1825     nCurTab = nStartTab;
1826 
1827     nNumFormat = 0;                 // will be initialized in GetNumberFormat()
1828     pAttrArray = 0;
1829     nAttrEndRow = 0;
1830 
1831     pCellIter = new ScHorizontalCellIterator( pDoc, nStartTab, nStartCol,
1832             nStartRow, nEndCol, nEndRow );
1833 }
1834 
1835 ScHorizontalValueIterator::~ScHorizontalValueIterator()
1836 {
1837     delete pCellIter;
1838 }
1839 
1840 bool ScHorizontalValueIterator::GetNext( double& rValue, sal_uInt16& rErr )
1841 {
1842     bool bFound = false;
1843     while ( !bFound )
1844     {
1845         ScBaseCell* pCell = pCellIter->GetNext( nCurCol, nCurRow );
1846         while ( !pCell )
1847         {
1848             if ( nCurTab < nEndTab )
1849             {
1850                 pCellIter->SetTab( ++nCurTab);
1851                 pCell = pCellIter->GetNext( nCurCol, nCurRow );
1852             }
1853             else
1854                 return false;
1855         }
1856         if ( !bSubTotal || !pDoc->pTab[nCurTab]->RowFiltered( nCurRow ) )
1857         {
1858             switch (pCell->GetCellType())
1859             {
1860                 case CELLTYPE_VALUE:
1861                     {
1862                         bNumValid = false;
1863                         rValue = ((ScValueCell*)pCell)->GetValue();
1864                         rErr = 0;
1865                         if ( bCalcAsShown )
1866                         {
1867                             ScColumn* pCol = &pDoc->pTab[nCurTab]->aCol[nCurCol];
1868                             lcl_IterGetNumberFormat( nNumFormat, pAttrArray,
1869                                     nAttrEndRow, pCol->pAttrArray, nCurRow, pDoc );
1870                             rValue = pDoc->RoundValueAsShown( rValue, nNumFormat );
1871                         }
1872                         bFound = true;
1873                     }
1874                     break;
1875                 case CELLTYPE_FORMULA:
1876                     {
1877                         if (!bSubTotal || !((ScFormulaCell*)pCell)->IsSubTotal())
1878                         {
1879                             rErr = ((ScFormulaCell*)pCell)->GetErrCode();
1880                             if ( rErr || ((ScFormulaCell*)pCell)->IsValue() )
1881                             {
1882                                 rValue = ((ScFormulaCell*)pCell)->GetValue();
1883                                 bNumValid = false;
1884                                 bFound = true;
1885                             }
1886                             else if ( bTextAsZero )
1887                             {
1888                                 rValue = 0.0;
1889                                 bNumValid = false;
1890                                 bFound = true;
1891                             }
1892                         }
1893                     }
1894                     break;
1895                 case CELLTYPE_STRING :
1896                 case CELLTYPE_EDIT :
1897                     {
1898                         if ( bTextAsZero )
1899                         {
1900                             rErr = 0;
1901                             rValue = 0.0;
1902                             nNumFmtType = NUMBERFORMAT_NUMBER;
1903                             nNumFmtIndex = 0;
1904                             bNumValid = true;
1905                             bFound = true;
1906                         }
1907                     }
1908                     break;
1909                 default:
1910                     ;   // nothing
1911             }
1912         }
1913     }
1914     return bFound;
1915 }
1916 
1917 void ScHorizontalValueIterator::GetCurNumFmtInfo( short& nType, sal_uLong& nIndex )
1918 {
1919     if (!bNumValid)
1920     {
1921         const ScColumn* pCol = &(pDoc->pTab[nCurTab])->aCol[nCurCol];
1922         nNumFmtIndex = pCol->GetNumberFormat( nCurRow );
1923         if ( (nNumFmtIndex % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
1924         {
1925             const ScBaseCell* pCell;
1926             SCSIZE nCurIndex;
1927             if ( pCol->Search( nCurRow, nCurIndex ) )
1928                 pCell = pCol->pItems[nCurIndex].pCell;
1929             else
1930                 pCell = NULL;
1931             if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
1932                 ((const ScFormulaCell*)pCell)->GetFormatInfo( nNumFmtType, nNumFmtIndex );
1933             else
1934                 nNumFmtType = pDoc->GetFormatTable()->GetType( nNumFmtIndex );
1935         }
1936         else
1937             nNumFmtType = pDoc->GetFormatTable()->GetType( nNumFmtIndex );
1938         bNumValid = true;
1939     }
1940     nType = nNumFmtType;
1941     nIndex = nNumFmtIndex;
1942 }
1943 
1944 //-------------------------------------------------------------------------------
1945 
1946 ScHorizontalAttrIterator::ScHorizontalAttrIterator( ScDocument* pDocument, SCTAB nTable,
1947                             SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) :
1948     pDoc( pDocument ),
1949     nTab( nTable ),
1950     nStartCol( nCol1 ),
1951     nStartRow( nRow1 ),
1952     nEndCol( nCol2 ),
1953     nEndRow( nRow2 )
1954 {
1955     DBG_ASSERT( pDoc->pTab[nTab], "Tabelle nicht da" );
1956 
1957     SCCOL i;
1958 
1959     nRow = nStartRow;
1960     nCol = nStartCol;
1961     bRowEmpty = sal_False;
1962 
1963     pIndices    = new SCSIZE[nEndCol-nStartCol+1];
1964     pNextEnd    = new SCROW[nEndCol-nStartCol+1];
1965     ppPatterns  = new const ScPatternAttr*[nEndCol-nStartCol+1];
1966 
1967     SCROW nSkipTo = MAXROW;
1968     sal_Bool bEmpty = sal_True;
1969     for (i=nStartCol; i<=nEndCol; i++)
1970     {
1971         SCCOL nPos = i - nStartCol;
1972         ScAttrArray* pArray = pDoc->pTab[nTab]->aCol[i].pAttrArray;
1973         DBG_ASSERT( pArray, "pArray == 0" );
1974 
1975         SCSIZE nIndex;
1976         pArray->Search( nStartRow, nIndex );
1977 
1978         const ScPatternAttr* pPattern = pArray->pData[nIndex].pPattern;
1979         SCROW nThisEnd = pArray->pData[nIndex].nRow;
1980         if ( IsDefaultItem( pPattern ) )
1981         {
1982             pPattern = NULL;
1983             if ( nThisEnd < nSkipTo )
1984                 nSkipTo = nThisEnd;         // nSkipTo kann gleich hier gesetzt werden
1985         }
1986         else
1987             bEmpty = sal_False;                 // Attribute gefunden
1988 
1989         pIndices[nPos] = nIndex;
1990         pNextEnd[nPos] = nThisEnd;
1991         ppPatterns[nPos] = pPattern;
1992     }
1993 
1994     if (bEmpty)
1995         nRow = nSkipTo;                     // bis zum naechsten Bereichsende ueberspringen
1996     bRowEmpty = bEmpty;
1997 }
1998 
1999 ScHorizontalAttrIterator::~ScHorizontalAttrIterator()
2000 {
2001     delete[] (ScPatternAttr**)ppPatterns;
2002     delete[] pNextEnd;
2003     delete[] pIndices;
2004 }
2005 
2006 const ScPatternAttr* ScHorizontalAttrIterator::GetNext( SCCOL& rCol1, SCCOL& rCol2, SCROW& rRow )
2007 {
2008     for (;;)
2009     {
2010         if (!bRowEmpty)
2011         {
2012             // in dieser Zeile suchen
2013 
2014             while ( nCol <= nEndCol && !ppPatterns[nCol-nStartCol] )
2015                 ++nCol;
2016 
2017             if ( nCol <= nEndCol )
2018             {
2019                 const ScPatternAttr* pPat = ppPatterns[nCol-nStartCol];
2020                 rRow = nRow;
2021                 rCol1 = nCol;
2022                 while ( nCol < nEndCol && ppPatterns[nCol+1-nStartCol] == pPat )
2023                     ++nCol;
2024                 rCol2 = nCol;
2025                 ++nCol;                 // hochzaehlen fuer naechsten Aufruf
2026                 return pPat;            // gefunden
2027             }
2028         }
2029 
2030         // naechste Zeile
2031 
2032         ++nRow;
2033         if ( nRow > nEndRow )       // schon am Ende?
2034             return NULL;            // nichts gefunden
2035 
2036         sal_Bool bEmpty = sal_True;
2037         SCCOL i;
2038 
2039         for ( i = nStartCol; i <= nEndCol; i++)
2040         {
2041             SCCOL nPos = i-nStartCol;
2042             if ( pNextEnd[nPos] < nRow )
2043             {
2044                 ScAttrArray* pArray = pDoc->pTab[nTab]->aCol[i].pAttrArray;
2045 
2046                 SCSIZE nIndex = ++pIndices[nPos];
2047                 if ( nIndex < pArray->nCount )
2048                 {
2049                     const ScPatternAttr* pPattern = pArray->pData[nIndex].pPattern;
2050                     SCROW nThisEnd = pArray->pData[nIndex].nRow;
2051                     if ( IsDefaultItem( pPattern ) )
2052                         pPattern = NULL;
2053                     else
2054                         bEmpty = sal_False;                 // Attribute gefunden
2055 
2056                     pNextEnd[nPos] = nThisEnd;
2057                     ppPatterns[nPos] = pPattern;
2058 
2059                     DBG_ASSERT( pNextEnd[nPos] >= nRow, "Reihenfolge durcheinander" );
2060                 }
2061                 else
2062                 {
2063                     DBG_ERROR("AttrArray reicht nicht bis MAXROW");
2064                     pNextEnd[nPos] = MAXROW;
2065                     ppPatterns[nPos] = NULL;
2066                 }
2067             }
2068             else if ( ppPatterns[nPos] )
2069                 bEmpty = sal_False;                         // Bereich noch nicht zuende
2070         }
2071 
2072         if (bEmpty)
2073         {
2074             SCCOL nCount = nEndCol-nStartCol+1;
2075             SCROW nSkipTo = pNextEnd[0];                // naechstes Bereichsende suchen
2076             for (i=1; i<nCount; i++)
2077                 if ( pNextEnd[i] < nSkipTo )
2078                     nSkipTo = pNextEnd[i];
2079             nRow = nSkipTo;                             // leere Zeilen ueberspringen
2080         }
2081         bRowEmpty = bEmpty;
2082         nCol = nStartCol;           // wieder links anfangen
2083     }
2084 
2085 //    return NULL;
2086 }
2087 
2088 //-------------------------------------------------------------------------------
2089 
2090 inline sal_Bool IsGreater( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
2091 {
2092     return ( nRow1 > nRow2 ) || ( nRow1 == nRow2 && nCol1 > nCol2 );
2093 }
2094 
2095 ScUsedAreaIterator::ScUsedAreaIterator( ScDocument* pDocument, SCTAB nTable,
2096                             SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) :
2097     aCellIter( pDocument, nTable, nCol1, nRow1, nCol2, nRow2 ),
2098     aAttrIter( pDocument, nTable, nCol1, nRow1, nCol2, nRow2 ),
2099     nNextCol( nCol1 ),
2100     nNextRow( nRow1 )
2101 {
2102     pCell    = aCellIter.GetNext( nCellCol, nCellRow );
2103     pPattern = aAttrIter.GetNext( nAttrCol1, nAttrCol2, nAttrRow );
2104 }
2105 
2106 ScUsedAreaIterator::~ScUsedAreaIterator()
2107 {
2108 }
2109 
2110 sal_Bool ScUsedAreaIterator::GetNext()
2111 {
2112     //  Iteratoren weiterzaehlen
2113 
2114     if ( pCell && IsGreater( nNextCol, nNextRow, nCellCol, nCellRow ) )
2115         pCell = aCellIter.GetNext( nCellCol, nCellRow );
2116 
2117     while ( pCell && pCell->IsBlank() )
2118         pCell = aCellIter.GetNext( nCellCol, nCellRow );
2119 
2120     if ( pPattern && IsGreater( nNextCol, nNextRow, nAttrCol2, nAttrRow ) )
2121         pPattern = aAttrIter.GetNext( nAttrCol1, nAttrCol2, nAttrRow );
2122 
2123     if ( pPattern && nAttrRow == nNextRow && nAttrCol1 < nNextCol )
2124         nAttrCol1 = nNextCol;
2125 
2126     //  naechsten Abschnitt heraussuchen
2127 
2128     sal_Bool bFound = sal_True;
2129     sal_Bool bUseCell = sal_False;
2130 
2131     if ( pCell && pPattern )
2132     {
2133         if ( IsGreater( nCellCol, nCellRow, nAttrCol1, nAttrRow ) )     // vorne nur Attribute ?
2134         {
2135             pFoundCell = NULL;
2136             pFoundPattern = pPattern;
2137             nFoundRow = nAttrRow;
2138             nFoundStartCol = nAttrCol1;
2139             if ( nCellRow == nAttrRow && nCellCol <= nAttrCol2 )        // auch Zelle im Bereich ?
2140                 nFoundEndCol = nCellCol - 1;                            // nur bis vor der Zelle
2141             else
2142                 nFoundEndCol = nAttrCol2;                               // alles
2143         }
2144         else
2145         {
2146             bUseCell = sal_True;
2147             if ( nAttrRow == nCellRow && nAttrCol1 == nCellCol )        // Attribute auf der Zelle ?
2148                 pFoundPattern = pPattern;
2149             else
2150                 pFoundPattern = NULL;
2151         }
2152     }
2153     else if ( pCell )                   // nur Zelle -> direkt uebernehmen
2154     {
2155         pFoundPattern = NULL;
2156         bUseCell = sal_True;                // Position von Zelle
2157     }
2158     else if ( pPattern )                // nur Attribute -> direkt uebernehmen
2159     {
2160         pFoundCell = NULL;
2161         pFoundPattern = pPattern;
2162         nFoundRow = nAttrRow;
2163         nFoundStartCol = nAttrCol1;
2164         nFoundEndCol = nAttrCol2;
2165     }
2166     else                                // gar nichts
2167         bFound = sal_False;
2168 
2169     if ( bUseCell )                     // Position von Zelle
2170     {
2171         pFoundCell = pCell;
2172         nFoundRow = nCellRow;
2173         nFoundStartCol = nFoundEndCol = nCellCol;
2174     }
2175 
2176     if (bFound)
2177     {
2178         nNextRow = nFoundRow;
2179         nNextCol = nFoundEndCol + 1;
2180     }
2181 
2182     return bFound;
2183 }
2184 
2185 //-------------------------------------------------------------------------------
2186 
2187 ScDocAttrIterator::ScDocAttrIterator(ScDocument* pDocument, SCTAB nTable,
2188                                     SCCOL nCol1, SCROW nRow1,
2189                                     SCCOL nCol2, SCROW nRow2) :
2190     pDoc( pDocument ),
2191     nTab( nTable ),
2192     nEndCol( nCol2 ),
2193     nStartRow( nRow1 ),
2194     nEndRow( nRow2 ),
2195     nCol( nCol1 )
2196 {
2197     if ( ValidTab(nTab) && pDoc->pTab[nTab] )
2198         pColIter = pDoc->pTab[nTab]->aCol[nCol].CreateAttrIterator( nStartRow, nEndRow );
2199     else
2200         pColIter = NULL;
2201 }
2202 
2203 ScDocAttrIterator::~ScDocAttrIterator()
2204 {
2205     delete pColIter;
2206 }
2207 
2208 const ScPatternAttr* ScDocAttrIterator::GetNext( SCCOL& rCol, SCROW& rRow1, SCROW& rRow2 )
2209 {
2210     while ( pColIter )
2211     {
2212         const ScPatternAttr* pPattern = pColIter->Next( rRow1, rRow2 );
2213         if ( pPattern )
2214         {
2215             rCol = nCol;
2216             return pPattern;
2217         }
2218 
2219         delete pColIter;
2220         ++nCol;
2221         if ( nCol <= nEndCol )
2222             pColIter = pDoc->pTab[nTab]->aCol[nCol].CreateAttrIterator( nStartRow, nEndRow );
2223         else
2224             pColIter = NULL;
2225     }
2226     return NULL;        // is nix mehr
2227 }
2228 
2229 //-------------------------------------------------------------------------------
2230 
2231 ScAttrRectIterator::ScAttrRectIterator(ScDocument* pDocument, SCTAB nTable,
2232                                     SCCOL nCol1, SCROW nRow1,
2233                                     SCCOL nCol2, SCROW nRow2) :
2234     pDoc( pDocument ),
2235     nTab( nTable ),
2236     nEndCol( nCol2 ),
2237     nStartRow( nRow1 ),
2238     nEndRow( nRow2 ),
2239     nIterStartCol( nCol1 ),
2240     nIterEndCol( nCol1 )
2241 {
2242     if ( ValidTab(nTab) && pDoc->pTab[nTab] )
2243     {
2244         pColIter = pDoc->pTab[nTab]->aCol[nIterStartCol].CreateAttrIterator( nStartRow, nEndRow );
2245         while ( nIterEndCol < nEndCol &&
2246                 pDoc->pTab[nTab]->aCol[nIterEndCol].IsAllAttrEqual(
2247                     pDoc->pTab[nTab]->aCol[nIterEndCol+1], nStartRow, nEndRow ) )
2248             ++nIterEndCol;
2249     }
2250     else
2251         pColIter = NULL;
2252 }
2253 
2254 ScAttrRectIterator::~ScAttrRectIterator()
2255 {
2256     delete pColIter;
2257 }
2258 
2259 void ScAttrRectIterator::DataChanged()
2260 {
2261     if (pColIter)
2262     {
2263         SCROW nNextRow = pColIter->GetNextRow();
2264         delete pColIter;
2265         pColIter = pDoc->pTab[nTab]->aCol[nIterStartCol].CreateAttrIterator( nNextRow, nEndRow );
2266     }
2267 }
2268 
2269 const ScPatternAttr* ScAttrRectIterator::GetNext( SCCOL& rCol1, SCCOL& rCol2,
2270                                                     SCROW& rRow1, SCROW& rRow2 )
2271 {
2272     while ( pColIter )
2273     {
2274         const ScPatternAttr* pPattern = pColIter->Next( rRow1, rRow2 );
2275         if ( pPattern )
2276         {
2277             rCol1 = nIterStartCol;
2278             rCol2 = nIterEndCol;
2279             return pPattern;
2280         }
2281 
2282         delete pColIter;
2283         nIterStartCol = nIterEndCol+1;
2284         if ( nIterStartCol <= nEndCol )
2285         {
2286             nIterEndCol = nIterStartCol;
2287             pColIter = pDoc->pTab[nTab]->aCol[nIterStartCol].CreateAttrIterator( nStartRow, nEndRow );
2288             while ( nIterEndCol < nEndCol &&
2289                     pDoc->pTab[nTab]->aCol[nIterEndCol].IsAllAttrEqual(
2290                         pDoc->pTab[nTab]->aCol[nIterEndCol+1], nStartRow, nEndRow ) )
2291                 ++nIterEndCol;
2292         }
2293         else
2294             pColIter = NULL;
2295     }
2296     return NULL;        // is nix mehr
2297 }
2298 
2299 // ============================================================================
2300 
2301 SCROW ScRowBreakIterator::NOT_FOUND = -1;
2302 
2303 ScRowBreakIterator::ScRowBreakIterator(set<SCROW>& rBreaks) :
2304     mrBreaks(rBreaks),
2305     maItr(rBreaks.begin()), maEnd(rBreaks.end())
2306 {
2307 }
2308 
2309 SCROW ScRowBreakIterator::first()
2310 {
2311     maItr = mrBreaks.begin();
2312     return maItr == maEnd ? NOT_FOUND : *maItr;
2313 }
2314 
2315 SCROW ScRowBreakIterator::next()
2316 {
2317     ++maItr;
2318     return maItr == maEnd ? NOT_FOUND : *maItr;
2319 }
2320