LCOV - code coverage report
Current view: top level - sc/source/ui/docshell - dbdocfun.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 877 0.0 %
Date: 2014-04-14 Functions: 0 21 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10