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 1356 : ScValueIterator::ScValueIterator( ScDocument* pDocument, const ScRange& rRange,
235 : bool bSTotal, bool bTextZero ) :
236 : pDoc( pDocument ),
237 : nNumFmtIndex(0),
238 1356 : nStartCol( rRange.aStart.Col() ),
239 1356 : nStartRow( rRange.aStart.Row() ),
240 1356 : nStartTab( rRange.aStart.Tab() ),
241 1356 : nEndCol( rRange.aEnd.Col() ),
242 1356 : nEndRow( rRange.aEnd.Row() ),
243 1356 : nEndTab( rRange.aEnd.Tab() ),
244 : nNumFmtType( NUMBERFORMAT_UNDEFINED ),
245 : bNumValid( false ),
246 : bSubTotal(bSTotal),
247 : bNextValid( false ),
248 1356 : bCalcAsShown( pDocument->GetDocOptions().IsCalcAsShown() ),
249 10848 : bTextAsZero( bTextZero )
250 : {
251 1356 : SCTAB nDocMaxTab = pDocument->GetTableCount() - 1;
252 :
253 1356 : PutInOrder( nStartCol, nEndCol);
254 1356 : PutInOrder( nStartRow, nEndRow);
255 1356 : PutInOrder( nStartTab, nEndTab );
256 :
257 1356 : if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
258 1356 : if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
259 1356 : if (!ValidRow(nStartRow)) nStartRow = MAXROW;
260 1356 : if (!ValidRow(nEndRow)) nEndRow = MAXROW;
261 1356 : if (!ValidTab(nStartTab) || nStartTab > nDocMaxTab) nStartTab = nDocMaxTab;
262 1356 : if (!ValidTab(nEndTab) || nEndTab > nDocMaxTab) nEndTab = nDocMaxTab;
263 :
264 1356 : nCol = nStartCol;
265 1356 : nRow = nStartRow;
266 1356 : nTab = nStartTab;
267 :
268 1356 : nColRow = 0; // wird bei GetFirst initialisiert
269 :
270 1356 : nNumFormat = 0; // werden bei GetNumberFormat initialisiert
271 1356 : pAttrArray = 0;
272 1356 : nAttrEndRow = 0;
273 1356 : }
274 :
275 6580 : bool ScValueIterator::GetThis(double& rValue, sal_uInt16& rErr)
276 : {
277 6580 : if (nTab >= pDoc->GetTableCount())
278 : {
279 : OSL_FAIL("try to access out of index, FIX IT");
280 : }
281 6580 : ScColumn* pCol = &(pDoc->maTabs[nTab])->aCol[nCol];
282 46 : for (;;)
283 : {
284 6626 : if ( nRow > nEndRow )
285 : {
286 1372 : nRow = nStartRow;
287 22 : do
288 : {
289 1378 : nCol++;
290 1378 : if ( nCol > nEndCol )
291 : {
292 1356 : nCol = nStartCol;
293 1356 : nTab++;
294 1356 : if ( nTab > nEndTab )
295 : {
296 : // rValue = 0.0; //! do not change caller's value!
297 1356 : rErr = 0;
298 1356 : return false; // Ende und Aus
299 : }
300 : }
301 22 : pCol = &(pDoc->maTabs[nTab])->aCol[nCol];
302 22 : } while ( pCol->maItems.empty() );
303 16 : pCol->Search( nRow, nColRow );
304 : }
305 :
306 10540 : while (( nColRow < pCol->maItems.size() ) && ( pCol->maItems[nColRow].nRow < nRow ))
307 0 : nColRow++;
308 :
309 5270 : if ( nColRow < pCol->maItems.size() && pCol->maItems[nColRow].nRow <= nEndRow )
310 : {
311 5230 : nRow = pCol->maItems[nColRow].nRow + 1;
312 5230 : if ( !bSubTotal || !pDoc->maTabs[nTab]->RowFiltered( nRow-1 ) )
313 : {
314 5230 : ScBaseCell* pCell = pCol->maItems[nColRow].pCell;
315 5230 : ++nColRow;
316 5230 : switch (pCell->GetCellType())
317 : {
318 : case CELLTYPE_VALUE:
319 : {
320 3836 : bNumValid = false;
321 3836 : rValue = ((ScValueCell*)pCell)->GetValue();
322 3836 : rErr = 0;
323 3836 : --nRow;
324 3836 : 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 14140 : if ( nColRow < pCol->maItems.size() &&
335 3816 : pCol->maItems[nColRow].nRow <= nEndRow &&
336 3268 : pCol->maItems[nColRow].pCell->GetCellType() == CELLTYPE_VALUE &&
337 3220 : !bSubTotal )
338 : {
339 3220 : fNextValue = ((ScValueCell*)pCol->maItems[nColRow].pCell)->GetValue();
340 3220 : nNextRow = pCol->maItems[nColRow].nRow;
341 3220 : bNextValid = true;
342 3220 : 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 3836 : return true; // gefunden
351 : }
352 : // break;
353 : case CELLTYPE_FORMULA:
354 : {
355 1388 : if (!bSubTotal || !((ScFormulaCell*)pCell)->IsSubTotal())
356 : {
357 1388 : rErr = ((ScFormulaCell*)pCell)->GetErrCode();
358 1388 : if ( rErr || ((ScFormulaCell*)pCell)->IsValue() )
359 : {
360 1388 : rValue = ((ScFormulaCell*)pCell)->GetValue();
361 1388 : nRow--;
362 1388 : bNumValid = false;
363 1388 : 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 6 : 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 6 : break;
390 : default:
391 : {
392 : // added to avoid warnings
393 : }
394 : }
395 : }
396 : }
397 : else
398 40 : nRow = nEndRow + 1; // naechste Spalte
399 : }
400 : }
401 :
402 1328 : void ScValueIterator::GetCurNumFmtInfo( short& nType, sal_uLong& nIndex )
403 : {
404 1328 : if (!bNumValid && nTab < pDoc->GetTableCount())
405 : {
406 1328 : const ScColumn* pCol = &(pDoc->maTabs[nTab])->aCol[nCol];
407 1328 : nNumFmtIndex = pCol->GetNumberFormat( nRow );
408 1328 : if ( (nNumFmtIndex % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
409 : {
410 : const ScBaseCell* pCell;
411 72 : SCSIZE nIdx = nColRow - 1;
412 : // there might be rearranged something, so be on the safe side
413 72 : if ( nIdx < pCol->maItems.size() && pCol->maItems[nIdx].nRow == nRow )
414 72 : 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 72 : if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
423 2 : ((const ScFormulaCell*)pCell)->GetFormatInfo( nNumFmtType, nNumFmtIndex );
424 : else
425 70 : nNumFmtType = pDoc->GetFormatTable()->GetType( nNumFmtIndex );
426 : }
427 : else
428 1256 : nNumFmtType = pDoc->GetFormatTable()->GetType( nNumFmtIndex );
429 1328 : bNumValid = true;
430 : }
431 1328 : nType = nNumFmtType;
432 1328 : nIndex = nNumFmtIndex;
433 1328 : }
434 :
435 1356 : bool ScValueIterator::GetFirst(double& rValue, sal_uInt16& rErr)
436 : {
437 1356 : nCol = nStartCol;
438 1356 : nRow = nStartRow;
439 1356 : nTab = nStartTab;
440 :
441 1356 : if (nTab >= pDoc->GetTableCount())
442 : OSL_FAIL("try to access index out of bounds, FIX IT");
443 1356 : ScColumn* pCol = &(pDoc->maTabs[nTab])->aCol[nCol];
444 1356 : pCol->Search( nRow, nColRow );
445 :
446 1356 : nNumFormat = 0; // werden bei GetNumberFormat initialisiert
447 1356 : pAttrArray = 0;
448 1356 : nAttrEndRow = 0;
449 :
450 1356 : return GetThis(rValue, rErr);
451 : }
452 :
453 : // ============================================================================
454 :
455 8 : ScDBQueryDataIterator::DataAccess::DataAccess(const ScDBQueryDataIterator* pParent) :
456 8 : mpParent(pParent)
457 : {
458 8 : }
459 :
460 8 : ScDBQueryDataIterator::DataAccess::~DataAccess()
461 : {
462 8 : }
463 :
464 88 : SCROW ScDBQueryDataIterator::GetRowByColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCSIZE nColRow)
465 : {
466 88 : if (nTab >= rDoc.GetTableCount())
467 : OSL_FAIL("try to access index out of bounds, FIX IT");
468 88 : ScColumn* pCol = &rDoc.maTabs[nTab]->aCol[nCol];
469 88 : return pCol->maItems[nColRow].nRow;
470 : }
471 :
472 48 : ScBaseCell* ScDBQueryDataIterator::GetCellByColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCSIZE nColRow)
473 : {
474 48 : if (nTab >= rDoc.GetTableCount())
475 : OSL_FAIL("try to access index out of bounds, FIX IT");
476 48 : ScColumn* pCol = &rDoc.maTabs[nTab]->aCol[nCol];
477 48 : 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 48 : bool ScDBQueryDataIterator::IsQueryValid(ScDocument& rDoc, const ScQueryParam& rParam, SCTAB nTab, SCROW nRow, ScBaseCell* pCell)
489 : {
490 48 : if (nTab >= rDoc.GetTableCount())
491 : OSL_FAIL("try to access index out of bounds, FIX IT");
492 48 : return rDoc.maTabs[nTab]->ValidQuery(nRow, rParam, pCell);
493 : }
494 :
495 8 : SCSIZE ScDBQueryDataIterator::SearchColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCROW nRow, SCCOL nCol)
496 : {
497 8 : if (nTab >= rDoc.GetTableCount())
498 : OSL_FAIL("try to access index out of bounds, FIX IT");
499 8 : ScColumn* pCol = &rDoc.maTabs[nTab]->aCol[nCol];
500 : SCSIZE nColRow;
501 8 : pCol->Search(nRow, nColRow);
502 8 : return nColRow;
503 : }
504 :
505 : // ----------------------------------------------------------------------------
506 :
507 8 : ScDBQueryDataIterator::DataAccessInternal::DataAccessInternal(const ScDBQueryDataIterator* pParent, ScDBQueryParamInternal* pParam, ScDocument* pDoc) :
508 : DataAccess(pParent),
509 : mpParam(pParam),
510 : mpDoc(pDoc),
511 8 : bCalcAsShown( pDoc->GetDocOptions().IsCalcAsShown() )
512 : {
513 8 : nCol = mpParam->mnField;
514 8 : nRow = mpParam->nRow1;
515 8 : nTab = mpParam->nTab;
516 :
517 8 : nColRow = 0; // wird bei GetFirst initialisiert
518 : SCSIZE i;
519 8 : SCSIZE nCount = mpParam->GetEntryCount();
520 16 : for (i=0; (i<nCount) && (mpParam->GetEntry(i).bDoQuery); i++)
521 : {
522 8 : ScQueryEntry& rEntry = mpParam->GetEntry(i);
523 8 : ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
524 8 : rItems.resize(1);
525 8 : ScQueryEntry::Item& rItem = rItems.front();
526 8 : sal_uInt32 nIndex = 0;
527 : bool bNumber = mpDoc->GetFormatTable()->IsNumberFormat(
528 8 : rItem.maString, nIndex, rItem.mfVal);
529 8 : rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
530 : }
531 8 : nNumFormat = 0; // werden bei GetNumberFormat initialisiert
532 8 : pAttrArray = 0;
533 8 : nAttrEndRow = 0;
534 8 : }
535 :
536 16 : ScDBQueryDataIterator::DataAccessInternal::~DataAccessInternal()
537 : {
538 16 : }
539 :
540 40 : bool ScDBQueryDataIterator::DataAccessInternal::getCurrent(Value& rValue)
541 : {
542 40 : SCCOLROW nFirstQueryField = mpParam->GetEntry(0).nField;
543 16 : for ( ;; )
544 : {
545 56 : if (nRow > mpParam->nRow2)
546 : {
547 : // Bottom of the range reached. Bail out.
548 8 : rValue.mnError = 0;
549 8 : return false;
550 : }
551 :
552 48 : SCSIZE nCellCount = mpDoc->GetCellCount(nTab, nCol);
553 48 : if (!nCellCount)
554 : // No cells found in this column. Bail out.
555 0 : return false;
556 :
557 48 : SCROW nThisRow = ScDBQueryDataIterator::GetRowByColEntryIndex(*mpDoc, nTab, nCol, nColRow);
558 136 : while ( (nColRow < nCellCount) && (nThisRow < nRow) )
559 : {
560 40 : ++nColRow;
561 40 : if(nColRow < nCellCount)
562 40 : nThisRow = ScDBQueryDataIterator::GetRowByColEntryIndex(*mpDoc, nTab, nCol, nColRow);
563 : }
564 :
565 48 : if ( nColRow < nCellCount && nThisRow <= mpParam->nRow2 )
566 : {
567 48 : nRow = nThisRow;
568 48 : ScBaseCell* pCell = NULL;
569 48 : if (nCol == static_cast<SCCOL>(nFirstQueryField))
570 48 : pCell = ScDBQueryDataIterator::GetCellByColEntryIndex(*mpDoc, nTab, nCol, nColRow);
571 :
572 48 : if (ScDBQueryDataIterator::IsQueryValid(*mpDoc, *mpParam, nTab, nRow, pCell))
573 : {
574 : // #i109812# get cell here if it wasn't done above
575 32 : if (nCol != static_cast<SCCOL>(nFirstQueryField))
576 0 : pCell = ScDBQueryDataIterator::GetCellByColEntryIndex(*mpDoc, nTab, nCol, nColRow);
577 :
578 32 : switch (pCell ? pCell->GetCellType() : CELLTYPE_NONE)
579 : {
580 : case CELLTYPE_VALUE:
581 : {
582 32 : rValue.mfValue = ((ScValueCell*)pCell)->GetValue();
583 32 : rValue.mbIsNumber = true;
584 32 : 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 32 : nNumFmtType = NUMBERFORMAT_NUMBER;
593 32 : nNumFmtIndex = 0;
594 32 : rValue.mnError = 0;
595 32 : 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 16 : nRow++;
642 : }
643 : else
644 0 : nRow = mpParam->nRow2 + 1; // Naechste Spalte
645 : }
646 : // statement unreachable
647 : }
648 :
649 8 : bool ScDBQueryDataIterator::DataAccessInternal::getFirst(Value& rValue)
650 : {
651 8 : if (mpParam->bHasHeader)
652 8 : nRow++;
653 :
654 8 : nColRow = ScDBQueryDataIterator::SearchColEntryIndex(*mpDoc, nTab, nRow, nCol);
655 8 : return getCurrent(rValue);
656 : }
657 :
658 32 : bool ScDBQueryDataIterator::DataAccessInternal::getNext(Value& rValue)
659 : {
660 32 : ++nRow;
661 32 : 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 8 : ScDBQueryDataIterator::Value::Value() :
898 8 : mnError(0), mbIsNumber(true)
899 : {
900 8 : ::rtl::math::setNan(&mfValue);
901 8 : }
902 :
903 : // ----------------------------------------------------------------------------
904 :
905 8 : ScDBQueryDataIterator::ScDBQueryDataIterator(ScDocument* pDocument, ScDBQueryParamBase* pParam) :
906 8 : mpParam (pParam)
907 : {
908 8 : switch (mpParam->GetType())
909 : {
910 : case ScDBQueryParamBase::INTERNAL:
911 : {
912 8 : ScDBQueryParamInternal* p = static_cast<ScDBQueryParamInternal*>(pParam);
913 8 : mpData.reset(new DataAccessInternal(this, p, pDocument));
914 : }
915 8 : 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 8 : }
923 :
924 8 : bool ScDBQueryDataIterator::GetFirst(Value& rValue)
925 : {
926 8 : return mpData->getFirst(rValue);
927 : }
928 :
929 32 : bool ScDBQueryDataIterator::GetNext(Value& rValue)
930 : {
931 32 : return mpData->getNext(rValue);
932 : }
933 :
934 : // ============================================================================
935 :
936 280 : 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 280 : bSubTotal(bSTotal)
947 :
948 : {
949 280 : SCTAB nDocMaxTab = pDocument->GetTableCount() - 1;
950 :
951 280 : PutInOrder( nStartCol, nEndCol);
952 280 : PutInOrder( nStartRow, nEndRow);
953 280 : PutInOrder( nStartTab, nEndTab );
954 :
955 280 : if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
956 280 : if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
957 280 : if (!ValidRow(nStartRow)) nStartRow = MAXROW;
958 280 : if (!ValidRow(nEndRow)) nEndRow = MAXROW;
959 280 : if (!ValidTab(nStartTab) || nStartTab > nDocMaxTab) nStartTab = nDocMaxTab;
960 280 : if (!ValidTab(nEndTab) || nEndTab > nDocMaxTab) nEndTab = nDocMaxTab;
961 :
962 560 : while (nEndTab>0 && !pDoc->maTabs[nEndTab])
963 0 : --nEndTab; // nur benutzte Tabellen
964 280 : if (nStartTab>nEndTab)
965 0 : nStartTab = nEndTab;
966 :
967 280 : nCol = nStartCol;
968 280 : nRow = nStartRow;
969 280 : nTab = nStartTab;
970 280 : nColRow = 0; // wird bei GetFirst initialisiert
971 :
972 280 : 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 280 : }
980 :
981 196 : ScCellIterator::ScCellIterator
982 : ( ScDocument* pDocument, const ScRange& rRange, bool bSTotal ) :
983 : pDoc( pDocument ),
984 196 : nStartCol( rRange.aStart.Col() ),
985 196 : nStartRow( rRange.aStart.Row() ),
986 196 : nStartTab( rRange.aStart.Tab() ),
987 196 : nEndCol( rRange.aEnd.Col() ),
988 196 : nEndRow( rRange.aEnd.Row() ),
989 196 : nEndTab( rRange.aEnd.Tab() ),
990 1372 : bSubTotal(bSTotal)
991 :
992 : {
993 196 : PutInOrder( nStartCol, nEndCol);
994 196 : PutInOrder( nStartRow, nEndRow);
995 196 : PutInOrder( nStartTab, nEndTab );
996 :
997 196 : if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
998 196 : if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
999 196 : if (!ValidRow(nStartRow)) nStartRow = MAXROW;
1000 196 : if (!ValidRow(nEndRow)) nEndRow = MAXROW;
1001 196 : if (!ValidTab(nStartTab)) nStartTab = pDoc->GetTableCount()-1;
1002 196 : if (!ValidTab(nEndTab)) nEndTab = pDoc->GetTableCount()-1;
1003 :
1004 392 : while (nEndTab>0 && !pDoc->maTabs[nEndTab])
1005 0 : --nEndTab; // nur benutzte Tabellen
1006 196 : if (nStartTab>nEndTab)
1007 0 : nStartTab = nEndTab;
1008 :
1009 196 : nCol = nStartCol;
1010 196 : nRow = nStartRow;
1011 196 : nTab = nStartTab;
1012 196 : nColRow = 0; // wird bei GetFirst initialisiert
1013 :
1014 196 : 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 196 : }
1022 :
1023 4850 : ScBaseCell* ScCellIterator::GetThis()
1024 : {
1025 :
1026 4850 : ScColumn* pCol = &(pDoc->maTabs[nTab])->aCol[nCol];
1027 746 : for ( ;; )
1028 : {
1029 5596 : if ( nRow > nEndRow )
1030 : {
1031 1014 : nRow = nStartRow;
1032 20322 : do
1033 : {
1034 20798 : nCol++;
1035 20798 : if ( nCol > nEndCol )
1036 : {
1037 476 : nCol = nStartCol;
1038 476 : nTab++;
1039 476 : if ( nTab > nEndTab )
1040 476 : return NULL; // Ende und Aus
1041 : }
1042 20322 : pCol = &(pDoc->maTabs[nTab])->aCol[nCol];
1043 20322 : } while ( pCol->maItems.empty() );
1044 538 : pCol->Search( nRow, nColRow );
1045 : }
1046 :
1047 14346 : while ( (nColRow < pCol->maItems.size()) && (pCol->maItems[nColRow].nRow < nRow) )
1048 4106 : nColRow++;
1049 :
1050 5120 : if ( nColRow < pCol->maItems.size() && pCol->maItems[nColRow].nRow <= nEndRow )
1051 : {
1052 4374 : nRow = pCol->maItems[nColRow].nRow;
1053 4374 : if ( !bSubTotal || !pDoc->maTabs[nTab]->RowFiltered( nRow ) )
1054 : {
1055 4374 : ScBaseCell* pCell = pCol->maItems[nColRow].pCell;
1056 :
1057 4374 : if ( bSubTotal && pCell->GetCellType() == CELLTYPE_FORMULA
1058 0 : && ((ScFormulaCell*)pCell)->IsSubTotal() )
1059 0 : nRow++; // Sub-Total-Zeilen nicht
1060 : else
1061 4374 : return pCell; // gefunden
1062 : }
1063 : else
1064 0 : nRow++;
1065 : }
1066 : else
1067 746 : nRow = nEndRow + 1; // Naechste Spalte
1068 : }
1069 : }
1070 :
1071 476 : ScBaseCell* ScCellIterator::GetFirst()
1072 : {
1073 476 : if ( !ValidTab(nTab) )
1074 0 : return NULL;
1075 476 : nCol = nStartCol;
1076 476 : nRow = nStartRow;
1077 476 : nTab = nStartTab;
1078 476 : ScColumn* pCol = &(pDoc->maTabs[nTab])->aCol[nCol];
1079 476 : pCol->Search( nRow, nColRow );
1080 476 : return GetThis();
1081 : }
1082 :
1083 4374 : ScBaseCell* ScCellIterator::GetNext()
1084 : {
1085 4374 : ++nRow;
1086 4374 : return GetThis();
1087 : }
1088 :
1089 : //-------------------------------------------------------------------------------
1090 :
1091 164 : ScQueryCellIterator::ScQueryCellIterator(ScDocument* pDocument, SCTAB nTable,
1092 : const ScQueryParam& rParam, bool bMod ) :
1093 164 : mpParam(new ScQueryParam(rParam)),
1094 : pDoc( pDocument ),
1095 : nTab( nTable),
1096 : nStopOnMismatch( nStopOnMismatchDisabled ),
1097 : nTestEqualCondition( nTestEqualConditionDisabled ),
1098 : bAdvanceQuery( false ),
1099 328 : bIgnoreMismatchOnLeadingStrings( false )
1100 : {
1101 164 : nCol = mpParam->nCol1;
1102 164 : nRow = mpParam->nRow1;
1103 164 : nColRow = 0; // wird bei GetFirst initialisiert
1104 : SCSIZE i;
1105 164 : if (bMod) // sonst schon eingetragen
1106 : {
1107 8 : SCSIZE nCount = mpParam->GetEntryCount();
1108 24 : for (i = 0; (i < nCount) && (mpParam->GetEntry(i).bDoQuery); ++i)
1109 : {
1110 16 : ScQueryEntry& rEntry = mpParam->GetEntry(i);
1111 16 : ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
1112 16 : sal_uInt32 nIndex = 0;
1113 : bool bNumber = pDoc->GetFormatTable()->IsNumberFormat(
1114 16 : rItem.maString, nIndex, rItem.mfVal);
1115 16 : rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
1116 : }
1117 : }
1118 164 : nNumFormat = 0; // werden bei GetNumberFormat initialisiert
1119 164 : pAttrArray = 0;
1120 164 : nAttrEndRow = 0;
1121 164 : }
1122 :
1123 452 : ScBaseCell* ScQueryCellIterator::GetThis()
1124 : {
1125 452 : if (nTab >= pDoc->GetTableCount())
1126 : OSL_FAIL("try to access index out of bounds, FIX IT");
1127 452 : ScColumn* pCol = &(pDoc->maTabs[nTab])->aCol[nCol];
1128 452 : const ScQueryEntry& rEntry = mpParam->GetEntry(0);
1129 452 : const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
1130 :
1131 452 : SCCOLROW nFirstQueryField = rEntry.nField;
1132 : bool bAllStringIgnore = bIgnoreMismatchOnLeadingStrings &&
1133 452 : rItem.meType != ScQueryEntry::ByString;
1134 : bool bFirstStringIgnore = bIgnoreMismatchOnLeadingStrings &&
1135 186 : !mpParam->bHasHeader && rItem.meType == ScQueryEntry::ByString &&
1136 116 : ((mpParam->bByRow && nRow == mpParam->nRow1) ||
1137 754 : (!mpParam->bByRow && nCol == mpParam->nCol1));
1138 524 : for ( ;; )
1139 : {
1140 976 : if ( nRow > mpParam->nRow2 )
1141 : {
1142 88 : nRow = mpParam->nRow1;
1143 88 : if (mpParam->bHasHeader && mpParam->bByRow)
1144 8 : nRow++;
1145 0 : do
1146 : {
1147 88 : if ( ++nCol > mpParam->nCol2 )
1148 88 : 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 2500 : while ( nColRow < pCol->maItems.size() && pCol->maItems[nColRow].nRow < nRow )
1163 724 : nColRow++;
1164 :
1165 2660 : if ( nColRow < pCol->maItems.size() &&
1166 1772 : (nRow = pCol->maItems[nColRow].nRow) <= mpParam->nRow2 )
1167 : {
1168 842 : ScBaseCell* pCell = pCol->maItems[nColRow].pCell;
1169 842 : if ( pCell->GetCellType() == CELLTYPE_NOTE )
1170 0 : ++nRow;
1171 842 : else if (bAllStringIgnore && pCell->HasStringData())
1172 54 : ++nRow;
1173 : else
1174 : {
1175 : bool bTestEqualCondition;
1176 2364 : if ( (pDoc->maTabs[nTab])->ValidQuery( nRow, *mpParam,
1177 : (nCol == static_cast<SCCOL>(nFirstQueryField) ? pCell : NULL),
1178 2364 : (nTestEqualCondition ? &bTestEqualCondition : NULL) ) )
1179 : {
1180 292 : if ( nTestEqualCondition && bTestEqualCondition )
1181 2 : nTestEqualCondition |= nTestEqualConditionMatched;
1182 292 : return pCell; // found
1183 : }
1184 496 : 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 72 : if ( nTestEqualCondition && bTestEqualCondition )
1190 : {
1191 0 : nTestEqualCondition |= nTestEqualConditionMatched;
1192 0 : nStopOnMismatch |= nStopOnMismatchOccurred;
1193 0 : return NULL;
1194 : }
1195 : bool bStop;
1196 72 : 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 72 : bStop = true;
1208 72 : if (bStop)
1209 : {
1210 72 : nStopOnMismatch |= nStopOnMismatchOccurred;
1211 72 : return NULL;
1212 : }
1213 : }
1214 : else
1215 424 : nRow++;
1216 : }
1217 : }
1218 : else
1219 46 : nRow = mpParam->nRow2 + 1; // Naechste Spalte
1220 524 : bFirstStringIgnore = false;
1221 : }
1222 : }
1223 :
1224 66 : ScBaseCell* ScQueryCellIterator::GetFirst()
1225 : {
1226 66 : if (nTab >= pDoc->GetTableCount())
1227 : OSL_FAIL("try to access index out of bounds, FIX IT");
1228 66 : nCol = mpParam->nCol1;
1229 66 : nRow = mpParam->nRow1;
1230 66 : if (mpParam->bHasHeader)
1231 8 : nRow++;
1232 66 : ScColumn* pCol = &(pDoc->maTabs[nTab])->aCol[nCol];
1233 66 : pCol->Search( nRow, nColRow );
1234 66 : return GetThis();
1235 : }
1236 :
1237 288 : ScBaseCell* ScQueryCellIterator::GetNext()
1238 : {
1239 288 : ++nRow;
1240 288 : if ( nStopOnMismatch )
1241 90 : nStopOnMismatch = nStopOnMismatchEnabled;
1242 288 : if ( nTestEqualCondition )
1243 88 : nTestEqualCondition = nTestEqualConditionEnabled;
1244 288 : 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 98 : bool ScQueryCellIterator::FindEqualOrSortedLastInRange( SCCOL& nFoundCol,
1269 : SCROW& nFoundRow, bool bSearchForEqualAfterMismatch,
1270 : bool bIgnoreMismatchOnLeadingStringsP )
1271 : {
1272 98 : nFoundCol = MAXCOL+1;
1273 98 : nFoundRow = MAXROW+1;
1274 98 : SetStopOnMismatch( true ); // assume sorted keys
1275 98 : SetTestEqualCondition( true );
1276 98 : bIgnoreMismatchOnLeadingStrings = bIgnoreMismatchOnLeadingStringsP;
1277 98 : bool bRegExp = mpParam->bRegExp && mpParam->GetEntry(0).GetQueryItem().meType == ScQueryEntry::ByString;
1278 294 : bool bBinary = !bRegExp && mpParam->bByRow && (mpParam->GetEntry(0).eOp ==
1279 294 : SC_LESS_EQUAL || mpParam->GetEntry(0).eOp == SC_GREATER_EQUAL);
1280 98 : if (bBinary ? (BinarySearch() ? GetThis() : 0) : GetFirst())
1281 : {
1282 : // First equal entry or last smaller than (greater than) entry.
1283 : SCSIZE nColRowSave;
1284 88 : ScBaseCell* pNext = 0;
1285 90 : do
1286 : {
1287 90 : nFoundCol = GetCol();
1288 90 : nFoundRow = GetRow();
1289 90 : nColRowSave = nColRow;
1290 90 : } 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 88 : if (!pNext && !IsEqualConditionFulfilled())
1294 : {
1295 : // Step back to last in range and adjust position markers for
1296 : // GetNumberFormat() or similar.
1297 86 : nCol = nFoundCol;
1298 86 : nRow = nFoundRow;
1299 86 : nColRow = nColRowSave;
1300 : }
1301 : }
1302 98 : if ( IsEqualConditionFulfilled() )
1303 : {
1304 : // Position on last equal entry.
1305 2 : SCSIZE nEntries = mpParam->GetEntryCount();
1306 8 : for ( SCSIZE j = 0; j < nEntries; j++ )
1307 : {
1308 4 : ScQueryEntry& rEntry = mpParam->GetEntry( j );
1309 4 : if ( rEntry.bDoQuery )
1310 : {
1311 2 : switch ( rEntry.eOp )
1312 : {
1313 : case SC_LESS_EQUAL :
1314 : case SC_GREATER_EQUAL :
1315 2 : rEntry.eOp = SC_EQUAL;
1316 2 : break;
1317 : default:
1318 : {
1319 : // added to avoid warnings
1320 : }
1321 : }
1322 : }
1323 : else
1324 2 : break; // for
1325 : }
1326 : SCSIZE nColRowSave;
1327 2 : bIgnoreMismatchOnLeadingStrings = false;
1328 2 : SetTestEqualCondition( false );
1329 2 : do
1330 : {
1331 2 : nFoundCol = GetCol();
1332 2 : nFoundRow = GetRow();
1333 2 : nColRowSave = nColRow;
1334 2 : } while (GetNext());
1335 : // Step back conditions same as above
1336 2 : nCol = nFoundCol;
1337 2 : nRow = nFoundRow;
1338 2 : nColRow = nColRowSave;
1339 2 : return true;
1340 : }
1341 96 : 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 96 : return (nFoundCol <= MAXCOL) && (nFoundRow <= MAXROW);
1388 : }
1389 :
1390 :
1391 98 : ScBaseCell* ScQueryCellIterator::BinarySearch()
1392 : {
1393 98 : if (nTab >= pDoc->GetTableCount())
1394 : OSL_FAIL("try to access index out of bounds, FIX IT");
1395 98 : nCol = mpParam->nCol1;
1396 98 : ScColumn* pCol = &(pDoc->maTabs[nTab])->aCol[nCol];
1397 98 : if (!pCol->maItems.size())
1398 0 : return 0;
1399 :
1400 : ScBaseCell* pCell;
1401 : SCSIZE nHi, nLo;
1402 98 : CollatorWrapper* pCollator = (mpParam->bCaseSens ? ScGlobal::GetCaseCollator() :
1403 98 : ScGlobal::GetCollator());
1404 98 : SvNumberFormatter& rFormatter = *(pDoc->GetFormatTable());
1405 98 : const ScQueryEntry& rEntry = mpParam->GetEntry(0);
1406 98 : const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
1407 98 : bool bLessEqual = rEntry.eOp == SC_LESS_EQUAL;
1408 98 : bool bByString = rItem.meType == ScQueryEntry::ByString;
1409 98 : bool bAllStringIgnore = bIgnoreMismatchOnLeadingStrings && !bByString;
1410 : bool bFirstStringIgnore = bIgnoreMismatchOnLeadingStrings &&
1411 98 : !mpParam->bHasHeader && bByString;
1412 :
1413 98 : nRow = mpParam->nRow1;
1414 98 : if (mpParam->bHasHeader)
1415 0 : nRow++;
1416 130 : if (pCol->Search( nRow, nLo ) && bFirstStringIgnore &&
1417 32 : pCol->maItems[nLo].pCell->HasStringData())
1418 : {
1419 8 : rtl::OUString aCellStr;
1420 8 : sal_uLong nFormat = pCol->GetNumberFormat( pCol->maItems[nLo].nRow);
1421 8 : ScCellFormat::GetInputString( pCol->maItems[nLo].pCell, nFormat, aCellStr,
1422 8 : rFormatter);
1423 8 : sal_Int32 nTmp = pCollator->compareString(aCellStr, rEntry.GetQueryItem().maString);
1424 8 : if ((rEntry.eOp == SC_LESS_EQUAL && nTmp > 0) ||
1425 : (rEntry.eOp == SC_GREATER_EQUAL && nTmp < 0) ||
1426 : (rEntry.eOp == SC_EQUAL && nTmp != 0))
1427 2 : ++nLo;
1428 : }
1429 98 : if (!pCol->Search( mpParam->nRow2, nHi ) && nHi>0)
1430 2 : --nHi;
1431 406 : while (bAllStringIgnore && nLo <= nHi && nLo < pCol->maItems.size() &&
1432 138 : pCol->maItems[nLo].pCell->HasStringData())
1433 72 : ++nLo;
1434 :
1435 : // Bookkeeping values for breaking up the binary search in case the data
1436 : // range isn't strictly sorted.
1437 98 : SCSIZE nLastInRange = nLo;
1438 98 : SCSIZE nFirstLastInRange = nLastInRange;
1439 : double fLastInRangeValue = bLessEqual ?
1440 64 : -(::std::numeric_limits<double>::max()) :
1441 162 : ::std::numeric_limits<double>::max();
1442 98 : String aLastInRangeString;
1443 98 : if (!bLessEqual)
1444 34 : aLastInRangeString.Assign( sal_Unicode(0xFFFF));
1445 98 : if (nLastInRange < pCol->maItems.size())
1446 : {
1447 98 : pCell = pCol->maItems[nLastInRange].pCell;
1448 98 : if (pCell->HasStringData())
1449 : {
1450 8 : sal_uLong nFormat = pCol->GetNumberFormat( pCol->maItems[nLastInRange].nRow);
1451 8 : rtl::OUString aStr;
1452 : ScCellFormat::GetInputString( pCell, nFormat, aStr,
1453 8 : rFormatter);
1454 8 : aLastInRangeString = aStr;
1455 : }
1456 : else
1457 : {
1458 90 : switch ( pCell->GetCellType() )
1459 : {
1460 : case CELLTYPE_VALUE :
1461 : fLastInRangeValue =
1462 90 : static_cast<ScValueCell*>(pCell)->GetValue();
1463 90 : 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 98 : sal_Int32 nRes = 0;
1477 98 : bool bFound = false;
1478 98 : bool bDone = false;
1479 552 : while (nLo <= nHi && !bDone)
1480 : {
1481 356 : SCSIZE nMid = (nLo+nHi)/2;
1482 356 : SCSIZE i = nMid;
1483 712 : while (i <= nHi && pCol->maItems[i].pCell->GetCellType() == CELLTYPE_NOTE)
1484 0 : ++i;
1485 356 : 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 356 : bool bStr = pCol->maItems[i].pCell->HasStringData();
1494 356 : nRes = 0;
1495 : // compares are content<query:-1, content>query:1
1496 : // Cell value comparison similar to ScTable::ValidQuery()
1497 356 : if (!bStr && !bByString)
1498 : {
1499 : double nCellVal;
1500 216 : pCell = pCol->maItems[i].pCell;
1501 216 : switch ( pCell->GetCellType() )
1502 : {
1503 : case CELLTYPE_VALUE :
1504 216 : nCellVal = static_cast<ScValueCell*>(pCell)->GetValue();
1505 216 : 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 316 : if ((nCellVal < rItem.mfVal) && !::rtl::math::approxEqual(
1513 100 : nCellVal, rItem.mfVal))
1514 : {
1515 100 : nRes = -1;
1516 100 : if (bLessEqual)
1517 : {
1518 70 : if (fLastInRangeValue < nCellVal)
1519 : {
1520 62 : fLastInRangeValue = nCellVal;
1521 62 : nLastInRange = i;
1522 : }
1523 8 : else if (fLastInRangeValue > nCellVal)
1524 : {
1525 : // not strictly sorted, continue with GetThis()
1526 0 : nLastInRange = nFirstLastInRange;
1527 0 : bDone = true;
1528 : }
1529 : }
1530 : }
1531 232 : else if ((nCellVal > rItem.mfVal) && !::rtl::math::approxEqual(
1532 116 : nCellVal, rItem.mfVal))
1533 : {
1534 116 : nRes = 1;
1535 116 : if (!bLessEqual)
1536 : {
1537 54 : if (fLastInRangeValue > nCellVal)
1538 : {
1539 52 : fLastInRangeValue = nCellVal;
1540 52 : nLastInRange = i;
1541 : }
1542 2 : else if (fLastInRangeValue < nCellVal)
1543 : {
1544 : // not strictly sorted, continue with GetThis()
1545 0 : nLastInRange = nFirstLastInRange;
1546 0 : bDone = true;
1547 : }
1548 : }
1549 216 : }
1550 : }
1551 140 : else if (bStr && bByString)
1552 : {
1553 76 : rtl::OUString aCellStr;
1554 76 : sal_uLong nFormat = pCol->GetNumberFormat( pCol->maItems[i].nRow);
1555 76 : ScCellFormat::GetInputString( pCol->maItems[i].pCell, nFormat, aCellStr,
1556 76 : rFormatter);
1557 76 : nRes = pCollator->compareString(aCellStr, rEntry.GetQueryItem().maString);
1558 76 : if (nRes < 0 && bLessEqual)
1559 : {
1560 : sal_Int32 nTmp = pCollator->compareString( aLastInRangeString,
1561 38 : aCellStr);
1562 38 : if (nTmp < 0)
1563 : {
1564 36 : aLastInRangeString = aCellStr;
1565 36 : nLastInRange = i;
1566 : }
1567 2 : else if (nTmp > 0)
1568 : {
1569 : // not strictly sorted, continue with GetThis()
1570 0 : nLastInRange = nFirstLastInRange;
1571 0 : bDone = true;
1572 38 : }
1573 : }
1574 38 : else if (nRes > 0 && !bLessEqual)
1575 : {
1576 : sal_Int32 nTmp = pCollator->compareString( aLastInRangeString,
1577 8 : aCellStr);
1578 8 : if (nTmp > 0)
1579 : {
1580 4 : aLastInRangeString = aCellStr;
1581 4 : nLastInRange = i;
1582 : }
1583 4 : else if (nTmp < 0)
1584 : {
1585 : // not strictly sorted, continue with GetThis()
1586 0 : nLastInRange = nFirstLastInRange;
1587 0 : bDone = true;
1588 : }
1589 76 : }
1590 : }
1591 64 : else if (!bStr && bByString)
1592 : {
1593 40 : nRes = -1; // numeric < string
1594 80 : if (bLessEqual)
1595 28 : nLastInRange = i;
1596 : }
1597 : else // if (bStr && !bByString)
1598 : {
1599 24 : nRes = 1; // string > numeric
1600 24 : if (!bLessEqual)
1601 0 : nLastInRange = i;
1602 : }
1603 356 : if (nRes < 0)
1604 : {
1605 186 : if (bLessEqual)
1606 136 : nLo = nMid + 1;
1607 : else // assumed to be SC_GREATER_EQUAL
1608 : {
1609 50 : if (nMid > 0)
1610 50 : nHi = nMid - 1;
1611 : else
1612 0 : bDone = true;
1613 : }
1614 : }
1615 170 : else if (nRes > 0)
1616 : {
1617 168 : if (bLessEqual)
1618 : {
1619 106 : if (nMid > 0)
1620 104 : nHi = nMid - 1;
1621 : else
1622 2 : bDone = true;
1623 : }
1624 : else // assumed to be SC_GREATER_EQUAL
1625 62 : nLo = nMid + 1;
1626 : }
1627 : else
1628 : {
1629 2 : nLo = i;
1630 2 : bDone = bFound = true;
1631 : }
1632 : }
1633 98 : 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 96 : nLo = nLastInRange;
1644 : }
1645 98 : if (nLo < pCol->maItems.size() && pCol->maItems[nLo].nRow <= mpParam->nRow2)
1646 : {
1647 98 : nRow = pCol->maItems[nLo].nRow;
1648 98 : pCell = pCol->maItems[nLo].pCell;
1649 98 : 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 98 : return pCell;
1658 : }
1659 :
1660 :
1661 : //-------------------------------------------------------------------------------
1662 :
1663 44 : 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 44 : bMore( true )
1674 : {
1675 44 : if (nTab >= pDoc->GetTableCount())
1676 : OSL_FAIL("try to access index out of bounds, FIX IT");
1677 :
1678 44 : pNextRows = new SCROW[ nCol2-nCol1+1 ];
1679 44 : pNextIndices = new SCSIZE[ nCol2-nCol1+1 ];
1680 :
1681 44 : SetTab( nTab );
1682 44 : }
1683 :
1684 44 : ScHorizontalCellIterator::~ScHorizontalCellIterator()
1685 : {
1686 44 : delete [] pNextRows;
1687 44 : delete [] pNextIndices;
1688 44 : }
1689 :
1690 44 : void ScHorizontalCellIterator::SetTab( SCTAB nTabP )
1691 : {
1692 44 : nTab = nTabP;
1693 44 : nRow = nStartRow;
1694 44 : nCol = nStartCol;
1695 44 : bMore = true;
1696 :
1697 21760 : for (SCCOL i=nStartCol; i<=nEndCol; i++)
1698 : {
1699 21716 : ScColumn* pCol = &pDoc->maTabs[nTab]->aCol[i];
1700 :
1701 : SCSIZE nIndex;
1702 21716 : pCol->Search( nStartRow, nIndex );
1703 21716 : if ( nIndex < pCol->maItems.size() )
1704 : {
1705 26 : pNextRows[i-nStartCol] = pCol->maItems[nIndex].nRow;
1706 26 : pNextIndices[i-nStartCol] = nIndex;
1707 : }
1708 : else
1709 : {
1710 21690 : pNextRows[i-nStartCol] = MAXROWCOUNT; // nichts gefunden
1711 21690 : pNextIndices[i-nStartCol] = MAXROWCOUNT;
1712 : }
1713 : }
1714 :
1715 44 : if (pNextRows[0] != nStartRow)
1716 37 : Advance();
1717 44 : }
1718 :
1719 400 : ScBaseCell* ScHorizontalCellIterator::GetNext( SCCOL& rCol, SCROW& rRow )
1720 : {
1721 400 : if ( bMore )
1722 : {
1723 362 : rCol = nCol;
1724 362 : rRow = nRow;
1725 :
1726 362 : ScColumn* pCol = &pDoc->maTabs[nTab]->aCol[nCol];
1727 362 : SCSIZE nIndex = pNextIndices[nCol-nStartCol];
1728 : OSL_ENSURE( nIndex < pCol->maItems.size(), "ScHorizontalCellIterator::GetNext: nIndex out of range" );
1729 362 : ScBaseCell* pCell = pCol->maItems[nIndex].pCell;
1730 362 : if ( ++nIndex < pCol->maItems.size() )
1731 : {
1732 336 : pNextRows[nCol-nStartCol] = pCol->maItems[nIndex].nRow;
1733 336 : pNextIndices[nCol-nStartCol] = nIndex;
1734 : }
1735 : else
1736 : {
1737 26 : pNextRows[nCol-nStartCol] = MAXROWCOUNT; // nichts gefunden
1738 26 : pNextIndices[nCol-nStartCol] = MAXROWCOUNT;
1739 : }
1740 :
1741 362 : Advance();
1742 362 : return pCell;
1743 : }
1744 : else
1745 38 : return NULL;
1746 : }
1747 :
1748 8 : bool ScHorizontalCellIterator::ReturnNext( SCCOL& rCol, SCROW& rRow )
1749 : {
1750 8 : rCol = nCol;
1751 8 : rRow = nRow;
1752 8 : return bMore;
1753 : }
1754 :
1755 399 : void ScHorizontalCellIterator::Advance()
1756 : {
1757 399 : bool bFound = false;
1758 : SCCOL i;
1759 :
1760 66040 : for (i=nCol+1; i<=nEndCol && !bFound; i++)
1761 65641 : if (pNextRows[i-nStartCol] == nRow)
1762 : {
1763 310 : nCol = i;
1764 310 : bFound = true;
1765 : }
1766 :
1767 399 : if (!bFound)
1768 : {
1769 89 : SCROW nMinRow = MAXROW+1;
1770 65861 : for (i=nStartCol; i<=nEndCol; i++)
1771 65772 : if (pNextRows[i-nStartCol] < nMinRow)
1772 : {
1773 45 : nCol = i;
1774 45 : nMinRow = pNextRows[i-nStartCol];
1775 : }
1776 :
1777 89 : if (nMinRow <= nEndRow)
1778 : {
1779 45 : nRow = nMinRow;
1780 45 : bFound = true;
1781 : }
1782 : }
1783 :
1784 399 : if ( !bFound )
1785 44 : bMore = false;
1786 399 : }
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 2 : 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 2 : nEndRow( nRow2 )
1921 : {
1922 2 : 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 2 : nRow = nStartRow;
1929 2 : nCol = nStartCol;
1930 2 : bRowEmpty = false;
1931 :
1932 2 : pIndices = new SCSIZE[nEndCol-nStartCol+1];
1933 2 : pNextEnd = new SCROW[nEndCol-nStartCol+1];
1934 2 : ppPatterns = new const ScPatternAttr*[nEndCol-nStartCol+1];
1935 :
1936 2 : SCROW nSkipTo = MAXROW;
1937 2 : bool bEmpty = true;
1938 2050 : for (i=nStartCol; i<=nEndCol; i++)
1939 : {
1940 2048 : SCCOL nPos = i - nStartCol;
1941 2048 : ScAttrArray* pArray = pDoc->maTabs[nTab]->aCol[i].pAttrArray;
1942 : OSL_ENSURE( pArray, "pArray == 0" );
1943 :
1944 : SCSIZE nIndex;
1945 2048 : pArray->Search( nStartRow, nIndex );
1946 :
1947 2048 : const ScPatternAttr* pPattern = pArray->pData[nIndex].pPattern;
1948 2048 : SCROW nThisEnd = pArray->pData[nIndex].nRow;
1949 2048 : if ( IsDefaultItem( pPattern ) )
1950 : {
1951 2048 : pPattern = NULL;
1952 2048 : if ( nThisEnd < nSkipTo )
1953 2 : nSkipTo = nThisEnd; // nSkipTo kann gleich hier gesetzt werden
1954 : }
1955 : else
1956 0 : bEmpty = false; // Attribute gefunden
1957 :
1958 2048 : pIndices[nPos] = nIndex;
1959 2048 : pNextEnd[nPos] = nThisEnd;
1960 2048 : ppPatterns[nPos] = pPattern;
1961 : }
1962 :
1963 2 : if (bEmpty)
1964 2 : nRow = nSkipTo; // bis zum naechsten Bereichsende ueberspringen
1965 2 : bRowEmpty = bEmpty;
1966 2 : }
1967 :
1968 2 : ScHorizontalAttrIterator::~ScHorizontalAttrIterator()
1969 : {
1970 2 : delete[] (ScPatternAttr**)ppPatterns;
1971 2 : delete[] pNextEnd;
1972 2 : delete[] pIndices;
1973 2 : }
1974 :
1975 338 : const ScPatternAttr* ScHorizontalAttrIterator::GetNext( SCCOL& rCol1, SCCOL& rCol2, SCROW& rRow )
1976 : {
1977 338 : if (nTab >= pDoc->GetTableCount())
1978 : OSL_FAIL("try to access index out of bounds, FIX IT");
1979 42 : for (;;)
1980 : {
1981 380 : if (!bRowEmpty)
1982 : {
1983 : // in dieser Zeile suchen
1984 :
1985 43428 : while ( nCol <= nEndCol && !ppPatterns[nCol-nStartCol] )
1986 42672 : ++nCol;
1987 :
1988 378 : if ( nCol <= nEndCol )
1989 : {
1990 336 : const ScPatternAttr* pPat = ppPatterns[nCol-nStartCol];
1991 336 : rRow = nRow;
1992 336 : rCol1 = nCol;
1993 672 : while ( nCol < nEndCol && ppPatterns[nCol+1-nStartCol] == pPat )
1994 0 : ++nCol;
1995 336 : rCol2 = nCol;
1996 336 : ++nCol; // hochzaehlen fuer naechsten Aufruf
1997 336 : return pPat; // gefunden
1998 : }
1999 : }
2000 :
2001 : // naechste Zeile
2002 :
2003 44 : ++nRow;
2004 44 : if ( nRow > nEndRow ) // schon am Ende?
2005 2 : return NULL; // nichts gefunden
2006 :
2007 42 : bool bEmpty = true;
2008 : SCCOL i;
2009 :
2010 43050 : for ( i = nStartCol; i <= nEndCol; i++)
2011 : {
2012 43008 : SCCOL nPos = i-nStartCol;
2013 43008 : if ( pNextEnd[nPos] < nRow )
2014 : {
2015 16 : ScAttrArray* pArray = pDoc->maTabs[nTab]->aCol[i].pAttrArray;
2016 :
2017 16 : SCSIZE nIndex = ++pIndices[nPos];
2018 16 : if ( nIndex < pArray->nCount )
2019 : {
2020 16 : const ScPatternAttr* pPattern = pArray->pData[nIndex].pPattern;
2021 16 : SCROW nThisEnd = pArray->pData[nIndex].nRow;
2022 16 : if ( IsDefaultItem( pPattern ) )
2023 0 : pPattern = NULL;
2024 : else
2025 16 : bEmpty = false; // Attribute gefunden
2026 :
2027 16 : pNextEnd[nPos] = nThisEnd;
2028 16 : 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 42992 : else if ( ppPatterns[nPos] )
2040 320 : bEmpty = false; // Bereich noch nicht zuende
2041 : }
2042 :
2043 42 : 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 42 : bRowEmpty = bEmpty;
2053 42 : nCol = nStartCol; // wieder links anfangen
2054 : }
2055 : }
2056 :
2057 : //-------------------------------------------------------------------------------
2058 :
2059 1060 : inline bool IsGreater( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
2060 : {
2061 1060 : return ( nRow1 > nRow2 ) || ( nRow1 == nRow2 && nCol1 > nCol2 );
2062 : }
2063 :
2064 2 : 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 2 : nNextRow( nRow1 )
2070 : {
2071 2 : pCell = aCellIter.GetNext( nCellCol, nCellRow );
2072 2 : pPattern = aAttrIter.GetNext( nAttrCol1, nAttrCol2, nAttrRow );
2073 2 : }
2074 :
2075 2 : ScUsedAreaIterator::~ScUsedAreaIterator()
2076 : {
2077 2 : }
2078 :
2079 354 : bool ScUsedAreaIterator::GetNext()
2080 : {
2081 : // Iteratoren weiterzaehlen
2082 :
2083 354 : if ( pCell && IsGreater( nNextCol, nNextRow, nCellCol, nCellRow ) )
2084 352 : pCell = aCellIter.GetNext( nCellCol, nCellRow );
2085 :
2086 708 : while ( pCell && pCell->IsBlank() )
2087 0 : pCell = aCellIter.GetNext( nCellCol, nCellRow );
2088 :
2089 354 : if ( pPattern && IsGreater( nNextCol, nNextRow, nAttrCol2, nAttrRow ) )
2090 336 : pPattern = aAttrIter.GetNext( nAttrCol1, nAttrCol2, nAttrRow );
2091 :
2092 354 : if ( pPattern && nAttrRow == nNextRow && nAttrCol1 < nNextCol )
2093 0 : nAttrCol1 = nNextCol;
2094 :
2095 : // naechsten Abschnitt heraussuchen
2096 :
2097 354 : bool bFound = true;
2098 354 : bool bUseCell = false;
2099 :
2100 354 : if ( pCell && pPattern )
2101 : {
2102 704 : 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 352 : bUseCell = true;
2116 352 : if ( nAttrRow == nCellRow && nAttrCol1 == nCellCol ) // Attribute auf der Zelle ?
2117 336 : pFoundPattern = pPattern;
2118 : else
2119 16 : pFoundPattern = NULL;
2120 : }
2121 : }
2122 2 : else if ( pCell ) // nur Zelle -> direkt uebernehmen
2123 : {
2124 0 : pFoundPattern = NULL;
2125 0 : bUseCell = true; // Position von Zelle
2126 : }
2127 2 : 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 2 : bFound = false;
2137 :
2138 354 : if ( bUseCell ) // Position von Zelle
2139 : {
2140 352 : pFoundCell = pCell;
2141 352 : nFoundRow = nCellRow;
2142 352 : nFoundStartCol = nFoundEndCol = nCellCol;
2143 : }
2144 :
2145 354 : if (bFound)
2146 : {
2147 352 : nNextRow = nFoundRow;
2148 352 : nNextCol = nFoundEndCol + 1;
2149 : }
2150 :
2151 354 : return bFound;
2152 : }
2153 :
2154 : //-------------------------------------------------------------------------------
2155 :
2156 6 : 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 6 : nCol( nCol1 )
2165 : {
2166 6 : if ( ValidTab(nTab) && nTab < pDoc->GetTableCount() && pDoc->maTabs[nTab] )
2167 6 : pColIter = pDoc->maTabs[nTab]->aCol[nCol].CreateAttrIterator( nStartRow, nEndRow );
2168 : else
2169 0 : pColIter = NULL;
2170 6 : }
2171 :
2172 6 : ScDocAttrIterator::~ScDocAttrIterator()
2173 : {
2174 6 : delete pColIter;
2175 6 : }
2176 :
2177 2054 : const ScPatternAttr* ScDocAttrIterator::GetNext( SCCOL& rCol, SCROW& rRow1, SCROW& rRow2 )
2178 : {
2179 6156 : while ( pColIter )
2180 : {
2181 4100 : const ScPatternAttr* pPattern = pColIter->Next( rRow1, rRow2 );
2182 4100 : if ( pPattern )
2183 : {
2184 2052 : rCol = nCol;
2185 2052 : return pPattern;
2186 : }
2187 :
2188 2048 : delete pColIter;
2189 2048 : ++nCol;
2190 2048 : if ( nCol <= nEndCol )
2191 2046 : pColIter = pDoc->maTabs[nTab]->aCol[nCol].CreateAttrIterator( nStartRow, nEndRow );
2192 : else
2193 2 : pColIter = NULL;
2194 : }
2195 2 : 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 14 : ScDocRowHeightUpdater::ScDocRowHeightUpdater(ScDocument& rDoc, OutputDevice* pOutDev, double fPPTX, double fPPTY, const vector<TabRanges>* pTabRangesArray) :
2206 14 : mrDoc(rDoc), mpOutDev(pOutDev), mfPPTX(fPPTX), mfPPTY(fPPTY), mpTabRangesArray(pTabRangesArray)
2207 : {
2208 14 : }
2209 :
2210 14 : void ScDocRowHeightUpdater::update()
2211 : {
2212 14 : if (!mpTabRangesArray || mpTabRangesArray->empty())
2213 : {
2214 : // No ranges defined. Update all rows in all tables.
2215 14 : updateAll();
2216 14 : 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 14 : void ScDocRowHeightUpdater::updateAll()
2261 : {
2262 14 : sal_uInt32 nCellCount = 0;
2263 28 : for (SCTAB nTab = 0; nTab < mrDoc.GetTableCount(); ++nTab)
2264 : {
2265 14 : if (!ValidTab(nTab) || !mrDoc.maTabs[nTab])
2266 0 : continue;
2267 :
2268 14 : nCellCount += mrDoc.maTabs[nTab]->GetWeightedCount();
2269 : }
2270 :
2271 14 : ScProgress aProgress(mrDoc.GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING), nCellCount);
2272 :
2273 14 : Fraction aZoom(1, 1);
2274 14 : sal_uLong nProgressStart = 0;
2275 28 : for (SCTAB nTab = 0; nTab < mrDoc.GetTableCount(); ++nTab)
2276 : {
2277 14 : if (!ValidTab(nTab) || !mrDoc.maTabs[nTab])
2278 0 : continue;
2279 :
2280 14 : mrDoc.maTabs[nTab]->SetOptimalHeight(
2281 28 : 0, MAXROW, 0, mpOutDev, mfPPTX, mfPPTY, aZoom, aZoom, false, &aProgress, nProgressStart);
2282 :
2283 14 : nProgressStart += mrDoc.maTabs[nTab]->GetWeightedCount();
2284 14 : }
2285 14 : }
2286 :
2287 : //-------------------------------------------------------------------------------
2288 :
2289 4 : 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 4 : nIterEndCol( nCol1 )
2299 : {
2300 4 : if ( ValidTab(nTab) && nTab < pDoc->GetTableCount() && pDoc->maTabs[nTab] )
2301 : {
2302 4 : pColIter = pDoc->maTabs[nTab]->aCol[nIterStartCol].CreateAttrIterator( nStartRow, nEndRow );
2303 8192 : while ( nIterEndCol < nEndCol &&
2304 4092 : pDoc->maTabs[nTab]->aCol[nIterEndCol].IsAllAttrEqual(
2305 8184 : pDoc->maTabs[nTab]->aCol[nIterEndCol+1], nStartRow, nEndRow ) )
2306 4092 : ++nIterEndCol;
2307 : }
2308 : else
2309 0 : pColIter = NULL;
2310 4 : }
2311 :
2312 4 : ScAttrRectIterator::~ScAttrRectIterator()
2313 : {
2314 4 : delete pColIter;
2315 4 : }
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 8 : const ScPatternAttr* ScAttrRectIterator::GetNext( SCCOL& rCol1, SCCOL& rCol2,
2328 : SCROW& rRow1, SCROW& rRow2 )
2329 : {
2330 20 : while ( pColIter )
2331 : {
2332 8 : const ScPatternAttr* pPattern = pColIter->Next( rRow1, rRow2 );
2333 8 : if ( pPattern )
2334 : {
2335 4 : rCol1 = nIterStartCol;
2336 4 : rCol2 = nIterEndCol;
2337 4 : return pPattern;
2338 : }
2339 :
2340 4 : delete pColIter;
2341 4 : nIterStartCol = nIterEndCol+1;
2342 4 : 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 4 : pColIter = NULL;
2353 : }
2354 4 : return NULL; // is nix mehr
2355 : }
2356 :
2357 : // ============================================================================
2358 :
2359 : SCROW ScRowBreakIterator::NOT_FOUND = -1;
2360 :
2361 38 : ScRowBreakIterator::ScRowBreakIterator(set<SCROW>& rBreaks) :
2362 : mrBreaks(rBreaks),
2363 38 : maItr(rBreaks.begin()), maEnd(rBreaks.end())
2364 : {
2365 38 : }
2366 :
2367 38 : SCROW ScRowBreakIterator::first()
2368 : {
2369 38 : maItr = mrBreaks.begin();
2370 38 : 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: */
|