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

Generated by: LCOV version 1.10