LCOV - code coverage report
Current view: top level - sc/source/core/tool - consoli.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 63 399 15.8 %
Date: 2015-06-13 12:38:46 Functions: 11 20 55.0 %
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 "consoli.hxx"
      21             : #include "document.hxx"
      22             : #include "olinetab.hxx"
      23             : #include "globstr.hrc"
      24             : #include "subtotal.hxx"
      25             : #include <formula/errorcodes.hxx>
      26             : #include "formulacell.hxx"
      27             : #include "tokenarray.hxx"
      28             : #include <osl/diagnose.h>
      29             : 
      30             : #include <math.h>
      31             : #include <string.h>
      32             : #include <boost/scoped_array.hpp>
      33             : 
      34             : #define SC_CONS_NOTFOUND    -1
      35             : 
      36             : // STATIC DATA
      37             : static const OpCode eOpCodeTable[] = {      //  order as for enum ScSubTotalFunc
      38             :         ocBad,                              //  none
      39             :         ocAverage,
      40             :         ocCount,
      41             :         ocCount2,
      42             :         ocMax,
      43             :         ocMin,
      44             :         ocProduct,
      45             :         ocStDev,
      46             :         ocStDevP,
      47             :         ocSum,
      48             :         ocVar,
      49             :         ocVarP };
      50             : 
      51           0 : void ScReferenceList::AddEntry( SCCOL nCol, SCROW nRow, SCTAB nTab )
      52             : {
      53           0 :     ScReferenceEntry* pOldData = pData;
      54           0 :     pData = new ScReferenceEntry[ nFullSize+1 ];
      55           0 :     if (pOldData)
      56             :     {
      57           0 :         memcpy( pData, pOldData, nCount * sizeof(ScReferenceEntry) );
      58           0 :         delete[] pOldData;
      59             :     }
      60           0 :     while (nCount < nFullSize)
      61             :     {
      62           0 :         pData[nCount].nCol = SC_CONS_NOTFOUND;
      63           0 :         pData[nCount].nRow = SC_CONS_NOTFOUND;
      64           0 :         pData[nCount].nTab = SC_CONS_NOTFOUND;
      65           0 :         ++nCount;
      66             :     }
      67           0 :     pData[nCount].nCol = nCol;
      68           0 :     pData[nCount].nRow = nRow;
      69           0 :     pData[nCount].nTab = nTab;
      70           0 :     ++nCount;
      71           0 :     nFullSize = nCount;
      72           0 : }
      73             : 
      74             : template< typename T >
      75           0 : static void lcl_AddString( ::std::vector<OUString>& rData, T& nCount, const OUString& rInsert )
      76             : {
      77           0 :     rData.push_back( rInsert);
      78           0 :     ++nCount;
      79           0 : }
      80             : 
      81           1 : ScConsData::ScConsData() :
      82             :     eFunction(SUBTOTAL_FUNC_SUM),
      83             :     bReference(false),
      84             :     bColByName(false),
      85             :     bRowByName(false),
      86             :     nColCount(0),
      87             :     nRowCount(0),
      88             :     ppUsed(NULL),
      89             :     ppSum(NULL),
      90             :     ppCount(NULL),
      91             :     ppSumSqr(NULL),
      92             :     ppRefs(NULL),
      93             :     nDataCount(0),
      94             :     ppTitlePos(NULL),
      95           1 :     bCornerUsed(false)
      96             : {
      97           1 : }
      98             : 
      99           2 : ScConsData::~ScConsData()
     100             : {
     101           1 :     DeleteData();
     102           1 : }
     103             : 
     104             : #define DELETEARR(ppArray,nCount)   \
     105             : {                                   \
     106             :     sal_uLong i;                        \
     107             :     if (ppArray)                    \
     108             :         for(i=0; i<nCount; i++)     \
     109             :             delete[] ppArray[i];    \
     110             :     delete[] ppArray;               \
     111             :     ppArray = NULL;                 \
     112             : }
     113             : 
     114           3 : void ScConsData::DeleteData()
     115             : {
     116           3 :     if (ppRefs)
     117             :     {
     118           0 :         for (SCSIZE i=0; i<nColCount; i++)
     119             :         {
     120           0 :             for (SCSIZE j=0; j<nRowCount; j++)
     121           0 :                 if (ppUsed[i][j])
     122           0 :                     ppRefs[i][j].Clear();
     123           0 :             delete[] ppRefs[i];
     124             :         }
     125           0 :         delete[] ppRefs;
     126           0 :         ppRefs = NULL;
     127             :     }
     128             : 
     129           3 :     DELETEARR( ppCount, nColCount );
     130           3 :     DELETEARR( ppSum,   nColCount );
     131           3 :     DELETEARR( ppSumSqr,nColCount );
     132           3 :     DELETEARR( ppUsed,  nColCount );                // only after ppRefs !!!
     133           3 :     DELETEARR( ppTitlePos, nRowCount );
     134           3 :     ::std::vector<OUString>().swap( maColHeaders);
     135           3 :     ::std::vector<OUString>().swap( maRowHeaders);
     136           3 :     ::std::vector<OUString>().swap( maTitles);
     137           3 :     nDataCount = 0;
     138             : 
     139           3 :     if (bColByName) nColCount = 0;                  // otherwise maColHeaders is wrong
     140           3 :     if (bRowByName) nRowCount = 0;
     141             : 
     142           3 :     bCornerUsed = false;
     143           3 :     aCornerText.clear();
     144           3 : }
     145             : 
     146             : #undef DELETEARR
     147             : #undef DELETESTR
     148             : 
     149           1 : void ScConsData::InitData()
     150             : {
     151           1 :     if (bReference && nColCount && !ppRefs)
     152             :     {
     153           0 :         ppRefs = new ScReferenceList*[nColCount];
     154           0 :         for (SCSIZE i=0; i<nColCount; i++)
     155           0 :             ppRefs[i] = new ScReferenceList[nRowCount];
     156             :     }
     157           1 :     else if (nColCount && !ppCount)
     158             :     {
     159           0 :         ppCount  = new double*[nColCount];
     160           0 :         ppSum    = new double*[nColCount];
     161           0 :         ppSumSqr = new double*[nColCount];
     162           0 :         for (SCSIZE i=0; i<nColCount; i++)
     163             :         {
     164           0 :             ppCount[i]  = new double[nRowCount];
     165           0 :             ppSum[i]    = new double[nRowCount];
     166           0 :             ppSumSqr[i] = new double[nRowCount];
     167             :         }
     168             :     }
     169             : 
     170           1 :     if (nColCount && !ppUsed)
     171             :     {
     172           0 :         ppUsed = new bool*[nColCount];
     173           0 :         for (SCSIZE i=0; i<nColCount; i++)
     174             :         {
     175           0 :             ppUsed[i] = new bool[nRowCount];
     176           0 :             memset( ppUsed[i], 0, nRowCount * sizeof(bool) );
     177             :         }
     178             :     }
     179             : 
     180           1 :     if (nRowCount && nDataCount && !ppTitlePos)
     181             :     {
     182           0 :         ppTitlePos = new SCSIZE*[nRowCount];
     183           0 :         for (SCSIZE i=0; i<nRowCount; i++)
     184             :         {
     185           0 :             ppTitlePos[i] = new SCSIZE[nDataCount];
     186           0 :             memset( ppTitlePos[i], 0, nDataCount * sizeof(SCSIZE) );    //TODO: not necessary ?
     187             :         }
     188             :     }
     189             : 
     190             :     //  CornerText: single String
     191           1 : }
     192             : 
     193           1 : void ScConsData::DoneFields()
     194             : {
     195           1 :     InitData();
     196           1 : }
     197             : 
     198           1 : void ScConsData::SetSize( SCCOL nCols, SCROW nRows )
     199             : {
     200           1 :     DeleteData();
     201           1 :     nColCount = static_cast<SCSIZE>(nCols);
     202           1 :     nRowCount = static_cast<SCSIZE>(nRows);
     203           1 : }
     204             : 
     205           1 : void ScConsData::GetSize( SCCOL& rCols, SCROW& rRows ) const
     206             : {
     207           1 :     rCols = static_cast<SCCOL>(nColCount);
     208           1 :     rRows = static_cast<SCROW>(nRowCount);
     209           1 : }
     210             : 
     211           1 : void ScConsData::SetFlags( ScSubTotalFunc eFunc, bool bColName, bool bRowName, bool bRef )
     212             : {
     213           1 :     DeleteData();
     214           1 :     bReference = bRef;
     215           1 :     bColByName = bColName;
     216           1 :     if (bColName) nColCount = 0;
     217           1 :     bRowByName = bRowName;
     218           1 :     if (bRowName) nRowCount = 0;
     219           1 :     eFunction = eFunc;
     220           1 : }
     221             : 
     222           0 : void ScConsData::AddFields( ScDocument* pSrcDoc, SCTAB nTab,
     223             :                             SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
     224             : {
     225           0 :     ++nDataCount;
     226             : 
     227           0 :     OUString aTitle;
     228             : 
     229           0 :     SCCOL nStartCol = nCol1;
     230           0 :     SCROW nStartRow = nRow1;
     231           0 :     if (bColByName) ++nStartRow;
     232           0 :     if (bRowByName) ++nStartCol;
     233             : 
     234           0 :     if (bColByName)
     235             :     {
     236           0 :         for (SCCOL nCol=nStartCol; nCol<=nCol2; nCol++)
     237             :         {
     238           0 :             aTitle = pSrcDoc->GetString(nCol, nRow1, nTab);
     239           0 :             if (!aTitle.isEmpty())
     240             :             {
     241           0 :                 bool bFound = false;
     242           0 :                 for (SCSIZE i=0; i<nColCount && !bFound; i++)
     243           0 :                     if ( maColHeaders[i] == aTitle )
     244           0 :                         bFound = true;
     245           0 :                 if (!bFound)
     246           0 :                     lcl_AddString( maColHeaders, nColCount, aTitle );
     247             :             }
     248             :         }
     249             :     }
     250             : 
     251           0 :     if (bRowByName)
     252             :     {
     253           0 :         for (SCROW nRow=nStartRow; nRow<=nRow2; nRow++)
     254             :         {
     255           0 :             aTitle = pSrcDoc->GetString(nCol1, nRow, nTab);
     256           0 :             if (!aTitle.isEmpty())
     257             :             {
     258           0 :                 bool bFound = false;
     259           0 :                 for (SCSIZE i=0; i<nRowCount && !bFound; i++)
     260           0 :                     if ( maRowHeaders[i] == aTitle )
     261           0 :                         bFound = true;
     262           0 :                 if (!bFound)
     263           0 :                     lcl_AddString( maRowHeaders, nRowCount, aTitle );
     264             :             }
     265             :         }
     266           0 :     }
     267           0 : }
     268             : 
     269           0 : void ScConsData::AddName( const OUString& rName )
     270             : {
     271             :     SCSIZE nArrX;
     272             :     SCSIZE nArrY;
     273             : 
     274           0 :     if (bReference)
     275             :     {
     276           0 :         maTitles.push_back( rName);
     277           0 :         size_t nTitleCount = maTitles.size();
     278             : 
     279           0 :         for (nArrY=0; nArrY<nRowCount; nArrY++)
     280             :         {
     281             :             //  set all data to same length
     282             : 
     283           0 :             SCSIZE nMax = 0;
     284           0 :             for (nArrX=0; nArrX<nColCount; nArrX++)
     285           0 :                 if (ppUsed[nArrX][nArrY])
     286           0 :                     nMax = std::max( nMax, ppRefs[nArrX][nArrY].GetCount() );
     287             : 
     288           0 :             for (nArrX=0; nArrX<nColCount; nArrX++)
     289             :             {
     290           0 :                 if (!ppUsed[nArrX][nArrY])
     291             :                 {
     292           0 :                     ppUsed[nArrX][nArrY] = true;
     293           0 :                     ppRefs[nArrX][nArrY].Init();
     294             :                 }
     295           0 :                 ppRefs[nArrX][nArrY].SetFullSize(nMax);
     296             :             }
     297             : 
     298             :             //  store positions
     299             : 
     300           0 :             if (ppTitlePos)
     301           0 :                 if (nTitleCount < nDataCount)
     302           0 :                     ppTitlePos[nArrY][nTitleCount] = nMax;
     303             :         }
     304             :     }
     305           0 : }
     306             : 
     307             : // rCount < 0 <=> error
     308           0 : static void lcl_UpdateArray( ScSubTotalFunc eFunc,
     309             :                          double& rCount, double& rSum, double& rSumSqr, double nVal )
     310             : {
     311           0 :     if (rCount < 0.0)
     312           0 :         return;
     313           0 :     switch (eFunc)
     314             :     {
     315             :         case SUBTOTAL_FUNC_SUM:
     316           0 :             if (!SubTotal::SafePlus(rSum, nVal))
     317           0 :                 rCount = -MAXDOUBLE;
     318           0 :             break;
     319             :         case SUBTOTAL_FUNC_PROD:
     320           0 :             if (!SubTotal::SafeMult(rSum, nVal))
     321           0 :                 rCount = -MAXDOUBLE;
     322           0 :             break;
     323             :         case SUBTOTAL_FUNC_CNT:
     324             :         case SUBTOTAL_FUNC_CNT2:
     325           0 :             rCount += 1.0;
     326           0 :             break;
     327             :         case SUBTOTAL_FUNC_AVE:
     328           0 :             if (!SubTotal::SafePlus(rSum, nVal))
     329           0 :                 rCount = -MAXDOUBLE;
     330             :             else
     331           0 :                 rCount += 1.0;
     332           0 :             break;
     333             :         case SUBTOTAL_FUNC_MAX:
     334           0 :             if (nVal > rSum)
     335           0 :                 rSum = nVal;
     336           0 :             break;
     337             :         case SUBTOTAL_FUNC_MIN:
     338           0 :             if (nVal < rSum)
     339           0 :                 rSum = nVal;
     340           0 :             break;
     341             :         case SUBTOTAL_FUNC_STD:
     342             :         case SUBTOTAL_FUNC_STDP:
     343             :         case SUBTOTAL_FUNC_VAR:
     344             :         case SUBTOTAL_FUNC_VARP:
     345             :         {
     346           0 :             bool bOk = SubTotal::SafePlus(rSum, nVal);
     347           0 :             bOk = bOk && SubTotal::SafeMult(nVal, nVal);
     348           0 :             bOk = bOk && SubTotal::SafePlus(rSumSqr, nVal);
     349           0 :             if (!bOk)
     350           0 :                 rCount = -MAXDOUBLE;
     351             :             else
     352           0 :                 rCount += 1.0;
     353           0 :             break;
     354             :         }
     355             :         default:
     356             :         {
     357             :             // added to avoid warnings
     358             :         }
     359             :     }
     360             : }
     361             : 
     362           0 : static void lcl_InitArray( ScSubTotalFunc eFunc,
     363             :                        double& rCount, double& rSum, double& rSumSqr, double nVal )
     364             : {
     365           0 :     rCount = 1.0;
     366           0 :     switch (eFunc)
     367             :     {
     368             :         case SUBTOTAL_FUNC_SUM:
     369             :         case SUBTOTAL_FUNC_MAX:
     370             :         case SUBTOTAL_FUNC_MIN:
     371             :         case SUBTOTAL_FUNC_PROD:
     372             :         case SUBTOTAL_FUNC_AVE:
     373           0 :             rSum = nVal;
     374           0 :             break;
     375             :         case SUBTOTAL_FUNC_STD:
     376             :         case SUBTOTAL_FUNC_STDP:
     377             :         case SUBTOTAL_FUNC_VAR:
     378             :         case SUBTOTAL_FUNC_VARP:
     379             :         {
     380           0 :             rSum = nVal;
     381           0 :             bool bOk = SubTotal::SafeMult(nVal, nVal);
     382           0 :             if (bOk)
     383           0 :                 rSumSqr = nVal;
     384             :             else
     385           0 :                 rCount = -MAXDOUBLE;
     386             :         }
     387           0 :             break;
     388             :         default:
     389           0 :             break;
     390             :     }
     391           0 : }
     392             : 
     393           0 : static double lcl_CalcData( ScSubTotalFunc eFunc,
     394             :                         double& fCount, double fSum, double fSumSqr)
     395             : {
     396           0 :     if (fCount < 0.0)
     397           0 :         return 0.0;
     398           0 :     double fVal = 0.0;
     399           0 :     switch (eFunc)
     400             :     {
     401             :         case SUBTOTAL_FUNC_CNT:
     402             :         case SUBTOTAL_FUNC_CNT2:
     403           0 :             fVal = fCount;
     404           0 :             break;
     405             :         case SUBTOTAL_FUNC_SUM:
     406             :         case SUBTOTAL_FUNC_MAX:
     407             :         case SUBTOTAL_FUNC_MIN:
     408             :         case SUBTOTAL_FUNC_PROD:
     409           0 :             fVal = fSum;
     410           0 :             break;
     411             :         case SUBTOTAL_FUNC_AVE:
     412           0 :             if (fCount > 0.0)
     413           0 :                 fVal = fSum / fCount;
     414             :             else
     415           0 :                 fCount = -MAXDOUBLE;
     416           0 :             break;
     417             :         case SUBTOTAL_FUNC_STD:
     418             :         {
     419           0 :             if (fCount > 1 && SubTotal::SafeMult(fSum, fSum))
     420           0 :                 fVal = sqrt((fSumSqr - fSum/fCount)/(fCount-1.0));
     421             :             else
     422           0 :                 fCount = -MAXDOUBLE;
     423             :         }
     424           0 :             break;
     425             :         case SUBTOTAL_FUNC_STDP:
     426             :         {
     427           0 :             if (fCount > 0 && SubTotal::SafeMult(fSum, fSum))
     428           0 :                 fVal = sqrt((fSumSqr - fSum/fCount)/fCount);
     429             :             else
     430           0 :                 fCount = -MAXDOUBLE;
     431             :         }
     432           0 :             break;
     433             :         case SUBTOTAL_FUNC_VAR:
     434             :         {
     435           0 :             if (fCount > 1 && SubTotal::SafeMult(fSum, fSum))
     436           0 :                 fVal = (fSumSqr - fSum/fCount)/(fCount-1.0);
     437             :             else
     438           0 :                 fCount = -MAXDOUBLE;
     439             :         }
     440           0 :             break;
     441             :         case SUBTOTAL_FUNC_VARP:
     442             :         {
     443           0 :             if (fCount > 0 && SubTotal::SafeMult(fSum, fSum))
     444           0 :                 fVal = (fSumSqr - fSum/fCount)/fCount;
     445             :             else
     446           0 :                 fCount = -MAXDOUBLE;
     447             :         }
     448           0 :             break;
     449             :         default:
     450             :         {
     451             :             OSL_FAIL("Consoli::CalcData: unknown function");
     452           0 :             fCount = -MAXDOUBLE;
     453             :         }
     454           0 :             break;
     455             :     }
     456           0 :     return fVal;
     457             : }
     458             : 
     459           0 : void ScConsData::AddData( ScDocument* pSrcDoc, SCTAB nTab,
     460             :                             SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
     461             : {
     462           0 :     PutInOrder(nCol1,nCol2);
     463           0 :     PutInOrder(nRow1,nRow2);
     464           0 :     if ( nCol2 >= sal::static_int_cast<SCCOL>(nCol1 + nColCount) && !bColByName )
     465             :     {
     466             :         OSL_FAIL("range too big");
     467           0 :         nCol2 = sal::static_int_cast<SCCOL>( nCol1 + nColCount - 1 );
     468             :     }
     469           0 :     if ( nRow2 >= sal::static_int_cast<SCROW>(nRow1 + nRowCount) && !bRowByName )
     470             :     {
     471             :         OSL_FAIL("range too big");
     472           0 :         nRow2 = sal::static_int_cast<SCROW>( nRow1 + nRowCount - 1 );
     473             :     }
     474             : 
     475             :     SCCOL nCol;
     476             :     SCROW nRow;
     477             : 
     478             :     // left top corner
     479             : 
     480           0 :     if ( bColByName && bRowByName )
     481             :     {
     482           0 :         OUString aThisCorner = pSrcDoc->GetString(nCol1, nRow1, nTab);
     483           0 :         if (bCornerUsed)
     484             :         {
     485           0 :             if (aCornerText != aThisCorner)
     486           0 :                 aCornerText.clear();
     487             :         }
     488             :         else
     489             :         {
     490           0 :             aCornerText = aThisCorner;
     491           0 :             bCornerUsed = true;
     492           0 :         }
     493             :     }
     494             : 
     495             :     // search title
     496             : 
     497           0 :     SCCOL nStartCol = nCol1;
     498           0 :     SCROW nStartRow = nRow1;
     499           0 :     if (bColByName) ++nStartRow;
     500           0 :     if (bRowByName) ++nStartCol;
     501           0 :     OUString aTitle;
     502           0 :     boost::scoped_array<SCCOL> pDestCols;
     503           0 :     boost::scoped_array<SCROW> pDestRows;
     504           0 :     if (bColByName)
     505             :     {
     506           0 :         pDestCols.reset(new SCCOL[nCol2-nStartCol+1]);
     507           0 :         for (nCol=nStartCol; nCol<=nCol2; nCol++)
     508             :         {
     509           0 :             aTitle = pSrcDoc->GetString(nCol, nRow1, nTab);
     510           0 :             SCCOL nPos = SC_CONS_NOTFOUND;
     511           0 :             if (!aTitle.isEmpty())
     512             :             {
     513           0 :                 bool bFound = false;
     514           0 :                 for (SCSIZE i=0; i<nColCount && !bFound; i++)
     515           0 :                     if ( maColHeaders[i] == aTitle )
     516             :                     {
     517           0 :                         nPos = static_cast<SCCOL>(i);
     518           0 :                         bFound = true;
     519             :                     }
     520             :                 OSL_ENSURE(bFound, "column not found");
     521             :             }
     522           0 :             pDestCols[nCol-nStartCol] = nPos;
     523             :         }
     524             :     }
     525           0 :     if (bRowByName)
     526             :     {
     527           0 :         pDestRows.reset(new SCROW[nRow2-nStartRow+1]);
     528           0 :         for (nRow=nStartRow; nRow<=nRow2; nRow++)
     529             :         {
     530           0 :             aTitle = pSrcDoc->GetString(nCol1, nRow, nTab);
     531           0 :             SCROW nPos = SC_CONS_NOTFOUND;
     532           0 :             if (!aTitle.isEmpty())
     533             :             {
     534           0 :                 bool bFound = false;
     535           0 :                 for (SCSIZE i=0; i<nRowCount && !bFound; i++)
     536           0 :                     if ( maRowHeaders[i] == aTitle )
     537             :                     {
     538           0 :                         nPos = static_cast<SCROW>(i);
     539           0 :                         bFound = true;
     540             :                     }
     541             :                 OSL_ENSURE(bFound, "row not found");
     542             :             }
     543           0 :             pDestRows[nRow-nStartRow] = nPos;
     544             :         }
     545             :     }
     546           0 :     nCol1 = nStartCol;
     547           0 :     nRow1 = nStartRow;
     548             : 
     549             :     // data
     550             : 
     551           0 :     bool bAnyCell = ( eFunction == SUBTOTAL_FUNC_CNT2 );
     552           0 :     for (nCol=nCol1; nCol<=nCol2; nCol++)
     553             :     {
     554           0 :         SCCOL nArrX = nCol-nCol1;
     555           0 :         if (bColByName) nArrX = pDestCols[nArrX];
     556           0 :         if (nArrX != SC_CONS_NOTFOUND)
     557             :         {
     558           0 :             for (nRow=nRow1; nRow<=nRow2; nRow++)
     559             :             {
     560           0 :                 SCROW nArrY = nRow-nRow1;
     561           0 :                 if (bRowByName) nArrY = pDestRows[nArrY];
     562           0 :                 if ( nArrY != SC_CONS_NOTFOUND && (
     563           0 :                         bAnyCell ? pSrcDoc->HasData( nCol, nRow, nTab )
     564           0 :                                  : pSrcDoc->HasValueData( nCol, nRow, nTab ) ) )
     565             :                 {
     566           0 :                     if (bReference)
     567             :                     {
     568           0 :                         if (ppUsed[nArrX][nArrY])
     569           0 :                             ppRefs[nArrX][nArrY].AddEntry( nCol, nRow, nTab );
     570             :                         else
     571             :                         {
     572           0 :                             ppUsed[nArrX][nArrY] = true;
     573           0 :                             ppRefs[nArrX][nArrY].Init();
     574           0 :                             ppRefs[nArrX][nArrY].AddEntry( nCol, nRow, nTab );
     575             :                         }
     576             :                     }
     577             :                     else
     578             :                     {
     579             :                         double nVal;
     580           0 :                         pSrcDoc->GetValue( nCol, nRow, nTab, nVal );
     581           0 :                         if (ppUsed[nArrX][nArrY])
     582           0 :                             lcl_UpdateArray( eFunction, ppCount[nArrX][nArrY],
     583           0 :                                          ppSum[nArrX][nArrY], ppSumSqr[nArrX][nArrY],
     584           0 :                                          nVal);
     585             :                         else
     586             :                         {
     587           0 :                             ppUsed[nArrX][nArrY] = true;
     588           0 :                             lcl_InitArray( eFunction, ppCount[nArrX][nArrY],
     589           0 :                                                   ppSum[nArrX][nArrY],
     590           0 :                                                   ppSumSqr[nArrX][nArrY], nVal );
     591             :                         }
     592             :                     }
     593             :                 }
     594             :             }
     595             :         }
     596           0 :     }
     597           0 : }
     598             : 
     599             : // check before, how many rows to insert (for Undo)
     600             : 
     601           0 : SCROW ScConsData::GetInsertCount() const
     602             : {
     603           0 :     SCROW nInsert = 0;
     604             :     SCSIZE nArrX;
     605             :     SCSIZE nArrY;
     606           0 :     if ( ppRefs && ppUsed )
     607             :     {
     608           0 :         for (nArrY=0; nArrY<nRowCount; nArrY++)
     609             :         {
     610           0 :             SCSIZE nNeeded = 0;
     611           0 :             for (nArrX=0; nArrX<nColCount; nArrX++)
     612           0 :                 if (ppUsed[nArrX][nArrY])
     613           0 :                     nNeeded = std::max( nNeeded, ppRefs[nArrX][nArrY].GetCount() );
     614             : 
     615           0 :             nInsert += nNeeded;
     616             :         }
     617             :     }
     618           0 :     return nInsert;
     619             : }
     620             : 
     621             : // store completed data to document
     622             : //TODO: optimize on columns?
     623             : 
     624           1 : void ScConsData::OutputToDocument( ScDocument* pDestDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
     625             : {
     626           1 :     OpCode eOpCode = eOpCodeTable[eFunction];
     627             : 
     628             :     SCSIZE nArrX;
     629             :     SCSIZE nArrY;
     630             : 
     631             :     // left top corner
     632             : 
     633           1 :     if ( bColByName && bRowByName && !aCornerText.isEmpty() )
     634           0 :         pDestDoc->SetString( nCol, nRow, nTab, aCornerText );
     635             : 
     636             :     // title
     637             : 
     638           1 :     SCCOL nStartCol = nCol;
     639           1 :     SCROW nStartRow = nRow;
     640           1 :     if (bColByName) ++nStartRow;
     641           1 :     if (bRowByName) ++nStartCol;
     642             : 
     643           1 :     if (bColByName)
     644           0 :         for (SCSIZE i=0; i<nColCount; i++)
     645           0 :             pDestDoc->SetString( sal::static_int_cast<SCCOL>(nStartCol+i), nRow, nTab, maColHeaders[i] );
     646           1 :     if (bRowByName)
     647           0 :         for (SCSIZE j=0; j<nRowCount; j++)
     648           0 :             pDestDoc->SetString( nCol, sal::static_int_cast<SCROW>(nStartRow+j), nTab, maRowHeaders[j] );
     649             : 
     650           1 :     nCol = nStartCol;
     651           1 :     nRow = nStartRow;
     652             : 
     653             :     // data
     654             : 
     655           1 :     if ( ppCount && ppUsed )    // insert values directly
     656             :     {
     657           0 :         for (nArrX=0; nArrX<nColCount; nArrX++)
     658           0 :             for (nArrY=0; nArrY<nRowCount; nArrY++)
     659           0 :                 if (ppUsed[nArrX][nArrY])
     660             :                 {
     661           0 :                     double fVal = lcl_CalcData( eFunction, ppCount[nArrX][nArrY],
     662           0 :                                                 ppSum[nArrX][nArrY],
     663           0 :                                                 ppSumSqr[nArrX][nArrY]);
     664           0 :                     if (ppCount[nArrX][nArrY] < 0.0)
     665           0 :                         pDestDoc->SetError( sal::static_int_cast<SCCOL>(nCol+nArrX),
     666           0 :                                             sal::static_int_cast<SCROW>(nRow+nArrY), nTab, errNoValue );
     667             :                     else
     668           0 :                         pDestDoc->SetValue( sal::static_int_cast<SCCOL>(nCol+nArrX),
     669           0 :                                             sal::static_int_cast<SCROW>(nRow+nArrY), nTab, fVal );
     670             :                 }
     671             :     }
     672             : 
     673           1 :     if ( ppRefs && ppUsed )     // insert Reference
     674             :     {
     675             :                                 //TODO: differentiate, if split into categories
     676           0 :         OUString aString;
     677             : 
     678             :         ScSingleRefData aSRef;  // data for Referece formula cells
     679           0 :         aSRef.InitFlags();      // this reference is absolute at all times
     680           0 :         aSRef.SetFlag3D(true);
     681             : 
     682             :         ScComplexRefData aCRef; // data for Sum cells
     683           0 :         aCRef.InitFlags();
     684           0 :         aCRef.Ref1.SetColRel(true); aCRef.Ref1.SetRowRel(true); aCRef.Ref1.SetTabRel(true);
     685           0 :         aCRef.Ref2.SetColRel(true); aCRef.Ref2.SetRowRel(true); aCRef.Ref2.SetTabRel(true);
     686             : 
     687           0 :         for (nArrY=0; nArrY<nRowCount; nArrY++)
     688             :         {
     689           0 :             SCSIZE nNeeded = 0;
     690           0 :             for (nArrX=0; nArrX<nColCount; nArrX++)
     691           0 :                 if (ppUsed[nArrX][nArrY])
     692           0 :                     nNeeded = std::max( nNeeded, ppRefs[nArrX][nArrY].GetCount() );
     693             : 
     694           0 :             if (nNeeded)
     695             :             {
     696           0 :                 pDestDoc->InsertRow( 0,nTab, MAXCOL,nTab, nRow+nArrY, nNeeded );
     697             : 
     698           0 :                 for (nArrX=0; nArrX<nColCount; nArrX++)
     699           0 :                     if (ppUsed[nArrX][nArrY])
     700             :                     {
     701           0 :                         ScReferenceList& rList = ppRefs[nArrX][nArrY];
     702           0 :                         SCSIZE nCount = rList.GetCount();
     703           0 :                         if (nCount)
     704             :                         {
     705           0 :                             for (SCSIZE nPos=0; nPos<nCount; nPos++)
     706             :                             {
     707           0 :                                 ScReferenceEntry aRef = rList.GetEntry(nPos);
     708           0 :                                 if (aRef.nTab != SC_CONS_NOTFOUND)
     709             :                                 {
     710             :                                     // insert reference (absolute, 3d)
     711             : 
     712           0 :                                     aSRef.SetAddress(ScAddress(aRef.nCol,aRef.nRow,aRef.nTab), ScAddress());
     713             : 
     714           0 :                                     ScTokenArray aRefArr;
     715           0 :                                     aRefArr.AddSingleReference(aSRef);
     716           0 :                                     aRefArr.AddOpCode(ocStop);
     717           0 :                                     ScAddress aDest( sal::static_int_cast<SCCOL>(nCol+nArrX),
     718           0 :                                                      sal::static_int_cast<SCROW>(nRow+nArrY+nPos), nTab );
     719           0 :                                     ScFormulaCell* pCell = new ScFormulaCell(pDestDoc, aDest, aRefArr);
     720           0 :                                     pDestDoc->SetFormulaCell(aDest, pCell);
     721             :                                 }
     722             :                             }
     723             : 
     724             :                             // insert sum (relativ, not 3d)
     725             : 
     726           0 :                             ScAddress aDest( sal::static_int_cast<SCCOL>(nCol+nArrX),
     727           0 :                                              sal::static_int_cast<SCROW>(nRow+nArrY+nNeeded), nTab );
     728             : 
     729           0 :                             ScRange aRange(sal::static_int_cast<SCCOL>(nCol+nArrX), nRow+nArrY, nTab);
     730           0 :                             aRange.aEnd.SetRow(nRow+nArrY+nNeeded-1);
     731           0 :                             aCRef.SetRange(aRange, aDest);
     732             : 
     733           0 :                             ScTokenArray aArr;
     734           0 :                             aArr.AddOpCode(eOpCode);            // selected function
     735           0 :                             aArr.AddOpCode(ocOpen);
     736           0 :                             aArr.AddDoubleReference(aCRef);
     737           0 :                             aArr.AddOpCode(ocClose);
     738           0 :                             aArr.AddOpCode(ocStop);
     739           0 :                             ScFormulaCell* pCell = new ScFormulaCell(pDestDoc, aDest, aArr);
     740           0 :                             pDestDoc->SetFormulaCell(aDest, pCell);
     741             :                         }
     742             :                     }
     743             : 
     744             :                 // insert outline
     745             : 
     746           0 :                 ScOutlineArray& rOutArr = pDestDoc->GetOutlineTable( nTab, true )->GetRowArray();
     747           0 :                 SCROW nOutStart = nRow+nArrY;
     748           0 :                 SCROW nOutEnd = nRow+nArrY+nNeeded-1;
     749           0 :                 bool bSize = false;
     750           0 :                 rOutArr.Insert( nOutStart, nOutEnd, bSize );
     751           0 :                 for (SCROW nOutRow=nOutStart; nOutRow<=nOutEnd; nOutRow++)
     752           0 :                     pDestDoc->ShowRow( nOutRow, nTab, false );
     753           0 :                 pDestDoc->SetDrawPageSize(nTab);
     754           0 :                 pDestDoc->UpdateOutlineRow( nOutStart, nOutEnd, nTab, false );
     755             : 
     756             :                 // sub title
     757             : 
     758           0 :                 if (ppTitlePos && !maTitles.empty() && !maRowHeaders.empty())
     759             :                 {
     760           0 :                     OUString aDelim( " / " );
     761           0 :                     for (SCSIZE nPos=0; nPos<nDataCount; nPos++)
     762             :                     {
     763           0 :                         SCSIZE nTPos = ppTitlePos[nArrY][nPos];
     764           0 :                         bool bDo = true;
     765           0 :                         if (nPos+1<nDataCount)
     766           0 :                             if (ppTitlePos[nArrY][nPos+1] == nTPos)
     767           0 :                                 bDo = false;                                    // empty
     768           0 :                         if ( bDo && nTPos < nNeeded )
     769             :                         {
     770           0 :                             aString =  maRowHeaders[nArrY];
     771           0 :                             aString += aDelim;
     772           0 :                             aString += maTitles[nPos];
     773           0 :                             pDestDoc->SetString( nCol-1, nRow+nArrY+nTPos, nTab, aString );
     774             :                         }
     775           0 :                     }
     776             :                 }
     777             : 
     778           0 :                 nRow += nNeeded;
     779             :             }
     780           0 :         }
     781             :     }
     782         157 : }
     783             : 
     784             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11