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