LCOV - code coverage report
Current view: top level - libreoffice/sc/source/ui/docshell - dbdocfun.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 26 779 3.3 %
Date: 2012-12-27 Functions: 3 15 20.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <sfx2/app.hxx>
      21             : #include <vcl/msgbox.hxx>
      22             : #include <vcl/waitobj.hxx>
      23             : #include <svx/dataaccessdescriptor.hxx>
      24             : 
      25             : #include <com/sun/star/sdb/CommandType.hpp>
      26             : 
      27             : #include "dbdocfun.hxx"
      28             : #include "sc.hrc"
      29             : #include "dbdata.hxx"
      30             : #include "undodat.hxx"
      31             : #include "docsh.hxx"
      32             : #include "docfunc.hxx"
      33             : #include "globstr.hrc"
      34             : #include "globalnames.hxx"
      35             : #include "tabvwsh.hxx"
      36             : #include "patattr.hxx"
      37             : #include "rangenam.hxx"
      38             : #include "olinetab.hxx"
      39             : #include "dpobject.hxx"
      40             : #include "dpsave.hxx"
      41             : #include "dociter.hxx"      // for lcl_EmptyExcept
      42             : #include "cell.hxx"         // for lcl_EmptyExcept
      43             : #include "editable.hxx"
      44             : #include "attrib.hxx"
      45             : #include "drwlayer.hxx"
      46             : #include "dpshttab.hxx"
      47             : #include "hints.hxx"
      48             : #include "queryentry.hxx"
      49             : #include "markdata.hxx"
      50             : #include "progress.hxx"
      51             : 
      52             : #include <set>
      53             : 
      54             : using namespace ::com::sun::star;
      55             : 
      56             : // -----------------------------------------------------------------
      57             : 
      58           0 : bool ScDBDocFunc::AddDBRange( const ::rtl::OUString& rName, const ScRange& rRange, sal_Bool /* bApi */ )
      59             : {
      60             : 
      61           0 :     ScDocShellModificator aModificator( rDocShell );
      62             : 
      63           0 :     ScDocument* pDoc = rDocShell.GetDocument();
      64           0 :     ScDBCollection* pDocColl = pDoc->GetDBCollection();
      65           0 :     sal_Bool bUndo (pDoc->IsUndoEnabled());
      66             : 
      67           0 :     ScDBCollection* pUndoColl = NULL;
      68           0 :     if (bUndo)
      69           0 :         pUndoColl = new ScDBCollection( *pDocColl );
      70             : 
      71           0 :     ScDBData* pNew = new ScDBData( rName, rRange.aStart.Tab(),
      72           0 :                                     rRange.aStart.Col(), rRange.aStart.Row(),
      73           0 :                                     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           0 :     bool bCompile = !pDoc->IsImportingXML();
      79             :     bool bOk;
      80           0 :     if ( bCompile )
      81           0 :         pDoc->CompileDBFormula( sal_True );     // CreateFormulaString
      82           0 :     if ( rName == STR_DB_LOCAL_NONAME )
      83             :     {
      84           0 :         pDoc->SetAnonymousDBData(rRange.aStart.Tab() , pNew);
      85           0 :         bOk = true;
      86             :     }
      87             :     else
      88             :     {
      89           0 :         bOk = pDocColl->getNamedDBs().insert(pNew);
      90             :     }
      91           0 :     if ( bCompile )
      92           0 :         pDoc->CompileDBFormula( false );    // CompileFormulaString
      93             : 
      94           0 :     if (!bOk)
      95             :     {
      96           0 :         delete pNew;
      97           0 :         delete pUndoColl;
      98           0 :         return false;
      99             :     }
     100             : 
     101           0 :     if (bUndo)
     102             :     {
     103           0 :         ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
     104           0 :         rDocShell.GetUndoManager()->AddUndoAction(
     105           0 :                         new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
     106             :     }
     107             : 
     108           0 :     aModificator.SetDocumentModified();
     109           0 :     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
     110           0 :     return true;
     111             : }
     112             : 
     113           0 : bool ScDBDocFunc::DeleteDBRange(const ::rtl::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           0 : bool ScDBDocFunc::RenameDBRange( const String& rOld, const String& rNew )
     150             : {
     151           0 :     bool bDone = false;
     152           0 :     ScDocument* pDoc = rDocShell.GetDocument();
     153           0 :     ScDBCollection* pDocColl = pDoc->GetDBCollection();
     154           0 :     bool bUndo = pDoc->IsUndoEnabled();
     155           0 :     ScDBCollection::NamedDBs& rDBs = pDocColl->getNamedDBs();
     156           0 :     const ScDBData* pOld = rDBs.findByUpperName(ScGlobal::pCharClass->uppercase(rOld));
     157           0 :     const ScDBData* pNew = rDBs.findByUpperName(ScGlobal::pCharClass->uppercase(rNew));
     158           0 :     if (pOld && !pNew)
     159             :     {
     160           0 :         ScDocShellModificator aModificator( rDocShell );
     161             : 
     162           0 :         ScDBData* pNewData = new ScDBData(rNew, *pOld);
     163             : 
     164           0 :         ScDBCollection* pUndoColl = new ScDBCollection( *pDocColl );
     165             : 
     166           0 :         pDoc->CompileDBFormula(true);               // CreateFormulaString
     167           0 :         rDBs.erase(*pOld);
     168           0 :         bool bInserted = rDBs.insert(pNewData);
     169           0 :         if (!bInserted)                             // Fehler -> alten Zustand wiederherstellen
     170           0 :             pDoc->SetDBCollection(pUndoColl);       // gehoert dann dem Dokument
     171             :                                                     //
     172           0 :         pDoc->CompileDBFormula( false );            // CompileFormulaString
     173             : 
     174           0 :         if (bInserted)                              // Einfuegen hat geklappt
     175             :         {
     176           0 :             if (bUndo)
     177             :             {
     178           0 :                 ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
     179           0 :                 rDocShell.GetUndoManager()->AddUndoAction(
     180           0 :                                 new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
     181             :             }
     182             :             else
     183           0 :                 delete pUndoColl;
     184             : 
     185           0 :             aModificator.SetDocumentModified();
     186           0 :             SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
     187           0 :             bDone = true;
     188           0 :         }
     189             :     }
     190             : 
     191           0 :     return bDone;
     192             : }
     193             : 
     194           8 : bool ScDBDocFunc::ModifyDBData( const ScDBData& rNewData )
     195             : {
     196           8 :     bool bDone = false;
     197           8 :     ScDocument* pDoc = rDocShell.GetDocument();
     198           8 :     ScDBCollection* pDocColl = pDoc->GetDBCollection();
     199           8 :     bool bUndo = pDoc->IsUndoEnabled();
     200             : 
     201           8 :     ScDBData* pData = NULL;
     202           8 :     if (rNewData.GetName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(STR_DB_LOCAL_NONAME)))
     203             :     {
     204           8 :         ScRange aRange;
     205           8 :         rNewData.GetArea(aRange);
     206           8 :         SCTAB nTab = aRange.aStart.Tab();
     207           8 :         pData = pDoc->GetAnonymousDBData(nTab);
     208             :     }
     209             :     else
     210           0 :         pData = pDocColl->getNamedDBs().findByUpperName(rNewData.GetUpperName());
     211             : 
     212           8 :     if (pData)
     213             :     {
     214           8 :         ScDocShellModificator aModificator( rDocShell );
     215           8 :         ScRange aOldRange, aNewRange;
     216           8 :         pData->GetArea(aOldRange);
     217           8 :         rNewData.GetArea(aNewRange);
     218           8 :         bool bAreaChanged = ( aOldRange != aNewRange );     // dann muss neu compiliert werden
     219             : 
     220           8 :         ScDBCollection* pUndoColl = NULL;
     221           8 :         if (bUndo)
     222           0 :             pUndoColl = new ScDBCollection( *pDocColl );
     223             : 
     224           8 :         *pData = rNewData;
     225           8 :         if (bAreaChanged)
     226           0 :             pDoc->CompileDBFormula();
     227             : 
     228           8 :         if (bUndo)
     229             :         {
     230           0 :             ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
     231           0 :             rDocShell.GetUndoManager()->AddUndoAction(
     232           0 :                             new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
     233             :         }
     234             : 
     235           8 :         aModificator.SetDocumentModified();
     236           8 :         bDone = true;
     237             :     }
     238             : 
     239           8 :     return bDone;
     240             : }
     241             : 
     242             : // -----------------------------------------------------------------
     243             : 
     244           0 : bool ScDBDocFunc::RepeatDB( const ::rtl::OUString& rDBName, bool bRecord, bool bApi, bool bIsUnnamed, SCTAB aTab )
     245             : {
     246             :     //! auch fuer ScDBFunc::RepeatDB benutzen!
     247             : 
     248           0 :     bool bDone = false;
     249           0 :     ScDocument* pDoc = rDocShell.GetDocument();
     250           0 :     if (bRecord && !pDoc->IsUndoEnabled())
     251           0 :         bRecord = false;
     252           0 :     ScDBData* pDBData = NULL;
     253           0 :     if (bIsUnnamed)
     254             :     {
     255           0 :         pDBData = pDoc->GetAnonymousDBData( aTab );
     256             :     }
     257             :     else
     258             :     {
     259           0 :         ScDBCollection* pColl = pDoc->GetDBCollection();
     260           0 :         if (pColl)
     261           0 :             pDBData = pColl->getNamedDBs().findByUpperName(ScGlobal::pCharClass->uppercase(rDBName));
     262             :     }
     263             : 
     264           0 :     if ( pDBData )
     265             :     {
     266           0 :         ScQueryParam aQueryParam;
     267           0 :         pDBData->GetQueryParam( aQueryParam );
     268           0 :         sal_Bool bQuery = aQueryParam.GetEntry(0).bDoQuery;
     269             : 
     270           0 :         ScSortParam aSortParam;
     271           0 :         pDBData->GetSortParam( aSortParam );
     272           0 :         sal_Bool bSort = aSortParam.maKeyState[0].bDoSort;
     273             : 
     274           0 :         ScSubTotalParam aSubTotalParam;
     275           0 :         pDBData->GetSubTotalParam( aSubTotalParam );
     276           0 :         sal_Bool bSubTotal = aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly;
     277             : 
     278           0 :         if ( bQuery || bSort || bSubTotal )
     279             :         {
     280           0 :             sal_Bool bQuerySize = false;
     281           0 :             ScRange aOldQuery;
     282           0 :             ScRange aNewQuery;
     283           0 :             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           0 :             pDBData->GetArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow );
     300             : 
     301             :             //!     Undo nur benoetigte Daten ?
     302             : 
     303           0 :             ScDocument* pUndoDoc = NULL;
     304           0 :             ScOutlineTable* pUndoTab = NULL;
     305           0 :             ScRangeName* pUndoRange = NULL;
     306           0 :             ScDBCollection* pUndoDB = NULL;
     307             : 
     308           0 :             if (bRecord)
     309             :             {
     310           0 :                 SCTAB nTabCount = pDoc->GetTableCount();
     311           0 :                 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
     312           0 :                 ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
     313           0 :                 if (pTable)
     314             :                 {
     315           0 :                     pUndoTab = new ScOutlineTable( *pTable );
     316             : 
     317             :                     // column/row state
     318             :                     SCCOLROW nOutStartCol, nOutEndCol;
     319             :                     SCCOLROW nOutStartRow, nOutEndRow;
     320           0 :                     pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol );
     321           0 :                     pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow );
     322             : 
     323           0 :                     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           0 :                             IDF_NONE, false, pUndoDoc );
     327             :                     pDoc->CopyToDocument( 0, static_cast<SCROW>(nOutStartRow),
     328             :                             nTab, MAXCOL, static_cast<SCROW>(nOutEndRow), nTab,
     329           0 :                             IDF_NONE, false, pUndoDoc );
     330             :                 }
     331             :                 else
     332           0 :                     pUndoDoc->InitUndo( pDoc, nTab, nTab, false, sal_True );
     333             : 
     334             :                 //  Datenbereich sichern - incl. Filter-Ergebnis
     335           0 :                 pDoc->CopyToDocument( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab, IDF_ALL, false, pUndoDoc );
     336             : 
     337             :                 //  alle Formeln wegen Referenzen
     338           0 :                 pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, IDF_FORMULA, false, pUndoDoc );
     339             : 
     340             :                 //  DB- und andere Bereiche
     341           0 :                 ScRangeName* pDocRange = pDoc->GetRangeName();
     342           0 :                 if (!pDocRange->empty())
     343           0 :                     pUndoRange = new ScRangeName( *pDocRange );
     344           0 :                 ScDBCollection* pDocDB = pDoc->GetDBCollection();
     345           0 :                 if (!pDocDB->empty())
     346           0 :                     pUndoDB = new ScDBCollection( *pDocDB );
     347             :             }
     348             : 
     349           0 :             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           0 :             if (bSort)
     358             :             {
     359           0 :                 pDBData->GetSortParam( aSortParam );            // Bereich kann sich geaendert haben
     360           0 :                 Sort( nTab, aSortParam, false, false, bApi );
     361             :             }
     362           0 :             if (bQuery)
     363             :             {
     364           0 :                 pDBData->GetQueryParam( aQueryParam );          // Bereich kann sich geaendert haben
     365           0 :                 ScRange aAdvSource;
     366           0 :                 if (pDBData->GetAdvancedQuerySource(aAdvSource))
     367           0 :                     Query( nTab, aQueryParam, &aAdvSource, false, bApi );
     368             :                 else
     369           0 :                     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           0 :             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           0 :             if (bRecord)
     383             :             {
     384             :                 SCTAB nDummyTab;
     385             :                 SCCOL nDummyCol;
     386             :                 SCROW nDummyRow;
     387             :                 SCROW nNewEndRow;
     388           0 :                 pDBData->GetArea( nDummyTab, nDummyCol,nDummyRow, nDummyCol,nNewEndRow );
     389             : 
     390           0 :                 const ScRange* pOld = NULL;
     391           0 :                 const ScRange* pNew = NULL;
     392           0 :                 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           0 :                 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           0 :                                             pOld, pNew ) );
     413             :             }
     414             : 
     415             :             rDocShell.PostPaint(ScRange(0, 0, nTab, MAXCOL, MAXROW, nTab),
     416           0 :                                 PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE);
     417           0 :             bDone = sal_True;
     418             :         }
     419           0 :         else if (!bApi)     // "Keine Operationen auszufuehren"
     420           0 :             rDocShell.ErrorMessage(STR_MSSG_REPEATDB_0);
     421             :     }
     422             : 
     423           0 :     return bDone;
     424             : }
     425             : 
     426             : // -----------------------------------------------------------------
     427             : 
     428           0 : sal_Bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam,
     429             :                             sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi )
     430             : {
     431           0 :     ScDocShellModificator aModificator( rDocShell );
     432             : 
     433           0 :     ScDocument* pDoc = rDocShell.GetDocument();
     434           0 :     if (bRecord && !pDoc->IsUndoEnabled())
     435           0 :         bRecord = false;
     436           0 :     SCTAB nSrcTab = nTab;
     437           0 :     ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
     438             : 
     439             :     ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rSortParam.nCol1, rSortParam.nRow1,
     440           0 :                                                     rSortParam.nCol2, rSortParam.nRow2 );
     441           0 :     if (!pDBData)
     442             :     {
     443             :         OSL_FAIL( "Sort: keine DBData" );
     444           0 :         return false;
     445             :     }
     446             : 
     447           0 :     ScDBData* pDestData = NULL;
     448           0 :     ScRange aOldDest;
     449           0 :     sal_Bool bCopy = !rSortParam.bInplace;
     450           0 :     if ( bCopy && rSortParam.nDestCol == rSortParam.nCol1 &&
     451             :                   rSortParam.nDestRow == rSortParam.nRow1 && rSortParam.nDestTab == nTab )
     452           0 :         bCopy = false;
     453           0 :     ScSortParam aLocalParam( rSortParam );
     454           0 :     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           0 :                                         aLocalParam.nCol2,aLocalParam.nRow2 );
     473           0 :     if (!aTester.IsEditable())
     474             :     {
     475           0 :         if (!bApi)
     476           0 :             rDocShell.ErrorMessage(aTester.GetMessageId());
     477           0 :         return false;
     478             :     }
     479             : 
     480           0 :     if ( aLocalParam.bIncludePattern && pDoc->HasAttrib(
     481             :                                         aLocalParam.nCol1, aLocalParam.nRow1, nTab,
     482             :                                         aLocalParam.nCol2, aLocalParam.nRow2, nTab,
     483           0 :                                         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           0 :     WaitObject aWait( rDocShell.GetActiveDialogParent() );
     495             : 
     496           0 :     sal_Bool bRepeatQuery = false;                          // bestehenden Filter wiederholen?
     497           0 :     ScQueryParam aQueryParam;
     498           0 :     pDBData->GetQueryParam( aQueryParam );
     499           0 :     if ( aQueryParam.GetEntry(0).bDoQuery )
     500           0 :         bRepeatQuery = sal_True;
     501             : 
     502           0 :     if (bRepeatQuery && bCopy)
     503             :     {
     504           0 :         if ( aQueryParam.bInplace ||
     505             :                 aQueryParam.nDestCol != rSortParam.nDestCol ||
     506             :                 aQueryParam.nDestRow != rSortParam.nDestRow ||
     507             :                 aQueryParam.nDestTab != rSortParam.nDestTab )       // Query auf selben Zielbereich?
     508           0 :             bRepeatQuery = false;
     509             :     }
     510             : 
     511           0 :     ScUndoSort* pUndoAction = 0;
     512           0 :     if ( bRecord )
     513             :     {
     514             :         //  Referenzen ausserhalb des Bereichs werden nicht veraendert !
     515             : 
     516           0 :         ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
     517             :         //  Zeilenhoehen immer (wegen automatischer Anpassung)
     518             :         //! auf ScBlockUndo umstellen
     519           0 :         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           0 :                                 IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc );
     529             : 
     530           0 :         const ScRange* pR = 0;
     531           0 :         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           0 :                                     IDF_NONE, false, pUndoDoc );
     548             : 
     549           0 :         ScDBCollection* pUndoDB = NULL;
     550           0 :         ScDBCollection* pDocDB = pDoc->GetDBCollection();
     551           0 :         if (!pDocDB->empty())
     552           0 :             pUndoDB = new ScDBCollection( *pDocDB );
     553             : 
     554           0 :         pUndoAction = new ScUndoSort( &rDocShell, nTab, rSortParam, pUndoDoc, pUndoDB, pR );
     555           0 :         rDocShell.GetUndoManager()->AddUndoAction( pUndoAction );
     556             : 
     557             :         // #i59745# collect all drawing undo actions affecting cell note captions
     558           0 :         if( pDrawLayer )
     559           0 :             pDrawLayer->BeginCalcUndo();
     560             :     }
     561             : 
     562           0 :     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           0 :     if (aLocalParam.GetSortKeyCount() && aLocalParam.maKeyState[0].bDoSort)
     576             :     {
     577           0 :         ScProgress aProgress(&rDocShell, ScGlobal::GetRscString(STR_PROGRESS_SORTING), 0);
     578           0 :         pDoc->Sort( nTab, aLocalParam, bRepeatQuery, &aProgress );
     579             :     }
     580             : 
     581           0 :     sal_Bool bSave = sal_True;
     582           0 :     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           0 :     if (bSave)                                              // Parameter merken
     597             :     {
     598           0 :         pDBData->SetSortParam( rSortParam );
     599           0 :         pDBData->SetHeader( rSortParam.bHasHeader );        //! ???
     600           0 :         pDBData->SetByRow( rSortParam.bByRow );             //! ???
     601             :     }
     602             : 
     603           0 :     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           0 :         aLocalParam.nCol2, aLocalParam.nRow2, nTab );
     632           0 :     pDoc->SetDirty( aDirtyRange );
     633             : 
     634           0 :     if (bPaint)
     635             :     {
     636           0 :         sal_uInt16 nPaint = PAINT_GRID;
     637           0 :         SCCOL nStartX = aLocalParam.nCol1;
     638           0 :         SCROW nStartY = aLocalParam.nRow1;
     639           0 :         SCCOL nEndX = aLocalParam.nCol2;
     640           0 :         SCROW nEndY = aLocalParam.nRow2;
     641           0 :         if ( bRepeatQuery )
     642             :         {
     643           0 :             nPaint |= PAINT_LEFT;
     644           0 :             nStartX = 0;
     645           0 :             nEndX = MAXCOL;
     646             :         }
     647           0 :         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           0 :         rDocShell.PostPaint(ScRange(nStartX, nStartY, nTab, nEndX, nEndY, nTab), nPaint);
     655             :     }
     656             : 
     657             :     //  AdjustRowHeight( aLocalParam.nRow1, aLocalParam.nRow2, bPaint );
     658           0 :     rDocShell.AdjustRowHeight( aLocalParam.nRow1, aLocalParam.nRow2, nTab );
     659             : 
     660             :     // #i59745# set collected drawing undo actions at sorting undo action
     661           0 :     if( pUndoAction && pDrawLayer )
     662           0 :         pUndoAction->SetDrawUndoAction( pDrawLayer->GetCalcUndo() );
     663             : 
     664           0 :     aModificator.SetDocumentModified();
     665             : 
     666           0 :     return sal_True;
     667             : }
     668             : 
     669             : // -----------------------------------------------------------------
     670             : 
     671           0 : sal_Bool ScDBDocFunc::Query( SCTAB nTab, const ScQueryParam& rQueryParam,
     672             :                         const ScRange* pAdvSource, sal_Bool bRecord, sal_Bool bApi )
     673             : {
     674           0 :     ScDocShellModificator aModificator( rDocShell );
     675             : 
     676           0 :     ScDocument* pDoc = rDocShell.GetDocument();
     677           0 :     if (bRecord && !pDoc->IsUndoEnabled())
     678           0 :         bRecord = false;
     679             :     ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rQueryParam.nCol1, rQueryParam.nRow1,
     680           0 :                                                     rQueryParam.nCol2, rQueryParam.nRow2 );
     681           0 :     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           0 :     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           0 :     ScQueryParam aLocalParam( rQueryParam );        // fuer Paint / Zielbereich
     707           0 :     sal_Bool bCopy = !rQueryParam.bInplace;             // kopiert wird in Table::Query
     708           0 :     ScDBData* pDestData = NULL;                     // Bereich, in den kopiert wird
     709           0 :     sal_Bool bDoSize = false;                           // Zielgroesse anpassen (einf./loeschen)
     710           0 :     SCCOL nFormulaCols = 0;                     // nur bei bDoSize
     711           0 :     sal_Bool bKeepFmt = false;
     712           0 :     ScRange aOldDest;
     713           0 :     ScRange aDestTotal;
     714           0 :     if ( bCopy && rQueryParam.nDestCol == rQueryParam.nCol1 &&
     715             :                   rQueryParam.nDestRow == rQueryParam.nRow1 && rQueryParam.nDestTab == nTab )
     716           0 :         bCopy = false;
     717           0 :     SCTAB nDestTab = nTab;
     718           0 :     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             :             aDestTotal=ScRange( rQueryParam.nDestCol,
     744             :                                 rQueryParam.nDestRow,
     745             :                                 nDestTab,
     746             :                                 rQueryParam.nDestCol + rQueryParam.nCol2 - rQueryParam.nCol1,
     747             :                                 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             :                 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           0 :         }
     770             :     }
     771             : 
     772             :     //      ausfuehren
     773             : 
     774           0 :     WaitObject aWait( rDocShell.GetActiveDialogParent() );
     775             : 
     776           0 :     sal_Bool bKeepSub = false;                          // bestehende Teilergebnisse wiederholen?
     777           0 :     ScSubTotalParam aSubTotalParam;
     778           0 :     if (rQueryParam.GetEntry(0).bDoQuery)           // nicht beim Aufheben
     779             :     {
     780           0 :         pDBData->GetSubTotalParam( aSubTotalParam );    // Teilergebnisse vorhanden?
     781             : 
     782           0 :         if ( aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly )
     783           0 :             bKeepSub = sal_True;
     784             :     }
     785             : 
     786           0 :     ScDocument* pUndoDoc = NULL;
     787           0 :     ScDBCollection* pUndoDB = NULL;
     788           0 :     const ScRange* pOld = NULL;
     789             : 
     790           0 :     if ( bRecord )
     791             :     {
     792           0 :         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
     793           0 :         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           0 :             pUndoDoc->InitUndo( pDoc, nTab, nTab, false, sal_True );
     810             :             pDoc->CopyToDocument( 0, rQueryParam.nRow1, nTab, MAXCOL, rQueryParam.nRow2, nTab,
     811           0 :                                         IDF_NONE, false, pUndoDoc );
     812             :         }
     813             : 
     814           0 :         ScDBCollection* pDocDB = pDoc->GetDBCollection();
     815           0 :         if (!pDocDB->empty())
     816           0 :             pUndoDB = new ScDBCollection( *pDocDB );
     817             : 
     818           0 :         pDoc->BeginDrawUndo();
     819             :     }
     820             : 
     821           0 :     ScDocument* pAttribDoc = NULL;
     822           0 :     ScRange aAttribRange;
     823           0 :     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           0 :     SCSIZE nCount = pDoc->Query( nTab, rQueryParam, bKeepSub );
     850           0 :     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             :                             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           0 :     sal_Bool bSave = rQueryParam.bInplace || rQueryParam.bDestPers;
     929           0 :     if (bSave)                                                  // merken
     930             :     {
     931           0 :         pDBData->SetQueryParam( rQueryParam );
     932           0 :         pDBData->SetHeader( rQueryParam.bHasHeader );       //! ???
     933           0 :         pDBData->SetAdvancedQuerySource( pAdvSource );      // after SetQueryParam
     934             :     }
     935             : 
     936           0 :     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           0 :     if (!bCopy)
     966             :     {
     967           0 :         pDoc->InvalidatePageBreaks(nTab);
     968           0 :         pDoc->UpdatePageBreaks( nTab );
     969             :     }
     970             : 
     971             :     // #i23299# Subtotal functions depend on cell's filtered states.
     972           0 :     ScRange aDirtyRange(0 , aLocalParam.nRow1, nDestTab, MAXCOL, aLocalParam.nRow2, nDestTab);
     973           0 :     pDoc->SetSubTotalCellsDirty(aDirtyRange);
     974             : 
     975           0 :     if ( bRecord )
     976             :     {
     977             :         // create undo action after executing, because of drawing layer undo
     978           0 :         rDocShell.GetUndoManager()->AddUndoAction(
     979             :                     new ScUndoQuery( &rDocShell, nTab, rQueryParam, pUndoDoc, pUndoDB,
     980           0 :                                         pOld, bDoSize, pAdvSource ) );
     981             :     }
     982             : 
     983             : 
     984           0 :     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           0 :             PAINT_GRID | PAINT_LEFT);
    1005           0 :     aModificator.SetDocumentModified();
    1006             : 
    1007           0 :     return sal_True;
    1008             : }
    1009             : 
    1010             : // -----------------------------------------------------------------
    1011             : 
    1012           0 : 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           0 :     sal_Bool bDo = !rParam.bRemoveOnly;                         // sal_False = nur loeschen
    1021           0 :     sal_Bool bRet = false;
    1022             : 
    1023           0 :     ScDocument* pDoc = rDocShell.GetDocument();
    1024           0 :     if (bRecord && !pDoc->IsUndoEnabled())
    1025           0 :         bRecord = false;
    1026             :     ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1,
    1027           0 :                                                 rParam.nCol2, rParam.nRow2 );
    1028           0 :     if (!pDBData)
    1029             :     {
    1030             :         OSL_FAIL( "SubTotals: keine DBData" );
    1031           0 :         return false;
    1032             :     }
    1033             : 
    1034           0 :     ScEditableTester aTester( pDoc, nTab, 0,rParam.nRow1+1, MAXCOL,MAXROW );
    1035           0 :     if (!aTester.IsEditable())
    1036             :     {
    1037           0 :         if (!bApi)
    1038           0 :             rDocShell.ErrorMessage(aTester.GetMessageId());
    1039           0 :         return false;
    1040             :     }
    1041             : 
    1042           0 :     if (pDoc->HasAttrib( rParam.nCol1, rParam.nRow1+1, nTab,
    1043           0 :                          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           0 :     sal_Bool bOk = true;
    1051           0 :     if (rParam.bReplace)
    1052           0 :         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           0 :     if (bOk)
    1062             :     {
    1063           0 :         WaitObject aWait( rDocShell.GetActiveDialogParent() );
    1064           0 :         ScDocShellModificator aModificator( rDocShell );
    1065             : 
    1066           0 :         ScSubTotalParam aNewParam( rParam );        // Bereichsende wird veraendert
    1067           0 :         ScDocument*     pUndoDoc = NULL;
    1068           0 :         ScOutlineTable* pUndoTab = NULL;
    1069           0 :         ScRangeName*    pUndoRange = NULL;
    1070           0 :         ScDBCollection* pUndoDB = NULL;
    1071             : 
    1072           0 :         if (bRecord)                                        // alte Daten sichern
    1073             :         {
    1074           0 :             sal_Bool bOldFilter = bDo && rParam.bDoSort;
    1075             : 
    1076           0 :             SCTAB nTabCount = pDoc->GetTableCount();
    1077           0 :             pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
    1078           0 :             ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
    1079           0 :             if (pTable)
    1080             :             {
    1081           0 :                 pUndoTab = new ScOutlineTable( *pTable );
    1082             : 
    1083             :                 // column/row state
    1084             :                 SCCOLROW nOutStartCol, nOutEndCol;
    1085             :                 SCCOLROW nOutStartRow, nOutEndRow;
    1086           0 :                 pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol );
    1087           0 :                 pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow );
    1088             : 
    1089           0 :                 pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True );
    1090           0 :                 pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab, IDF_NONE, false, pUndoDoc );
    1091           0 :                 pDoc->CopyToDocument( 0, nOutStartRow, nTab, MAXCOL, nOutEndRow, nTab, IDF_NONE, false, pUndoDoc );
    1092             :             }
    1093             :             else
    1094           0 :                 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           0 :                                     IDF_ALL, false, pUndoDoc );
    1099             : 
    1100             :             //  alle Formeln wegen Referenzen
    1101             :             pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
    1102           0 :                                         IDF_FORMULA, false, pUndoDoc );
    1103             : 
    1104             :             //  DB- und andere Bereiche
    1105           0 :             ScRangeName* pDocRange = pDoc->GetRangeName();
    1106           0 :             if (!pDocRange->empty())
    1107           0 :                 pUndoRange = new ScRangeName( *pDocRange );
    1108           0 :             ScDBCollection* pDocDB = pDoc->GetDBCollection();
    1109           0 :             if (!pDocDB->empty())
    1110           0 :                 pUndoDB = new ScDBCollection( *pDocDB );
    1111             :         }
    1112             : 
    1113             : //      pDoc->SetOutlineTable( nTab, NULL );
    1114           0 :         ScOutlineTable* pOut = pDoc->GetOutlineTable( nTab );
    1115           0 :         if (pOut)
    1116           0 :             pOut->GetRowArray()->RemoveAll();       // nur Zeilen-Outlines loeschen
    1117             : 
    1118           0 :         if (rParam.bReplace)
    1119           0 :             pDoc->RemoveSubTotals( nTab, aNewParam );
    1120           0 :         sal_Bool bSuccess = sal_True;
    1121           0 :         if (bDo)
    1122             :         {
    1123             :             // Sortieren
    1124           0 :             if ( rParam.bDoSort || pForceNewSort )
    1125             :             {
    1126           0 :                 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           0 :                 ScSortParam aOldSort;
    1132           0 :                 pDBData->GetSortParam( aOldSort );
    1133           0 :                 ScSortParam aSortParam( aNewParam, pForceNewSort ? *pForceNewSort : aOldSort );
    1134           0 :                 Sort( nTab, aSortParam, false, false, bApi );
    1135             :             }
    1136             : 
    1137           0 :             pDoc->InitializeNoteCaptions(nTab);
    1138           0 :             bSuccess = pDoc->DoSubTotals( nTab, aNewParam );
    1139           0 :             pDoc->SetDrawPageSize(nTab);
    1140             :         }
    1141             :         ScRange aDirtyRange( aNewParam.nCol1, aNewParam.nRow1, nTab,
    1142           0 :             aNewParam.nCol2, aNewParam.nRow2, nTab );
    1143           0 :         pDoc->SetDirty( aDirtyRange );
    1144             : 
    1145           0 :         if (bRecord)
    1146             :         {
    1147             : //          ScDBData* pUndoDBData = pDBData ? new ScDBData( *pDBData ) : NULL;
    1148           0 :             rDocShell.GetUndoManager()->AddUndoAction(
    1149             :                 new ScUndoSubTotals( &rDocShell, nTab,
    1150             :                                         rParam, aNewParam.nRow2,
    1151             :                                         pUndoDoc, pUndoTab, // pUndoDBData,
    1152           0 :                                         pUndoRange, pUndoDB ) );
    1153             :         }
    1154             : 
    1155           0 :         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           0 :         pDBData->SetSubTotalParam( aNewParam );
    1164           0 :         pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
    1165           0 :         pDoc->CompileDBFormula();
    1166             : 
    1167             :         rDocShell.PostPaint(ScRange(0, 0, nTab, MAXCOL,MAXROW,nTab),
    1168           0 :                             PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE);
    1169           0 :         aModificator.SetDocumentModified();
    1170             : 
    1171           0 :         bRet = bSuccess;
    1172             :     }
    1173           0 :     return bRet;
    1174             : }
    1175             : 
    1176             : //==================================================================
    1177             : 
    1178           0 : static sal_Bool lcl_EmptyExcept( ScDocument* pDoc, const ScRange& rRange, const ScRange& rExcept )
    1179             : {
    1180           0 :     ScCellIterator aIter( pDoc, rRange );
    1181           0 :     ScBaseCell* pCell = aIter.GetFirst();
    1182           0 :     while (pCell)
    1183             :     {
    1184           0 :         if ( !pCell->IsBlank() )      // real content?
    1185             :         {
    1186           0 :             if ( !rExcept.In( ScAddress( aIter.GetCol(), aIter.GetRow(), aIter.GetTab() ) ) )
    1187           0 :                 return false;       // cell found
    1188             :         }
    1189           0 :         pCell = aIter.GetNext();
    1190             :     }
    1191             : 
    1192           0 :     return sal_True;        // nothing found - empty
    1193             : }
    1194             : 
    1195           0 : bool ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewObj,
    1196             :                                    bool bRecord, bool bApi, bool bAllowMove )
    1197             : {
    1198           0 :     ScDocShellModificator aModificator( rDocShell );
    1199           0 :     WaitObject aWait( rDocShell.GetActiveDialogParent() );
    1200             : 
    1201           0 :     bool bDone = false;
    1202           0 :     bool bUndoSelf = false;
    1203           0 :     sal_uInt16 nErrId = 0;
    1204             : 
    1205           0 :     ScDocument* pOldUndoDoc = NULL;
    1206           0 :     ScDocument* pNewUndoDoc = NULL;
    1207           0 :     ScDPObject* pUndoDPObj = NULL;
    1208           0 :     if ( bRecord && pOldObj )
    1209           0 :         pUndoDPObj = new ScDPObject( *pOldObj );    // copy old settings for undo
    1210             : 
    1211           0 :     ScDocument* pDoc = rDocShell.GetDocument();
    1212           0 :     if (bRecord && !pDoc->IsUndoEnabled())
    1213           0 :         bRecord = false;
    1214           0 :     if ( !rDocShell.IsEditable() || pDoc->GetChangeTrack() )
    1215             :     {
    1216             :         //  not recorded -> disallow
    1217             :         //! different error messages?
    1218             : 
    1219           0 :         nErrId = STR_PROTECTIONERR;
    1220             :     }
    1221           0 :     if ( pOldObj && !nErrId )
    1222             :     {
    1223           0 :         ScRange aOldOut = pOldObj->GetOutRange();
    1224           0 :         ScEditableTester aTester( pDoc, aOldOut );
    1225           0 :         if ( !aTester.IsEditable() )
    1226           0 :             nErrId = aTester.GetMessageId();
    1227             :     }
    1228           0 :     if ( pNewObj && !nErrId )
    1229             :     {
    1230             :         //  at least one cell at the output position must be editable
    1231             :         //  -> check in advance
    1232             :         //  (start of output range in pNewObj is valid)
    1233             : 
    1234           0 :         ScRange aNewStart( pNewObj->GetOutRange().aStart );
    1235           0 :         ScEditableTester aTester( pDoc, aNewStart );
    1236           0 :         if ( !aTester.IsEditable() )
    1237           0 :             nErrId = aTester.GetMessageId();
    1238             :     }
    1239             : 
    1240           0 :     ScDPObject* pDestObj = NULL;
    1241           0 :     if ( !nErrId )
    1242             :     {
    1243           0 :         if ( pOldObj && !pNewObj )
    1244             :         {
    1245             :             //  delete table
    1246             : 
    1247           0 :             ScRange aRange = pOldObj->GetOutRange();
    1248           0 :             SCTAB nTab = aRange.aStart.Tab();
    1249             : 
    1250           0 :             if ( bRecord )
    1251             :             {
    1252           0 :                 pOldUndoDoc = new ScDocument( SCDOCMODE_UNDO );
    1253           0 :                 pOldUndoDoc->InitUndo( pDoc, nTab, nTab );
    1254           0 :                 pDoc->CopyToDocument( aRange, IDF_ALL, false, pOldUndoDoc );
    1255             :             }
    1256             : 
    1257           0 :             pDoc->DeleteAreaTab( aRange.aStart.Col(), aRange.aStart.Row(),
    1258           0 :                                  aRange.aEnd.Col(),   aRange.aEnd.Row(),
    1259           0 :                                  nTab, IDF_ALL );
    1260           0 :             pDoc->RemoveFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(),
    1261           0 :                                   aRange.aEnd.Col(),   aRange.aEnd.Row(),
    1262           0 :                                   nTab, SC_MF_AUTO );
    1263             : 
    1264           0 :             pDoc->GetDPCollection()->FreeTable( pOldObj );  // object is deleted here
    1265             : 
    1266           0 :             rDocShell.PostPaintGridAll();   //! only necessary parts
    1267           0 :             rDocShell.PostPaint(aRange, PAINT_GRID);
    1268           0 :             bDone = true;
    1269             :         }
    1270           0 :         else if ( pNewObj )
    1271             :         {
    1272           0 :             if ( pOldObj )
    1273             :             {
    1274           0 :                 if ( bRecord )
    1275             :                 {
    1276           0 :                     ScRange aRange = pOldObj->GetOutRange();
    1277           0 :                     SCTAB nTab = aRange.aStart.Tab();
    1278           0 :                     pOldUndoDoc = new ScDocument( SCDOCMODE_UNDO );
    1279           0 :                     pOldUndoDoc->InitUndo( pDoc, nTab, nTab );
    1280           0 :                     pDoc->CopyToDocument( aRange, IDF_ALL, false, pOldUndoDoc );
    1281             :                 }
    1282             : 
    1283           0 :                 if ( pNewObj == pOldObj )
    1284             :                 {
    1285             :                     //  refresh only - no settings modified
    1286             :                 }
    1287             :                 else
    1288             :                 {
    1289           0 :                     pNewObj->WriteSourceDataTo( *pOldObj );     // copy source data
    1290             : 
    1291           0 :                     ScDPSaveData* pData = pNewObj->GetSaveData();
    1292             :                     OSL_ENSURE( pData, "no SaveData from living DPObject" );
    1293           0 :                     if ( pData )
    1294           0 :                         pOldObj->SetSaveData( *pData );     // copy SaveData
    1295             :                 }
    1296             : 
    1297           0 :                 pDestObj = pOldObj;
    1298           0 :                 pDestObj->SetAllowMove( bAllowMove );
    1299             :             }
    1300             :             else
    1301             :             {
    1302             :                 //  output range must be set at pNewObj
    1303             : 
    1304           0 :                 pDestObj = new ScDPObject( *pNewObj );
    1305             : 
    1306             :                 // #i94570# When changing the output position in the dialog, a new table is created
    1307             :                 // with the settings from the old table, including the name.
    1308             :                 // So we have to check for duplicate names here (before inserting).
    1309           0 :                 if ( pDoc->GetDPCollection()->GetByName(pDestObj->GetName()) )
    1310           0 :                     pDestObj->SetName( String() );      // ignore the invalid name, create a new name below
    1311             : 
    1312           0 :                 pDestObj->SetAlive(sal_True);
    1313           0 :                 if ( !pDoc->GetDPCollection()->InsertNewTable(pDestObj) )
    1314             :                 {
    1315             :                     OSL_FAIL("cannot insert DPObject");
    1316           0 :                     DELETEZ( pDestObj );
    1317             :                 }
    1318             :             }
    1319           0 :             if ( pDestObj )
    1320             :             {
    1321           0 :                 pDestObj->ReloadGroupTableData();
    1322           0 :                 pDestObj->InvalidateData();             // before getting the new output area
    1323             : 
    1324             :                 //  make sure the table has a name (not set by dialog)
    1325           0 :                 if (pDestObj->GetName().isEmpty())
    1326           0 :                     pDestObj->SetName( pDoc->GetDPCollection()->CreateNewName() );
    1327             : 
    1328           0 :                 bool bOverflow = false;
    1329           0 :                 ScRange aNewOut = pDestObj->GetNewOutputRange( bOverflow );
    1330             : 
    1331             :                 //! test for overlap with other data pilot tables
    1332           0 :                 if( pOldObj )
    1333             :                 {
    1334           0 :                     const ScSheetSourceDesc* pSheetDesc = pOldObj->GetSheetDesc();
    1335           0 :                     if( pSheetDesc && pSheetDesc->GetSourceRange().Intersects( aNewOut ) )
    1336             :                     {
    1337           0 :                         ScRange aOldRange = pOldObj->GetOutRange();
    1338           0 :                         SCsROW nDiff = aOldRange.aStart.Row()-aNewOut.aStart.Row();
    1339           0 :                         aNewOut.aStart.SetRow( aOldRange.aStart.Row() );
    1340           0 :                         aNewOut.aEnd.SetRow( aNewOut.aEnd.Row()+nDiff );
    1341           0 :                         if( !ValidRow( aNewOut.aStart.Row() ) || !ValidRow( aNewOut.aEnd.Row() ) )
    1342           0 :                             bOverflow = sal_True;
    1343             :                     }
    1344             :                 }
    1345             : 
    1346           0 :                 if ( bOverflow )
    1347             :                 {
    1348             :                     //  like with STR_PROTECTIONERR, use undo to reverse everything
    1349             :                     OSL_ENSURE( bRecord, "DataPilotUpdate: can't undo" );
    1350           0 :                     bUndoSelf = true;
    1351           0 :                     nErrId = STR_PIVOT_ERROR;
    1352             :                 }
    1353             :                 else
    1354             :                 {
    1355           0 :                     ScEditableTester aTester( pDoc, aNewOut );
    1356           0 :                     if ( !aTester.IsEditable() )
    1357             :                     {
    1358             :                         //  destination area isn't editable
    1359             :                         //! reverse everything done so far, don't proceed
    1360             : 
    1361             :                         //  quick solution: proceed to end, use undo action
    1362             :                         //  to reverse everything:
    1363             :                         OSL_ENSURE( bRecord, "DataPilotUpdate: can't undo" );
    1364           0 :                         bUndoSelf = sal_True;
    1365           0 :                         nErrId = aTester.GetMessageId();
    1366           0 :                     }
    1367             :                 }
    1368             : 
    1369             :                 //  test if new output area is empty except for old area
    1370           0 :                 if ( !bApi )
    1371             :                 {
    1372             :                     bool bEmpty;
    1373           0 :                     if ( pOldObj )  // OutRange of pOldObj (pDestObj) is still old area
    1374           0 :                         bEmpty = lcl_EmptyExcept( pDoc, aNewOut, pOldObj->GetOutRange() );
    1375             :                     else
    1376           0 :                         bEmpty = pDoc->IsBlockEmpty( aNewOut.aStart.Tab(),
    1377           0 :                                             aNewOut.aStart.Col(), aNewOut.aStart.Row(),
    1378           0 :                                             aNewOut.aEnd.Col(), aNewOut.aEnd.Row() );
    1379             : 
    1380           0 :                     if ( !bEmpty )
    1381             :                     {
    1382             :                         QueryBox aBox( rDocShell.GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
    1383           0 :                                          ScGlobal::GetRscString(STR_PIVOT_NOTEMPTY) );
    1384           0 :                         if (aBox.Execute() == RET_NO)
    1385             :                         {
    1386             :                             //! like above (not editable), use undo to reverse everything
    1387             :                             OSL_ENSURE( bRecord, "DataPilotUpdate: can't undo" );
    1388           0 :                             bUndoSelf = true;
    1389           0 :                         }
    1390             :                     }
    1391             :                 }
    1392             : 
    1393           0 :                 if ( bRecord )
    1394             :                 {
    1395           0 :                     SCTAB nTab = aNewOut.aStart.Tab();
    1396           0 :                     pNewUndoDoc = new ScDocument( SCDOCMODE_UNDO );
    1397           0 :                     pNewUndoDoc->InitUndo( pDoc, nTab, nTab );
    1398           0 :                     pDoc->CopyToDocument( aNewOut, IDF_ALL, false, pNewUndoDoc );
    1399             :                 }
    1400             : 
    1401           0 :                 pDestObj->Output( aNewOut.aStart );
    1402             : 
    1403           0 :                 rDocShell.PostPaintGridAll();           //! only necessary parts
    1404           0 :                 bDone = true;
    1405             :             }
    1406             :         }
    1407             :         // else nothing (no old, no new)
    1408             :     }
    1409             : 
    1410           0 :     if ( bRecord && bDone )
    1411             :     {
    1412             :         SfxUndoAction* pAction = new ScUndoDataPilot( &rDocShell,
    1413           0 :                                     pOldUndoDoc, pNewUndoDoc, pUndoDPObj, pDestObj, bAllowMove );
    1414           0 :         pOldUndoDoc = NULL;
    1415           0 :         pNewUndoDoc = NULL;     // pointers are used in undo action
    1416             :         // pUndoDPObj is copied
    1417             : 
    1418           0 :         if (bUndoSelf)
    1419             :         {
    1420             :             //  use undo action to restore original state
    1421             :             //! prevent setting the document modified? (ScDocShellModificator)
    1422             : 
    1423           0 :             pAction->Undo();
    1424           0 :             delete pAction;
    1425           0 :             bDone = false;
    1426             :         }
    1427             :         else
    1428           0 :             rDocShell.GetUndoManager()->AddUndoAction( pAction );
    1429             :     }
    1430             : 
    1431           0 :     delete pOldUndoDoc;     // if not used for undo
    1432           0 :     delete pNewUndoDoc;
    1433           0 :     delete pUndoDPObj;
    1434             : 
    1435           0 :     if (bDone)
    1436             :     {
    1437             :         // notify API objects
    1438           0 :         if (pDestObj)
    1439           0 :             pDoc->BroadcastUno( ScDataPilotModifiedHint( pDestObj->GetName() ) );
    1440           0 :         aModificator.SetDocumentModified();
    1441             :     }
    1442             : 
    1443           0 :     if ( nErrId && !bApi )
    1444           0 :         rDocShell.ErrorMessage( nErrId );
    1445             : 
    1446           0 :     return bDone;
    1447             : }
    1448             : 
    1449           0 : sal_uLong ScDBDocFunc::RefreshPivotTables(ScDPObject* pDPObj, bool bApi)
    1450             : {
    1451           0 :     ScDPCollection* pDPs = rDocShell.GetDocument()->GetDPCollection();
    1452           0 :     if (!pDPs)
    1453           0 :         return 0;
    1454             : 
    1455           0 :     std::set<ScDPObject*> aRefs;
    1456           0 :     sal_uLong nErrId = pDPs->ReloadCache(pDPObj, aRefs);
    1457           0 :     if (nErrId)
    1458           0 :         return nErrId;
    1459             : 
    1460           0 :     std::set<ScDPObject*>::iterator it = aRefs.begin(), itEnd = aRefs.end();
    1461           0 :     for (; it != itEnd; ++it)
    1462             :     {
    1463           0 :         ScDPObject* pObj = *it;
    1464           0 :         if (!pObj->SyncAllDimensionMembers())
    1465           0 :             continue;
    1466             : 
    1467             :         // This action is intentionally not undoable since it modifies cache.
    1468           0 :         DataPilotUpdate(pObj, pObj, false, bApi);
    1469             :     }
    1470             : 
    1471           0 :     return 0;
    1472             : }
    1473             : 
    1474           0 : void ScDBDocFunc::RefreshPivotTableGroups(ScDPObject* pDPObj)
    1475             : {
    1476           0 :     if (!pDPObj)
    1477             :         return;
    1478             : 
    1479           0 :     ScDPCollection* pDPs = rDocShell.GetDocument()->GetDPCollection();
    1480           0 :     if (!pDPs)
    1481             :         return;
    1482             : 
    1483           0 :     ScDPSaveData* pSaveData = pDPObj->GetSaveData();
    1484           0 :     if (!pSaveData)
    1485             :         return;
    1486             : 
    1487           0 :     std::set<ScDPObject*> aRefs;
    1488           0 :     if (!pDPs->ReloadGroupsInCache(pDPObj, aRefs))
    1489             :         return;
    1490             : 
    1491             :     // We allow pDimData being NULL.
    1492           0 :     const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData();
    1493           0 :     std::set<ScDPObject*>::iterator it = aRefs.begin(), itEnd = aRefs.end();
    1494           0 :     for (; it != itEnd; ++it)
    1495             :     {
    1496           0 :         ScDPObject* pObj = *it;
    1497           0 :         if (pObj != pDPObj)
    1498             :         {
    1499           0 :             pSaveData = pObj->GetSaveData();
    1500           0 :             if (pSaveData)
    1501           0 :                 pSaveData->SetDimensionData(pDimData);
    1502             :         }
    1503             : 
    1504             :         // This action is intentionally not undoable since it modifies cache.
    1505           0 :         DataPilotUpdate(pObj, pObj, false, false);
    1506           0 :     }
    1507             : }
    1508             : 
    1509             : //==================================================================
    1510             : //
    1511             : //      database import
    1512             : 
    1513           0 : void ScDBDocFunc::UpdateImport( const String& rTarget, const svx::ODataAccessDescriptor& rDescriptor )
    1514             : {
    1515             :     // rTarget is the name of a database range
    1516             : 
    1517           0 :     ScDocument* pDoc = rDocShell.GetDocument();
    1518           0 :     ScDBCollection& rDBColl = *pDoc->GetDBCollection();
    1519           0 :     const ScDBData* pData = rDBColl.getNamedDBs().findByUpperName(ScGlobal::pCharClass->uppercase(rTarget));
    1520           0 :     if (!pData)
    1521             :     {
    1522             :         InfoBox aInfoBox(rDocShell.GetActiveDialogParent(),
    1523           0 :                     ScGlobal::GetRscString( STR_TARGETNOTFOUND ) );
    1524           0 :         aInfoBox.Execute();
    1525           0 :         return;
    1526             :     }
    1527             : 
    1528             :     SCTAB nTab;
    1529             :     SCCOL nDummyCol;
    1530             :     SCROW nDummyRow;
    1531           0 :     pData->GetArea( nTab, nDummyCol,nDummyRow,nDummyCol,nDummyRow );
    1532             : 
    1533           0 :     ScImportParam aImportParam;
    1534           0 :     pData->GetImportParam( aImportParam );
    1535             : 
    1536           0 :     rtl::OUString sDBName;
    1537           0 :     rtl::OUString sDBTable;
    1538           0 :     sal_Int32 nCommandType = 0;
    1539           0 :     rDescriptor[svx::daDataSource]  >>= sDBName;
    1540           0 :     rDescriptor[svx::daCommand]     >>= sDBTable;
    1541           0 :     rDescriptor[svx::daCommandType] >>= nCommandType;
    1542             : 
    1543           0 :     aImportParam.aDBName    = sDBName;
    1544           0 :     aImportParam.bSql       = ( nCommandType == sdb::CommandType::COMMAND );
    1545           0 :     aImportParam.aStatement = sDBTable;
    1546           0 :     aImportParam.bNative    = false;
    1547           0 :     aImportParam.nType      = static_cast<sal_uInt8>( ( nCommandType == sdb::CommandType::QUERY ) ? ScDbQuery : ScDbTable );
    1548           0 :     aImportParam.bImport    = true;
    1549             : 
    1550           0 :     bool bContinue = DoImport( nTab, aImportParam, &rDescriptor, true );
    1551             : 
    1552             :     //  DB-Operationen wiederholen
    1553             : 
    1554           0 :     ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
    1555           0 :     if (pViewSh)
    1556             :     {
    1557           0 :         ScRange aRange;
    1558           0 :         pData->GetArea(aRange);
    1559           0 :         pViewSh->MarkRange(aRange);         // selektieren
    1560             : 
    1561           0 :         if ( bContinue )        // Fehler beim Import -> Abbruch
    1562             :         {
    1563             :             //  interne Operationen, wenn welche gespeichert
    1564             : 
    1565           0 :             if ( pData->HasQueryParam() || pData->HasSortParam() || pData->HasSubTotalParam() )
    1566           0 :                 pViewSh->RepeatDB();
    1567             : 
    1568             :             //  Pivottabellen die den Bereich als Quelldaten haben
    1569             : 
    1570           0 :             rDocShell.RefreshPivotTables(aRange);
    1571             :         }
    1572           0 :     }
    1573          15 : }
    1574             : 
    1575             : 
    1576             : 
    1577             : 
    1578             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10