LCOV - code coverage report
Current view: top level - sc/source/ui/docshell - dbdocfun.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 472 777 60.7 %
Date: 2012-08-25 Functions: 13 15 86.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 498 1492 33.4 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include <sfx2/app.hxx>
      30                 :            : #include <vcl/msgbox.hxx>
      31                 :            : #include <vcl/waitobj.hxx>
      32                 :            : #include <svx/dataaccessdescriptor.hxx>
      33                 :            : 
      34                 :            : #include <com/sun/star/sdb/CommandType.hpp>
      35                 :            : 
      36                 :            : #include "dbdocfun.hxx"
      37                 :            : #include "sc.hrc"
      38                 :            : #include "dbdata.hxx"
      39                 :            : #include "undodat.hxx"
      40                 :            : #include "docsh.hxx"
      41                 :            : #include "docfunc.hxx"
      42                 :            : #include "globstr.hrc"
      43                 :            : #include "globalnames.hxx"
      44                 :            : #include "tabvwsh.hxx"
      45                 :            : #include "patattr.hxx"
      46                 :            : #include "rangenam.hxx"
      47                 :            : #include "olinetab.hxx"
      48                 :            : #include "dpobject.hxx"
      49                 :            : #include "dpsave.hxx"
      50                 :            : #include "dociter.hxx"      // for lcl_EmptyExcept
      51                 :            : #include "cell.hxx"         // for lcl_EmptyExcept
      52                 :            : #include "editable.hxx"
      53                 :            : #include "attrib.hxx"
      54                 :            : #include "drwlayer.hxx"
      55                 :            : #include "dpshttab.hxx"
      56                 :            : #include "hints.hxx"
      57                 :            : #include "queryentry.hxx"
      58                 :            : #include "markdata.hxx"
      59                 :            : #include "progress.hxx"
      60                 :            : 
      61                 :            : #include <set>
      62                 :            : 
      63                 :            : using namespace ::com::sun::star;
      64                 :            : 
      65                 :            : // -----------------------------------------------------------------
      66                 :            : 
      67                 :          3 : bool ScDBDocFunc::AddDBRange( const ::rtl::OUString& rName, const ScRange& rRange, sal_Bool /* bApi */ )
      68                 :            : {
      69                 :            : 
      70         [ +  - ]:          3 :     ScDocShellModificator aModificator( rDocShell );
      71                 :            : 
      72                 :          3 :     ScDocument* pDoc = rDocShell.GetDocument();
      73         [ +  - ]:          3 :     ScDBCollection* pDocColl = pDoc->GetDBCollection();
      74                 :          3 :     sal_Bool bUndo (pDoc->IsUndoEnabled());
      75                 :            : 
      76                 :          3 :     ScDBCollection* pUndoColl = NULL;
      77         [ +  - ]:          3 :     if (bUndo)
      78 [ +  - ][ +  - ]:          3 :         pUndoColl = new ScDBCollection( *pDocColl );
      79                 :            : 
      80                 :          3 :     ScDBData* pNew = new ScDBData( rName, rRange.aStart.Tab(),
      81                 :          3 :                                     rRange.aStart.Col(), rRange.aStart.Row(),
      82 [ +  - ][ +  - ]:          3 :                                     rRange.aEnd.Col(), rRange.aEnd.Row() );
      83                 :            : 
      84                 :            :     // #i55926# While loading XML, formula cells only have a single string token,
      85                 :            :     // so CompileDBFormula would never find any name (index) tokens, and would
      86                 :            :     // unnecessarily loop through all cells.
      87                 :          3 :     bool bCompile = !pDoc->IsImportingXML();
      88                 :            :     bool bOk;
      89         [ +  - ]:          3 :     if ( bCompile )
      90         [ +  - ]:          3 :         pDoc->CompileDBFormula( sal_True );     // CreateFormulaString
      91         [ -  + ]:          3 :     if ( rName == STR_DB_LOCAL_NONAME )
      92                 :            :     {
      93         [ #  # ]:          0 :         pDoc->SetAnonymousDBData(rRange.aStart.Tab() , pNew);
      94                 :          0 :         bOk = true;
      95                 :            :     }
      96                 :            :     else
      97                 :            :     {
      98 [ +  - ][ +  - ]:          3 :         bOk = pDocColl->getNamedDBs().insert(pNew);
      99                 :            :     }
     100         [ +  - ]:          3 :     if ( bCompile )
     101         [ +  - ]:          3 :         pDoc->CompileDBFormula( false );    // CompileFormulaString
     102                 :            : 
     103         [ -  + ]:          3 :     if (!bOk)
     104                 :            :     {
     105 [ #  # ][ #  # ]:          0 :         delete pNew;
     106 [ #  # ][ #  # ]:          0 :         delete pUndoColl;
     107                 :          0 :         return false;
     108                 :            :     }
     109                 :            : 
     110         [ +  - ]:          3 :     if (bUndo)
     111                 :            :     {
     112 [ +  - ][ +  - ]:          3 :         ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
     113         [ +  - ]:          3 :         rDocShell.GetUndoManager()->AddUndoAction(
     114 [ +  - ][ +  - ]:          3 :                         new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
                 [ +  - ]
     115                 :            :     }
     116                 :            : 
     117         [ +  - ]:          3 :     aModificator.SetDocumentModified();
     118 [ +  - ][ +  - ]:          3 :     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
         [ +  - ][ +  - ]
     119         [ +  - ]:          3 :     return true;
     120                 :            : }
     121                 :            : 
     122                 :          0 : bool ScDBDocFunc::DeleteDBRange(const ::rtl::OUString& rName)
     123                 :            : {
     124                 :          0 :     bool bDone = false;
     125                 :          0 :     ScDocument* pDoc = rDocShell.GetDocument();
     126                 :          0 :     ScDBCollection* pDocColl = pDoc->GetDBCollection();
     127                 :          0 :     bool bUndo = pDoc->IsUndoEnabled();
     128                 :            : 
     129                 :          0 :     ScDBCollection::NamedDBs& rDBs = pDocColl->getNamedDBs();
     130                 :          0 :     const ScDBData* p = rDBs.findByName(rName);
     131         [ #  # ]:          0 :     if (p)
     132                 :            :     {
     133         [ #  # ]:          0 :         ScDocShellModificator aModificator( rDocShell );
     134                 :            : 
     135                 :          0 :         ScDBCollection* pUndoColl = NULL;
     136         [ #  # ]:          0 :         if (bUndo)
     137 [ #  # ][ #  # ]:          0 :             pUndoColl = new ScDBCollection( *pDocColl );
     138                 :            : 
     139         [ #  # ]:          0 :         pDoc->CompileDBFormula( true );     // CreateFormulaString
     140         [ #  # ]:          0 :         rDBs.erase(*p);
     141         [ #  # ]:          0 :         pDoc->CompileDBFormula( false );    // CompileFormulaString
     142                 :            : 
     143         [ #  # ]:          0 :         if (bUndo)
     144                 :            :         {
     145 [ #  # ][ #  # ]:          0 :             ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
     146         [ #  # ]:          0 :             rDocShell.GetUndoManager()->AddUndoAction(
     147 [ #  # ][ #  # ]:          0 :                             new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
                 [ #  # ]
     148                 :            :         }
     149                 :            : 
     150         [ #  # ]:          0 :         aModificator.SetDocumentModified();
     151 [ #  # ][ #  # ]:          0 :         SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
         [ #  # ][ #  # ]
     152         [ #  # ]:          0 :         bDone = true;
     153                 :            :     }
     154                 :            : 
     155                 :          0 :     return bDone;
     156                 :            : }
     157                 :            : 
     158                 :          2 : bool ScDBDocFunc::RenameDBRange( const String& rOld, const String& rNew )
     159                 :            : {
     160                 :          2 :     bool bDone = false;
     161                 :          2 :     ScDocument* pDoc = rDocShell.GetDocument();
     162                 :          2 :     ScDBCollection* pDocColl = pDoc->GetDBCollection();
     163                 :          2 :     bool bUndo = pDoc->IsUndoEnabled();
     164                 :          2 :     ScDBCollection::NamedDBs& rDBs = pDocColl->getNamedDBs();
     165         [ +  - ]:          2 :     const ScDBData* pOld = rDBs.findByName(rOld);
     166         [ +  - ]:          2 :     const ScDBData* pNew = rDBs.findByName(rNew);
     167 [ +  - ][ +  - ]:          2 :     if (pOld && !pNew)
     168                 :            :     {
     169         [ +  - ]:          2 :         ScDocShellModificator aModificator( rDocShell );
     170                 :            : 
     171 [ +  - ][ +  - ]:          2 :         ScDBData* pNewData = new ScDBData(rNew, *pOld);
                 [ +  - ]
     172                 :            : 
     173 [ +  - ][ +  - ]:          2 :         ScDBCollection* pUndoColl = new ScDBCollection( *pDocColl );
     174                 :            : 
     175         [ +  - ]:          2 :         pDoc->CompileDBFormula(true);               // CreateFormulaString
     176         [ +  - ]:          2 :         rDBs.erase(*pOld);
     177         [ +  - ]:          2 :         bool bInserted = rDBs.insert(pNewData);
     178         [ -  + ]:          2 :         if (!bInserted)                             // Fehler -> alten Zustand wiederherstellen
     179         [ #  # ]:          0 :             pDoc->SetDBCollection(pUndoColl);       // gehoert dann dem Dokument
     180                 :            :                                                     //
     181         [ +  - ]:          2 :         pDoc->CompileDBFormula( false );            // CompileFormulaString
     182                 :            : 
     183         [ +  - ]:          2 :         if (bInserted)                              // Einfuegen hat geklappt
     184                 :            :         {
     185         [ +  - ]:          2 :             if (bUndo)
     186                 :            :             {
     187 [ +  - ][ +  - ]:          2 :                 ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
     188         [ +  - ]:          2 :                 rDocShell.GetUndoManager()->AddUndoAction(
     189 [ +  - ][ +  - ]:          2 :                                 new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
                 [ +  - ]
     190                 :            :             }
     191                 :            :             else
     192 [ #  # ][ #  # ]:          0 :                 delete pUndoColl;
     193                 :            : 
     194         [ +  - ]:          2 :             aModificator.SetDocumentModified();
     195 [ +  - ][ +  - ]:          2 :             SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
         [ +  - ][ +  - ]
     196                 :          2 :             bDone = true;
     197         [ +  - ]:          2 :         }
     198                 :            :     }
     199                 :            : 
     200                 :          2 :     return bDone;
     201                 :            : }
     202                 :            : 
     203                 :         48 : bool ScDBDocFunc::ModifyDBData( const ScDBData& rNewData )
     204                 :            : {
     205                 :         48 :     bool bDone = false;
     206                 :         48 :     ScDocument* pDoc = rDocShell.GetDocument();
     207                 :         48 :     ScDBCollection* pDocColl = pDoc->GetDBCollection();
     208                 :         48 :     bool bUndo = pDoc->IsUndoEnabled();
     209                 :            : 
     210                 :         48 :     ScDBData* pData = NULL;
     211         [ +  + ]:         48 :     if (rNewData.GetName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(STR_DB_LOCAL_NONAME)))
     212                 :            :     {
     213                 :         24 :         ScRange aRange;
     214         [ +  - ]:         24 :         rNewData.GetArea(aRange);
     215                 :         24 :         SCTAB nTab = aRange.aStart.Tab();
     216         [ +  - ]:         24 :         pData = pDoc->GetAnonymousDBData(nTab);
     217                 :            :     }
     218                 :            :     else
     219                 :         24 :         pData = pDocColl->getNamedDBs().findByName(rNewData.GetName());
     220                 :            : 
     221         [ +  - ]:         48 :     if (pData)
     222                 :            :     {
     223         [ +  - ]:         48 :         ScDocShellModificator aModificator( rDocShell );
     224                 :         48 :         ScRange aOldRange, aNewRange;
     225         [ +  - ]:         48 :         pData->GetArea(aOldRange);
     226         [ +  - ]:         48 :         rNewData.GetArea(aNewRange);
     227                 :         48 :         bool bAreaChanged = ( aOldRange != aNewRange );     // dann muss neu compiliert werden
     228                 :            : 
     229                 :         48 :         ScDBCollection* pUndoColl = NULL;
     230         [ +  + ]:         48 :         if (bUndo)
     231 [ +  - ][ +  - ]:         24 :             pUndoColl = new ScDBCollection( *pDocColl );
     232                 :            : 
     233         [ +  - ]:         48 :         *pData = rNewData;
     234         [ +  + ]:         48 :         if (bAreaChanged)
     235         [ +  - ]:          2 :             pDoc->CompileDBFormula();
     236                 :            : 
     237         [ +  + ]:         48 :         if (bUndo)
     238                 :            :         {
     239 [ +  - ][ +  - ]:         24 :             ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
     240         [ +  - ]:         24 :             rDocShell.GetUndoManager()->AddUndoAction(
     241 [ +  - ][ +  - ]:         24 :                             new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
                 [ +  - ]
     242                 :            :         }
     243                 :            : 
     244         [ +  - ]:         48 :         aModificator.SetDocumentModified();
     245         [ +  - ]:         48 :         bDone = true;
     246                 :            :     }
     247                 :            : 
     248                 :         48 :     return bDone;
     249                 :            : }
     250                 :            : 
     251                 :            : // -----------------------------------------------------------------
     252                 :            : 
     253                 :          2 : bool ScDBDocFunc::RepeatDB( const ::rtl::OUString& rDBName, bool bRecord, bool bApi, bool bIsUnnamed, SCTAB aTab )
     254                 :            : {
     255                 :            :     //! auch fuer ScDBFunc::RepeatDB benutzen!
     256                 :            : 
     257                 :          2 :     bool bDone = false;
     258                 :          2 :     ScDocument* pDoc = rDocShell.GetDocument();
     259 [ -  + ][ -  + ]:          2 :     if (bRecord && !pDoc->IsUndoEnabled())
                 [ +  - ]
     260                 :          0 :         bRecord = false;
     261                 :          2 :     ScDBData* pDBData = NULL;
     262         [ -  + ]:          2 :     if (bIsUnnamed)
     263                 :            :     {
     264                 :          0 :         pDBData = pDoc->GetAnonymousDBData( aTab );
     265                 :            :     }
     266                 :            :     else
     267                 :            :     {
     268                 :          2 :         ScDBCollection* pColl = pDoc->GetDBCollection();
     269         [ +  - ]:          2 :         if (pColl)
     270                 :          2 :             pDBData = pColl->getNamedDBs().findByName(rDBName);
     271                 :            :     }
     272                 :            : 
     273         [ +  - ]:          2 :     if ( pDBData )
     274                 :            :     {
     275         [ +  - ]:          2 :         ScQueryParam aQueryParam;
     276         [ +  - ]:          2 :         pDBData->GetQueryParam( aQueryParam );
     277         [ +  - ]:          2 :         sal_Bool bQuery = aQueryParam.GetEntry(0).bDoQuery;
     278                 :            : 
     279         [ +  - ]:          2 :         ScSortParam aSortParam;
     280         [ +  - ]:          2 :         pDBData->GetSortParam( aSortParam );
     281                 :          2 :         sal_Bool bSort = aSortParam.maKeyState[0].bDoSort;
     282                 :            : 
     283         [ +  - ]:          2 :         ScSubTotalParam aSubTotalParam;
     284         [ +  - ]:          2 :         pDBData->GetSubTotalParam( aSubTotalParam );
     285 [ -  + ][ #  # ]:          2 :         sal_Bool bSubTotal = aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly;
     286                 :            : 
     287 [ -  + ][ #  # ]:          2 :         if ( bQuery || bSort || bSubTotal )
                 [ #  # ]
     288                 :            :         {
     289                 :          2 :             sal_Bool bQuerySize = false;
     290                 :          2 :             ScRange aOldQuery;
     291                 :          2 :             ScRange aNewQuery;
     292 [ -  + ][ +  - ]:          2 :             if (bQuery && !aQueryParam.bInplace)
     293                 :            :             {
     294                 :            :                 ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
     295         [ #  # ]:          0 :                                                         aQueryParam.nDestTab, sal_True );
     296 [ #  # ][ #  # ]:          0 :                 if (pDest && pDest->IsDoSize())
                 [ #  # ]
     297                 :            :                 {
     298         [ #  # ]:          0 :                     pDest->GetArea( aOldQuery );
     299                 :          0 :                     bQuerySize = sal_True;
     300                 :            :                 }
     301                 :            :             }
     302                 :            : 
     303                 :            :             SCTAB nTab;
     304                 :            :             SCCOL nStartCol;
     305                 :            :             SCROW nStartRow;
     306                 :            :             SCCOL nEndCol;
     307                 :            :             SCROW nEndRow;
     308         [ +  - ]:          2 :             pDBData->GetArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow );
     309                 :            : 
     310                 :            :             //!     Undo nur benoetigte Daten ?
     311                 :            : 
     312                 :          2 :             ScDocument* pUndoDoc = NULL;
     313                 :          2 :             ScOutlineTable* pUndoTab = NULL;
     314                 :          2 :             ScRangeName* pUndoRange = NULL;
     315                 :          2 :             ScDBCollection* pUndoDB = NULL;
     316                 :            : 
     317         [ +  - ]:          2 :             if (bRecord)
     318                 :            :             {
     319         [ +  - ]:          2 :                 SCTAB nTabCount = pDoc->GetTableCount();
     320 [ +  - ][ +  - ]:          2 :                 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
     321         [ +  - ]:          2 :                 ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
     322         [ -  + ]:          2 :                 if (pTable)
     323                 :            :                 {
     324 [ #  # ][ #  # ]:          0 :                     pUndoTab = new ScOutlineTable( *pTable );
     325                 :            : 
     326                 :            :                     // column/row state
     327                 :            :                     SCCOLROW nOutStartCol, nOutEndCol;
     328                 :            :                     SCCOLROW nOutStartRow, nOutEndRow;
     329         [ #  # ]:          0 :                     pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol );
     330         [ #  # ]:          0 :                     pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow );
     331                 :            : 
     332         [ #  # ]:          0 :                     pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True );
     333                 :            :                     pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0,
     334                 :            :                             nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab,
     335         [ #  # ]:          0 :                             IDF_NONE, false, pUndoDoc );
     336                 :            :                     pDoc->CopyToDocument( 0, static_cast<SCROW>(nOutStartRow),
     337                 :            :                             nTab, MAXCOL, static_cast<SCROW>(nOutEndRow), nTab,
     338         [ #  # ]:          0 :                             IDF_NONE, false, pUndoDoc );
     339                 :            :                 }
     340                 :            :                 else
     341         [ +  - ]:          2 :                     pUndoDoc->InitUndo( pDoc, nTab, nTab, false, sal_True );
     342                 :            : 
     343                 :            :                 //  Datenbereich sichern - incl. Filter-Ergebnis
     344         [ +  - ]:          2 :                 pDoc->CopyToDocument( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab, IDF_ALL, false, pUndoDoc );
     345                 :            : 
     346                 :            :                 //  alle Formeln wegen Referenzen
     347         [ +  - ]:          2 :                 pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, IDF_FORMULA, false, pUndoDoc );
     348                 :            : 
     349                 :            :                 //  DB- und andere Bereiche
     350         [ +  - ]:          2 :                 ScRangeName* pDocRange = pDoc->GetRangeName();
     351 [ +  - ][ -  + ]:          2 :                 if (!pDocRange->empty())
     352 [ #  # ][ #  # ]:          0 :                     pUndoRange = new ScRangeName( *pDocRange );
     353         [ +  - ]:          2 :                 ScDBCollection* pDocDB = pDoc->GetDBCollection();
     354 [ +  - ][ +  - ]:          2 :                 if (!pDocDB->empty())
     355 [ +  - ][ +  - ]:          2 :                     pUndoDB = new ScDBCollection( *pDocDB );
     356                 :            :             }
     357                 :            : 
     358 [ -  + ][ #  # ]:          2 :             if (bSort && bSubTotal)
     359                 :            :             {
     360                 :            :                 //  Sortieren ohne SubTotals
     361                 :            : 
     362                 :          0 :                 aSubTotalParam.bRemoveOnly = sal_True;      // wird unten wieder zurueckgesetzt
     363         [ #  # ]:          0 :                 DoSubTotals( nTab, aSubTotalParam, NULL, false, bApi );
     364                 :            :             }
     365                 :            : 
     366         [ -  + ]:          2 :             if (bSort)
     367                 :            :             {
     368         [ #  # ]:          0 :                 pDBData->GetSortParam( aSortParam );            // Bereich kann sich geaendert haben
     369         [ #  # ]:          0 :                 Sort( nTab, aSortParam, false, false, bApi );
     370                 :            :             }
     371         [ +  - ]:          2 :             if (bQuery)
     372                 :            :             {
     373         [ +  - ]:          2 :                 pDBData->GetQueryParam( aQueryParam );          // Bereich kann sich geaendert haben
     374                 :          2 :                 ScRange aAdvSource;
     375 [ -  + ][ +  - ]:          2 :                 if (pDBData->GetAdvancedQuerySource(aAdvSource))
     376         [ #  # ]:          0 :                     Query( nTab, aQueryParam, &aAdvSource, false, bApi );
     377                 :            :                 else
     378         [ +  - ]:          2 :                     Query( nTab, aQueryParam, NULL, false, bApi );
     379                 :            : 
     380                 :            :                 //  bei nicht-inplace kann die Tabelle umgestellt worden sein
     381                 :            : //              if ( !aQueryParam.bInplace && aQueryParam.nDestTab != nTab )
     382                 :            : //                  SetTabNo( nTab );
     383                 :            :             }
     384         [ -  + ]:          2 :             if (bSubTotal)
     385                 :            :             {
     386         [ #  # ]:          0 :                 pDBData->GetSubTotalParam( aSubTotalParam );    // Bereich kann sich geaendert haben
     387                 :          0 :                 aSubTotalParam.bRemoveOnly = false;
     388         [ #  # ]:          0 :                 DoSubTotals( nTab, aSubTotalParam, NULL, false, bApi );
     389                 :            :             }
     390                 :            : 
     391         [ +  - ]:          2 :             if (bRecord)
     392                 :            :             {
     393                 :            :                 SCTAB nDummyTab;
     394                 :            :                 SCCOL nDummyCol;
     395                 :            :                 SCROW nDummyRow;
     396                 :            :                 SCROW nNewEndRow;
     397         [ +  - ]:          2 :                 pDBData->GetArea( nDummyTab, nDummyCol,nDummyRow, nDummyCol,nNewEndRow );
     398                 :            : 
     399                 :          2 :                 const ScRange* pOld = NULL;
     400                 :          2 :                 const ScRange* pNew = NULL;
     401         [ -  + ]:          2 :                 if (bQuerySize)
     402                 :            :                 {
     403                 :            :                     ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
     404         [ #  # ]:          0 :                                                             aQueryParam.nDestTab, sal_True );
     405         [ #  # ]:          0 :                     if (pDest)
     406                 :            :                     {
     407         [ #  # ]:          0 :                         pDest->GetArea( aNewQuery );
     408                 :          0 :                         pOld = &aOldQuery;
     409                 :          0 :                         pNew = &aNewQuery;
     410                 :            :                     }
     411                 :            :                 }
     412                 :            : 
     413         [ +  - ]:          2 :                 rDocShell.GetUndoManager()->AddUndoAction(
     414                 :            :                     new ScUndoRepeatDB( &rDocShell, nTab,
     415                 :            :                                             nStartCol, nStartRow, nEndCol, nEndRow,
     416                 :            :                                             nNewEndRow,
     417                 :            :                                             //nCurX, nCurY,
     418                 :            :                                             nStartCol, nStartRow,
     419                 :            :                                             pUndoDoc, pUndoTab,
     420                 :            :                                             pUndoRange, pUndoDB,
     421 [ +  - ][ +  - ]:          2 :                                             pOld, pNew ) );
                 [ +  - ]
     422                 :            :             }
     423                 :            : 
     424                 :            :             rDocShell.PostPaint(ScRange(0, 0, nTab, MAXCOL, MAXROW, nTab),
     425 [ +  - ][ +  - ]:          2 :                                 PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE);
                 [ +  - ]
     426                 :          2 :             bDone = sal_True;
     427                 :            :         }
     428         [ #  # ]:          0 :         else if (!bApi)     // "Keine Operationen auszufuehren"
     429 [ #  # ][ +  - ]:          2 :             rDocShell.ErrorMessage(STR_MSSG_REPEATDB_0);
                 [ +  - ]
     430                 :            :     }
     431                 :            : 
     432                 :          2 :     return bDone;
     433                 :            : }
     434                 :            : 
     435                 :            : // -----------------------------------------------------------------
     436                 :            : 
     437                 :         10 : sal_Bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam,
     438                 :            :                             sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi )
     439                 :            : {
     440         [ +  - ]:         10 :     ScDocShellModificator aModificator( rDocShell );
     441                 :            : 
     442                 :         10 :     ScDocument* pDoc = rDocShell.GetDocument();
     443 [ -  + ][ -  + ]:         10 :     if (bRecord && !pDoc->IsUndoEnabled())
                 [ +  + ]
     444                 :          0 :         bRecord = false;
     445                 :         10 :     SCTAB nSrcTab = nTab;
     446         [ +  - ]:         10 :     ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
     447                 :            : 
     448                 :            :     ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rSortParam.nCol1, rSortParam.nRow1,
     449         [ +  - ]:         10 :                                                     rSortParam.nCol2, rSortParam.nRow2 );
     450         [ -  + ]:         10 :     if (!pDBData)
     451                 :            :     {
     452                 :            :         OSL_FAIL( "Sort: keine DBData" );
     453                 :          0 :         return false;
     454                 :            :     }
     455                 :            : 
     456                 :         10 :     ScDBData* pDestData = NULL;
     457                 :         10 :     ScRange aOldDest;
     458                 :         10 :     sal_Bool bCopy = !rSortParam.bInplace;
     459 [ #  # ][ #  # ]:         10 :     if ( bCopy && rSortParam.nDestCol == rSortParam.nCol1 &&
         [ #  # ][ -  + ]
     460                 :            :                   rSortParam.nDestRow == rSortParam.nRow1 && rSortParam.nDestTab == nTab )
     461                 :          0 :         bCopy = false;
     462         [ +  - ]:         10 :     ScSortParam aLocalParam( rSortParam );
     463         [ -  + ]:         10 :     if ( bCopy )
     464                 :            :     {
     465         [ #  # ]:          0 :         aLocalParam.MoveToDest();
     466         [ #  # ]:          0 :         if ( !ValidColRow( aLocalParam.nCol2, aLocalParam.nRow2 ) )
     467                 :            :         {
     468         [ #  # ]:          0 :             if (!bApi)
     469         [ #  # ]:          0 :                 rDocShell.ErrorMessage(STR_PASTE_FULL);
     470                 :          0 :             return false;
     471                 :            :         }
     472                 :            : 
     473                 :          0 :         nTab = rSortParam.nDestTab;
     474                 :            :         pDestData = pDoc->GetDBAtCursor( rSortParam.nDestCol, rSortParam.nDestRow,
     475         [ #  # ]:          0 :                                             rSortParam.nDestTab, sal_True );
     476         [ #  # ]:          0 :         if (pDestData)
     477         [ #  # ]:          0 :             pDestData->GetArea(aOldDest);
     478                 :            :     }
     479                 :            : 
     480                 :            :     ScEditableTester aTester( pDoc, nTab, aLocalParam.nCol1,aLocalParam.nRow1,
     481         [ +  - ]:         10 :                                         aLocalParam.nCol2,aLocalParam.nRow2 );
     482         [ -  + ]:         10 :     if (!aTester.IsEditable())
     483                 :            :     {
     484         [ #  # ]:          0 :         if (!bApi)
     485 [ #  # ][ #  # ]:          0 :             rDocShell.ErrorMessage(aTester.GetMessageId());
     486                 :          0 :         return false;
     487                 :            :     }
     488                 :            : 
     489 [ +  + ][ -  + ]:         18 :     if ( aLocalParam.bIncludePattern && pDoc->HasAttrib(
                 [ -  + ]
     490                 :            :                                         aLocalParam.nCol1, aLocalParam.nRow1, nTab,
     491                 :            :                                         aLocalParam.nCol2, aLocalParam.nRow2, nTab,
     492         [ +  - ]:          8 :                                         HASATTR_MERGED | HASATTR_OVERLAPPED ) )
     493                 :            :     {
     494                 :            :         //  Merge-Attribute wuerden beim Sortieren durcheinanderkommen
     495         [ #  # ]:          0 :         if (!bApi)
     496         [ #  # ]:          0 :             rDocShell.ErrorMessage(STR_SORT_ERR_MERGED);
     497                 :          0 :         return false;
     498                 :            :     }
     499                 :            : 
     500                 :            : 
     501                 :            :     //      ausfuehren
     502                 :            : 
     503 [ +  - ][ +  - ]:         10 :     WaitObject aWait( rDocShell.GetActiveDialogParent() );
     504                 :            : 
     505                 :         10 :     sal_Bool bRepeatQuery = false;                          // bestehenden Filter wiederholen?
     506         [ +  - ]:         10 :     ScQueryParam aQueryParam;
     507         [ +  - ]:         10 :     pDBData->GetQueryParam( aQueryParam );
     508 [ +  - ][ -  + ]:         10 :     if ( aQueryParam.GetEntry(0).bDoQuery )
     509                 :          0 :         bRepeatQuery = sal_True;
     510                 :            : 
     511 [ -  + ][ #  # ]:         10 :     if (bRepeatQuery && bCopy)
     512                 :            :     {
     513 [ #  # ][ #  # ]:          0 :         if ( aQueryParam.bInplace ||
         [ #  # ][ #  # ]
     514                 :            :                 aQueryParam.nDestCol != rSortParam.nDestCol ||
     515                 :            :                 aQueryParam.nDestRow != rSortParam.nDestRow ||
     516                 :            :                 aQueryParam.nDestTab != rSortParam.nDestTab )       // Query auf selben Zielbereich?
     517                 :          0 :             bRepeatQuery = false;
     518                 :            :     }
     519                 :            : 
     520                 :         10 :     ScUndoSort* pUndoAction = 0;
     521         [ +  + ]:         10 :     if ( bRecord )
     522                 :            :     {
     523                 :            :         //  Referenzen ausserhalb des Bereichs werden nicht veraendert !
     524                 :            : 
     525 [ +  - ][ +  - ]:          8 :         ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
     526                 :            :         //  Zeilenhoehen immer (wegen automatischer Anpassung)
     527                 :            :         //! auf ScBlockUndo umstellen
     528         [ +  - ]:          8 :         pUndoDoc->InitUndo( pDoc, nTab, nTab, false, sal_True );
     529                 :            : 
     530                 :            :         /*  #i59745# Do not copy note captions to undo document. All existing
     531                 :            :             caption objects will be repositioned while sorting which is tracked
     532                 :            :             in drawing undo. When undo is executed, the old positions will be
     533                 :            :             restored, and the cells with the old notes (which still refer to the
     534                 :            :             existing captions) will be copied back into the source document. */
     535                 :            :         pDoc->CopyToDocument( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
     536                 :            :                                 aLocalParam.nCol2, aLocalParam.nRow2, nTab,
     537         [ +  - ]:          8 :                                 IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc );
     538                 :            : 
     539                 :          8 :         const ScRange* pR = 0;
     540         [ -  + ]:          8 :         if (pDestData)
     541                 :            :         {
     542                 :            :             /*  #i59745# Do not copy note captions from destination range to
     543                 :            :                 undo document. All existing caption objects will be removed
     544                 :            :                 which is tracked in drawing undo. When undo is executed, the
     545                 :            :                 caption objects are reinserted with drawing undo, and the cells
     546                 :            :                 with the old notes (which still refer to the existing captions)
     547                 :            :                 will be copied back into the source document. */
     548         [ #  # ]:          0 :             pDoc->CopyToDocument( aOldDest, IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc );
     549                 :          0 :             pR = &aOldDest;
     550                 :            :         }
     551                 :            : 
     552                 :            :         //  Zeilenhoehen immer (wegen automatischer Anpassung)
     553                 :            :         //! auf ScBlockUndo umstellen
     554                 :            : //        if (bRepeatQuery)
     555                 :            :             pDoc->CopyToDocument( 0, aLocalParam.nRow1, nTab, MAXCOL, aLocalParam.nRow2, nTab,
     556         [ +  - ]:          8 :                                     IDF_NONE, false, pUndoDoc );
     557                 :            : 
     558                 :          8 :         ScDBCollection* pUndoDB = NULL;
     559         [ +  - ]:          8 :         ScDBCollection* pDocDB = pDoc->GetDBCollection();
     560 [ +  - ][ -  + ]:          8 :         if (!pDocDB->empty())
     561 [ #  # ][ #  # ]:          0 :             pUndoDB = new ScDBCollection( *pDocDB );
     562                 :            : 
     563 [ +  - ][ +  - ]:          8 :         pUndoAction = new ScUndoSort( &rDocShell, nTab, rSortParam, bRepeatQuery, pUndoDoc, pUndoDB, pR );
     564 [ +  - ][ +  - ]:          8 :         rDocShell.GetUndoManager()->AddUndoAction( pUndoAction );
     565                 :            : 
     566                 :            :         // #i59745# collect all drawing undo actions affecting cell note captions
     567         [ +  - ]:          8 :         if( pDrawLayer )
     568         [ +  - ]:          8 :             pDrawLayer->BeginCalcUndo();
     569                 :            :     }
     570                 :            : 
     571         [ -  + ]:         10 :     if ( bCopy )
     572                 :            :     {
     573         [ #  # ]:          0 :         if (pDestData)
     574         [ #  # ]:          0 :             pDoc->DeleteAreaTab(aOldDest, IDF_CONTENTS);            // Zielbereich vorher loeschen
     575                 :            : 
     576                 :            :         ScRange aSource( rSortParam.nCol1,rSortParam.nRow1,nSrcTab,
     577                 :          0 :                             rSortParam.nCol2,rSortParam.nRow2,nSrcTab );
     578                 :          0 :         ScAddress aDest( rSortParam.nDestCol, rSortParam.nDestRow, rSortParam.nDestTab );
     579                 :            : 
     580         [ #  # ]:          0 :         rDocShell.GetDocFunc().MoveBlock( aSource, aDest, false, false, false, sal_True );
     581                 :            :     }
     582                 :            : 
     583                 :            :     // don't call ScDocument::Sort with an empty SortParam (may be empty here if bCopy is set)
     584 [ +  - ][ +  - ]:         10 :     if (aLocalParam.GetSortKeyCount() && aLocalParam.maKeyState[0].bDoSort)
                 [ +  - ]
     585         [ +  - ]:         10 :         pDoc->Sort( nTab, aLocalParam, bRepeatQuery );
     586                 :            : 
     587                 :         10 :     sal_Bool bSave = sal_True;
     588         [ -  + ]:         10 :     if (bCopy)
     589                 :            :     {
     590         [ #  # ]:          0 :         ScSortParam aOldSortParam;
     591         [ #  # ]:          0 :         pDBData->GetSortParam( aOldSortParam );
     592   [ #  #  #  # ]:          0 :         if (aOldSortParam.GetSortKeyCount() &&
         [ #  # ][ #  # ]
     593                 :          0 :             aOldSortParam.maKeyState[0].bDoSort && aOldSortParam.bInplace)
     594                 :            :         {
     595                 :          0 :             bSave = false;
     596                 :          0 :             aOldSortParam.nDestCol = rSortParam.nDestCol;
     597                 :          0 :             aOldSortParam.nDestRow = rSortParam.nDestRow;
     598                 :          0 :             aOldSortParam.nDestTab = rSortParam.nDestTab;
     599         [ #  # ]:          0 :             pDBData->SetSortParam( aOldSortParam );                 // dann nur DestPos merken
     600         [ #  # ]:          0 :         }
     601                 :            :     }
     602         [ +  - ]:         10 :     if (bSave)                                              // Parameter merken
     603                 :            :     {
     604         [ +  - ]:         10 :         pDBData->SetSortParam( rSortParam );
     605                 :         10 :         pDBData->SetHeader( rSortParam.bHasHeader );        //! ???
     606                 :         10 :         pDBData->SetByRow( rSortParam.bByRow );             //! ???
     607                 :            :     }
     608                 :            : 
     609         [ -  + ]:         10 :     if (bCopy)                                          // neuen DB-Bereich merken
     610                 :            :     {
     611                 :            :         //  Tabelle umschalten von aussen (View)
     612                 :            :         //! SetCursor ??!?!
     613                 :            : 
     614                 :            :         ScRange aDestPos( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
     615                 :          0 :                             aLocalParam.nCol2, aLocalParam.nRow2, nTab );
     616                 :            :         ScDBData* pNewData;
     617         [ #  # ]:          0 :         if (pDestData)
     618                 :          0 :             pNewData = pDestData;               // Bereich vorhanden -> anpassen
     619                 :            :         else                                    // Bereich ab Cursor/Markierung wird angelegt
     620         [ #  # ]:          0 :             pNewData = rDocShell.GetDBData(aDestPos, SC_DB_MAKE, SC_DBSEL_FORCE_MARK );
     621         [ #  # ]:          0 :         if (pNewData)
     622                 :            :         {
     623                 :            :             pNewData->SetArea( nTab,
     624                 :            :                                 aLocalParam.nCol1,aLocalParam.nRow1,
     625         [ #  # ]:          0 :                                 aLocalParam.nCol2,aLocalParam.nRow2 );
     626         [ #  # ]:          0 :             pNewData->SetSortParam( aLocalParam );
     627                 :          0 :             pNewData->SetHeader( aLocalParam.bHasHeader );      //! ???
     628                 :          0 :             pNewData->SetByRow( aLocalParam.bByRow );
     629                 :            :         }
     630                 :            :         else
     631                 :            :         {
     632                 :            :             OSL_FAIL("Zielbereich nicht da");
     633                 :            :         }
     634                 :            :     }
     635                 :            : 
     636                 :            :     ScRange aDirtyRange( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
     637                 :         10 :         aLocalParam.nCol2, aLocalParam.nRow2, nTab );
     638         [ +  - ]:         10 :     pDoc->SetDirty( aDirtyRange );
     639                 :            : 
     640         [ +  + ]:         10 :     if (bPaint)
     641                 :            :     {
     642                 :          8 :         sal_uInt16 nPaint = PAINT_GRID;
     643                 :          8 :         SCCOL nStartX = aLocalParam.nCol1;
     644                 :          8 :         SCROW nStartY = aLocalParam.nRow1;
     645                 :          8 :         SCCOL nEndX = aLocalParam.nCol2;
     646                 :          8 :         SCROW nEndY = aLocalParam.nRow2;
     647         [ -  + ]:          8 :         if ( bRepeatQuery )
     648                 :            :         {
     649                 :          0 :             nPaint |= PAINT_LEFT;
     650                 :          0 :             nStartX = 0;
     651                 :          0 :             nEndX = MAXCOL;
     652                 :            :         }
     653         [ -  + ]:          8 :         if (pDestData)
     654                 :            :         {
     655         [ #  # ]:          0 :             if ( nEndX < aOldDest.aEnd.Col() )
     656                 :          0 :                 nEndX = aOldDest.aEnd.Col();
     657         [ #  # ]:          0 :             if ( nEndY < aOldDest.aEnd.Row() )
     658                 :          0 :                 nEndY = aOldDest.aEnd.Row();
     659                 :            :         }
     660 [ +  - ][ +  - ]:          8 :         rDocShell.PostPaint(ScRange(nStartX, nStartY, nTab, nEndX, nEndY, nTab), nPaint);
                 [ +  - ]
     661                 :            :     }
     662                 :            : 
     663                 :            :     //  AdjustRowHeight( aLocalParam.nRow1, aLocalParam.nRow2, bPaint );
     664         [ +  - ]:         10 :     rDocShell.AdjustRowHeight( aLocalParam.nRow1, aLocalParam.nRow2, nTab );
     665                 :            : 
     666                 :            :     // #i59745# set collected drawing undo actions at sorting undo action
     667 [ +  + ][ +  - ]:         10 :     if( pUndoAction && pDrawLayer )
     668 [ +  - ][ +  - ]:          8 :         pUndoAction->SetDrawUndoAction( pDrawLayer->GetCalcUndo() );
     669                 :            : 
     670         [ +  - ]:         10 :     aModificator.SetDocumentModified();
     671                 :            : 
     672 [ +  - ][ +  - ]:         10 :     return sal_True;
         [ +  - ][ +  - ]
     673                 :            : }
     674                 :            : 
     675                 :            : // -----------------------------------------------------------------
     676                 :            : 
     677                 :          4 : sal_Bool ScDBDocFunc::Query( SCTAB nTab, const ScQueryParam& rQueryParam,
     678                 :            :                         const ScRange* pAdvSource, sal_Bool bRecord, sal_Bool bApi )
     679                 :            : {
     680         [ +  - ]:          4 :     ScDocShellModificator aModificator( rDocShell );
     681                 :            : 
     682                 :          4 :     ScDocument* pDoc = rDocShell.GetDocument();
     683 [ -  + ][ -  + ]:          4 :     if (bRecord && !pDoc->IsUndoEnabled())
                 [ +  + ]
     684                 :          0 :         bRecord = false;
     685                 :            :     ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rQueryParam.nCol1, rQueryParam.nRow1,
     686         [ +  - ]:          4 :                                                     rQueryParam.nCol2, rQueryParam.nRow2 );
     687         [ -  + ]:          4 :     if (!pDBData)
     688                 :            :     {
     689                 :            :         OSL_FAIL( "Query: keine DBData" );
     690                 :          0 :         return false;
     691                 :            :     }
     692                 :            : 
     693                 :            :     //  Wechsel von Inplace auf nicht-Inplace, dann erst Inplace aufheben:
     694                 :            :     //  (nur, wenn im Dialog "Persistent" ausgewaehlt ist)
     695                 :            : 
     696 [ -  + ][ #  # ]:          4 :     if ( !rQueryParam.bInplace && pDBData->HasQueryParam() && rQueryParam.bDestPers )
         [ #  # ][ #  # ]
                 [ -  + ]
     697                 :            :     {
     698         [ #  # ]:          0 :         ScQueryParam aOldQuery;
     699         [ #  # ]:          0 :         pDBData->GetQueryParam(aOldQuery);
     700         [ #  # ]:          0 :         if (aOldQuery.bInplace)
     701                 :            :         {
     702                 :            :             //  alte Filterung aufheben
     703                 :            : 
     704         [ #  # ]:          0 :             SCSIZE nEC = aOldQuery.GetEntryCount();
     705         [ #  # ]:          0 :             for (SCSIZE i=0; i<nEC; i++)
     706         [ #  # ]:          0 :                 aOldQuery.GetEntry(i).bDoQuery = false;
     707                 :          0 :             aOldQuery.bDuplicate = sal_True;
     708         [ #  # ]:          0 :             Query( nTab, aOldQuery, NULL, bRecord, bApi );
     709         [ #  # ]:          0 :         }
     710                 :            :     }
     711                 :            : 
     712         [ +  - ]:          4 :     ScQueryParam aLocalParam( rQueryParam );        // fuer Paint / Zielbereich
     713                 :          4 :     sal_Bool bCopy = !rQueryParam.bInplace;             // kopiert wird in Table::Query
     714                 :          4 :     ScDBData* pDestData = NULL;                     // Bereich, in den kopiert wird
     715                 :          4 :     sal_Bool bDoSize = false;                           // Zielgroesse anpassen (einf./loeschen)
     716                 :          4 :     SCCOL nFormulaCols = 0;                     // nur bei bDoSize
     717                 :          4 :     sal_Bool bKeepFmt = false;
     718                 :          4 :     ScRange aOldDest;
     719                 :          4 :     ScRange aDestTotal;
     720 [ #  # ][ #  # ]:          4 :     if ( bCopy && rQueryParam.nDestCol == rQueryParam.nCol1 &&
         [ #  # ][ -  + ]
     721                 :            :                   rQueryParam.nDestRow == rQueryParam.nRow1 && rQueryParam.nDestTab == nTab )
     722                 :          0 :         bCopy = false;
     723                 :          4 :     SCTAB nDestTab = nTab;
     724         [ -  + ]:          4 :     if ( bCopy )
     725                 :            :     {
     726         [ #  # ]:          0 :         aLocalParam.MoveToDest();
     727                 :          0 :         nDestTab = rQueryParam.nDestTab;
     728         [ #  # ]:          0 :         if ( !ValidColRow( aLocalParam.nCol2, aLocalParam.nRow2 ) )
     729                 :            :         {
     730         [ #  # ]:          0 :             if (!bApi)
     731         [ #  # ]:          0 :                 rDocShell.ErrorMessage(STR_PASTE_FULL);
     732                 :          0 :             return false;
     733                 :            :         }
     734                 :            : 
     735                 :            :         ScEditableTester aTester( pDoc, nDestTab, aLocalParam.nCol1,aLocalParam.nRow1,
     736         [ #  # ]:          0 :                                                 aLocalParam.nCol2,aLocalParam.nRow2);
     737         [ #  # ]:          0 :         if (!aTester.IsEditable())
     738                 :            :         {
     739         [ #  # ]:          0 :             if (!bApi)
     740 [ #  # ][ #  # ]:          0 :                 rDocShell.ErrorMessage(aTester.GetMessageId());
     741                 :          0 :             return false;
     742                 :            :         }
     743                 :            : 
     744                 :            :         pDestData = pDoc->GetDBAtCursor( rQueryParam.nDestCol, rQueryParam.nDestRow,
     745         [ #  # ]:          0 :                                             rQueryParam.nDestTab, sal_True );
     746         [ #  # ]:          0 :         if (pDestData)
     747                 :            :         {
     748         [ #  # ]:          0 :             pDestData->GetArea( aOldDest );
     749                 :            :             aDestTotal=ScRange( rQueryParam.nDestCol,
     750                 :            :                                 rQueryParam.nDestRow,
     751                 :            :                                 nDestTab,
     752                 :            :                                 rQueryParam.nDestCol + rQueryParam.nCol2 - rQueryParam.nCol1,
     753                 :            :                                 rQueryParam.nDestRow + rQueryParam.nRow2 - rQueryParam.nRow1,
     754                 :          0 :                                 nDestTab );
     755                 :            : 
     756                 :          0 :             bDoSize = pDestData->IsDoSize();
     757                 :            :             //  Test, ob Formeln aufgefuellt werden muessen (nFormulaCols):
     758 [ #  # ][ #  # ]:          0 :             if ( bDoSize && aOldDest.aEnd.Col() == aDestTotal.aEnd.Col() )
                 [ #  # ]
     759                 :            :             {
     760                 :          0 :                 SCCOL nTestCol = aOldDest.aEnd.Col() + 1;       // neben dem Bereich
     761                 :            :                 SCROW nTestRow = rQueryParam.nDestRow +
     762         [ #  # ]:          0 :                                     ( aLocalParam.bHasHeader ? 1 : 0 );
     763 [ #  # ][ #  # ]:          0 :                 while ( nTestCol <= MAXCOL &&
                 [ #  # ]
     764 [ #  # ][ #  # ]:          0 :                         pDoc->GetCellType(ScAddress( nTestCol, nTestRow, nTab )) == CELLTYPE_FORMULA )
                 [ #  # ]
     765                 :          0 :                     ++nTestCol, ++nFormulaCols;
     766                 :            :             }
     767                 :            : 
     768                 :          0 :             bKeepFmt = pDestData->IsKeepFmt();
     769 [ #  # ][ #  # ]:          0 :             if ( bDoSize && !pDoc->CanFitBlock( aOldDest, aDestTotal ) )
         [ #  # ][ #  # ]
     770                 :            :             {
     771         [ #  # ]:          0 :                 if (!bApi)
     772         [ #  # ]:          0 :                     rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2);     // kann keine Zeilen einfuegen
     773                 :          0 :                 return false;
     774                 :            :             }
     775         [ #  # ]:          0 :         }
     776                 :            :     }
     777                 :            : 
     778                 :            :     //      ausfuehren
     779                 :            : 
     780 [ +  - ][ +  - ]:          4 :     WaitObject aWait( rDocShell.GetActiveDialogParent() );
     781                 :            : 
     782                 :          4 :     sal_Bool bKeepSub = false;                          // bestehende Teilergebnisse wiederholen?
     783         [ +  - ]:          4 :     ScSubTotalParam aSubTotalParam;
     784 [ +  - ][ +  - ]:          4 :     if (rQueryParam.GetEntry(0).bDoQuery)           // nicht beim Aufheben
     785                 :            :     {
     786         [ +  - ]:          4 :         pDBData->GetSubTotalParam( aSubTotalParam );    // Teilergebnisse vorhanden?
     787                 :            : 
     788 [ -  + ][ #  # ]:          4 :         if ( aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly )
     789                 :          0 :             bKeepSub = sal_True;
     790                 :            :     }
     791                 :            : 
     792                 :          4 :     ScDocument* pUndoDoc = NULL;
     793                 :          4 :     ScDBCollection* pUndoDB = NULL;
     794                 :          4 :     const ScRange* pOld = NULL;
     795                 :            : 
     796         [ +  + ]:          4 :     if ( bRecord )
     797                 :            :     {
     798 [ +  - ][ +  - ]:          2 :         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
     799         [ -  + ]:          2 :         if (bCopy)
     800                 :            :         {
     801         [ #  # ]:          0 :             pUndoDoc->InitUndo( pDoc, nDestTab, nDestTab, false, sal_True );
     802                 :            :             pDoc->CopyToDocument( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
     803                 :            :                                     aLocalParam.nCol2, aLocalParam.nRow2, nDestTab,
     804         [ #  # ]:          0 :                                     IDF_ALL, false, pUndoDoc );
     805                 :            :             //  Attribute sichern, falls beim Filtern mitkopiert
     806                 :            : 
     807         [ #  # ]:          0 :             if (pDestData)
     808                 :            :             {
     809         [ #  # ]:          0 :                 pDoc->CopyToDocument( aOldDest, IDF_ALL, false, pUndoDoc );
     810                 :          0 :                 pOld = &aOldDest;
     811                 :            :             }
     812                 :            :         }
     813                 :            :         else
     814                 :            :         {
     815         [ +  - ]:          2 :             pUndoDoc->InitUndo( pDoc, nTab, nTab, false, sal_True );
     816                 :            :             pDoc->CopyToDocument( 0, rQueryParam.nRow1, nTab, MAXCOL, rQueryParam.nRow2, nTab,
     817         [ +  - ]:          2 :                                         IDF_NONE, false, pUndoDoc );
     818                 :            :         }
     819                 :            : 
     820         [ +  - ]:          2 :         ScDBCollection* pDocDB = pDoc->GetDBCollection();
     821 [ +  - ][ -  + ]:          2 :         if (!pDocDB->empty())
     822 [ #  # ][ #  # ]:          0 :             pUndoDB = new ScDBCollection( *pDocDB );
     823                 :            : 
     824         [ +  - ]:          2 :         pDoc->BeginDrawUndo();
     825                 :            :     }
     826                 :            : 
     827                 :          4 :     ScDocument* pAttribDoc = NULL;
     828                 :          4 :     ScRange aAttribRange;
     829         [ -  + ]:          4 :     if (pDestData)                                      // Zielbereich loeschen
     830                 :            :     {
     831         [ #  # ]:          0 :         if ( bKeepFmt )
     832                 :            :         {
     833                 :            :             //  kleinere der End-Spalten, Header+1 Zeile
     834                 :          0 :             aAttribRange = aOldDest;
     835         [ #  # ]:          0 :             if ( aAttribRange.aEnd.Col() > aDestTotal.aEnd.Col() )
     836                 :          0 :                 aAttribRange.aEnd.SetCol( aDestTotal.aEnd.Col() );
     837                 :          0 :             aAttribRange.aEnd.SetRow( aAttribRange.aStart.Row() +
     838         [ #  # ]:          0 :                                         ( aLocalParam.bHasHeader ? 1 : 0 ) );
     839                 :            : 
     840                 :            :             //  auch fuer aufgefuellte Formeln
     841                 :          0 :             aAttribRange.aEnd.SetCol( aAttribRange.aEnd.Col() + nFormulaCols );
     842                 :            : 
     843 [ #  # ][ #  # ]:          0 :             pAttribDoc = new ScDocument( SCDOCMODE_UNDO );
     844         [ #  # ]:          0 :             pAttribDoc->InitUndo( pDoc, nDestTab, nDestTab, false, sal_True );
     845         [ #  # ]:          0 :             pDoc->CopyToDocument( aAttribRange, IDF_ATTRIB, false, pAttribDoc );
     846                 :            :         }
     847                 :            : 
     848         [ #  # ]:          0 :         if ( bDoSize )
     849         [ #  # ]:          0 :             pDoc->FitBlock( aOldDest, aDestTotal );
     850                 :            :         else
     851         [ #  # ]:          0 :             pDoc->DeleteAreaTab(aOldDest, IDF_ALL);         // einfach loeschen
     852                 :            :     }
     853                 :            : 
     854                 :            :     //  Filtern am Dokument ausfuehren
     855         [ +  - ]:          4 :     SCSIZE nCount = pDoc->Query( nTab, rQueryParam, bKeepSub );
     856         [ -  + ]:          4 :     if (bCopy)
     857                 :            :     {
     858                 :          0 :         aLocalParam.nRow2 = aLocalParam.nRow1 + nCount;
     859 [ #  # ][ #  # ]:          0 :         if (!aLocalParam.bHasHeader && nCount > 0)
     860                 :          0 :             --aLocalParam.nRow2;
     861                 :            : 
     862         [ #  # ]:          0 :         if ( bDoSize )
     863                 :            :         {
     864                 :            :             //  auf wirklichen Ergebnis-Bereich anpassen
     865                 :            :             //  (das hier ist immer eine Verkleinerung)
     866                 :            : 
     867                 :            :             ScRange aNewDest( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
     868                 :          0 :                                 aLocalParam.nCol2, aLocalParam.nRow2, nDestTab );
     869         [ #  # ]:          0 :             pDoc->FitBlock( aDestTotal, aNewDest, false );      // sal_False - nicht loeschen
     870                 :            : 
     871         [ #  # ]:          0 :             if ( nFormulaCols > 0 )
     872                 :            :             {
     873                 :            :                 //  Formeln ausfuellen
     874                 :            :                 //! Undo (Query und Repeat) !!!
     875                 :            : 
     876                 :            :                 ScRange aNewForm( aLocalParam.nCol2+1, aLocalParam.nRow1, nDestTab,
     877                 :          0 :                                   aLocalParam.nCol2+nFormulaCols, aLocalParam.nRow2, nDestTab );
     878                 :          0 :                 ScRange aOldForm = aNewForm;
     879                 :          0 :                 aOldForm.aEnd.SetRow( aOldDest.aEnd.Row() );
     880         [ #  # ]:          0 :                 pDoc->FitBlock( aOldForm, aNewForm, false );
     881                 :            : 
     882         [ #  # ]:          0 :                 ScMarkData aMark;
     883         [ #  # ]:          0 :                 aMark.SelectOneTable(nDestTab);
     884         [ #  # ]:          0 :                 SCROW nFStartY = aLocalParam.nRow1 + ( aLocalParam.bHasHeader ? 1 : 0 );
     885                 :            : 
     886                 :          0 :                 sal_uLong nProgCount = nFormulaCols;
     887                 :          0 :                 nProgCount *= aLocalParam.nRow2 - nFStartY;
     888                 :            :                 ScProgress aProgress( pDoc->GetDocumentShell(),
     889 [ #  # ][ #  # ]:          0 :                         ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
     890                 :            : 
     891                 :            :                 pDoc->Fill( aLocalParam.nCol2+1, nFStartY,
     892                 :            :                             aLocalParam.nCol2+nFormulaCols, nFStartY, &aProgress, aMark,
     893                 :            :                             aLocalParam.nRow2 - nFStartY,
     894 [ #  # ][ #  # ]:          0 :                             FILL_TO_BOTTOM, FILL_SIMPLE );
                 [ #  # ]
     895                 :            :             }
     896                 :            :         }
     897                 :            : 
     898         [ #  # ]:          0 :         if ( pAttribDoc )       // gemerkte Attribute zurueckkopieren
     899                 :            :         {
     900                 :            :             //  Header
     901         [ #  # ]:          0 :             if (aLocalParam.bHasHeader)
     902                 :            :             {
     903                 :          0 :                 ScRange aHdrRange = aAttribRange;
     904                 :          0 :                 aHdrRange.aEnd.SetRow( aHdrRange.aStart.Row() );
     905         [ #  # ]:          0 :                 pAttribDoc->CopyToDocument( aHdrRange, IDF_ATTRIB, false, pDoc );
     906                 :            :             }
     907                 :            : 
     908                 :            :             //  Daten
     909                 :          0 :             SCCOL nAttrEndCol = aAttribRange.aEnd.Col();
     910         [ #  # ]:          0 :             SCROW nAttrRow = aAttribRange.aStart.Row() + ( aLocalParam.bHasHeader ? 1 : 0 );
     911         [ #  # ]:          0 :             for (SCCOL nCol = aAttribRange.aStart.Col(); nCol<=nAttrEndCol; nCol++)
     912                 :            :             {
     913                 :            :                 const ScPatternAttr* pSrcPattern = pAttribDoc->GetPattern(
     914         [ #  # ]:          0 :                                                     nCol, nAttrRow, nDestTab );
     915                 :            :                 OSL_ENSURE(pSrcPattern,"Pattern ist 0");
     916         [ #  # ]:          0 :                 if (pSrcPattern)
     917                 :            :                 {
     918                 :            :                     pDoc->ApplyPatternAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
     919         [ #  # ]:          0 :                                                     nDestTab, *pSrcPattern );
     920                 :          0 :                     const ScStyleSheet* pStyle = pSrcPattern->GetStyleSheet();
     921         [ #  # ]:          0 :                     if (pStyle)
     922                 :            :                         pDoc->ApplyStyleAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
     923         [ #  # ]:          0 :                                                     nDestTab, *pStyle );
     924                 :            :                 }
     925                 :            :             }
     926                 :            : 
     927 [ #  # ][ #  # ]:          0 :             delete pAttribDoc;
     928                 :            :         }
     929                 :            :     }
     930                 :            : 
     931                 :            :     //  speichern: Inplace immer, sonst je nach Einstellung
     932                 :            :     //             alter Inplace-Filter ist ggf. schon aufgehoben
     933                 :            : 
     934 [ -  + ][ #  # ]:          4 :     sal_Bool bSave = rQueryParam.bInplace || rQueryParam.bDestPers;
     935         [ +  - ]:          4 :     if (bSave)                                                  // merken
     936                 :            :     {
     937         [ +  - ]:          4 :         pDBData->SetQueryParam( rQueryParam );
     938                 :          4 :         pDBData->SetHeader( rQueryParam.bHasHeader );       //! ???
     939         [ +  - ]:          4 :         pDBData->SetAdvancedQuerySource( pAdvSource );      // after SetQueryParam
     940                 :            :     }
     941                 :            : 
     942         [ -  + ]:          4 :     if (bCopy)                                              // neuen DB-Bereich merken
     943                 :            :     {
     944                 :            :         //  selektieren wird hinterher von aussen (dbfunc)
     945                 :            :         //  momentan ueber DB-Bereich an der Zielposition, darum muss dort
     946                 :            :         //  auf jeden Fall ein Bereich angelegt werden.
     947                 :            : 
     948                 :            :         ScDBData* pNewData;
     949         [ #  # ]:          0 :         if (pDestData)
     950                 :          0 :             pNewData = pDestData;               // Bereich vorhanden -> anpassen (immer!)
     951                 :            :         else                                    // Bereich anlegen
     952                 :            :             pNewData = rDocShell.GetDBData(
     953                 :            :                             ScRange( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
     954                 :            :                                      aLocalParam.nCol2, aLocalParam.nRow2, nDestTab ),
     955         [ #  # ]:          0 :                             SC_DB_MAKE, SC_DBSEL_FORCE_MARK );
     956                 :            : 
     957         [ #  # ]:          0 :         if (pNewData)
     958                 :            :         {
     959                 :            :             pNewData->SetArea( nDestTab, aLocalParam.nCol1, aLocalParam.nRow1,
     960         [ #  # ]:          0 :                                             aLocalParam.nCol2, aLocalParam.nRow2 );
     961                 :            : 
     962                 :            :             //  Query-Param wird am Ziel nicht mehr eingestellt, fuehrt nur zu Verwirrung
     963                 :            :             //  und Verwechslung mit dem Query-Param am Quellbereich (#37187#)
     964                 :            :         }
     965                 :            :         else
     966                 :            :         {
     967                 :            :             OSL_FAIL("Zielbereich nicht da");
     968                 :            :         }
     969                 :            :     }
     970                 :            : 
     971         [ +  - ]:          4 :     if (!bCopy)
     972                 :            :     {
     973         [ +  - ]:          4 :         pDoc->InvalidatePageBreaks(nTab);
     974         [ +  - ]:          4 :         pDoc->UpdatePageBreaks( nTab );
     975                 :            :     }
     976                 :            : 
     977                 :            :     // #i23299# Subtotal functions depend on cell's filtered states.
     978                 :          4 :     ScRange aDirtyRange(0 , aLocalParam.nRow1, nDestTab, MAXCOL, aLocalParam.nRow2, nDestTab);
     979         [ +  - ]:          4 :     pDoc->SetSubTotalCellsDirty(aDirtyRange);
     980                 :            : 
     981         [ +  + ]:          4 :     if ( bRecord )
     982                 :            :     {
     983                 :            :         // create undo action after executing, because of drawing layer undo
     984         [ +  - ]:          2 :         rDocShell.GetUndoManager()->AddUndoAction(
     985                 :            :                     new ScUndoQuery( &rDocShell, nTab, rQueryParam, pUndoDoc, pUndoDB,
     986 [ +  - ][ +  - ]:          2 :                                         pOld, bDoSize, pAdvSource ) );
                 [ +  - ]
     987                 :            :     }
     988                 :            : 
     989                 :            : 
     990         [ -  + ]:          4 :     if (bCopy)
     991                 :            :     {
     992                 :          0 :         SCCOL nEndX = aLocalParam.nCol2;
     993                 :          0 :         SCROW nEndY = aLocalParam.nRow2;
     994         [ #  # ]:          0 :         if (pDestData)
     995                 :            :         {
     996         [ #  # ]:          0 :             if ( aOldDest.aEnd.Col() > nEndX )
     997                 :          0 :                 nEndX = aOldDest.aEnd.Col();
     998         [ #  # ]:          0 :             if ( aOldDest.aEnd.Row() > nEndY )
     999                 :          0 :                 nEndY = aOldDest.aEnd.Row();
    1000                 :            :         }
    1001         [ #  # ]:          0 :         if (bDoSize)
    1002                 :          0 :             nEndY = MAXROW;
    1003                 :            :         rDocShell.PostPaint(
    1004                 :            :             ScRange(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab, nEndX, nEndY, nDestTab),
    1005 [ #  # ][ #  # ]:          0 :             PAINT_GRID);
                 [ #  # ]
    1006                 :            :     }
    1007                 :            :     else
    1008                 :            :         rDocShell.PostPaint(
    1009                 :            :             ScRange(0, rQueryParam.nRow1, nTab, MAXCOL, MAXROW, nTab),
    1010 [ +  - ][ +  - ]:          4 :             PAINT_GRID | PAINT_LEFT);
                 [ +  - ]
    1011         [ +  - ]:          4 :     aModificator.SetDocumentModified();
    1012                 :            : 
    1013 [ +  - ][ +  - ]:          4 :     return sal_True;
                 [ +  - ]
    1014                 :            : }
    1015                 :            : 
    1016                 :            : // -----------------------------------------------------------------
    1017                 :            : 
    1018                 :          4 : sal_Bool ScDBDocFunc::DoSubTotals( SCTAB nTab, const ScSubTotalParam& rParam,
    1019                 :            :                                 const ScSortParam* pForceNewSort, sal_Bool bRecord, sal_Bool bApi )
    1020                 :            : {
    1021                 :            :     //! auch fuer ScDBFunc::DoSubTotals benutzen!
    1022                 :            :     //  dann bleibt aussen:
    1023                 :            :     //  - neuen Bereich (aus DBData) markieren
    1024                 :            :     //  - SelectionChanged (?)
    1025                 :            : 
    1026                 :          4 :     sal_Bool bDo = !rParam.bRemoveOnly;                         // sal_False = nur loeschen
    1027                 :          4 :     sal_Bool bRet = false;
    1028                 :            : 
    1029                 :          4 :     ScDocument* pDoc = rDocShell.GetDocument();
    1030 [ -  + ][ -  + ]:          4 :     if (bRecord && !pDoc->IsUndoEnabled())
                 [ +  - ]
    1031                 :          0 :         bRecord = false;
    1032                 :            :     ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1,
    1033         [ +  - ]:          4 :                                                 rParam.nCol2, rParam.nRow2 );
    1034         [ -  + ]:          4 :     if (!pDBData)
    1035                 :            :     {
    1036                 :            :         OSL_FAIL( "SubTotals: keine DBData" );
    1037                 :          0 :         return false;
    1038                 :            :     }
    1039                 :            : 
    1040         [ +  - ]:          4 :     ScEditableTester aTester( pDoc, nTab, 0,rParam.nRow1+1, MAXCOL,MAXROW );
    1041         [ -  + ]:          4 :     if (!aTester.IsEditable())
    1042                 :            :     {
    1043         [ #  # ]:          0 :         if (!bApi)
    1044 [ #  # ][ #  # ]:          0 :             rDocShell.ErrorMessage(aTester.GetMessageId());
    1045                 :          0 :         return false;
    1046                 :            :     }
    1047                 :            : 
    1048 [ +  - ][ -  + ]:          4 :     if (pDoc->HasAttrib( rParam.nCol1, rParam.nRow1+1, nTab,
    1049                 :          4 :                          rParam.nCol2, rParam.nRow2, nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ))
    1050                 :            :     {
    1051         [ #  # ]:          0 :         if (!bApi)
    1052         [ #  # ]:          0 :             rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); // nicht in zusammengefasste einfuegen
    1053                 :          0 :         return false;
    1054                 :            :     }
    1055                 :            : 
    1056                 :          4 :     sal_Bool bOk = true;
    1057         [ +  - ]:          4 :     if (rParam.bReplace)
    1058 [ +  - ][ -  + ]:          4 :         if (pDoc->TestRemoveSubTotals( nTab, rParam ))
    1059                 :            :         {
    1060                 :            :             bOk = ( MessBox( rDocShell.GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
    1061                 :            :                 // "StarCalc" "Daten loeschen?"
    1062         [ #  # ]:          0 :                 ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ),
    1063 [ #  # ][ #  # ]:          0 :                 ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_1 ) ).Execute()
         [ #  # ][ #  # ]
                 [ #  # ]
    1064                 :          0 :                 == RET_YES );
    1065                 :            :         }
    1066                 :            : 
    1067         [ +  - ]:          4 :     if (bOk)
    1068                 :            :     {
    1069 [ +  - ][ +  - ]:          4 :         WaitObject aWait( rDocShell.GetActiveDialogParent() );
    1070         [ +  - ]:          4 :         ScDocShellModificator aModificator( rDocShell );
    1071                 :            : 
    1072         [ +  - ]:          4 :         ScSubTotalParam aNewParam( rParam );        // Bereichsende wird veraendert
    1073                 :          4 :         ScDocument*     pUndoDoc = NULL;
    1074                 :          4 :         ScOutlineTable* pUndoTab = NULL;
    1075                 :          4 :         ScRangeName*    pUndoRange = NULL;
    1076                 :          4 :         ScDBCollection* pUndoDB = NULL;
    1077                 :            : 
    1078         [ +  - ]:          4 :         if (bRecord)                                        // alte Daten sichern
    1079                 :            :         {
    1080 [ +  + ][ +  - ]:          4 :             sal_Bool bOldFilter = bDo && rParam.bDoSort;
    1081                 :            : 
    1082         [ +  - ]:          4 :             SCTAB nTabCount = pDoc->GetTableCount();
    1083 [ +  - ][ +  - ]:          4 :             pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
    1084         [ +  - ]:          4 :             ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
    1085         [ +  + ]:          4 :             if (pTable)
    1086                 :            :             {
    1087 [ +  - ][ +  - ]:          2 :                 pUndoTab = new ScOutlineTable( *pTable );
    1088                 :            : 
    1089                 :            :                 // column/row state
    1090                 :            :                 SCCOLROW nOutStartCol, nOutEndCol;
    1091                 :            :                 SCCOLROW nOutStartRow, nOutEndRow;
    1092         [ +  - ]:          2 :                 pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol );
    1093         [ +  - ]:          2 :                 pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow );
    1094                 :            : 
    1095         [ +  - ]:          2 :                 pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True );
    1096         [ +  - ]:          2 :                 pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab, IDF_NONE, false, pUndoDoc );
    1097         [ +  - ]:          2 :                 pDoc->CopyToDocument( 0, nOutStartRow, nTab, MAXCOL, nOutEndRow, nTab, IDF_NONE, false, pUndoDoc );
    1098                 :            :             }
    1099                 :            :             else
    1100         [ +  - ]:          2 :                 pUndoDoc->InitUndo( pDoc, nTab, nTab, false, bOldFilter );
    1101                 :            : 
    1102                 :            :             //  Datenbereich sichern - incl. Filter-Ergebnis
    1103                 :            :             pDoc->CopyToDocument( 0,rParam.nRow1+1,nTab, MAXCOL,rParam.nRow2,nTab,
    1104         [ +  - ]:          4 :                                     IDF_ALL, false, pUndoDoc );
    1105                 :            : 
    1106                 :            :             //  alle Formeln wegen Referenzen
    1107                 :            :             pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
    1108         [ +  - ]:          4 :                                         IDF_FORMULA, false, pUndoDoc );
    1109                 :            : 
    1110                 :            :             //  DB- und andere Bereiche
    1111         [ +  - ]:          4 :             ScRangeName* pDocRange = pDoc->GetRangeName();
    1112 [ +  - ][ -  + ]:          4 :             if (!pDocRange->empty())
    1113 [ #  # ][ #  # ]:          0 :                 pUndoRange = new ScRangeName( *pDocRange );
    1114         [ +  - ]:          4 :             ScDBCollection* pDocDB = pDoc->GetDBCollection();
    1115 [ +  - ][ -  + ]:          4 :             if (!pDocDB->empty())
    1116 [ #  # ][ #  # ]:          0 :                 pUndoDB = new ScDBCollection( *pDocDB );
    1117                 :            :         }
    1118                 :            : 
    1119                 :            : //      pDoc->SetOutlineTable( nTab, NULL );
    1120         [ +  - ]:          4 :         ScOutlineTable* pOut = pDoc->GetOutlineTable( nTab );
    1121         [ +  + ]:          4 :         if (pOut)
    1122         [ +  - ]:          2 :             pOut->GetRowArray()->RemoveAll();       // nur Zeilen-Outlines loeschen
    1123                 :            : 
    1124         [ +  - ]:          4 :         if (rParam.bReplace)
    1125         [ +  - ]:          4 :             pDoc->RemoveSubTotals( nTab, aNewParam );
    1126                 :          4 :         sal_Bool bSuccess = sal_True;
    1127         [ +  + ]:          4 :         if (bDo)
    1128                 :            :         {
    1129                 :            :             // Sortieren
    1130 [ -  + ][ #  # ]:          2 :             if ( rParam.bDoSort || pForceNewSort )
    1131                 :            :             {
    1132         [ +  - ]:          2 :                 pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
    1133                 :            : 
    1134                 :            :                 //  Teilergebnis-Felder vor die Sortierung setzen
    1135                 :            :                 //  (doppelte werden weggelassen, kann darum auch wieder aufgerufen werden)
    1136                 :            : 
    1137         [ +  - ]:          2 :                 ScSortParam aOldSort;
    1138         [ +  - ]:          2 :                 pDBData->GetSortParam( aOldSort );
    1139 [ +  - ][ +  - ]:          2 :                 ScSortParam aSortParam( aNewParam, pForceNewSort ? *pForceNewSort : aOldSort );
    1140 [ +  - ][ +  - ]:          2 :                 Sort( nTab, aSortParam, false, false, bApi );
                 [ +  - ]
    1141                 :            :             }
    1142                 :            : 
    1143         [ +  - ]:          2 :             pDoc->InitializeNoteCaptions(nTab);
    1144         [ +  - ]:          2 :             bSuccess = pDoc->DoSubTotals( nTab, aNewParam );
    1145         [ +  - ]:          2 :             pDoc->SetDrawPageSize(nTab);
    1146                 :            :         }
    1147                 :            :         ScRange aDirtyRange( aNewParam.nCol1, aNewParam.nRow1, nTab,
    1148                 :          4 :             aNewParam.nCol2, aNewParam.nRow2, nTab );
    1149         [ +  - ]:          4 :         pDoc->SetDirty( aDirtyRange );
    1150                 :            : 
    1151         [ +  - ]:          4 :         if (bRecord)
    1152                 :            :         {
    1153                 :            : //          ScDBData* pUndoDBData = pDBData ? new ScDBData( *pDBData ) : NULL;
    1154         [ +  - ]:          4 :             rDocShell.GetUndoManager()->AddUndoAction(
    1155                 :            :                 new ScUndoSubTotals( &rDocShell, nTab,
    1156                 :            :                                         rParam, aNewParam.nRow2,
    1157                 :            :                                         pUndoDoc, pUndoTab, // pUndoDBData,
    1158 [ +  - ][ +  - ]:          4 :                                         pUndoRange, pUndoDB ) );
                 [ +  - ]
    1159                 :            :         }
    1160                 :            : 
    1161         [ -  + ]:          4 :         if (!bSuccess)
    1162                 :            :         {
    1163                 :            :             // "Kann keine Zeilen einfuegen"
    1164         [ #  # ]:          0 :             if (!bApi)
    1165         [ #  # ]:          0 :                 rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2);
    1166                 :            :         }
    1167                 :            : 
    1168                 :            :                                                     // merken
    1169         [ +  - ]:          4 :         pDBData->SetSubTotalParam( aNewParam );
    1170         [ +  - ]:          4 :         pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
    1171         [ +  - ]:          4 :         pDoc->CompileDBFormula();
    1172                 :            : 
    1173                 :            :         rDocShell.PostPaint(ScRange(0, 0, nTab, MAXCOL,MAXROW,nTab),
    1174 [ +  - ][ +  - ]:          4 :                             PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE);
                 [ +  - ]
    1175         [ +  - ]:          4 :         aModificator.SetDocumentModified();
    1176                 :            : 
    1177 [ +  - ][ +  - ]:          4 :         bRet = bSuccess;
    1178                 :            :     }
    1179                 :          4 :     return bRet;
    1180                 :            : }
    1181                 :            : 
    1182                 :            : //==================================================================
    1183                 :            : 
    1184                 :          5 : sal_Bool lcl_EmptyExcept( ScDocument* pDoc, const ScRange& rRange, const ScRange& rExcept )
    1185                 :            : {
    1186         [ +  - ]:          5 :     ScCellIterator aIter( pDoc, rRange );
    1187         [ +  - ]:          5 :     ScBaseCell* pCell = aIter.GetFirst();
    1188         [ +  + ]:        163 :     while (pCell)
    1189                 :            :     {
    1190 [ +  - ][ +  - ]:        158 :         if ( !pCell->IsBlank() )      // real content?
    1191                 :            :         {
    1192         [ -  + ]:        158 :             if ( !rExcept.In( ScAddress( aIter.GetCol(), aIter.GetRow(), aIter.GetTab() ) ) )
    1193                 :          0 :                 return false;       // cell found
    1194                 :            :         }
    1195         [ +  - ]:        158 :         pCell = aIter.GetNext();
    1196                 :            :     }
    1197                 :            : 
    1198                 :          5 :     return sal_True;        // nothing found - empty
    1199                 :            : }
    1200                 :            : 
    1201                 :         75 : bool ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewObj,
    1202                 :            :                                    bool bRecord, bool bApi, bool bAllowMove )
    1203                 :            : {
    1204         [ +  - ]:         75 :     ScDocShellModificator aModificator( rDocShell );
    1205 [ +  - ][ +  - ]:         75 :     WaitObject aWait( rDocShell.GetActiveDialogParent() );
    1206                 :            : 
    1207                 :         75 :     bool bDone = false;
    1208                 :         75 :     bool bUndoSelf = false;
    1209                 :         75 :     sal_uInt16 nErrId = 0;
    1210                 :            : 
    1211                 :         75 :     ScDocument* pOldUndoDoc = NULL;
    1212                 :         75 :     ScDocument* pNewUndoDoc = NULL;
    1213                 :         75 :     ScDPObject* pUndoDPObj = NULL;
    1214 [ +  + ][ +  + ]:         75 :     if ( bRecord && pOldObj )
    1215 [ +  - ][ +  - ]:         43 :         pUndoDPObj = new ScDPObject( *pOldObj );    // copy old settings for undo
    1216                 :            : 
    1217                 :         75 :     ScDocument* pDoc = rDocShell.GetDocument();
    1218 [ -  + ][ -  + ]:         75 :     if (bRecord && !pDoc->IsUndoEnabled())
                 [ +  + ]
    1219                 :          0 :         bRecord = false;
    1220 [ +  - ][ +  - ]:         75 :     if ( !rDocShell.IsEditable() || pDoc->GetChangeTrack() )
         [ -  + ][ -  + ]
    1221                 :            :     {
    1222                 :            :         //  not recorded -> disallow
    1223                 :            :         //! different error messages?
    1224                 :            : 
    1225                 :          0 :         nErrId = STR_PROTECTIONERR;
    1226                 :            :     }
    1227 [ +  + ][ +  - ]:         75 :     if ( pOldObj && !nErrId )
    1228                 :            :     {
    1229                 :         56 :         ScRange aOldOut = pOldObj->GetOutRange();
    1230         [ +  - ]:         56 :         ScEditableTester aTester( pDoc, aOldOut );
    1231         [ -  + ]:         56 :         if ( !aTester.IsEditable() )
    1232         [ #  # ]:         56 :             nErrId = aTester.GetMessageId();
    1233                 :            :     }
    1234 [ +  + ][ +  - ]:         75 :     if ( pNewObj && !nErrId )
    1235                 :            :     {
    1236                 :            :         //  at least one cell at the output position must be editable
    1237                 :            :         //  -> check in advance
    1238                 :            :         //  (start of output range in pNewObj is valid)
    1239                 :            : 
    1240                 :         74 :         ScRange aNewStart( pNewObj->GetOutRange().aStart );
    1241         [ +  - ]:         74 :         ScEditableTester aTester( pDoc, aNewStart );
    1242         [ -  + ]:         74 :         if ( !aTester.IsEditable() )
    1243         [ #  # ]:         74 :             nErrId = aTester.GetMessageId();
    1244                 :            :     }
    1245                 :            : 
    1246                 :         75 :     ScDPObject* pDestObj = NULL;
    1247         [ +  - ]:         75 :     if ( !nErrId )
    1248                 :            :     {
    1249 [ +  + ][ +  + ]:         75 :         if ( pOldObj && !pNewObj )
    1250                 :            :         {
    1251                 :            :             //  delete table
    1252                 :            : 
    1253                 :          1 :             ScRange aRange = pOldObj->GetOutRange();
    1254                 :          1 :             SCTAB nTab = aRange.aStart.Tab();
    1255                 :            : 
    1256         [ +  - ]:          1 :             if ( bRecord )
    1257                 :            :             {
    1258 [ +  - ][ +  - ]:          1 :                 pOldUndoDoc = new ScDocument( SCDOCMODE_UNDO );
    1259         [ +  - ]:          1 :                 pOldUndoDoc->InitUndo( pDoc, nTab, nTab );
    1260         [ +  - ]:          1 :                 pDoc->CopyToDocument( aRange, IDF_ALL, false, pOldUndoDoc );
    1261                 :            :             }
    1262                 :            : 
    1263                 :          1 :             pDoc->DeleteAreaTab( aRange.aStart.Col(), aRange.aStart.Row(),
    1264                 :          1 :                                  aRange.aEnd.Col(),   aRange.aEnd.Row(),
    1265         [ +  - ]:          3 :                                  nTab, IDF_ALL );
    1266                 :          1 :             pDoc->RemoveFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(),
    1267                 :          1 :                                   aRange.aEnd.Col(),   aRange.aEnd.Row(),
    1268         [ +  - ]:          3 :                                   nTab, SC_MF_AUTO );
    1269                 :            : 
    1270 [ +  - ][ +  - ]:          1 :             pDoc->GetDPCollection()->FreeTable( pOldObj );  // object is deleted here
    1271                 :            : 
    1272         [ +  - ]:          1 :             rDocShell.PostPaintGridAll();   //! only necessary parts
    1273 [ +  - ][ +  - ]:          1 :             rDocShell.PostPaint(aRange, PAINT_GRID);
                 [ +  - ]
    1274                 :          1 :             bDone = true;
    1275                 :            :         }
    1276         [ +  - ]:         74 :         else if ( pNewObj )
    1277                 :            :         {
    1278         [ +  + ]:         74 :             if ( pOldObj )
    1279                 :            :             {
    1280         [ +  + ]:         55 :                 if ( bRecord )
    1281                 :            :                 {
    1282                 :         42 :                     ScRange aRange = pOldObj->GetOutRange();
    1283                 :         42 :                     SCTAB nTab = aRange.aStart.Tab();
    1284 [ +  - ][ +  - ]:         42 :                     pOldUndoDoc = new ScDocument( SCDOCMODE_UNDO );
    1285         [ +  - ]:         42 :                     pOldUndoDoc->InitUndo( pDoc, nTab, nTab );
    1286         [ +  - ]:         42 :                     pDoc->CopyToDocument( aRange, IDF_ALL, false, pOldUndoDoc );
    1287                 :            :                 }
    1288                 :            : 
    1289         [ -  + ]:         55 :                 if ( pNewObj == pOldObj )
    1290                 :            :                 {
    1291                 :            :                     //  refresh only - no settings modified
    1292                 :            :                 }
    1293                 :            :                 else
    1294                 :            :                 {
    1295         [ #  # ]:          0 :                     pNewObj->WriteSourceDataTo( *pOldObj );     // copy source data
    1296                 :            : 
    1297                 :          0 :                     ScDPSaveData* pData = pNewObj->GetSaveData();
    1298                 :            :                     OSL_ENSURE( pData, "no SaveData from living DPObject" );
    1299         [ #  # ]:          0 :                     if ( pData )
    1300         [ #  # ]:          0 :                         pOldObj->SetSaveData( *pData );     // copy SaveData
    1301                 :            :                 }
    1302                 :            : 
    1303                 :         55 :                 pDestObj = pOldObj;
    1304         [ +  - ]:         55 :                 pDestObj->SetAllowMove( bAllowMove );
    1305                 :            :             }
    1306                 :            :             else
    1307                 :            :             {
    1308                 :            :                 //  output range must be set at pNewObj
    1309                 :            : 
    1310 [ +  - ][ +  - ]:         19 :                 pDestObj = new ScDPObject( *pNewObj );
    1311                 :            : 
    1312                 :            :                 // #i94570# When changing the output position in the dialog, a new table is created
    1313                 :            :                 // with the settings from the old table, including the name.
    1314                 :            :                 // So we have to check for duplicate names here (before inserting).
    1315 [ +  - ][ +  - ]:         19 :                 if ( pDoc->GetDPCollection()->GetByName(pDestObj->GetName()) )
                 [ -  + ]
    1316 [ #  # ][ #  # ]:          0 :                     pDestObj->SetName( String() );      // ignore the invalid name, create a new name below
         [ #  # ][ #  # ]
    1317                 :            : 
    1318         [ +  - ]:         19 :                 pDestObj->SetAlive(sal_True);
    1319 [ +  - ][ +  - ]:         19 :                 if ( !pDoc->GetDPCollection()->InsertNewTable(pDestObj) )
                 [ -  + ]
    1320                 :            :                 {
    1321                 :            :                     OSL_FAIL("cannot insert DPObject");
    1322 [ #  # ][ #  # ]:          0 :                     DELETEZ( pDestObj );
    1323                 :            :                 }
    1324                 :            :             }
    1325         [ +  - ]:         74 :             if ( pDestObj )
    1326                 :            :             {
    1327         [ +  - ]:         74 :                 pDestObj->ReloadGroupTableData();
    1328         [ +  - ]:         74 :                 pDestObj->InvalidateData();             // before getting the new output area
    1329                 :            : 
    1330                 :            :                 //  make sure the table has a name (not set by dialog)
    1331         [ -  + ]:         74 :                 if (pDestObj->GetName().isEmpty())
    1332 [ #  # ][ #  # ]:          0 :                     pDestObj->SetName( pDoc->GetDPCollection()->CreateNewName() );
                 [ #  # ]
    1333                 :            : 
    1334                 :         74 :                 bool bOverflow = false;
    1335         [ +  - ]:         74 :                 ScRange aNewOut = pDestObj->GetNewOutputRange( bOverflow );
    1336                 :            : 
    1337                 :            :                 //! test for overlap with other data pilot tables
    1338         [ +  + ]:         74 :                 if( pOldObj )
    1339                 :            :                 {
    1340                 :         55 :                     const ScSheetSourceDesc* pSheetDesc = pOldObj->GetSheetDesc();
    1341 [ +  - ][ +  - ]:         55 :                     if( pSheetDesc && pSheetDesc->GetSourceRange().Intersects( aNewOut ) )
         [ -  + ][ -  + ]
                 [ +  - ]
    1342                 :            :                     {
    1343                 :          0 :                         ScRange aOldRange = pOldObj->GetOutRange();
    1344                 :          0 :                         SCsROW nDiff = aOldRange.aStart.Row()-aNewOut.aStart.Row();
    1345                 :          0 :                         aNewOut.aStart.SetRow( aOldRange.aStart.Row() );
    1346                 :          0 :                         aNewOut.aEnd.SetRow( aNewOut.aEnd.Row()+nDiff );
    1347 [ #  # ][ #  # ]:          0 :                         if( !ValidRow( aNewOut.aStart.Row() ) || !ValidRow( aNewOut.aEnd.Row() ) )
                 [ #  # ]
    1348                 :          0 :                             bOverflow = sal_True;
    1349                 :            :                     }
    1350                 :            :                 }
    1351                 :            : 
    1352         [ -  + ]:         74 :                 if ( bOverflow )
    1353                 :            :                 {
    1354                 :            :                     //  like with STR_PROTECTIONERR, use undo to reverse everything
    1355                 :            :                     OSL_ENSURE( bRecord, "DataPilotUpdate: can't undo" );
    1356                 :          0 :                     bUndoSelf = true;
    1357                 :          0 :                     nErrId = STR_PIVOT_ERROR;
    1358                 :            :                 }
    1359                 :            :                 else
    1360                 :            :                 {
    1361         [ +  - ]:         74 :                     ScEditableTester aTester( pDoc, aNewOut );
    1362         [ -  + ]:         74 :                     if ( !aTester.IsEditable() )
    1363                 :            :                     {
    1364                 :            :                         //  destination area isn't editable
    1365                 :            :                         //! reverse everything done so far, don't proceed
    1366                 :            : 
    1367                 :            :                         //  quick solution: proceed to end, use undo action
    1368                 :            :                         //  to reverse everything:
    1369                 :            :                         OSL_ENSURE( bRecord, "DataPilotUpdate: can't undo" );
    1370                 :          0 :                         bUndoSelf = sal_True;
    1371         [ #  # ]:          0 :                         nErrId = aTester.GetMessageId();
    1372                 :         74 :                     }
    1373                 :            :                 }
    1374                 :            : 
    1375                 :            :                 //  test if new output area is empty except for old area
    1376         [ +  + ]:         74 :                 if ( !bApi )
    1377                 :            :                 {
    1378                 :            :                     bool bEmpty;
    1379         [ +  - ]:          5 :                     if ( pOldObj )  // OutRange of pOldObj (pDestObj) is still old area
    1380         [ +  - ]:          5 :                         bEmpty = lcl_EmptyExcept( pDoc, aNewOut, pOldObj->GetOutRange() );
    1381                 :            :                     else
    1382                 :          0 :                         bEmpty = pDoc->IsBlockEmpty( aNewOut.aStart.Tab(),
    1383                 :          0 :                                             aNewOut.aStart.Col(), aNewOut.aStart.Row(),
    1384         [ #  # ]:          0 :                                             aNewOut.aEnd.Col(), aNewOut.aEnd.Row() );
    1385                 :            : 
    1386         [ -  + ]:          5 :                     if ( !bEmpty )
    1387                 :            :                     {
    1388                 :            :                         QueryBox aBox( rDocShell.GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
    1389 [ #  # ][ #  # ]:          0 :                                          ScGlobal::GetRscString(STR_PIVOT_NOTEMPTY) );
                 [ #  # ]
    1390 [ #  # ][ #  # ]:          0 :                         if (aBox.Execute() == RET_NO)
    1391                 :            :                         {
    1392                 :            :                             //! like above (not editable), use undo to reverse everything
    1393                 :            :                             OSL_ENSURE( bRecord, "DataPilotUpdate: can't undo" );
    1394                 :          0 :                             bUndoSelf = true;
    1395         [ #  # ]:          0 :                         }
    1396                 :            :                     }
    1397                 :            :                 }
    1398                 :            : 
    1399         [ +  + ]:         74 :                 if ( bRecord )
    1400                 :            :                 {
    1401                 :         61 :                     SCTAB nTab = aNewOut.aStart.Tab();
    1402 [ +  - ][ +  - ]:         61 :                     pNewUndoDoc = new ScDocument( SCDOCMODE_UNDO );
    1403         [ +  - ]:         61 :                     pNewUndoDoc->InitUndo( pDoc, nTab, nTab );
    1404         [ +  - ]:         61 :                     pDoc->CopyToDocument( aNewOut, IDF_ALL, false, pNewUndoDoc );
    1405                 :            :                 }
    1406                 :            : 
    1407         [ +  - ]:         74 :                 pDestObj->Output( aNewOut.aStart );
    1408                 :            : 
    1409         [ +  - ]:         74 :                 rDocShell.PostPaintGridAll();           //! only necessary parts
    1410                 :         75 :                 bDone = true;
    1411                 :            :             }
    1412                 :            :         }
    1413                 :            :         // else nothing (no old, no new)
    1414                 :            :     }
    1415                 :            : 
    1416 [ +  + ][ +  - ]:         75 :     if ( bRecord && bDone )
    1417                 :            :     {
    1418                 :            :         SfxUndoAction* pAction = new ScUndoDataPilot( &rDocShell,
    1419 [ +  - ][ +  - ]:         62 :                                     pOldUndoDoc, pNewUndoDoc, pUndoDPObj, pDestObj, bAllowMove );
    1420                 :         62 :         pOldUndoDoc = NULL;
    1421                 :         62 :         pNewUndoDoc = NULL;     // pointers are used in undo action
    1422                 :            :         // pUndoDPObj is copied
    1423                 :            : 
    1424         [ -  + ]:         62 :         if (bUndoSelf)
    1425                 :            :         {
    1426                 :            :             //  use undo action to restore original state
    1427                 :            :             //! prevent setting the document modified? (ScDocShellModificator)
    1428                 :            : 
    1429         [ #  # ]:          0 :             pAction->Undo();
    1430 [ #  # ][ #  # ]:          0 :             delete pAction;
    1431                 :          0 :             bDone = false;
    1432                 :            :         }
    1433                 :            :         else
    1434 [ +  - ][ +  - ]:         62 :             rDocShell.GetUndoManager()->AddUndoAction( pAction );
    1435                 :            :     }
    1436                 :            : 
    1437 [ -  + ][ #  # ]:         75 :     delete pOldUndoDoc;     // if not used for undo
    1438 [ -  + ][ #  # ]:         75 :     delete pNewUndoDoc;
    1439 [ +  + ][ +  - ]:         75 :     delete pUndoDPObj;
    1440                 :            : 
    1441         [ +  - ]:         75 :     if (bDone)
    1442                 :            :     {
    1443                 :            :         // notify API objects
    1444         [ +  + ]:         75 :         if (pDestObj)
    1445 [ +  - ][ +  - ]:         74 :             pDoc->BroadcastUno( ScDataPilotModifiedHint( pDestObj->GetName() ) );
         [ +  - ][ +  - ]
                 [ +  - ]
    1446         [ +  - ]:         75 :         aModificator.SetDocumentModified();
    1447                 :            :     }
    1448                 :            : 
    1449 [ -  + ][ #  # ]:         75 :     if ( nErrId && !bApi )
    1450         [ #  # ]:          0 :         rDocShell.ErrorMessage( nErrId );
    1451                 :            : 
    1452 [ +  - ][ +  - ]:         75 :     return bDone;
    1453                 :            : }
    1454                 :            : 
    1455                 :          4 : sal_uLong ScDBDocFunc::RefreshPivotTables(ScDPObject* pDPObj, bool bApi)
    1456                 :            : {
    1457         [ +  - ]:          4 :     ScDPCollection* pDPs = rDocShell.GetDocument()->GetDPCollection();
    1458         [ -  + ]:          4 :     if (!pDPs)
    1459                 :          0 :         return 0;
    1460                 :            : 
    1461         [ +  - ]:          4 :     std::set<ScDPObject*> aRefs;
    1462         [ +  - ]:          4 :     sal_uLong nErrId = pDPs->ReloadCache(pDPObj, aRefs);
    1463         [ -  + ]:          4 :     if (nErrId)
    1464                 :          0 :         return nErrId;
    1465                 :            : 
    1466                 :          4 :     std::set<ScDPObject*>::iterator it = aRefs.begin(), itEnd = aRefs.end();
    1467 [ +  - ][ +  - ]:         12 :     for (; it != itEnd; ++it)
                 [ +  + ]
    1468                 :            :     {
    1469         [ +  - ]:          8 :         ScDPObject* pObj = *it;
    1470         [ +  - ]:          8 :         pObj->SyncAllDimensionMembers();
    1471                 :            : 
    1472                 :            :         // This action is intentionally not undoable since it modifies cache.
    1473         [ +  - ]:          8 :         DataPilotUpdate(pObj, pObj, false, bApi);
    1474                 :            :     }
    1475                 :            : 
    1476                 :          4 :     return 0;
    1477                 :            : }
    1478                 :            : 
    1479                 :          5 : void ScDBDocFunc::RefreshPivotTableGroups(ScDPObject* pDPObj)
    1480                 :            : {
    1481         [ +  - ]:          5 :     if (!pDPObj)
    1482                 :            :         return;
    1483                 :            : 
    1484         [ +  - ]:          5 :     ScDPCollection* pDPs = rDocShell.GetDocument()->GetDPCollection();
    1485         [ +  - ]:          5 :     if (!pDPs)
    1486                 :            :         return;
    1487                 :            : 
    1488                 :          5 :     ScDPSaveData* pSaveData = pDPObj->GetSaveData();
    1489         [ +  - ]:          5 :     if (!pSaveData)
    1490                 :            :         return;
    1491                 :            : 
    1492         [ +  - ]:          5 :     std::set<ScDPObject*> aRefs;
    1493 [ +  - ][ -  + ]:          5 :     if (!pDPs->ReloadGroupsInCache(pDPObj, aRefs))
    1494                 :            :         return;
    1495                 :            : 
    1496                 :            :     // We allow pDimData being NULL.
    1497                 :          5 :     const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData();
    1498                 :          5 :     std::set<ScDPObject*>::iterator it = aRefs.begin(), itEnd = aRefs.end();
    1499 [ +  - ][ +  - ]:         10 :     for (; it != itEnd; ++it)
                 [ +  + ]
    1500                 :            :     {
    1501         [ +  - ]:          5 :         ScDPObject* pObj = *it;
    1502         [ -  + ]:          5 :         if (pObj != pDPObj)
    1503                 :            :         {
    1504                 :          0 :             pSaveData = pObj->GetSaveData();
    1505         [ #  # ]:          0 :             if (pSaveData)
    1506         [ #  # ]:          0 :                 pSaveData->SetDimensionData(pDimData);
    1507                 :            :         }
    1508                 :            : 
    1509                 :            :         // This action is intentionally not undoable since it modifies cache.
    1510         [ +  - ]:          5 :         DataPilotUpdate(pObj, pObj, false, false);
    1511         [ +  - ]:          5 :     }
    1512                 :            : }
    1513                 :            : 
    1514                 :            : //==================================================================
    1515                 :            : //
    1516                 :            : //      database import
    1517                 :            : 
    1518                 :          0 : void ScDBDocFunc::UpdateImport( const String& rTarget, const svx::ODataAccessDescriptor& rDescriptor )
    1519                 :            : {
    1520                 :            :     // rTarget is the name of a database range
    1521                 :            : 
    1522                 :          0 :     ScDocument* pDoc = rDocShell.GetDocument();
    1523         [ #  # ]:          0 :     ScDBCollection& rDBColl = *pDoc->GetDBCollection();
    1524 [ #  # ][ #  # ]:          0 :     const ScDBData* pData = rDBColl.getNamedDBs().findByName(rTarget);
                 [ #  # ]
    1525         [ #  # ]:          0 :     if (!pData)
    1526                 :            :     {
    1527                 :            :         InfoBox aInfoBox(rDocShell.GetActiveDialogParent(),
    1528 [ #  # ][ #  # ]:          0 :                     ScGlobal::GetRscString( STR_TARGETNOTFOUND ) );
                 [ #  # ]
    1529         [ #  # ]:          0 :         aInfoBox.Execute();
    1530         [ #  # ]:          0 :         return;
    1531                 :            :     }
    1532                 :            : 
    1533                 :            :     SCTAB nTab;
    1534                 :            :     SCCOL nDummyCol;
    1535                 :            :     SCROW nDummyRow;
    1536         [ #  # ]:          0 :     pData->GetArea( nTab, nDummyCol,nDummyRow,nDummyCol,nDummyRow );
    1537                 :            : 
    1538         [ #  # ]:          0 :     ScImportParam aImportParam;
    1539         [ #  # ]:          0 :     pData->GetImportParam( aImportParam );
    1540                 :            : 
    1541                 :          0 :     rtl::OUString sDBName;
    1542                 :          0 :     rtl::OUString sDBTable;
    1543                 :          0 :     sal_Int32 nCommandType = 0;
    1544         [ #  # ]:          0 :     rDescriptor[svx::daDataSource]  >>= sDBName;
    1545         [ #  # ]:          0 :     rDescriptor[svx::daCommand]     >>= sDBTable;
    1546         [ #  # ]:          0 :     rDescriptor[svx::daCommandType] >>= nCommandType;
    1547                 :            : 
    1548                 :          0 :     aImportParam.aDBName    = sDBName;
    1549                 :          0 :     aImportParam.bSql       = ( nCommandType == sdb::CommandType::COMMAND );
    1550                 :          0 :     aImportParam.aStatement = sDBTable;
    1551                 :          0 :     aImportParam.bNative    = false;
    1552         [ #  # ]:          0 :     aImportParam.nType      = static_cast<sal_uInt8>( ( nCommandType == sdb::CommandType::QUERY ) ? ScDbQuery : ScDbTable );
    1553                 :          0 :     aImportParam.bImport    = true;
    1554                 :            : 
    1555         [ #  # ]:          0 :     bool bContinue = DoImport( nTab, aImportParam, &rDescriptor, true );
    1556                 :            : 
    1557                 :            :     //  DB-Operationen wiederholen
    1558                 :            : 
    1559         [ #  # ]:          0 :     ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
    1560         [ #  # ]:          0 :     if (pViewSh)
    1561                 :            :     {
    1562                 :          0 :         ScRange aRange;
    1563         [ #  # ]:          0 :         pData->GetArea(aRange);
    1564         [ #  # ]:          0 :         pViewSh->MarkRange(aRange);         // selektieren
    1565                 :            : 
    1566         [ #  # ]:          0 :         if ( bContinue )        // Fehler beim Import -> Abbruch
    1567                 :            :         {
    1568                 :            :             //  interne Operationen, wenn welche gespeichert
    1569                 :            : 
    1570 [ #  # ][ #  # ]:          0 :             if ( pData->HasQueryParam() || pData->HasSortParam() || pData->HasSubTotalParam() )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1571         [ #  # ]:          0 :                 pViewSh->RepeatDB();
    1572                 :            : 
    1573                 :            :             //  Pivottabellen die den Bereich als Quelldaten haben
    1574                 :            : 
    1575         [ #  # ]:          0 :             rDocShell.RefreshPivotTables(aRange);
    1576                 :            :         }
    1577         [ #  # ]:          0 :     }
    1578 [ +  - ][ +  - ]:        153 : }
    1579                 :            : 
    1580                 :            : 
    1581                 :            : 
    1582                 :            : 
    1583                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10