xref: /aoo41x/main/sc/source/core/data/dociter.cxx (revision f689a31b)
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
10b3f79822SAndrew Rist  *
11b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12b3f79822SAndrew Rist  *
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.
19b3f79822SAndrew Rist  *
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 
305cdf0e10cSrcweir 	nColRow = 0;					// wird bei GetFirst initialisiert
306cdf0e10cSrcweir 
307cdf0e10cSrcweir 	nNumFormat = 0;					// werden bei GetNumberFormat initialisiert
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;
331cdf0e10cSrcweir 						return sal_False;				// Ende und Aus
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 						//
364cdf0e10cSrcweir 						//	wenn in der selben Spalte gleich noch eine Value-Cell folgt, die
365cdf0e10cSrcweir 						//	auch noch im Block liegt, den Wert jetzt schon holen
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 
383cdf0e10cSrcweir 						return sal_True;									// gefunden
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;
396cdf0e10cSrcweir 								return sal_True;							// gefunden
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
431cdf0e10cSrcweir 			nRow = nEndRow + 1;			// naechste Spalte
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 
478cdf0e10cSrcweir 	nNumFormat = 0;					// werden bei GetNumberFormat initialisiert
479cdf0e10cSrcweir 	pAttrArray = 0;
480cdf0e10cSrcweir 	nAttrEndRow = 0;
481cdf0e10cSrcweir 
482cdf0e10cSrcweir 	return GetThis(rValue, rErr);
483cdf0e10cSrcweir }
484cdf0e10cSrcweir 
485cdf0e10cSrcweir /*	ist 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 
547cdf0e10cSrcweir 	nColRow = 0;					// wird bei GetFirst initialisiert
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 	}
557cdf0e10cSrcweir 	nNumFormat = 0;					// werden bei GetNumberFormat initialisiert
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;
613cdf0e10cSrcweir 							return sal_True;		// gefunden
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();
626cdf0e10cSrcweir 								return sal_True;	// gefunden
627cdf0e10cSrcweir 							}
628cdf0e10cSrcweir 							else
629*f689a31bSAndrea Pescetti 							{
630*f689a31bSAndrea Pescetti 							    if (mpParam->mbSkipString)
631*f689a31bSAndrea Pescetti 							        ++nRow;
632*f689a31bSAndrea Pescetti 							    else
633*f689a31bSAndrea Pescetti 							    {
634*f689a31bSAndrea Pescetti                                     rValue.maString = ((ScFormulaCell*)pCell)->GetStringData();
635*f689a31bSAndrea Pescetti                                     rValue.mbIsNumber = false;
636*f689a31bSAndrea Pescetti                                     rValue.mnError = ((ScFormulaCell*)pCell)->GetErrCode();
637*f689a31bSAndrea Pescetti                                     return sal_True;
638*f689a31bSAndrea Pescetti 							    }
639*f689a31bSAndrea Pescetti 							}
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
664cdf0e10cSrcweir             nRow = mpParam->nRow2 + 1; // Naechste Spalte
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])
988cdf0e10cSrcweir 		--nEndTab;										// nur benutzte Tabellen
989cdf0e10cSrcweir 	if (nStartTab>nEndTab)
990cdf0e10cSrcweir 		nStartTab = nEndTab;
991cdf0e10cSrcweir 
992cdf0e10cSrcweir 	nCol = nStartCol;
993cdf0e10cSrcweir 	nRow = nStartRow;
994cdf0e10cSrcweir 	nTab = nStartTab;
995cdf0e10cSrcweir 	nColRow = 0;					// wird bei GetFirst initialisiert
996cdf0e10cSrcweir 
997cdf0e10cSrcweir 	if (!pDoc->pTab[nTab])
998cdf0e10cSrcweir 	{
999cdf0e10cSrcweir 		DBG_ERROR("Tabelle nicht gefunden");
1000cdf0e10cSrcweir 		nStartCol = nCol = MAXCOL+1;
1001cdf0e10cSrcweir 		nStartRow = nRow = MAXROW+1;
1002cdf0e10cSrcweir 		nStartTab = nTab = MAXTAB+1;	// -> Abbruch bei 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])
1030cdf0e10cSrcweir 		--nEndTab;										// nur benutzte Tabellen
1031cdf0e10cSrcweir 	if (nStartTab>nEndTab)
1032cdf0e10cSrcweir 		nStartTab = nEndTab;
1033cdf0e10cSrcweir 
1034cdf0e10cSrcweir 	nCol = nStartCol;
1035cdf0e10cSrcweir 	nRow = nStartRow;
1036cdf0e10cSrcweir 	nTab = nStartTab;
1037cdf0e10cSrcweir 	nColRow = 0;					// wird bei GetFirst initialisiert
1038cdf0e10cSrcweir 
1039cdf0e10cSrcweir 	if (!pDoc->pTab[nTab])
1040cdf0e10cSrcweir 	{
1041cdf0e10cSrcweir 		DBG_ERROR("Tabelle nicht gefunden");
1042cdf0e10cSrcweir 		nStartCol = nCol = MAXCOL+1;
1043cdf0e10cSrcweir 		nStartRow = nRow = MAXROW+1;
1044cdf0e10cSrcweir 		nStartTab = nTab = MAXTAB+1;	// -> Abbruch bei 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 )
1064cdf0e10cSrcweir 						return NULL;				// Ende und Aus
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() )
1083cdf0e10cSrcweir 					nRow++;				// Sub-Total-Zeilen nicht
1084cdf0e10cSrcweir 				else
1085cdf0e10cSrcweir 					return pCell;		// gefunden
1086cdf0e10cSrcweir 			}
1087cdf0e10cSrcweir 			else
1088cdf0e10cSrcweir 				nRow++;
1089cdf0e10cSrcweir 		}
1090cdf0e10cSrcweir 		else
1091cdf0e10cSrcweir 			nRow = nEndRow + 1; // Naechste Spalte
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;
1128cdf0e10cSrcweir 	nColRow = 0;					// wird bei GetFirst initialisiert
1129cdf0e10cSrcweir 	SCSIZE i;
1130cdf0e10cSrcweir 	if (bMod)								// sonst schon eingetragen
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 	}
1141cdf0e10cSrcweir 	nNumFormat = 0;					// werden bei GetNumberFormat initialisiert
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 )
1167cdf0e10cSrcweir 					return NULL;				// Ende und Aus
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
1238cdf0e10cSrcweir 			nRow = aParam.nRow2 + 1; // Naechste Spalte
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 		{
1722cdf0e10cSrcweir 			pNextRows[i-nStartCol] = MAXROWCOUNT;		// nichts gefunden
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 		{
1749cdf0e10cSrcweir 			pNextRows[nCol-nStartCol] = MAXROWCOUNT;		// nichts gefunden
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 {
1961cdf0e10cSrcweir 	DBG_ASSERT( pDoc->pTab[nTab], "Tabelle nicht da" );
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 )
1990cdf0e10cSrcweir 				nSkipTo = nThisEnd;			// nSkipTo kann gleich hier gesetzt werden
1991cdf0e10cSrcweir 		}
1992cdf0e10cSrcweir 		else
1993cdf0e10cSrcweir 			bEmpty = sal_False;					// Attribute gefunden
1994cdf0e10cSrcweir 
1995cdf0e10cSrcweir 		pIndices[nPos] = nIndex;
1996cdf0e10cSrcweir 		pNextEnd[nPos] = nThisEnd;
1997cdf0e10cSrcweir 		ppPatterns[nPos] = pPattern;
1998cdf0e10cSrcweir 	}
1999cdf0e10cSrcweir 
2000cdf0e10cSrcweir 	if (bEmpty)
2001cdf0e10cSrcweir 		nRow = nSkipTo;						// bis zum naechsten Bereichsende ueberspringen
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 		{
2018cdf0e10cSrcweir 			// in dieser Zeile suchen
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;
2031cdf0e10cSrcweir 				++nCol;					// hochzaehlen fuer naechsten Aufruf
2032cdf0e10cSrcweir 				return pPat;			// gefunden
2033cdf0e10cSrcweir 			}
2034cdf0e10cSrcweir 		}
2035cdf0e10cSrcweir 
2036cdf0e10cSrcweir 		// naechste Zeile
2037cdf0e10cSrcweir 
2038cdf0e10cSrcweir 		++nRow;
2039cdf0e10cSrcweir 		if ( nRow > nEndRow )		// schon am Ende?
2040cdf0e10cSrcweir 			return NULL;			// nichts gefunden
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
2060cdf0e10cSrcweir 						bEmpty = sal_False;					// Attribute gefunden
2061cdf0e10cSrcweir 
2062cdf0e10cSrcweir 					pNextEnd[nPos] = nThisEnd;
2063cdf0e10cSrcweir 					ppPatterns[nPos] = pPattern;
2064cdf0e10cSrcweir 
2065cdf0e10cSrcweir 					DBG_ASSERT( pNextEnd[nPos] >= nRow, "Reihenfolge durcheinander" );
2066cdf0e10cSrcweir 				}
2067cdf0e10cSrcweir 				else
2068cdf0e10cSrcweir 				{
2069cdf0e10cSrcweir 					DBG_ERROR("AttrArray reicht nicht bis MAXROW");
2070cdf0e10cSrcweir 					pNextEnd[nPos] = MAXROW;
2071cdf0e10cSrcweir 					ppPatterns[nPos] = NULL;
2072cdf0e10cSrcweir 				}
2073cdf0e10cSrcweir 			}
2074cdf0e10cSrcweir 			else if ( ppPatterns[nPos] )
2075cdf0e10cSrcweir 				bEmpty = sal_False;							// Bereich noch nicht zuende
2076cdf0e10cSrcweir 		}
2077cdf0e10cSrcweir 
2078cdf0e10cSrcweir 		if (bEmpty)
2079cdf0e10cSrcweir 		{
2080cdf0e10cSrcweir 			SCCOL nCount = nEndCol-nStartCol+1;
2081cdf0e10cSrcweir 			SCROW nSkipTo = pNextEnd[0];				// naechstes Bereichsende suchen
2082cdf0e10cSrcweir 			for (i=1; i<nCount; i++)
2083cdf0e10cSrcweir 				if ( pNextEnd[i] < nSkipTo )
2084cdf0e10cSrcweir 					nSkipTo = pNextEnd[i];
2085cdf0e10cSrcweir 			nRow = nSkipTo;								// leere Zeilen ueberspringen
2086cdf0e10cSrcweir 		}
2087cdf0e10cSrcweir 		bRowEmpty = bEmpty;
2088cdf0e10cSrcweir 		nCol = nStartCol;			// wieder links anfangen
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 {
2118cdf0e10cSrcweir 	//	Iteratoren weiterzaehlen
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 
2132cdf0e10cSrcweir 	//	naechsten Abschnitt heraussuchen
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;
2145cdf0e10cSrcweir 			if ( nCellRow == nAttrRow && nCellCol <= nAttrCol2 )		// auch Zelle im Bereich ?
2146cdf0e10cSrcweir 				nFoundEndCol = nCellCol - 1;							// nur bis vor der Zelle
2147cdf0e10cSrcweir 			else
2148cdf0e10cSrcweir 				nFoundEndCol = nAttrCol2;								// alles
2149cdf0e10cSrcweir 		}
2150cdf0e10cSrcweir 		else
2151cdf0e10cSrcweir 		{
2152cdf0e10cSrcweir 			bUseCell = sal_True;
2153cdf0e10cSrcweir 			if ( nAttrRow == nCellRow && nAttrCol1 == nCellCol )		// Attribute auf der Zelle ?
2154cdf0e10cSrcweir 				pFoundPattern = pPattern;
2155cdf0e10cSrcweir 			else
2156cdf0e10cSrcweir 				pFoundPattern = NULL;
2157cdf0e10cSrcweir 		}
2158cdf0e10cSrcweir 	}
2159cdf0e10cSrcweir 	else if ( pCell )					// nur Zelle -> direkt uebernehmen
2160cdf0e10cSrcweir 	{
2161cdf0e10cSrcweir 		pFoundPattern = NULL;
2162cdf0e10cSrcweir 		bUseCell = sal_True;				// Position von Zelle
2163cdf0e10cSrcweir 	}
2164cdf0e10cSrcweir 	else if ( pPattern )				// nur Attribute -> direkt uebernehmen
2165cdf0e10cSrcweir 	{
2166cdf0e10cSrcweir 		pFoundCell = NULL;
2167cdf0e10cSrcweir 		pFoundPattern = pPattern;
2168cdf0e10cSrcweir 		nFoundRow = nAttrRow;
2169cdf0e10cSrcweir 		nFoundStartCol = nAttrCol1;
2170cdf0e10cSrcweir 		nFoundEndCol = nAttrCol2;
2171cdf0e10cSrcweir 	}
2172cdf0e10cSrcweir 	else								// gar nichts
2173cdf0e10cSrcweir 		bFound = sal_False;
2174cdf0e10cSrcweir 
2175cdf0e10cSrcweir 	if ( bUseCell )						// Position von Zelle
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 	}
2232cdf0e10cSrcweir 	return NULL;		// is nix mehr
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 	}
2302cdf0e10cSrcweir 	return NULL;		// is nix mehr
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