LCOV - code coverage report
Current view: top level - sc/source/ui/docshell - dbdocfun.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 512 848 60.4 %
Date: 2014-11-03 Functions: 20 22 90.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10