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