LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sc/source/core/data - documen4.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 287 638 45.0 %
Date: 2013-07-09 Functions: 23 37 62.2 %
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/intitem.hxx>
      21             : #include <svl/zforlist.hxx>
      22             : #include <formula/token.hxx>
      23             : 
      24             : #include "document.hxx"
      25             : #include "table.hxx"
      26             : #include "globstr.hrc"
      27             : #include "subtotal.hxx"
      28             : #include "docoptio.hxx"
      29             : #include "interpre.hxx"
      30             : #include "markdata.hxx"
      31             : #include "validat.hxx"
      32             : #include "scitems.hxx"
      33             : #include "stlpool.hxx"
      34             : #include "poolhelp.hxx"
      35             : #include "detdata.hxx"
      36             : #include "patattr.hxx"
      37             : #include "chgtrack.hxx"
      38             : #include "progress.hxx"
      39             : #include "paramisc.hxx"
      40             : #include "compiler.hxx"
      41             : #include "externalrefmgr.hxx"
      42             : #include "colorscale.hxx"
      43             : #include "attrib.hxx"
      44             : #include "formulacell.hxx"
      45             : #include "tokenarray.hxx"
      46             : #include "scmatrix.hxx"
      47             : 
      48             : using namespace formula;
      49             : 
      50             : // -----------------------------------------------------------------------
      51             : 
      52             : // Nach der Regula Falsi Methode
      53           5 : bool ScDocument::Solver(SCCOL nFCol, SCROW nFRow, SCTAB nFTab,
      54             :                         SCCOL nVCol, SCROW nVRow, SCTAB nVTab,
      55             :                         const OUString& sValStr, double& nX)
      56             : {
      57           5 :     bool bRet = false;
      58           5 :     nX = 0.0;
      59          20 :     if (ValidColRow(nFCol, nFRow) && ValidColRow(nVCol, nVRow) &&
      60          15 :         ValidTab(nFTab) && ValidTab(nVTab) &&
      61          15 :         nFTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nFTab] &&
      62          15 :         nVTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nVTab])
      63             :     {
      64             :         CellType eFType, eVType;
      65           5 :         GetCellType(nFCol, nFRow, nFTab, eFType);
      66           5 :         GetCellType(nVCol, nVRow, nVTab, eVType);
      67             :         // CELLTYPE_NOTE: no value, but referenced by formula
      68             :         // #i108005# convert target value to number using default format,
      69             :         // as previously done in ScInterpreter::GetDouble
      70           5 :         double nTargetVal = 0.0;
      71           5 :         sal_uInt32 nFIndex = 0;
      72          10 :         if (eFType == CELLTYPE_FORMULA && (eVType == CELLTYPE_VALUE) &&
      73           5 :             GetFormatTable()->IsNumberFormat(sValStr, nFIndex, nTargetVal))
      74             :         {
      75             :             ScSingleRefData aRefData;
      76           5 :             aRefData.InitFlags();
      77           5 :             aRefData.nCol = nVCol;
      78           5 :             aRefData.nRow = nVRow;
      79           5 :             aRefData.nTab = nVTab;
      80             : 
      81           5 :             ScTokenArray aArr;
      82           5 :             aArr.AddOpCode( ocBackSolver );
      83           5 :             aArr.AddOpCode( ocOpen );
      84           5 :             aArr.AddSingleReference( aRefData );
      85           5 :             aArr.AddOpCode( ocSep );
      86             : 
      87           5 :             aRefData.nCol = nFCol;
      88           5 :             aRefData.nRow = nFRow;
      89           5 :             aRefData.nTab = nFTab;
      90             : 
      91           5 :             aArr.AddSingleReference( aRefData );
      92           5 :             aArr.AddOpCode( ocSep );
      93           5 :             aArr.AddDouble( nTargetVal );
      94           5 :             aArr.AddOpCode( ocClose );
      95           5 :             aArr.AddOpCode( ocStop );
      96             : 
      97           5 :             ScFormulaCell* pCell = new ScFormulaCell( this, ScAddress(), &aArr );
      98             : 
      99           5 :             if (pCell)
     100             :             {
     101             :                 // FIXME FIXME FIXME this might need to be reworked now that we have formula::FormulaErrorToken and ScFormulaResult, double check !!!
     102             :                 OSL_FAIL("ScDocument::Solver: -> ScFormulaCell::GetValueAlways might need reimplementation");
     103           5 :                 pCell->Interpret();
     104           5 :                 sal_uInt16 nErrCode = pCell->GetErrCode();
     105           5 :                 nX = pCell->GetValueAlways();
     106           5 :                 if (nErrCode == 0)                  // kein fehler beim Rechnen
     107           4 :                     bRet = true;
     108           5 :                 delete pCell;
     109           5 :             }
     110             :         }
     111             :     }
     112           5 :     return bRet;
     113             : }
     114             : 
     115          36 : void ScDocument::InsertMatrixFormula(SCCOL nCol1, SCROW nRow1,
     116             :                                      SCCOL nCol2, SCROW nRow2,
     117             :                                      const ScMarkData& rMark,
     118             :                                      const OUString& rFormula,
     119             :                                      const ScTokenArray* pArr,
     120             :                                      const formula::FormulaGrammar::Grammar eGram,
     121             :                                      bool bDirtyFlag )
     122             : {
     123          36 :     PutInOrder(nCol1, nCol2);
     124          36 :     PutInOrder(nRow1, nRow2);
     125          36 :     nCol2 = std::min<SCCOL>(nCol2, MAXCOL);
     126          36 :     nRow2 = std::min<SCROW>(nRow2, MAXROW);
     127          36 :     if (!rMark.GetSelectCount())
     128             :     {
     129             :         SAL_WARN("sc", "ScDocument::InsertMatrixFormula: No table marked");
     130           0 :         return;
     131             :     }
     132             : 
     133          36 :     SCTAB nTab1 = *rMark.begin();
     134             : 
     135             :     ScFormulaCell* pCell;
     136          36 :     ScAddress aPos( nCol1, nRow1, nTab1 );
     137          36 :     if (pArr)
     138          34 :         pCell = new ScFormulaCell( this, aPos, pArr, eGram, MM_FORMULA );
     139             :     else
     140           2 :         pCell = new ScFormulaCell( this, aPos, rFormula, eGram, MM_FORMULA );
     141          36 :     pCell->SetMatColsRows( nCol2 - nCol1 + 1, nRow2 - nRow1 + 1, bDirtyFlag );
     142          36 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
     143          36 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
     144          72 :     for (; itr != itrEnd && *itr < nMax; ++itr)
     145             :     {
     146          36 :         if (!maTabs[*itr])
     147           0 :             continue;
     148             : 
     149          36 :         if (*itr == nTab1)
     150          36 :             maTabs[*itr]->SetFormulaCell(nCol1, nRow1, pCell);
     151             :         else
     152           0 :             maTabs[*itr]->SetFormulaCell(
     153             :                 nCol1, nRow1,
     154             :                 new ScFormulaCell(
     155           0 :                     *pCell, *this, ScAddress(nCol1, nRow1, *itr), SC_CLONECELL_STARTLISTENING));
     156             :     }
     157             : 
     158             :     ScSingleRefData aRefData;
     159          36 :     aRefData.InitFlags();
     160          36 :     aRefData.nCol = nCol1;
     161          36 :     aRefData.nRow = nRow1;
     162          36 :     aRefData.nTab = nTab1;
     163          36 :     aRefData.SetColRel( true );
     164          36 :     aRefData.SetRowRel( true );
     165          36 :     aRefData.SetTabRel( true );
     166          36 :     aRefData.CalcRelFromAbs( ScAddress( nCol1, nRow1, nTab1 ) );
     167             : 
     168          36 :     ScTokenArray aArr;
     169          36 :     ScToken* t = static_cast<ScToken*>(aArr.AddMatrixSingleReference( aRefData));
     170             : 
     171          36 :     itr = rMark.begin();
     172          72 :     for (; itr != itrEnd && *itr < nMax; ++itr)
     173             :     {
     174          36 :         if (maTabs[*itr])
     175             :         {
     176          36 :             if (*itr != nTab1)
     177             :             {
     178           0 :                 aRefData.nTab = *itr;
     179           0 :                 aRefData.nRelTab = *itr - nTab1;
     180           0 :                 t->GetSingleRef() = aRefData;
     181             :             }
     182         106 :             for (SCCOL j = nCol1; j <= nCol2; j++)
     183             :             {
     184         196 :                 for (SCROW k = nRow1; k <= nRow2; k++)
     185             :                 {
     186         126 :                     if (j != nCol1 || k != nRow1)       // nicht in der ersten Zelle
     187             :                     {
     188             :                         // Array muss geklont werden, damit jede
     189             :                         // Zelle ein eigenes Array erhaelt!
     190          90 :                         aPos = ScAddress( j, k, *itr );
     191          90 :                         t->CalcRelFromAbs( aPos );
     192          90 :                         boost::scoped_ptr<ScTokenArray> pTokArr(aArr.Clone());
     193          90 :                         pCell = new ScFormulaCell( this, aPos, pTokArr.get(), eGram, MM_REFERENCE );
     194          90 :                         maTabs[*itr]->SetFormulaCell(j, k, pCell);
     195             :                     }
     196             :                 }
     197             :             }
     198             :         }
     199          36 :     }
     200             : }
     201             : 
     202           3 : void ScDocument::InsertTableOp(const ScTabOpParam& rParam,      // Mehrfachoperation
     203             :                                SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
     204             :                                const ScMarkData& rMark)
     205             : {
     206           3 :     PutInOrder(nCol1, nCol2);
     207           3 :     PutInOrder(nRow1, nRow2);
     208             :     SCTAB i, nTab1;
     209             :     SCCOL j;
     210             :     SCROW k;
     211           3 :     i = 0;
     212           3 :     bool bStop = false;
     213           3 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
     214           3 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
     215           3 :     for (; itr != itrEnd && *itr < nMax; ++itr)
     216             :     {
     217           3 :         if (maTabs[*itr])
     218             :         {
     219           3 :             i = *itr;
     220           3 :             bStop = true;
     221           3 :             break;
     222             :         }
     223             :     }
     224           3 :     nTab1 = i;
     225           3 :     if (!bStop)
     226             :     {
     227             :         OSL_FAIL("ScDocument::InsertTableOp: No table marked");
     228           3 :         return;
     229             :     }
     230             : 
     231           3 :     ScRefAddress aRef;
     232           3 :     OUStringBuffer aForString('=');
     233           3 :     aForString.append(ScCompiler::GetNativeSymbol(ocTableOp));
     234           3 :     aForString.append(ScCompiler::GetNativeSymbol( ocOpen));
     235             : 
     236           3 :     const String& sSep = ScCompiler::GetNativeSymbol( ocSep);
     237           3 :     if (rParam.nMode == 0)                          // nur Spalte
     238             :     {
     239           1 :         aRef.Set( rParam.aRefFormulaCell.GetAddress(), true, false, false );
     240           1 :         aForString.append(aRef.GetRefString(this, nTab1));
     241           1 :         aForString.append(sSep);
     242           1 :         aForString.append(rParam.aRefColCell.GetRefString(this, nTab1));
     243           1 :         aForString.append(sSep);
     244           1 :         aRef.Set( nCol1, nRow1, nTab1, false, true, true );
     245           1 :         aForString.append(aRef.GetRefString(this, nTab1));
     246           1 :         nCol1++;
     247           1 :         nCol2 = std::min( nCol2, (SCCOL)(rParam.aRefFormulaEnd.Col() -
     248           1 :                     rParam.aRefFormulaCell.Col() + nCol1 + 1));
     249             :     }
     250           2 :     else if (rParam.nMode == 1)                 // nur zeilenweise
     251             :     {
     252           1 :         aRef.Set( rParam.aRefFormulaCell.GetAddress(), false, true, false );
     253           1 :         aForString.append(aRef.GetRefString(this, nTab1));
     254           1 :         aForString.append(sSep);
     255           1 :         aForString.append(rParam.aRefRowCell.GetRefString(this, nTab1));
     256           1 :         aForString.append(sSep);
     257           1 :         aRef.Set( nCol1, nRow1, nTab1, true, false, true );
     258           1 :         aForString.append(aRef.GetRefString(this, nTab1));
     259           1 :         nRow1++;
     260           2 :         nRow2 = std::min( nRow2, (SCROW)(rParam.aRefFormulaEnd.Row() -
     261           2 :                     rParam.aRefFormulaCell.Row() + nRow1 + 1));
     262             :     }
     263             :     else                    // beides
     264             :     {
     265           1 :         aForString.append(rParam.aRefFormulaCell.GetRefString(this, nTab1));
     266           1 :         aForString.append(sSep);
     267           1 :         aForString.append(rParam.aRefColCell.GetRefString(this, nTab1));
     268           1 :         aForString.append(sSep);
     269           1 :         aRef.Set( nCol1, nRow1 + 1, nTab1, false, true, true );
     270           1 :         aForString.append(aRef.GetRefString(this, nTab1));
     271           1 :         aForString.append(sSep);
     272           1 :         aForString.append(rParam.aRefRowCell.GetRefString(this, nTab1));
     273           1 :         aForString.append(sSep);
     274           1 :         aRef.Set( nCol1 + 1, nRow1, nTab1, true, false, true );
     275           1 :         aForString.append(aRef.GetRefString(this, nTab1));
     276           1 :         nCol1++; nRow1++;
     277             :     }
     278           3 :     aForString.append(ScCompiler::GetNativeSymbol( ocClose ));
     279             : 
     280             :     ScFormulaCell aRefCell( this, ScAddress( nCol1, nRow1, nTab1 ), aForString.makeStringAndClear(),
     281           6 :            formula::FormulaGrammar::GRAM_NATIVE, MM_NONE );
     282          12 :     for( j = nCol1; j <= nCol2; j++ )
     283          39 :         for( k = nRow1; k <= nRow2; k++ )
     284          60 :             for (i = 0; i < static_cast<SCTAB>(maTabs.size()); i++)
     285             :             {
     286          30 :                 itr = rMark.begin();
     287          60 :                 for (; itr != itrEnd && *itr < nMax; ++itr)
     288          30 :                 if( maTabs[*itr] )
     289          30 :                     maTabs[*itr]->SetFormulaCell(
     290          60 :                         j, k, new ScFormulaCell(aRefCell, *this, ScAddress(j, k, *itr), SC_CLONECELL_STARTLISTENING));
     291           3 :             }
     292             : }
     293             : 
     294             : namespace {
     295             : 
     296           0 : bool setCacheTableReferenced(ScToken& rToken, ScExternalRefManager& rRefMgr)
     297             : {
     298           0 :     switch (rToken.GetType())
     299             :     {
     300             :         case svExternalSingleRef:
     301             :             return rRefMgr.setCacheTableReferenced(
     302           0 :                 rToken.GetIndex(), rToken.GetString(), 1);
     303             :         case svExternalDoubleRef:
     304             :         {
     305           0 :             const ScComplexRefData& rRef = rToken.GetDoubleRef();
     306           0 :             size_t nSheets = rRef.Ref2.nTab - rRef.Ref1.nTab + 1;
     307             :             return rRefMgr.setCacheTableReferenced(
     308           0 :                     rToken.GetIndex(), rToken.GetString(), nSheets);
     309             :         }
     310             :         case svExternalName:
     311             :             /* TODO: external names aren't supported yet, but would
     312             :              * have to be marked as well, if so. Mechanism would be
     313             :              * different. */
     314             :             OSL_FAIL("ScDocument::MarkUsedExternalReferences: implement the svExternalName case!");
     315             :         default:
     316             :             ;
     317             :     }
     318           0 :     return false;
     319             : }
     320             : 
     321             : }
     322             : 
     323           0 : bool ScDocument::MarkUsedExternalReferences( ScTokenArray & rArr )
     324             : {
     325           0 :     if (!rArr.GetLen())
     326           0 :         return false;
     327             : 
     328           0 :     ScExternalRefManager* pRefMgr = NULL;
     329           0 :     rArr.Reset();
     330           0 :     ScToken* t = NULL;
     331           0 :     bool bAllMarked = false;
     332           0 :     while (!bAllMarked && (t = static_cast<ScToken*>(rArr.GetNextReferenceOrName())) != NULL)
     333             :     {
     334           0 :         if (t->IsExternalRef())
     335             :         {
     336           0 :             if (!pRefMgr)
     337           0 :                 pRefMgr = GetExternalRefManager();
     338             : 
     339           0 :             bAllMarked = setCacheTableReferenced(*t, *pRefMgr);
     340             :         }
     341           0 :         else if (t->GetType() == svIndex)
     342             :         {
     343             :             // this is a named range.  Check if the range contains an external
     344             :             // reference.
     345           0 :             ScRangeData* pRangeData = GetRangeName()->findByIndex(t->GetIndex());
     346           0 :             if (!pRangeData)
     347           0 :                 continue;
     348             : 
     349           0 :             ScTokenArray* pArray = pRangeData->GetCode();
     350           0 :             for (t = static_cast<ScToken*>(pArray->First()); t; t = static_cast<ScToken*>(pArray->Next()))
     351             :             {
     352           0 :                 if (!t->IsExternalRef())
     353           0 :                     continue;
     354             : 
     355           0 :                 if (!pRefMgr)
     356           0 :                     pRefMgr = GetExternalRefManager();
     357             : 
     358           0 :                 bAllMarked = setCacheTableReferenced(*t, *pRefMgr);
     359             :             }
     360             :         }
     361             :     }
     362           0 :     return bAllMarked;
     363             : }
     364             : 
     365           0 : bool ScDocument::GetNextSpellingCell(SCCOL& nCol, SCROW& nRow, SCTAB nTab,
     366             :                         bool bInSel, const ScMarkData& rMark) const
     367             : {
     368           0 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
     369           0 :         return maTabs[nTab]->GetNextSpellingCell( nCol, nRow, bInSel, rMark );
     370             :     else
     371           0 :         return false;
     372             : }
     373             : 
     374           2 : bool ScDocument::GetNextMarkedCell( SCCOL& rCol, SCROW& rRow, SCTAB nTab,
     375             :                                         const ScMarkData& rMark )
     376             : {
     377           2 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
     378           2 :         return maTabs[nTab]->GetNextMarkedCell( rCol, rRow, rMark );
     379             :     else
     380           0 :         return false;
     381             : }
     382             : 
     383           0 : bool ScDocument::ReplaceStyle(const SvxSearchItem& rSearchItem,
     384             :                               SCCOL nCol, SCROW nRow, SCTAB nTab,
     385             :                               ScMarkData& rMark,
     386             :                               bool bIsUndoP)
     387             : {
     388           0 :     if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
     389           0 :         return maTabs[nTab]->ReplaceStyle(rSearchItem, nCol, nRow, rMark, bIsUndoP);
     390             :     else
     391           0 :         return false;
     392             : }
     393             : 
     394           7 : void ScDocument::CompileDBFormula()
     395             : {
     396           7 :     TableContainer::iterator it = maTabs.begin();
     397          16 :     for (;it != maTabs.end(); ++it)
     398             :     {
     399           9 :         if (*it)
     400           9 :             (*it)->CompileDBFormula();
     401             :     }
     402           7 : }
     403             : 
     404          12 : void ScDocument::CompileDBFormula( bool bCreateFormulaString )
     405             : {
     406          12 :     TableContainer::iterator it = maTabs.begin();
     407          28 :     for (;it != maTabs.end(); ++it)
     408             :     {
     409          16 :         if (*it)
     410          16 :             (*it)->CompileDBFormula( bCreateFormulaString );
     411             :     }
     412          12 : }
     413             : 
     414         104 : void ScDocument::CompileNameFormula( bool bCreateFormulaString )
     415             : {
     416         104 :     TableContainer::iterator it = maTabs.begin();
     417         306 :     for (;it != maTabs.end(); ++it)
     418             :     {
     419         202 :         if (*it)
     420         202 :             (*it)->CompileNameFormula( bCreateFormulaString );
     421             :     }
     422         104 : }
     423             : 
     424           7 : void ScDocument::CompileColRowNameFormula()
     425             : {
     426           7 :     TableContainer::iterator it = maTabs.begin();
     427          14 :     for (;it != maTabs.end(); ++it)
     428             :     {
     429           7 :         if (*it)
     430           7 :             (*it)->CompileColRowNameFormula();
     431             :     }
     432           7 : }
     433             : 
     434       12967 : void ScDocument::InvalidateTableArea()
     435             : {
     436       12967 :     TableContainer::iterator it = maTabs.begin();
     437       38644 :     for (;it != maTabs.end() && *it; ++it)
     438             :     {
     439       25677 :         (*it)->InvalidateTableArea();
     440       25677 :         if ( (*it)->IsScenario() )
     441           1 :             (*it)->InvalidateScenarioRanges();
     442             :     }
     443       12967 : }
     444             : 
     445           0 : sal_Int32 ScDocument::GetMaxStringLen( SCTAB nTab, SCCOL nCol,
     446             :         SCROW nRowStart, SCROW nRowEnd, CharSet eCharSet ) const
     447             : {
     448           0 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
     449           0 :         return maTabs[nTab]->GetMaxStringLen( nCol, nRowStart, nRowEnd, eCharSet );
     450             :     else
     451           0 :         return 0;
     452             : }
     453             : 
     454           0 : xub_StrLen ScDocument::GetMaxNumberStringLen( sal_uInt16& nPrecision, SCTAB nTab,
     455             :                                     SCCOL nCol,
     456             :                                     SCROW nRowStart, SCROW nRowEnd ) const
     457             : {
     458           0 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
     459           0 :         return maTabs[nTab]->GetMaxNumberStringLen( nPrecision, nCol,
     460           0 :             nRowStart, nRowEnd );
     461             :     else
     462           0 :         return 0;
     463             : }
     464             : 
     465         191 : bool ScDocument::GetSelectionFunction( ScSubTotalFunc eFunc,
     466             :                                         const ScAddress& rCursor, const ScMarkData& rMark,
     467             :                                         double& rResult )
     468             : {
     469         191 :     ScFunctionData aData(eFunc);
     470             : 
     471         191 :     ScRange aSingle( rCursor );
     472         191 :     if ( rMark.IsMarked() )
     473           2 :         rMark.GetMarkArea(aSingle);
     474             : 
     475         191 :     SCCOL nStartCol = aSingle.aStart.Col();
     476         191 :     SCROW nStartRow = aSingle.aStart.Row();
     477         191 :     SCCOL nEndCol = aSingle.aEnd.Col();
     478         191 :     SCROW nEndRow = aSingle.aEnd.Row();
     479             : 
     480         191 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
     481         191 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
     482             : 
     483         382 :     for (; itr != itrEnd && *itr < nMax && !aData.bError; ++itr)
     484         191 :         if (maTabs[*itr])
     485         191 :             maTabs[*itr]->UpdateSelectionFunction( aData,
     486         382 :                             nStartCol, nStartRow, nEndCol, nEndRow, rMark );
     487             : 
     488             :             //! rMark an UpdateSelectionFunction uebergeben !!!!!
     489             : 
     490         191 :     if (!aData.bError)
     491         191 :         switch (eFunc)
     492             :         {
     493             :             case SUBTOTAL_FUNC_SUM:
     494         163 :                 rResult = aData.nVal;
     495         163 :                 break;
     496             :             case SUBTOTAL_FUNC_SELECTION_COUNT:
     497          26 :                 rResult = aData.nCount;
     498          26 :                 break;
     499             :             case SUBTOTAL_FUNC_CNT:
     500             :             case SUBTOTAL_FUNC_CNT2:
     501           2 :                 rResult = aData.nCount;
     502           2 :                 break;
     503             :             case SUBTOTAL_FUNC_AVE:
     504           0 :                 if (aData.nCount)
     505           0 :                     rResult = aData.nVal / (double) aData.nCount;
     506             :                 else
     507           0 :                     aData.bError = true;
     508           0 :                 break;
     509             :             case SUBTOTAL_FUNC_MAX:
     510             :             case SUBTOTAL_FUNC_MIN:
     511           0 :                 if (aData.nCount)
     512           0 :                     rResult = aData.nVal;
     513             :                 else
     514           0 :                     aData.bError = true;
     515           0 :                 break;
     516             :             default:
     517             :             {
     518             :                 // added to avoid warnings
     519             :             }
     520             :         }
     521             : 
     522         191 :     if (aData.bError)
     523           0 :         rResult = 0.0;
     524             : 
     525         191 :     return !aData.bError;
     526             : }
     527             : 
     528          45 : double ScDocument::RoundValueAsShown( double fVal, sal_uInt32 nFormat ) const
     529             : {
     530             :     short nType;
     531          90 :     if ( (nType = GetFormatTable()->GetType( nFormat )) != NUMBERFORMAT_DATE
     532          45 :       && nType != NUMBERFORMAT_TIME && nType != NUMBERFORMAT_DATETIME )
     533             :     {
     534             :         short nPrecision;
     535          45 :         if ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0)
     536             :         {
     537           0 :             nPrecision = (short)GetFormatTable()->GetFormatPrecision( nFormat );
     538           0 :             switch ( nType )
     539             :             {
     540             :                 case NUMBERFORMAT_PERCENT:      // 0,41% == 0,0041
     541           0 :                     nPrecision += 2;
     542           0 :                     break;
     543             :                 case NUMBERFORMAT_SCIENTIFIC:   // 1,23e-3 == 0,00123
     544             :                 {
     545           0 :                     if ( fVal > 0.0 )
     546           0 :                         nPrecision = sal::static_int_cast<short>( nPrecision - (short)floor( log10( fVal ) ) );
     547           0 :                     else if ( fVal < 0.0 )
     548           0 :                         nPrecision = sal::static_int_cast<short>( nPrecision - (short)floor( log10( -fVal ) ) );
     549           0 :                     break;
     550             :                 }
     551             :             }
     552             :         }
     553             :         else
     554             :         {
     555          45 :             nPrecision = (short)GetDocOptions().GetStdPrecision();
     556             :             // #i115512# no rounding for automatic decimals
     557          45 :             if (nPrecision == static_cast<short>(SvNumberFormatter::UNLIMITED_PRECISION))
     558           0 :                 return fVal;
     559             :         }
     560          45 :         double fRound = ::rtl::math::round( fVal, nPrecision );
     561          45 :         if ( ::rtl::math::approxEqual( fVal, fRound ) )
     562          39 :             return fVal;        // durch Rundung hoechstens Fehler
     563             :         else
     564           6 :             return fRound;
     565             :     }
     566             :     else
     567           0 :         return fVal;
     568             : }
     569             : 
     570             : //
     571             : //          bedingte Formate und Gueltigkeitsbereiche
     572             : //
     573             : 
     574         107 : sal_uLong ScDocument::AddCondFormat( ScConditionalFormat* pNew, SCTAB nTab )
     575             : {
     576         107 :     if(!pNew)
     577           0 :         return 0;
     578             : 
     579         107 :     if(ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
     580         107 :         return maTabs[nTab]->AddCondFormat( pNew );
     581             : 
     582           0 :     return 0;
     583             : }
     584             : 
     585          33 : sal_uLong ScDocument::AddValidationEntry( const ScValidationData& rNew )
     586             : {
     587          33 :     if (rNew.IsEmpty())
     588           0 :         return 0;                   // leer ist immer 0
     589             : 
     590          33 :     if (!pValidationList)
     591           6 :         pValidationList = new ScValidationDataList;
     592             : 
     593          33 :     sal_uLong nMax = 0;
     594          95 :     for( ScValidationDataList::iterator it = pValidationList->begin(); it != pValidationList->end(); ++it )
     595             :     {
     596          79 :         const ScValidationData* pData = *it;
     597          79 :         sal_uLong nKey = pData->GetKey();
     598          79 :         if ( pData->EqualEntries( rNew ) )
     599          17 :             return nKey;
     600          62 :         if ( nKey > nMax )
     601          62 :             nMax = nKey;
     602             :     }
     603             : 
     604             :     // Der Aufruf kann aus ScPatternAttr::PutInPool kommen, darum Clone (echte Kopie)
     605             : 
     606          16 :     sal_uLong nNewKey = nMax + 1;
     607          16 :     ScValidationData* pInsert = rNew.Clone(this);
     608          16 :     pInsert->SetKey( nNewKey );
     609          16 :     pValidationList->InsertNew( pInsert );
     610          16 :     return nNewKey;
     611             : }
     612             : 
     613         686 : const SfxPoolItem* ScDocument::GetEffItem(
     614             :                         SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich ) const
     615             : {
     616         686 :     const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
     617         686 :     if ( pPattern )
     618             :     {
     619         686 :         const SfxItemSet& rSet = pPattern->GetItemSet();
     620             :         const SfxPoolItem* pItem;
     621         686 :         if ( rSet.GetItemState( ATTR_CONDITIONAL, true, &pItem ) == SFX_ITEM_SET )
     622             :         {
     623           0 :             const std::vector<sal_uInt32>& rIndex = static_cast<const ScCondFormatItem&>(pPattern->GetItem(ATTR_CONDITIONAL)).GetCondFormatData();
     624           0 :             ScConditionalFormatList* pCondFormList = GetCondFormList( nTab );
     625           0 :             if (!rIndex.empty() && pCondFormList)
     626             :             {
     627           0 :                 for(std::vector<sal_uInt32>::const_iterator itr = rIndex.begin(), itrEnd = rIndex.end();
     628             :                         itr != itrEnd; ++itr)
     629             :                 {
     630           0 :                     const ScConditionalFormat* pForm = pCondFormList->GetFormat( *itr );
     631           0 :                     if ( pForm )
     632             :                     {
     633           0 :                         ScAddress aPos(nCol, nRow, nTab);
     634           0 :                         ScRefCellValue aCell;
     635           0 :                         aCell.assign(const_cast<ScDocument&>(*this), aPos);
     636           0 :                         OUString aStyle = pForm->GetCellStyle(aCell, aPos);
     637           0 :                         if (!aStyle.isEmpty())
     638             :                         {
     639           0 :                             SfxStyleSheetBase* pStyleSheet = xPoolHelper->GetStylePool()->Find(
     640           0 :                                     aStyle, SFX_STYLE_FAMILY_PARA );
     641           0 :                             if ( pStyleSheet && pStyleSheet->GetItemSet().GetItemState(
     642           0 :                                         nWhich, true, &pItem ) == SFX_ITEM_SET )
     643           0 :                                 return pItem;
     644           0 :                         }
     645             :                     }
     646             :                 }
     647             :             }
     648             :         }
     649         686 :         return &rSet.Get( nWhich );
     650             :     }
     651             :     OSL_FAIL("no pattern");
     652           0 :     return NULL;
     653             : }
     654             : 
     655        4133 : const SfxItemSet* ScDocument::GetCondResult( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
     656             : {
     657        4133 :     ScConditionalFormatList* pFormatList = GetCondFormList(nTab);
     658        4133 :     if (!pFormatList)
     659           0 :         return NULL;
     660             : 
     661        4133 :     ScAddress aPos(nCol, nRow, nTab);
     662        4133 :     ScRefCellValue aCell;
     663        4133 :     aCell.assign(const_cast<ScDocument&>(*this), aPos);
     664        4133 :     const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
     665             :     const std::vector<sal_uInt32>& rIndex =
     666        4133 :         static_cast<const ScCondFormatItem&>(pPattern->GetItem(ATTR_CONDITIONAL)).GetCondFormatData();
     667             : 
     668        4133 :     return GetCondResult(aCell, aPos, *pFormatList, rIndex);
     669             : }
     670             : 
     671       27434 : const SfxItemSet* ScDocument::GetCondResult(
     672             :     ScRefCellValue& rCell, const ScAddress& rPos, const ScConditionalFormatList& rList,
     673             :     const std::vector<sal_uInt32>& rIndex ) const
     674             : {
     675       27434 :     std::vector<sal_uInt32>::const_iterator itr = rIndex.begin(), itrEnd = rIndex.end();
     676       31157 :     for (; itr != itrEnd; ++itr)
     677             :     {
     678        3971 :         const ScConditionalFormat* pForm = rList.GetFormat(*itr);
     679        3971 :         if (!pForm)
     680           0 :             continue;
     681             : 
     682        3971 :         const OUString& aStyle = pForm->GetCellStyle(rCell, rPos);
     683        3971 :         if (!aStyle.isEmpty())
     684             :         {
     685             :             SfxStyleSheetBase* pStyleSheet =
     686         248 :                 xPoolHelper->GetStylePool()->Find(aStyle, SFX_STYLE_FAMILY_PARA);
     687             : 
     688         248 :             if (pStyleSheet)
     689         248 :                 return &pStyleSheet->GetItemSet();
     690             : 
     691             :             // if style is not there, treat like no condition
     692             :         }
     693             :     }
     694             : 
     695       27186 :     return NULL;
     696             : }
     697             : 
     698           3 : ScConditionalFormat* ScDocument::GetCondFormat(
     699             :                             SCCOL nCol, SCROW nRow, SCTAB nTab ) const
     700             : {
     701           3 :     sal_uInt32 nIndex = 0;
     702           3 :     const std::vector<sal_uInt32>& rCondFormats = static_cast<const ScCondFormatItem*>(GetAttr(nCol, nRow, nTab, ATTR_CONDITIONAL))->GetCondFormatData();
     703             : 
     704           3 :     if(!rCondFormats.empty())
     705           3 :         nIndex = rCondFormats[0];
     706             : 
     707           3 :     if (nIndex)
     708             :     {
     709           3 :         ScConditionalFormatList* pCondFormList = GetCondFormList(nTab);
     710           3 :         if (pCondFormList)
     711           3 :             return pCondFormList->GetFormat( nIndex );
     712             :         else
     713             :         {
     714             :             OSL_FAIL("pCondFormList is 0");
     715             :         }
     716             :     }
     717             : 
     718           0 :     return NULL;
     719             : }
     720             : 
     721      109988 : ScConditionalFormatList* ScDocument::GetCondFormList(SCTAB nTab) const
     722             : {
     723      109988 :     if(ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
     724      109988 :         return maTabs[nTab]->GetCondFormList();
     725             : 
     726           0 :     return NULL;
     727             : }
     728             : 
     729          10 : void ScDocument::SetCondFormList( ScConditionalFormatList* pList, SCTAB nTab )
     730             : {
     731          10 :     if(ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
     732          10 :         maTabs[nTab]->SetCondFormList(pList);
     733          10 : }
     734             : 
     735             : 
     736          82 : const ScValidationData* ScDocument::GetValidationEntry( sal_uLong nIndex ) const
     737             : {
     738          82 :     if ( pValidationList )
     739          82 :         return pValidationList->GetData( nIndex );
     740             :     else
     741           0 :         return NULL;
     742             : }
     743             : 
     744           0 : void ScDocument::DeleteConditionalFormat(sal_uLong nOldIndex, SCTAB nTab)
     745             : {
     746           0 :     if(ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
     747           0 :         maTabs[nTab]->DeleteConditionalFormat(nOldIndex);
     748           0 : }
     749             : 
     750             : //------------------------------------------------------------------------
     751             : 
     752           0 : bool ScDocument::HasDetectiveOperations() const
     753             : {
     754           0 :     return pDetOpList && pDetOpList->Count();
     755             : }
     756             : 
     757           1 : void ScDocument::AddDetectiveOperation( const ScDetOpData& rData )
     758             : {
     759           1 :     if (!pDetOpList)
     760           1 :         pDetOpList = new ScDetOpList;
     761             : 
     762           1 :     pDetOpList->Append( new ScDetOpData( rData ) );
     763           1 : }
     764             : 
     765           0 : void ScDocument::ClearDetectiveOperations()
     766             : {
     767           0 :     delete pDetOpList;      // loescht auch die Eintraege
     768           0 :     pDetOpList = NULL;
     769           0 : }
     770             : 
     771           0 : void ScDocument::SetDetOpList(ScDetOpList* pNew)
     772             : {
     773           0 :     delete pDetOpList;      // loescht auch die Eintraege
     774           0 :     pDetOpList = pNew;
     775           0 : }
     776             : 
     777             : //------------------------------------------------------------------------
     778             : //
     779             : //      Vergleich von Dokumenten
     780             : //
     781             : //------------------------------------------------------------------------
     782             : 
     783             : //  Pfriemel-Faktoren
     784             : #define SC_DOCCOMP_MAXDIFF  256
     785             : #define SC_DOCCOMP_MINGOOD  128
     786             : #define SC_DOCCOMP_COLUMNS  10
     787             : #define SC_DOCCOMP_ROWS     100
     788             : 
     789             : 
     790           0 : sal_uInt16 ScDocument::RowDifferences( SCROW nThisRow, SCTAB nThisTab,
     791             :                                     ScDocument& rOtherDoc, SCROW nOtherRow, SCTAB nOtherTab,
     792             :                                     SCCOL nMaxCol, SCCOLROW* pOtherCols )
     793             : {
     794           0 :     sal_uLong nDif = 0;
     795           0 :     sal_uLong nUsed = 0;
     796           0 :     for (SCCOL nThisCol=0; nThisCol<=nMaxCol; nThisCol++)
     797             :     {
     798             :         SCCOL nOtherCol;
     799           0 :         if ( pOtherCols )
     800           0 :             nOtherCol = static_cast<SCCOL>(pOtherCols[nThisCol]);
     801             :         else
     802           0 :             nOtherCol = nThisCol;
     803             : 
     804           0 :         if (ValidCol(nOtherCol))    // nur Spalten vergleichen, die in beiden Dateien sind
     805             :         {
     806           0 :             ScRefCellValue aThisCell, aOtherCell;
     807           0 :             aThisCell.assign(*this, ScAddress(nThisCol, nThisRow, nThisTab));
     808           0 :             aOtherCell.assign(rOtherDoc, ScAddress(nOtherCol, nOtherRow, nOtherTab));
     809           0 :             if (!aThisCell.equalsWithoutFormat(aOtherCell))
     810             :             {
     811           0 :                 if (!aThisCell.isEmpty() && !aOtherCell.isEmpty())
     812           0 :                     nDif += 3;
     813             :                 else
     814           0 :                     nDif += 4;      // Inhalt <-> leer zaehlt mehr
     815             :             }
     816             : 
     817           0 :             if (!aThisCell.isEmpty() || !aOtherCell.isEmpty())
     818           0 :                 ++nUsed;
     819             :         }
     820             :     }
     821             : 
     822           0 :     if (nUsed > 0)
     823           0 :         return static_cast<sal_uInt16>((nDif*64)/nUsed);            // max.256 (SC_DOCCOMP_MAXDIFF)
     824             : 
     825             :     OSL_ENSURE(!nDif,"Diff withoud Used");
     826           0 :     return 0;
     827             : }
     828             : 
     829           0 : sal_uInt16 ScDocument::ColDifferences( SCCOL nThisCol, SCTAB nThisTab,
     830             :                                     ScDocument& rOtherDoc, SCCOL nOtherCol, SCTAB nOtherTab,
     831             :                                     SCROW nMaxRow, SCCOLROW* pOtherRows )
     832             : {
     833             :     //! optimieren mit Iterator oder so
     834             : 
     835           0 :     sal_uLong nDif = 0;
     836           0 :     sal_uLong nUsed = 0;
     837           0 :     for (SCROW nThisRow=0; nThisRow<=nMaxRow; nThisRow++)
     838             :     {
     839             :         SCROW nOtherRow;
     840           0 :         if ( pOtherRows )
     841           0 :             nOtherRow = pOtherRows[nThisRow];
     842             :         else
     843           0 :             nOtherRow = nThisRow;
     844             : 
     845           0 :         if (ValidRow(nOtherRow))    // nur Zeilen vergleichen, die in beiden Dateien sind
     846             :         {
     847           0 :             ScRefCellValue aThisCell, aOtherCell;
     848           0 :             aThisCell.assign(*this, ScAddress(nThisCol, nThisRow, nThisTab));
     849           0 :             aOtherCell.assign(rOtherDoc, ScAddress(nOtherCol, nOtherRow, nOtherTab));
     850           0 :             if (!aThisCell.equalsWithoutFormat(aOtherCell))
     851             :             {
     852           0 :                 if (!aThisCell.isEmpty() && !aOtherCell.isEmpty())
     853           0 :                     nDif += 3;
     854             :                 else
     855           0 :                     nDif += 4;      // Inhalt <-> leer zaehlt mehr
     856             :             }
     857             : 
     858           0 :             if (!aThisCell.isEmpty() || !aOtherCell.isEmpty())
     859           0 :                 ++nUsed;
     860             :         }
     861             :     }
     862             : 
     863           0 :     if (nUsed > 0)
     864           0 :         return static_cast<sal_uInt16>((nDif*64)/nUsed);    // max.256
     865             : 
     866             :     OSL_ENSURE(!nDif,"Diff without Used");
     867           0 :     return 0;
     868             : }
     869             : 
     870           0 : void ScDocument::FindOrder( SCCOLROW* pOtherRows, SCCOLROW nThisEndRow, SCCOLROW nOtherEndRow,
     871             :                             bool bColumns, ScDocument& rOtherDoc, SCTAB nThisTab, SCTAB nOtherTab,
     872             :                             SCCOLROW nEndCol, SCCOLROW* pTranslate, ScProgress* pProgress, sal_uLong nProAdd )
     873             : {
     874             :     //  bColumns=true: Zeilen sind Spalten und umgekehrt
     875             : 
     876             :     SCCOLROW nMaxCont;                      // wieviel weiter
     877             :     SCCOLROW nMinGood;                      // was ist ein Treffer (incl.)
     878           0 :     if ( bColumns )
     879             :     {
     880           0 :         nMaxCont = SC_DOCCOMP_COLUMNS;      // 10 Spalten
     881           0 :         nMinGood = SC_DOCCOMP_MINGOOD;
     882             :         //! Extra Durchgang mit nMinGood = 0 ????
     883             :     }
     884             :     else
     885             :     {
     886           0 :         nMaxCont = SC_DOCCOMP_ROWS;         // 100 Zeilen
     887           0 :         nMinGood = SC_DOCCOMP_MINGOOD;
     888             :     }
     889           0 :     bool bUseTotal = bColumns && !pTranslate;       // nur beim ersten Durchgang
     890             : 
     891             : 
     892           0 :     SCCOLROW nOtherRow = 0;
     893             :     sal_uInt16 nComp;
     894             :     SCCOLROW nThisRow;
     895           0 :     bool bTotal = false;        // ueber verschiedene nThisRow beibehalten
     896           0 :     SCCOLROW nUnknown = 0;
     897           0 :     for (nThisRow = 0; nThisRow <= nThisEndRow; nThisRow++)
     898             :     {
     899           0 :         SCCOLROW nTempOther = nOtherRow;
     900           0 :         bool bFound = false;
     901           0 :         sal_uInt16 nBest = SC_DOCCOMP_MAXDIFF;
     902           0 :         SCCOLROW nMax = std::min( nOtherEndRow, static_cast<SCCOLROW>(( nTempOther + nMaxCont + nUnknown )) );
     903           0 :         for (SCCOLROW i=nTempOther; i<=nMax && nBest>0; i++)    // bei 0 abbrechen
     904             :         {
     905           0 :             if (bColumns)
     906           0 :                 nComp = ColDifferences( static_cast<SCCOL>(nThisRow), nThisTab, rOtherDoc, static_cast<SCCOL>(i), nOtherTab, nEndCol, pTranslate );
     907             :             else
     908           0 :                 nComp = RowDifferences( nThisRow, nThisTab, rOtherDoc, i, nOtherTab, static_cast<SCCOL>(nEndCol), pTranslate );
     909           0 :             if ( nComp < nBest && ( nComp <= nMinGood || bTotal ) )
     910             :             {
     911           0 :                 nTempOther = i;
     912           0 :                 nBest = nComp;
     913           0 :                 bFound = true;
     914             :             }
     915           0 :             if ( nComp < SC_DOCCOMP_MAXDIFF || bFound )
     916           0 :                 bTotal = false;
     917           0 :             else if ( i == nTempOther && bUseTotal )
     918           0 :                 bTotal = true;                          // nur ganz oben
     919             :         }
     920           0 :         if ( bFound )
     921             :         {
     922           0 :             pOtherRows[nThisRow] = nTempOther;
     923           0 :             nOtherRow = nTempOther + 1;
     924           0 :             nUnknown = 0;
     925             :         }
     926             :         else
     927             :         {
     928           0 :             pOtherRows[nThisRow] = SCROW_MAX;
     929           0 :             ++nUnknown;
     930             :         }
     931             : 
     932           0 :         if (pProgress)
     933           0 :             pProgress->SetStateOnPercent(nProAdd+static_cast<sal_uLong>(nThisRow));
     934             :     }
     935             : 
     936             :     //  Bloecke ohne Uebereinstimmung ausfuellen
     937             : 
     938           0 :     SCROW nFillStart = 0;
     939           0 :     SCROW nFillPos = 0;
     940           0 :     bool bInFill = false;
     941           0 :     for (nThisRow = 0; nThisRow <= nThisEndRow+1; nThisRow++)
     942             :     {
     943           0 :         SCROW nThisOther = ( nThisRow <= nThisEndRow ) ? pOtherRows[nThisRow] : (nOtherEndRow+1);
     944           0 :         if ( ValidRow(nThisOther) )
     945             :         {
     946           0 :             if ( bInFill )
     947             :             {
     948           0 :                 if ( nThisOther > nFillStart )      // ist was zu verteilen da?
     949             :                 {
     950           0 :                     SCROW nDiff1 = nThisOther - nFillStart;
     951           0 :                     SCROW nDiff2 = nThisRow   - nFillPos;
     952           0 :                     SCROW nMinDiff = std::min(nDiff1, nDiff2);
     953           0 :                     for (SCROW i=0; i<nMinDiff; i++)
     954           0 :                         pOtherRows[nFillPos+i] = nFillStart+i;
     955             :                 }
     956             : 
     957           0 :                 bInFill = false;
     958             :             }
     959           0 :             nFillStart = nThisOther + 1;
     960           0 :             nFillPos = nThisRow + 1;
     961             :         }
     962             :         else
     963           0 :             bInFill = true;
     964             :     }
     965           0 : }
     966             : 
     967           0 : void ScDocument::CompareDocument( ScDocument& rOtherDoc )
     968             : {
     969           0 :     if (!pChangeTrack)
     970           0 :         return;
     971             : 
     972           0 :     SCTAB nThisCount = GetTableCount();
     973           0 :     SCTAB nOtherCount = rOtherDoc.GetTableCount();
     974           0 :     SCTAB* pOtherTabs = new SCTAB[nThisCount];
     975             :     SCTAB nThisTab;
     976             : 
     977             :     //  Tabellen mit gleichen Namen vergleichen
     978           0 :     OUString aThisName;
     979           0 :     OUString aOtherName;
     980           0 :     for (nThisTab=0; nThisTab<nThisCount; nThisTab++)
     981             :     {
     982           0 :         SCTAB nOtherTab = SCTAB_MAX;
     983           0 :         if (!IsScenario(nThisTab))  // Szenarien weglassen
     984             :         {
     985           0 :             GetName( nThisTab, aThisName );
     986           0 :             for (SCTAB nTemp=0; nTemp<nOtherCount && nOtherTab>MAXTAB; nTemp++)
     987           0 :                 if (!rOtherDoc.IsScenario(nTemp))
     988             :                 {
     989           0 :                     rOtherDoc.GetName( nTemp, aOtherName );
     990           0 :                     if ( aThisName.equals(aOtherName) )
     991           0 :                         nOtherTab = nTemp;
     992             :                 }
     993             :         }
     994           0 :         pOtherTabs[nThisTab] = nOtherTab;
     995             :     }
     996             :     //  auffuellen, damit einzeln umbenannte Tabellen nicht wegfallen
     997           0 :     SCTAB nFillStart = 0;
     998           0 :     SCTAB nFillPos = 0;
     999           0 :     bool bInFill = false;
    1000           0 :     for (nThisTab = 0; nThisTab <= nThisCount; nThisTab++)
    1001             :     {
    1002           0 :         SCTAB nThisOther = ( nThisTab < nThisCount ) ? pOtherTabs[nThisTab] : nOtherCount;
    1003           0 :         if ( ValidTab(nThisOther) )
    1004             :         {
    1005           0 :             if ( bInFill )
    1006             :             {
    1007           0 :                 if ( nThisOther > nFillStart )      // ist was zu verteilen da?
    1008             :                 {
    1009           0 :                     SCTAB nDiff1 = nThisOther - nFillStart;
    1010           0 :                     SCTAB nDiff2 = nThisTab   - nFillPos;
    1011           0 :                     SCTAB nMinDiff = std::min(nDiff1, nDiff2);
    1012           0 :                     for (SCTAB i=0; i<nMinDiff; i++)
    1013           0 :                         if ( !IsScenario(nFillPos+i) && !rOtherDoc.IsScenario(nFillStart+i) )
    1014           0 :                             pOtherTabs[nFillPos+i] = nFillStart+i;
    1015             :                 }
    1016             : 
    1017           0 :                 bInFill = false;
    1018             :             }
    1019           0 :             nFillStart = nThisOther + 1;
    1020           0 :             nFillPos = nThisTab + 1;
    1021             :         }
    1022             :         else
    1023           0 :             bInFill = true;
    1024             :     }
    1025             : 
    1026             :     //
    1027             :     //  Tabellen in der gefundenen Reihenfolge vergleichen
    1028             :     //
    1029             : 
    1030           0 :     for (nThisTab=0; nThisTab<nThisCount; nThisTab++)
    1031             :     {
    1032           0 :         SCTAB nOtherTab = pOtherTabs[nThisTab];
    1033           0 :         if ( ValidTab(nOtherTab) )
    1034             :         {
    1035           0 :             SCCOL nThisEndCol = 0;
    1036           0 :             SCROW nThisEndRow = 0;
    1037           0 :             SCCOL nOtherEndCol = 0;
    1038           0 :             SCROW nOtherEndRow = 0;
    1039           0 :             GetCellArea( nThisTab, nThisEndCol, nThisEndRow );
    1040           0 :             rOtherDoc.GetCellArea( nOtherTab, nOtherEndCol, nOtherEndRow );
    1041           0 :             SCCOL nEndCol = std::max(nThisEndCol, nOtherEndCol);
    1042           0 :             SCROW nEndRow = std::max(nThisEndRow, nOtherEndRow);
    1043             :             SCCOL nThisCol;
    1044             :             SCROW nThisRow;
    1045             :             sal_uLong n1,n2;    // fuer AppendDeleteRange
    1046             : 
    1047             :             //! ein Progress ueber alle Tabellen ???
    1048           0 :             OUString aTabName;
    1049           0 :             GetName( nThisTab, aTabName );
    1050           0 :             OUString aTemplate = ScGlobal::GetRscString(STR_PROGRESS_COMPARING);
    1051           0 :             sal_Int32 nIndex = 0;
    1052           0 :             OUStringBuffer aProText = aTemplate.getToken( 0, '#', nIndex );
    1053           0 :             aProText.append(aTabName);
    1054           0 :             nIndex = 0;
    1055           0 :             aProText.append(aTemplate.getToken( 1, '#', nIndex ));
    1056             :             ScProgress aProgress( GetDocumentShell(),
    1057           0 :                                         aProText.makeStringAndClear(), 3*nThisEndRow );  // 2x FindOrder, 1x hier
    1058           0 :             long nProgressStart = 2*nThisEndRow;                    // start fuer hier
    1059             : 
    1060           0 :             SCCOLROW* pTempRows = new SCCOLROW[nThisEndRow+1];
    1061           0 :             SCCOLROW* pOtherRows = new SCCOLROW[nThisEndRow+1];
    1062           0 :             SCCOLROW* pOtherCols = new SCCOLROW[nThisEndCol+1];
    1063             : 
    1064             :             //  eingefuegte/geloeschte Spalten/Zeilen finden:
    1065             :             //  Zwei Versuche:
    1066             :             //  1) Original Zeilen vergleichen                          (pTempRows)
    1067             :             //  2) Original Spalten vergleichen                         (pOtherCols)
    1068             :             //     mit dieser Spaltenreihenfolge Zeilen vergleichen     (pOtherRows)
    1069             : 
    1070             :             //! Spalten vergleichen zweimal mit unterschiedlichem nMinGood ???
    1071             : 
    1072             :             // 1
    1073             :             FindOrder( pTempRows, nThisEndRow, nOtherEndRow, false,
    1074           0 :                         rOtherDoc, nThisTab, nOtherTab, nEndCol, NULL, &aProgress, 0 );
    1075             :             // 2
    1076             :             FindOrder( pOtherCols, nThisEndCol, nOtherEndCol, true,
    1077           0 :                         rOtherDoc, nThisTab, nOtherTab, nEndRow, NULL, NULL, 0 );
    1078             :             FindOrder( pOtherRows, nThisEndRow, nOtherEndRow, false,
    1079             :                         rOtherDoc, nThisTab, nOtherTab, nThisEndCol,
    1080           0 :                         pOtherCols, &aProgress, nThisEndRow );
    1081             : 
    1082           0 :             sal_uLong nMatch1 = 0;  // pTempRows, keine Spalten
    1083           0 :             for (nThisRow = 0; nThisRow<=nThisEndRow; nThisRow++)
    1084           0 :                 if (ValidRow(pTempRows[nThisRow]))
    1085           0 :                     nMatch1 += SC_DOCCOMP_MAXDIFF -
    1086           0 :                                RowDifferences( nThisRow, nThisTab, rOtherDoc, pTempRows[nThisRow],
    1087           0 :                                                 nOtherTab, nEndCol, NULL );
    1088             : 
    1089           0 :             sal_uLong nMatch2 = 0;  // pOtherRows, pOtherCols
    1090           0 :             for (nThisRow = 0; nThisRow<=nThisEndRow; nThisRow++)
    1091           0 :                 if (ValidRow(pOtherRows[nThisRow]))
    1092           0 :                     nMatch2 += SC_DOCCOMP_MAXDIFF -
    1093           0 :                                RowDifferences( nThisRow, nThisTab, rOtherDoc, pOtherRows[nThisRow],
    1094           0 :                                                 nOtherTab, nThisEndCol, pOtherCols );
    1095             : 
    1096           0 :             if ( nMatch1 >= nMatch2 )           // ohne Spalten ?
    1097             :             {
    1098             :                 //  Spalten zuruecksetzen
    1099           0 :                 for (nThisCol = 0; nThisCol<=nThisEndCol; nThisCol++)
    1100           0 :                     pOtherCols[nThisCol] = nThisCol;
    1101             : 
    1102             :                 //  Zeilenarrays vertauschen (geloescht werden sowieso beide)
    1103           0 :                 SCCOLROW* pSwap = pTempRows;
    1104           0 :                 pTempRows = pOtherRows;
    1105           0 :                 pOtherRows = pSwap;
    1106             :             }
    1107             :             else
    1108             :             {
    1109             :                 //  bleibt bei pOtherCols, pOtherRows
    1110             :             }
    1111             : 
    1112             : 
    1113             :             //  Change-Actions erzeugen
    1114             :             //  1) Spalten von rechts
    1115             :             //  2) Zeilen von unten
    1116             :             //  3) einzelne Zellen in normaler Reihenfolge
    1117             : 
    1118             :             //  Actions fuer eingefuegte/geloeschte Spalten
    1119             : 
    1120           0 :             SCCOL nLastOtherCol = static_cast<SCCOL>(nOtherEndCol + 1);
    1121             :             //  nThisEndCol ... 0
    1122           0 :             for ( nThisCol = nThisEndCol+1; nThisCol > 0; )
    1123             :             {
    1124           0 :                 --nThisCol;
    1125           0 :                 SCCOL nOtherCol = static_cast<SCCOL>(pOtherCols[nThisCol]);
    1126           0 :                 if ( ValidCol(nOtherCol) && nOtherCol+1 < nLastOtherCol )
    1127             :                 {
    1128             :                     // Luecke -> geloescht
    1129             :                     ScRange aDelRange( nOtherCol+1, 0, nOtherTab,
    1130           0 :                                         nLastOtherCol-1, MAXROW, nOtherTab );
    1131           0 :                     pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
    1132             :                 }
    1133           0 :                 if ( nOtherCol > MAXCOL )                       // eingefuegt
    1134             :                 {
    1135             :                     //  zusammenfassen
    1136           0 :                     if ( nThisCol == nThisEndCol || ValidCol(static_cast<SCCOL>(pOtherCols[nThisCol+1])) )
    1137             :                     {
    1138           0 :                         SCCOL nFirstNew = static_cast<SCCOL>(nThisCol);
    1139           0 :                         while ( nFirstNew > 0 && pOtherCols[nFirstNew-1] > MAXCOL )
    1140           0 :                             --nFirstNew;
    1141           0 :                         SCCOL nDiff = nThisCol - nFirstNew;
    1142             :                         ScRange aRange( nLastOtherCol, 0, nOtherTab,
    1143           0 :                                         nLastOtherCol+nDiff, MAXROW, nOtherTab );
    1144           0 :                         pChangeTrack->AppendInsert( aRange );
    1145             :                     }
    1146             :                 }
    1147             :                 else
    1148           0 :                     nLastOtherCol = nOtherCol;
    1149             :             }
    1150           0 :             if ( nLastOtherCol > 0 )                            // ganz oben geloescht
    1151             :             {
    1152             :                 ScRange aDelRange( 0, 0, nOtherTab,
    1153           0 :                                     nLastOtherCol-1, MAXROW, nOtherTab );
    1154           0 :                 pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
    1155             :             }
    1156             : 
    1157             :             //  Actions fuer eingefuegte/geloeschte Zeilen
    1158             : 
    1159           0 :             SCROW nLastOtherRow = nOtherEndRow + 1;
    1160             :             //  nThisEndRow ... 0
    1161           0 :             for ( nThisRow = nThisEndRow+1; nThisRow > 0; )
    1162             :             {
    1163           0 :                 --nThisRow;
    1164           0 :                 SCROW nOtherRow = pOtherRows[nThisRow];
    1165           0 :                 if ( ValidRow(nOtherRow) && nOtherRow+1 < nLastOtherRow )
    1166             :                 {
    1167             :                     // Luecke -> geloescht
    1168             :                     ScRange aDelRange( 0, nOtherRow+1, nOtherTab,
    1169           0 :                                         MAXCOL, nLastOtherRow-1, nOtherTab );
    1170           0 :                     pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
    1171             :                 }
    1172           0 :                 if ( nOtherRow > MAXROW )                       // eingefuegt
    1173             :                 {
    1174             :                     //  zusammenfassen
    1175           0 :                     if ( nThisRow == nThisEndRow || ValidRow(pOtherRows[nThisRow+1]) )
    1176             :                     {
    1177           0 :                         SCROW nFirstNew = nThisRow;
    1178           0 :                         while ( nFirstNew > 0 && pOtherRows[nFirstNew-1] > MAXROW )
    1179           0 :                             --nFirstNew;
    1180           0 :                         SCROW nDiff = nThisRow - nFirstNew;
    1181             :                         ScRange aRange( 0, nLastOtherRow, nOtherTab,
    1182           0 :                                         MAXCOL, nLastOtherRow+nDiff, nOtherTab );
    1183           0 :                         pChangeTrack->AppendInsert( aRange );
    1184             :                     }
    1185             :                 }
    1186             :                 else
    1187           0 :                     nLastOtherRow = nOtherRow;
    1188             :             }
    1189           0 :             if ( nLastOtherRow > 0 )                            // ganz oben geloescht
    1190             :             {
    1191             :                 ScRange aDelRange( 0, 0, nOtherTab,
    1192           0 :                                     MAXCOL, nLastOtherRow-1, nOtherTab );
    1193           0 :                 pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
    1194             :             }
    1195             : 
    1196             :             //  Zeilen durchgehen um einzelne Zellen zu finden
    1197             : 
    1198           0 :             for (nThisRow = 0; nThisRow <= nThisEndRow; nThisRow++)
    1199             :             {
    1200           0 :                 SCROW nOtherRow = pOtherRows[nThisRow];
    1201           0 :                 for (nThisCol = 0; nThisCol <= nThisEndCol; nThisCol++)
    1202             :                 {
    1203           0 :                     SCCOL nOtherCol = static_cast<SCCOL>(pOtherCols[nThisCol]);
    1204           0 :                     ScAddress aThisPos( nThisCol, nThisRow, nThisTab );
    1205           0 :                     ScCellValue aThisCell;
    1206           0 :                     aThisCell.assign(*this, aThisPos);
    1207           0 :                     ScCellValue aOtherCell; // start empty
    1208           0 :                     if ( ValidCol(nOtherCol) && ValidRow(nOtherRow) )
    1209             :                     {
    1210           0 :                         ScAddress aOtherPos( nOtherCol, nOtherRow, nOtherTab );
    1211           0 :                         aOtherCell.assign(*this, aOtherPos);
    1212             :                     }
    1213             : 
    1214           0 :                     if (!aThisCell.equalsWithoutFormat(aOtherCell))
    1215             :                     {
    1216           0 :                         ScRange aRange( aThisPos );
    1217           0 :                         ScChangeActionContent* pAction = new ScChangeActionContent( aRange );
    1218           0 :                         pAction->SetOldValue(aOtherCell, &rOtherDoc, this);
    1219           0 :                         pAction->SetNewValue(aThisCell, this);
    1220           0 :                         pChangeTrack->Append( pAction );
    1221             :                     }
    1222           0 :                 }
    1223           0 :                 aProgress.SetStateOnPercent(nProgressStart+nThisRow);
    1224             :             }
    1225             : 
    1226           0 :             delete[] pOtherCols;
    1227           0 :             delete[] pOtherRows;
    1228           0 :             delete[] pTempRows;
    1229             :         }
    1230             :     }
    1231             : 
    1232             :     //! Inhalt von eingefuegten / geloeschten Tabellen ???
    1233             :     //! Aktionen fuer eingefuegte / geloeschte Tabellen ???
    1234             : 
    1235           0 :     delete[] pOtherTabs;
    1236          93 : }
    1237             : 
    1238             : 
    1239             : 
    1240             : 
    1241             : 
    1242             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10