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