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

Generated by: LCOV version 1.10