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