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