LCOV - code coverage report
Current view: top level - libreoffice/sc/source/core/data - dociter.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 757 1246 60.8 %
Date: 2012-12-27 Functions: 55 84 65.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10