Files
libreoffice/sc/source/ui/docshell/dbdocfun.cxx

1741 lines
60 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
re-base on ALv2 code. Includes: Patches contributed by Herbert Duerr i#118735 prevent endless loop if vlookup/hlookup doesn't find anything http://svn.apache.org/viewvc?view=revision&revision=1239673 Patches contributed by Andre Fischer remove lp_solver http://svn.apache.org/viewvc?view=revision&revision=1199180 i#118160: Added external CoinMP library. http://svn.apache.org/viewvc?view=revision&revision=1233909 Patches contributed by Armin Le-Grand i#118485 - Styles for OLEs are not saved. http://svn.apache.org/viewvc?view=revision&revision=1182166 i#118524: apply patch, followup fixes to 118485 http://svn.apache.org/viewvc?view=revision&revision=1186077 Patches contributed by lihuiibm i#108860 - Fix range validation. http://svn.apache.org/viewvc?view=revision&revision=1242846 i#118954 Chart data will lost after copy to different file http://svn.apache.org/viewvc?view=revision&revision=1301345 Patches contributed by Ariel Constenla-Haile Fix Linux build breaker: extra qualification on member http://svn.apache.org/viewvc?view=revision&revision=1301591 i#118696 - i#118697 - Fix some Sheet Tab Color API issues http://svn.apache.org/viewvc?view=revision&revision=1225428 i#118697 - Fix uninitialized variable http://svn.apache.org/viewvc?view=revision&revision=1225859 i#118771 - ScUndoImportTab should preserve tab background color http://svn.apache.org/viewvc?view=revision&revision=1230356 i#118921 - Repaint linked sheet tab background color after updating link http://svn.apache.org/viewvc?view=revision&revision=1245177 i#118927 - Undo/Redo "Update Link" does not reset sheet tab color http://svn.apache.org/viewvc?view=revision&revision=1245241 i#118747 - Copy tab color when transferring sheets across documents http://svn.apache.org/viewvc?view=revision&revision=1230355 Patch contributed by Oliver Rainer-Wittman i#118012 - methods <ScBroadcastAreaSlot::AreaBroadcast(..)> and <ScBroadcastAreaSlot::AreaBroadcastInRange(..)> adapt stl-container iteration in order to avoid destroyed iterators during iteration. http://svn.apache.org/viewvc?view=revision&revision=1297916 Patches contributed by Mathias Bauer gnumake4 work variously http://svn.apache.org/viewvc?view=revision&revision=1394707 http://svn.apache.org/viewvc?view=revision&revision=1394326 http://svn.apache.org/viewvc?view=revision&revision=1396797 http://svn.apache.org/viewvc?view=revision&revision=1397315 Patch contributed by Daniel Rentz calc69: #i116936# fix VBA symbol Cells http://svn.apache.org/viewvc?view=revision&revision=1172135 Patches contributed by leiw: i#118546 CPU 100% on switched off AutoCalculate with Conditional Formatting on date values http://svn.apache.org/viewvc?view=revision&revision=1301380 Re-add new function documentation. Many various cleanups. Add missing calc66: #o11817313# also look at formula result number format, remove redundant binaries.
2012-11-30 12:23:25 +00:00
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
2000-09-18 16:07:07 +00:00
#include <sfx2/app.hxx>
#include <vcl/msgbox.hxx>
#include <vcl/waitobj.hxx>
#include <svx/dataaccessdescriptor.hxx>
2000-09-18 16:07:07 +00:00
#include <com/sun/star/sdb/CommandType.hpp>
2000-09-18 16:07:07 +00:00
#include "dbdocfun.hxx"
#include "sc.hrc"
#include "dbdata.hxx"
2000-09-18 16:07:07 +00:00
#include "undodat.hxx"
#include "docsh.hxx"
#include "docfunc.hxx"
#include "globstr.hrc"
#include "globalnames.hxx"
2000-09-18 16:07:07 +00:00
#include "tabvwsh.hxx"
#include "patattr.hxx"
#include "rangenam.hxx"
#include "olinetab.hxx"
#include "dpobject.hxx"
#include "dpsave.hxx"
#include "dociter.hxx" // for lcl_EmptyExcept
#include "editable.hxx"
#include "attrib.hxx"
#include "drwlayer.hxx"
CWS-TOOLING: integrate CWS calc50 2009-05-28 12:32:46 +0200 nn r272399 : gcc warning 2009-05-28 10:56:48 +0200 nn r272382 : CWS-TOOLING: rebase CWS calc50 to trunk@272291 (milestone: DEV300:m49) 2009-05-27 14:24:52 +0200 nn r272343 : #i50825# DataPilotUpdate: prevent overwriting source data above the table 2009-05-26 18:29:21 +0200 nn r272316 : #i50019# allow borders for multiple cell ranges 2009-05-26 13:43:36 +0200 nn r272300 : #i101960# UpdateExternalRefLinks: set document modified 2009-05-25 18:01:23 +0200 nn r272267 : #i102056# copied from CWS calc311fixes 2009-05-20 12:24:22 +0200 nn r272114 : #i59672# ExecFilter/SC_AUTOFILTER_CUSTOM: select database range (patch from gaozm) 2009-05-15 18:24:44 +0200 nn r271961 : #i100544# correct ScTokenConversion::ConvertToTokenArray 2009-05-13 17:45:02 +0200 nn r271866 : #i101869# DeleteRange: before broadcasting, check if EndListening removed the note cells 2009-05-13 12:43:31 +0200 nn r271856 : #i101806# correct reference undo for inserting/deleting columns/rows across sheets 2009-05-11 18:44:46 +0200 nn r271783 : #i101725# don't copy hash_set with pointers from the other collection 2009-05-11 17:54:21 +0200 nn r271780 : #i101690# correct merge error in frmdlg integration 2009-05-07 15:28:55 +0200 nn r271674 : #i96940# check for negative count in fillAuto 2009-05-07 13:47:58 +0200 nn r271661 : #i101512# SetCompileForFAP is in formula::FormulaCompiler 2009-05-07 13:47:27 +0200 nn r271660 : #i101512# use SetCompileForFAP for CompileTokenArray 2009-05-05 18:47:03 +0200 nn r271551 : #i73074# RepeatDB: re-evaluate advanced filter source range 2009-05-05 18:23:21 +0200 nn r271546 : #i97857# use GetInputString for direct reference as validity range source 2009-05-05 17:38:23 +0200 nn r271538 : #i95834# better enable/disable handling of next/previous buttons (patch by cmc)
2009-06-15 10:46:14 +00:00
#include "dpshttab.hxx"
#include "hints.hxx"
#include "queryentry.hxx"
#include "markdata.hxx"
#include "progress.hxx"
2000-09-18 16:07:07 +00:00
#include <set>
#include <memory>
using namespace ::com::sun::star;
2000-09-18 16:07:07 +00:00
// -----------------------------------------------------------------
bool ScDBDocFunc::AddDBRange( const OUString& rName, const ScRange& rRange, sal_Bool /* bApi */ )
2000-09-18 16:07:07 +00:00
{
2000-09-18 16:07:07 +00:00
ScDocShellModificator aModificator( rDocShell );
ScDocument* pDoc = rDocShell.GetDocument();
ScDBCollection* pDocColl = pDoc->GetDBCollection();
sal_Bool bUndo (pDoc->IsUndoEnabled());
2000-09-18 16:07:07 +00:00
ScDBCollection* pUndoColl = NULL;
if (bUndo)
pUndoColl = new ScDBCollection( *pDocColl );
2000-09-18 16:07:07 +00:00
ScDBData* pNew = new ScDBData( rName, rRange.aStart.Tab(),
rRange.aStart.Col(), rRange.aStart.Row(),
rRange.aEnd.Col(), rRange.aEnd.Row() );
// #i55926# While loading XML, formula cells only have a single string token,
// so CompileDBFormula would never find any name (index) tokens, and would
// unnecessarily loop through all cells.
bool bCompile = !pDoc->IsImportingXML();
bool bOk;
if ( bCompile )
pDoc->CompileDBFormula( sal_True ); // CreateFormulaString
if ( rName == STR_DB_LOCAL_NONAME )
{
pDoc->SetAnonymousDBData(rRange.aStart.Tab() , pNew);
bOk = true;
}
else
{
bOk = pDocColl->getNamedDBs().insert(pNew);
}
if ( bCompile )
pDoc->CompileDBFormula( false ); // CompileFormulaString
2000-09-18 16:07:07 +00:00
if (!bOk)
{
delete pNew;
delete pUndoColl;
return false;
2000-09-18 16:07:07 +00:00
}
if (bUndo)
{
ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
rDocShell.GetUndoManager()->AddUndoAction(
new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
}
2000-09-18 16:07:07 +00:00
aModificator.SetDocumentModified();
SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
return true;
2000-09-18 16:07:07 +00:00
}
bool ScDBDocFunc::DeleteDBRange(const OUString& rName)
2000-09-18 16:07:07 +00:00
{
bool bDone = false;
2000-09-18 16:07:07 +00:00
ScDocument* pDoc = rDocShell.GetDocument();
ScDBCollection* pDocColl = pDoc->GetDBCollection();
bool bUndo = pDoc->IsUndoEnabled();
2000-09-18 16:07:07 +00:00
ScDBCollection::NamedDBs& rDBs = pDocColl->getNamedDBs();
const ScDBData* p = rDBs.findByUpperName(ScGlobal::pCharClass->uppercase(rName));
if (p)
2000-09-18 16:07:07 +00:00
{
ScDocShellModificator aModificator( rDocShell );
ScDBCollection* pUndoColl = NULL;
if (bUndo)
pUndoColl = new ScDBCollection( *pDocColl );
2000-09-18 16:07:07 +00:00
pDoc->CompileDBFormula( true ); // CreateFormulaString
rDBs.erase(*p);
pDoc->CompileDBFormula( false ); // CompileFormulaString
2000-09-18 16:07:07 +00:00
if (bUndo)
{
ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
rDocShell.GetUndoManager()->AddUndoAction(
new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
}
2000-09-18 16:07:07 +00:00
aModificator.SetDocumentModified();
SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
bDone = true;
2000-09-18 16:07:07 +00:00
}
return bDone;
}
bool ScDBDocFunc::RenameDBRange( const OUString& rOld, const OUString& rNew )
2000-09-18 16:07:07 +00:00
{
bool bDone = false;
2000-09-18 16:07:07 +00:00
ScDocument* pDoc = rDocShell.GetDocument();
ScDBCollection* pDocColl = pDoc->GetDBCollection();
bool bUndo = pDoc->IsUndoEnabled();
ScDBCollection::NamedDBs& rDBs = pDocColl->getNamedDBs();
const ScDBData* pOld = rDBs.findByUpperName(ScGlobal::pCharClass->uppercase(rOld));
const ScDBData* pNew = rDBs.findByUpperName(ScGlobal::pCharClass->uppercase(rNew));
if (pOld && !pNew)
2000-09-18 16:07:07 +00:00
{
ScDocShellModificator aModificator( rDocShell );
ScDBData* pNewData = new ScDBData(rNew, *pOld);
2000-09-18 16:07:07 +00:00
ScDBCollection* pUndoColl = new ScDBCollection( *pDocColl );
pDoc->CompileDBFormula(true); // CreateFormulaString
rDBs.erase(*pOld);
bool bInserted = rDBs.insert(pNewData);
2000-09-18 16:07:07 +00:00
if (!bInserted) // Fehler -> alten Zustand wiederherstellen
pDoc->SetDBCollection(pUndoColl); // gehoert dann dem Dokument
//
pDoc->CompileDBFormula( false ); // CompileFormulaString
2000-09-18 16:07:07 +00:00
if (bInserted) // Einfuegen hat geklappt
{
if (bUndo)
{
ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
rDocShell.GetUndoManager()->AddUndoAction(
new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
}
else
delete pUndoColl;
2000-09-18 16:07:07 +00:00
aModificator.SetDocumentModified();
SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
bDone = true;
2000-09-18 16:07:07 +00:00
}
}
return bDone;
}
bool ScDBDocFunc::ModifyDBData( const ScDBData& rNewData )
2000-09-18 16:07:07 +00:00
{
bool bDone = false;
2000-09-18 16:07:07 +00:00
ScDocument* pDoc = rDocShell.GetDocument();
ScDBCollection* pDocColl = pDoc->GetDBCollection();
bool bUndo = pDoc->IsUndoEnabled();
2000-09-18 16:07:07 +00:00
ScDBData* pData = NULL;
2012-02-23 03:20:53 +09:00
if (rNewData.GetName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(STR_DB_LOCAL_NONAME)))
{
ScRange aRange;
rNewData.GetArea(aRange);
SCTAB nTab = aRange.aStart.Tab();
pData = pDoc->GetAnonymousDBData(nTab);
}
else
pData = pDocColl->getNamedDBs().findByUpperName(rNewData.GetUpperName());
if (pData)
2000-09-18 16:07:07 +00:00
{
ScDocShellModificator aModificator( rDocShell );
ScRange aOldRange, aNewRange;
pData->GetArea(aOldRange);
rNewData.GetArea(aNewRange);
bool bAreaChanged = ( aOldRange != aNewRange ); // dann muss neu compiliert werden
2000-09-18 16:07:07 +00:00
ScDBCollection* pUndoColl = NULL;
if (bUndo)
pUndoColl = new ScDBCollection( *pDocColl );
2000-09-18 16:07:07 +00:00
*pData = rNewData;
if (bAreaChanged)
pDoc->CompileDBFormula();
if (bUndo)
{
ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
rDocShell.GetUndoManager()->AddUndoAction(
new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
}
2000-09-18 16:07:07 +00:00
aModificator.SetDocumentModified();
bDone = true;
2000-09-18 16:07:07 +00:00
}
return bDone;
}
// -----------------------------------------------------------------
bool ScDBDocFunc::RepeatDB( const OUString& rDBName, bool bRecord, bool bApi, bool bIsUnnamed, SCTAB aTab )
2000-09-18 16:07:07 +00:00
{
//! auch fuer ScDBFunc::RepeatDB benutzen!
bool bDone = false;
2000-09-18 16:07:07 +00:00
ScDocument* pDoc = rDocShell.GetDocument();
if (bRecord && !pDoc->IsUndoEnabled())
bRecord = false;
ScDBData* pDBData = NULL;
if (bIsUnnamed)
2000-09-18 16:07:07 +00:00
{
pDBData = pDoc->GetAnonymousDBData( aTab );
}
else
{
ScDBCollection* pColl = pDoc->GetDBCollection();
if (pColl)
pDBData = pColl->getNamedDBs().findByUpperName(ScGlobal::pCharClass->uppercase(rDBName));
}
2000-09-18 16:07:07 +00:00
if ( pDBData )
{
2000-09-18 16:07:07 +00:00
ScQueryParam aQueryParam;
pDBData->GetQueryParam( aQueryParam );
sal_Bool bQuery = aQueryParam.GetEntry(0).bDoQuery;
2000-09-18 16:07:07 +00:00
ScSortParam aSortParam;
pDBData->GetSortParam( aSortParam );
sal_Bool bSort = aSortParam.maKeyState[0].bDoSort;
2000-09-18 16:07:07 +00:00
ScSubTotalParam aSubTotalParam;
pDBData->GetSubTotalParam( aSubTotalParam );
sal_Bool bSubTotal = aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly;
2000-09-18 16:07:07 +00:00
if ( bQuery || bSort || bSubTotal )
{
sal_Bool bQuerySize = false;
2000-09-18 16:07:07 +00:00
ScRange aOldQuery;
ScRange aNewQuery;
if (bQuery && !aQueryParam.bInplace)
{
ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
aQueryParam.nDestTab, sal_True );
2000-09-18 16:07:07 +00:00
if (pDest && pDest->IsDoSize())
{
pDest->GetArea( aOldQuery );
bQuerySize = sal_True;
2000-09-18 16:07:07 +00:00
}
}
SCTAB nTab;
SCCOL nStartCol;
SCROW nStartRow;
SCCOL nEndCol;
SCROW nEndRow;
2000-09-18 16:07:07 +00:00
pDBData->GetArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow );
//! Undo nur benoetigte Daten ?
ScDocument* pUndoDoc = NULL;
ScOutlineTable* pUndoTab = NULL;
ScRangeName* pUndoRange = NULL;
ScDBCollection* pUndoDB = NULL;
if (bRecord)
{
SCTAB nTabCount = pDoc->GetTableCount();
2000-09-18 16:07:07 +00:00
pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
if (pTable)
{
pUndoTab = new ScOutlineTable( *pTable );
// column/row state
SCCOLROW nOutStartCol, nOutEndCol;
SCCOLROW nOutStartRow, nOutEndRow;
2000-09-18 16:07:07 +00:00
pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol );
pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow );
pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True );
pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0,
nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab,
IDF_NONE, false, pUndoDoc );
pDoc->CopyToDocument( 0, static_cast<SCROW>(nOutStartRow),
nTab, MAXCOL, static_cast<SCROW>(nOutEndRow), nTab,
IDF_NONE, false, pUndoDoc );
2000-09-18 16:07:07 +00:00
}
else
pUndoDoc->InitUndo( pDoc, nTab, nTab, false, sal_True );
2000-09-18 16:07:07 +00:00
// Datenbereich sichern - incl. Filter-Ergebnis
pDoc->CopyToDocument( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab, IDF_ALL, false, pUndoDoc );
2000-09-18 16:07:07 +00:00
// alle Formeln wegen Referenzen
pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, IDF_FORMULA, false, pUndoDoc );
2000-09-18 16:07:07 +00:00
// DB- und andere Bereiche
ScRangeName* pDocRange = pDoc->GetRangeName();
if (!pDocRange->empty())
2000-09-18 16:07:07 +00:00
pUndoRange = new ScRangeName( *pDocRange );
ScDBCollection* pDocDB = pDoc->GetDBCollection();
if (!pDocDB->empty())
2000-09-18 16:07:07 +00:00
pUndoDB = new ScDBCollection( *pDocDB );
}
if (bSort && bSubTotal)
{
// Sortieren ohne SubTotals
aSubTotalParam.bRemoveOnly = sal_True; // wird unten wieder zurueckgesetzt
DoSubTotals( nTab, aSubTotalParam, NULL, false, bApi );
2000-09-18 16:07:07 +00:00
}
if (bSort)
{
pDBData->GetSortParam( aSortParam ); // Bereich kann sich geaendert haben
Sort( nTab, aSortParam, false, false, bApi );
2000-09-18 16:07:07 +00:00
}
if (bQuery)
{
pDBData->GetQueryParam( aQueryParam ); // Bereich kann sich geaendert haben
ScRange aAdvSource;
if (pDBData->GetAdvancedQuerySource(aAdvSource))
Query( nTab, aQueryParam, &aAdvSource, false, bApi );
2000-09-18 16:07:07 +00:00
else
Query( nTab, aQueryParam, NULL, false, bApi );
2000-09-18 16:07:07 +00:00
// bei nicht-inplace kann die Tabelle umgestellt worden sein
// if ( !aQueryParam.bInplace && aQueryParam.nDestTab != nTab )
// SetTabNo( nTab );
}
if (bSubTotal)
{
pDBData->GetSubTotalParam( aSubTotalParam ); // Bereich kann sich geaendert haben
aSubTotalParam.bRemoveOnly = false;
DoSubTotals( nTab, aSubTotalParam, NULL, false, bApi );
2000-09-18 16:07:07 +00:00
}
if (bRecord)
{
SCTAB nDummyTab;
SCCOL nDummyCol;
SCROW nDummyRow;
SCROW nNewEndRow;
pDBData->GetArea( nDummyTab, nDummyCol,nDummyRow, nDummyCol,nNewEndRow );
2000-09-18 16:07:07 +00:00
const ScRange* pOld = NULL;
const ScRange* pNew = NULL;
if (bQuerySize)
{
ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
aQueryParam.nDestTab, sal_True );
2000-09-18 16:07:07 +00:00
if (pDest)
{
pDest->GetArea( aNewQuery );
pOld = &aOldQuery;
pNew = &aNewQuery;
}
}
rDocShell.GetUndoManager()->AddUndoAction(
new ScUndoRepeatDB( &rDocShell, nTab,
nStartCol, nStartRow, nEndCol, nEndRow,
nNewEndRow,
//nCurX, nCurY,
nStartCol, nStartRow,
pUndoDoc, pUndoTab,
pUndoRange, pUndoDB,
pOld, pNew ) );
}
rDocShell.PostPaint(ScRange(0, 0, nTab, MAXCOL, MAXROW, nTab),
PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE);
bDone = sal_True;
2000-09-18 16:07:07 +00:00
}
else if (!bApi) // "Keine Operationen auszufuehren"
rDocShell.ErrorMessage(STR_MSSG_REPEATDB_0);
}
return bDone;
}
// -----------------------------------------------------------------
sal_Bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam,
sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi )
2000-09-18 16:07:07 +00:00
{
ScDocShellModificator aModificator( rDocShell );
ScDocument* pDoc = rDocShell.GetDocument();
if (bRecord && !pDoc->IsUndoEnabled())
bRecord = false;
SCTAB nSrcTab = nTab;
ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
2000-09-18 16:07:07 +00:00
ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rSortParam.nCol1, rSortParam.nRow1,
rSortParam.nCol2, rSortParam.nRow2 );
if (!pDBData)
{
2011-03-01 19:05:02 +01:00
OSL_FAIL( "Sort: keine DBData" );
return false;
2000-09-18 16:07:07 +00:00
}
ScDBData* pDestData = NULL;
ScRange aOldDest;
sal_Bool bCopy = !rSortParam.bInplace;
2000-09-18 16:07:07 +00:00
if ( bCopy && rSortParam.nDestCol == rSortParam.nCol1 &&
rSortParam.nDestRow == rSortParam.nRow1 && rSortParam.nDestTab == nTab )
bCopy = false;
2000-09-18 16:07:07 +00:00
ScSortParam aLocalParam( rSortParam );
if ( bCopy )
{
aLocalParam.MoveToDest();
if ( !ValidColRow( aLocalParam.nCol2, aLocalParam.nRow2 ) )
{
if (!bApi)
rDocShell.ErrorMessage(STR_PASTE_FULL);
return false;
}
2000-09-18 16:07:07 +00:00
nTab = rSortParam.nDestTab;
pDestData = pDoc->GetDBAtCursor( rSortParam.nDestCol, rSortParam.nDestRow,
rSortParam.nDestTab, sal_True );
2000-09-18 16:07:07 +00:00
if (pDestData)
pDestData->GetArea(aOldDest);
}
ScEditableTester aTester( pDoc, nTab, aLocalParam.nCol1,aLocalParam.nRow1,
aLocalParam.nCol2,aLocalParam.nRow2 );
if (!aTester.IsEditable())
2000-09-18 16:07:07 +00:00
{
if (!bApi)
rDocShell.ErrorMessage(aTester.GetMessageId());
return false;
2000-09-18 16:07:07 +00:00
}
if ( aLocalParam.bIncludePattern && pDoc->HasAttrib(
aLocalParam.nCol1, aLocalParam.nRow1, nTab,
aLocalParam.nCol2, aLocalParam.nRow2, nTab,
HASATTR_MERGED | HASATTR_OVERLAPPED ) )
{
// Merge-Attribute wuerden beim Sortieren durcheinanderkommen
if (!bApi)
rDocShell.ErrorMessage(STR_SORT_ERR_MERGED);
return false;
2000-09-18 16:07:07 +00:00
}
// ausfuehren
WaitObject aWait( rDocShell.GetActiveDialogParent() );
2000-09-18 16:07:07 +00:00
sal_Bool bRepeatQuery = false; // bestehenden Filter wiederholen?
2000-09-18 16:07:07 +00:00
ScQueryParam aQueryParam;
pDBData->GetQueryParam( aQueryParam );
if ( aQueryParam.GetEntry(0).bDoQuery )
bRepeatQuery = sal_True;
2000-09-18 16:07:07 +00:00
if (bRepeatQuery && bCopy)
{
if ( aQueryParam.bInplace ||
aQueryParam.nDestCol != rSortParam.nDestCol ||
aQueryParam.nDestRow != rSortParam.nDestRow ||
aQueryParam.nDestTab != rSortParam.nDestTab ) // Query auf selben Zielbereich?
bRepeatQuery = false;
2000-09-18 16:07:07 +00:00
}
ScUndoSort* pUndoAction = 0;
2000-09-18 16:07:07 +00:00
if ( bRecord )
{
// Referenzen ausserhalb des Bereichs werden nicht veraendert !
ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
// Zeilenhoehen immer (wegen automatischer Anpassung)
//! auf ScBlockUndo umstellen
pUndoDoc->InitUndo( pDoc, nTab, nTab, false, sal_True );
/* #i59745# Do not copy note captions to undo document. All existing
caption objects will be repositioned while sorting which is tracked
in drawing undo. When undo is executed, the old positions will be
restored, and the cells with the old notes (which still refer to the
existing captions) will be copied back into the source document. */
2000-09-18 16:07:07 +00:00
pDoc->CopyToDocument( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
aLocalParam.nCol2, aLocalParam.nRow2, nTab,
IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc );
2000-09-18 16:07:07 +00:00
const ScRange* pR = 0;
if (pDestData)
{
/* #i59745# Do not copy note captions from destination range to
undo document. All existing caption objects will be removed
which is tracked in drawing undo. When undo is executed, the
caption objects are reinserted with drawing undo, and the cells
with the old notes (which still refer to the existing captions)
will be copied back into the source document. */
pDoc->CopyToDocument( aOldDest, IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc );
2000-09-18 16:07:07 +00:00
pR = &aOldDest;
}
// Zeilenhoehen immer (wegen automatischer Anpassung)
//! auf ScBlockUndo umstellen
// if (bRepeatQuery)
2000-09-18 16:07:07 +00:00
pDoc->CopyToDocument( 0, aLocalParam.nRow1, nTab, MAXCOL, aLocalParam.nRow2, nTab,
IDF_NONE, false, pUndoDoc );
2000-09-18 16:07:07 +00:00
ScDBCollection* pUndoDB = NULL;
ScDBCollection* pDocDB = pDoc->GetDBCollection();
if (!pDocDB->empty())
2000-09-18 16:07:07 +00:00
pUndoDB = new ScDBCollection( *pDocDB );
pUndoAction = new ScUndoSort( &rDocShell, nTab, rSortParam, pUndoDoc, pUndoDB, pR );
rDocShell.GetUndoManager()->AddUndoAction( pUndoAction );
2000-09-18 16:07:07 +00:00
// #i59745# collect all drawing undo actions affecting cell note captions
if( pDrawLayer )
pDrawLayer->BeginCalcUndo(false);
2000-09-18 16:07:07 +00:00
}
if ( bCopy )
{
if (pDestData)
pDoc->DeleteAreaTab(aOldDest, IDF_CONTENTS); // Zielbereich vorher loeschen
ScRange aSource( rSortParam.nCol1,rSortParam.nRow1,nSrcTab,
rSortParam.nCol2,rSortParam.nRow2,nSrcTab );
ScAddress aDest( rSortParam.nDestCol, rSortParam.nDestRow, rSortParam.nDestTab );
rDocShell.GetDocFunc().MoveBlock( aSource, aDest, false, false, false, sal_True );
2000-09-18 16:07:07 +00:00
}
2011-03-01 14:29:24 +01:00
// don't call ScDocument::Sort with an empty SortParam (may be empty here if bCopy is set)
if (aLocalParam.GetSortKeyCount() && aLocalParam.maKeyState[0].bDoSort)
{
ScProgress aProgress(&rDocShell, ScGlobal::GetRscString(STR_PROGRESS_SORTING), 0);
pDoc->Sort( nTab, aLocalParam, bRepeatQuery, &aProgress );
}
2000-09-18 16:07:07 +00:00
sal_Bool bSave = sal_True;
2000-09-18 16:07:07 +00:00
if (bCopy)
{
ScSortParam aOldSortParam;
pDBData->GetSortParam( aOldSortParam );
if (aOldSortParam.GetSortKeyCount() &&
aOldSortParam.maKeyState[0].bDoSort && aOldSortParam.bInplace)
2000-09-18 16:07:07 +00:00
{
bSave = false;
2000-09-18 16:07:07 +00:00
aOldSortParam.nDestCol = rSortParam.nDestCol;
aOldSortParam.nDestRow = rSortParam.nDestRow;
aOldSortParam.nDestTab = rSortParam.nDestTab;
pDBData->SetSortParam( aOldSortParam ); // dann nur DestPos merken
}
}
if (bSave) // Parameter merken
{
pDBData->SetSortParam( rSortParam );
pDBData->SetHeader( rSortParam.bHasHeader ); //! ???
pDBData->SetByRow( rSortParam.bByRow ); //! ???
}
if (bCopy) // neuen DB-Bereich merken
{
// Tabelle umschalten von aussen (View)
//! SetCursor ??!?!
ScRange aDestPos( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
aLocalParam.nCol2, aLocalParam.nRow2, nTab );
ScDBData* pNewData;
if (pDestData)
pNewData = pDestData; // Bereich vorhanden -> anpassen
else // Bereich ab Cursor/Markierung wird angelegt
pNewData = rDocShell.GetDBData(aDestPos, SC_DB_MAKE, SC_DBSEL_FORCE_MARK );
2000-09-18 16:07:07 +00:00
if (pNewData)
{
pNewData->SetArea( nTab,
aLocalParam.nCol1,aLocalParam.nRow1,
aLocalParam.nCol2,aLocalParam.nRow2 );
pNewData->SetSortParam( aLocalParam );
pNewData->SetHeader( aLocalParam.bHasHeader ); //! ???
pNewData->SetByRow( aLocalParam.bByRow );
}
else
{
2011-03-01 19:05:02 +01:00
OSL_FAIL("Zielbereich nicht da");
}
2000-09-18 16:07:07 +00:00
}
ScRange aDirtyRange( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
aLocalParam.nCol2, aLocalParam.nRow2, nTab );
pDoc->SetDirty( aDirtyRange );
if (bPaint)
{
sal_uInt16 nPaint = PAINT_GRID;
SCCOL nStartX = aLocalParam.nCol1;
SCROW nStartY = aLocalParam.nRow1;
SCCOL nEndX = aLocalParam.nCol2;
SCROW nEndY = aLocalParam.nRow2;
2000-09-18 16:07:07 +00:00
if ( bRepeatQuery )
{
nPaint |= PAINT_LEFT;
nStartX = 0;
nEndX = MAXCOL;
}
if (pDestData)
{
if ( nEndX < aOldDest.aEnd.Col() )
nEndX = aOldDest.aEnd.Col();
if ( nEndY < aOldDest.aEnd.Row() )
nEndY = aOldDest.aEnd.Row();
}
rDocShell.PostPaint(ScRange(nStartX, nStartY, nTab, nEndX, nEndY, nTab), nPaint);
2000-09-18 16:07:07 +00:00
}
// AdjustRowHeight( aLocalParam.nRow1, aLocalParam.nRow2, bPaint );
2000-09-18 16:07:07 +00:00
rDocShell.AdjustRowHeight( aLocalParam.nRow1, aLocalParam.nRow2, nTab );
// #i59745# set collected drawing undo actions at sorting undo action
if( pUndoAction && pDrawLayer )
pUndoAction->SetDrawUndoAction( pDrawLayer->GetCalcUndo() );
2000-09-18 16:07:07 +00:00
aModificator.SetDocumentModified();
return sal_True;
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------
sal_Bool ScDBDocFunc::Query( SCTAB nTab, const ScQueryParam& rQueryParam,
const ScRange* pAdvSource, sal_Bool bRecord, sal_Bool bApi )
2000-09-18 16:07:07 +00:00
{
ScDocShellModificator aModificator( rDocShell );
ScDocument* pDoc = rDocShell.GetDocument();
if (bRecord && !pDoc->IsUndoEnabled())
bRecord = false;
2000-09-18 16:07:07 +00:00
ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rQueryParam.nCol1, rQueryParam.nRow1,
rQueryParam.nCol2, rQueryParam.nRow2 );
if (!pDBData)
{
2011-03-01 19:05:02 +01:00
OSL_FAIL( "Query: keine DBData" );
return false;
2000-09-18 16:07:07 +00:00
}
// Wechsel von Inplace auf nicht-Inplace, dann erst Inplace aufheben:
// (nur, wenn im Dialog "Persistent" ausgewaehlt ist)
if ( !rQueryParam.bInplace && pDBData->HasQueryParam() && rQueryParam.bDestPers )
{
ScQueryParam aOldQuery;
pDBData->GetQueryParam(aOldQuery);
if (aOldQuery.bInplace)
{
// alte Filterung aufheben
SCSIZE nEC = aOldQuery.GetEntryCount();
for (SCSIZE i=0; i<nEC; i++)
aOldQuery.GetEntry(i).bDoQuery = false;
aOldQuery.bDuplicate = sal_True;
2000-09-18 16:07:07 +00:00
Query( nTab, aOldQuery, NULL, bRecord, bApi );
}
}
ScQueryParam aLocalParam( rQueryParam ); // fuer Paint / Zielbereich
sal_Bool bCopy = !rQueryParam.bInplace; // kopiert wird in Table::Query
2000-09-18 16:07:07 +00:00
ScDBData* pDestData = NULL; // Bereich, in den kopiert wird
sal_Bool bDoSize = false; // Zielgroesse anpassen (einf./loeschen)
SCCOL nFormulaCols = 0; // nur bei bDoSize
sal_Bool bKeepFmt = false;
2000-09-18 16:07:07 +00:00
ScRange aOldDest;
ScRange aDestTotal;
if ( bCopy && rQueryParam.nDestCol == rQueryParam.nCol1 &&
rQueryParam.nDestRow == rQueryParam.nRow1 && rQueryParam.nDestTab == nTab )
bCopy = false;
SCTAB nDestTab = nTab;
2000-09-18 16:07:07 +00:00
if ( bCopy )
{
aLocalParam.MoveToDest();
nDestTab = rQueryParam.nDestTab;
if ( !ValidColRow( aLocalParam.nCol2, aLocalParam.nRow2 ) )
{
if (!bApi)
rDocShell.ErrorMessage(STR_PASTE_FULL);
return false;
}
2000-09-18 16:07:07 +00:00
ScEditableTester aTester( pDoc, nDestTab, aLocalParam.nCol1,aLocalParam.nRow1,
aLocalParam.nCol2,aLocalParam.nRow2);
if (!aTester.IsEditable())
2000-09-18 16:07:07 +00:00
{
if (!bApi)
rDocShell.ErrorMessage(aTester.GetMessageId());
return false;
2000-09-18 16:07:07 +00:00
}
pDestData = pDoc->GetDBAtCursor( rQueryParam.nDestCol, rQueryParam.nDestRow,
rQueryParam.nDestTab, sal_True );
2000-09-18 16:07:07 +00:00
if (pDestData)
{
pDestData->GetArea( aOldDest );
aDestTotal=ScRange( rQueryParam.nDestCol,
rQueryParam.nDestRow,
nDestTab,
rQueryParam.nDestCol + rQueryParam.nCol2 - rQueryParam.nCol1,
rQueryParam.nDestRow + rQueryParam.nRow2 - rQueryParam.nRow1,
nDestTab );
bDoSize = pDestData->IsDoSize();
// Test, ob Formeln aufgefuellt werden muessen (nFormulaCols):
if ( bDoSize && aOldDest.aEnd.Col() == aDestTotal.aEnd.Col() )
{
SCCOL nTestCol = aOldDest.aEnd.Col() + 1; // neben dem Bereich
SCROW nTestRow = rQueryParam.nDestRow +
2000-09-18 16:07:07 +00:00
( aLocalParam.bHasHeader ? 1 : 0 );
while ( nTestCol <= MAXCOL &&
pDoc->GetCellType(ScAddress( nTestCol, nTestRow, nTab )) == CELLTYPE_FORMULA )
++nTestCol, ++nFormulaCols;
}
bKeepFmt = pDestData->IsKeepFmt();
if ( bDoSize && !pDoc->CanFitBlock( aOldDest, aDestTotal ) )
{
if (!bApi)
rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2); // kann keine Zeilen einfuegen
return false;
2000-09-18 16:07:07 +00:00
}
}
}
// ausfuehren
WaitObject aWait( rDocShell.GetActiveDialogParent() );
2000-09-18 16:07:07 +00:00
sal_Bool bKeepSub = false; // bestehende Teilergebnisse wiederholen?
2000-09-18 16:07:07 +00:00
ScSubTotalParam aSubTotalParam;
if (rQueryParam.GetEntry(0).bDoQuery) // nicht beim Aufheben
{
pDBData->GetSubTotalParam( aSubTotalParam ); // Teilergebnisse vorhanden?
if ( aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly )
bKeepSub = sal_True;
2000-09-18 16:07:07 +00:00
}
ScDocument* pUndoDoc = NULL;
ScDBCollection* pUndoDB = NULL;
const ScRange* pOld = NULL;
2000-09-18 16:07:07 +00:00
if ( bRecord )
{
pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2000-09-18 16:07:07 +00:00
if (bCopy)
{
pUndoDoc->InitUndo( pDoc, nDestTab, nDestTab, false, sal_True );
2000-09-18 16:07:07 +00:00
pDoc->CopyToDocument( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
aLocalParam.nCol2, aLocalParam.nRow2, nDestTab,
IDF_ALL, false, pUndoDoc );
2000-09-18 16:07:07 +00:00
// Attribute sichern, falls beim Filtern mitkopiert
if (pDestData)
{
pDoc->CopyToDocument( aOldDest, IDF_ALL, false, pUndoDoc );
2000-09-18 16:07:07 +00:00
pOld = &aOldDest;
}
}
else
{
pUndoDoc->InitUndo( pDoc, nTab, nTab, false, sal_True );
2000-09-18 16:07:07 +00:00
pDoc->CopyToDocument( 0, rQueryParam.nRow1, nTab, MAXCOL, rQueryParam.nRow2, nTab,
IDF_NONE, false, pUndoDoc );
2000-09-18 16:07:07 +00:00
}
ScDBCollection* pDocDB = pDoc->GetDBCollection();
if (!pDocDB->empty())
2000-09-18 16:07:07 +00:00
pUndoDB = new ScDBCollection( *pDocDB );
pDoc->BeginDrawUndo();
2000-09-18 16:07:07 +00:00
}
ScDocument* pAttribDoc = NULL;
ScRange aAttribRange;
if (pDestData) // Zielbereich loeschen
{
if ( bKeepFmt )
{
// kleinere der End-Spalten, Header+1 Zeile
aAttribRange = aOldDest;
if ( aAttribRange.aEnd.Col() > aDestTotal.aEnd.Col() )
aAttribRange.aEnd.SetCol( aDestTotal.aEnd.Col() );
aAttribRange.aEnd.SetRow( aAttribRange.aStart.Row() +
( aLocalParam.bHasHeader ? 1 : 0 ) );
// auch fuer aufgefuellte Formeln
aAttribRange.aEnd.SetCol( aAttribRange.aEnd.Col() + nFormulaCols );
pAttribDoc = new ScDocument( SCDOCMODE_UNDO );
pAttribDoc->InitUndo( pDoc, nDestTab, nDestTab, false, sal_True );
pDoc->CopyToDocument( aAttribRange, IDF_ATTRIB, false, pAttribDoc );
2000-09-18 16:07:07 +00:00
}
if ( bDoSize )
pDoc->FitBlock( aOldDest, aDestTotal );
else
pDoc->DeleteAreaTab(aOldDest, IDF_ALL); // einfach loeschen
}
// Filtern am Dokument ausfuehren
SCSIZE nCount = pDoc->Query( nTab, rQueryParam, bKeepSub );
2000-09-18 16:07:07 +00:00
if (bCopy)
{
aLocalParam.nRow2 = aLocalParam.nRow1 + nCount;
if (!aLocalParam.bHasHeader && nCount > 0)
2000-09-18 16:07:07 +00:00
--aLocalParam.nRow2;
if ( bDoSize )
{
// auf wirklichen Ergebnis-Bereich anpassen
// (das hier ist immer eine Verkleinerung)
ScRange aNewDest( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
aLocalParam.nCol2, aLocalParam.nRow2, nDestTab );
pDoc->FitBlock( aDestTotal, aNewDest, false ); // sal_False - nicht loeschen
2000-09-18 16:07:07 +00:00
if ( nFormulaCols > 0 )
2000-09-18 16:07:07 +00:00
{
// Formeln ausfuellen
//! Undo (Query und Repeat) !!!
ScRange aNewForm( aLocalParam.nCol2+1, aLocalParam.nRow1, nDestTab,
aLocalParam.nCol2+nFormulaCols, aLocalParam.nRow2, nDestTab );
ScRange aOldForm = aNewForm;
aOldForm.aEnd.SetRow( aOldDest.aEnd.Row() );
pDoc->FitBlock( aOldForm, aNewForm, false );
2000-09-18 16:07:07 +00:00
ScMarkData aMark;
aMark.SelectOneTable(nDestTab);
SCROW nFStartY = aLocalParam.nRow1 + ( aLocalParam.bHasHeader ? 1 : 0 );
sal_uLong nProgCount = nFormulaCols;
nProgCount *= aLocalParam.nRow2 - nFStartY;
ScProgress aProgress( pDoc->GetDocumentShell(),
ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
2000-09-18 16:07:07 +00:00
pDoc->Fill( aLocalParam.nCol2+1, nFStartY,
aLocalParam.nCol2+nFormulaCols, nFStartY, &aProgress, aMark,
2000-09-18 16:07:07 +00:00
aLocalParam.nRow2 - nFStartY,
FILL_TO_BOTTOM, FILL_SIMPLE );
}
}
if ( pAttribDoc ) // gemerkte Attribute zurueckkopieren
{
// Header
if (aLocalParam.bHasHeader)
{
ScRange aHdrRange = aAttribRange;
aHdrRange.aEnd.SetRow( aHdrRange.aStart.Row() );
pAttribDoc->CopyToDocument( aHdrRange, IDF_ATTRIB, false, pDoc );
2000-09-18 16:07:07 +00:00
}
// Daten
SCCOL nAttrEndCol = aAttribRange.aEnd.Col();
SCROW nAttrRow = aAttribRange.aStart.Row() + ( aLocalParam.bHasHeader ? 1 : 0 );
for (SCCOL nCol = aAttribRange.aStart.Col(); nCol<=nAttrEndCol; nCol++)
2000-09-18 16:07:07 +00:00
{
const ScPatternAttr* pSrcPattern = pAttribDoc->GetPattern(
nCol, nAttrRow, nDestTab );
OSL_ENSURE(pSrcPattern,"Pattern ist 0");
2000-09-18 16:07:07 +00:00
if (pSrcPattern)
2011-02-05 23:59:52 +01:00
{
2000-09-18 16:07:07 +00:00
pDoc->ApplyPatternAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
nDestTab, *pSrcPattern );
2011-02-05 23:59:52 +01:00
const ScStyleSheet* pStyle = pSrcPattern->GetStyleSheet();
if (pStyle)
pDoc->ApplyStyleAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
2000-09-18 16:07:07 +00:00
nDestTab, *pStyle );
2011-02-05 23:59:52 +01:00
}
2000-09-18 16:07:07 +00:00
}
delete pAttribDoc;
}
}
// speichern: Inplace immer, sonst je nach Einstellung
// alter Inplace-Filter ist ggf. schon aufgehoben
sal_Bool bSave = rQueryParam.bInplace || rQueryParam.bDestPers;
2000-09-18 16:07:07 +00:00
if (bSave) // merken
{
pDBData->SetQueryParam( rQueryParam );
pDBData->SetHeader( rQueryParam.bHasHeader ); //! ???
pDBData->SetAdvancedQuerySource( pAdvSource ); // after SetQueryParam
}
if (bCopy) // neuen DB-Bereich merken
{
// selektieren wird hinterher von aussen (dbfunc)
// momentan ueber DB-Bereich an der Zielposition, darum muss dort
// auf jeden Fall ein Bereich angelegt werden.
ScDBData* pNewData;
if (pDestData)
pNewData = pDestData; // Bereich vorhanden -> anpassen (immer!)
else // Bereich anlegen
pNewData = rDocShell.GetDBData(
ScRange( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
aLocalParam.nCol2, aLocalParam.nRow2, nDestTab ),
SC_DB_MAKE, SC_DBSEL_FORCE_MARK );
2000-09-18 16:07:07 +00:00
if (pNewData)
{
pNewData->SetArea( nDestTab, aLocalParam.nCol1, aLocalParam.nRow1,
aLocalParam.nCol2, aLocalParam.nRow2 );
// Query-Param wird am Ziel nicht mehr eingestellt, fuehrt nur zu Verwirrung
// und Verwechslung mit dem Query-Param am Quellbereich (#37187#)
}
else
{
2011-03-01 19:05:02 +01:00
OSL_FAIL("Zielbereich nicht da");
}
2000-09-18 16:07:07 +00:00
}
if (!bCopy)
{
pDoc->InvalidatePageBreaks(nTab);
2000-09-18 16:07:07 +00:00
pDoc->UpdatePageBreaks( nTab );
}
2000-09-18 16:07:07 +00:00
// #i23299# Subtotal functions depend on cell's filtered states.
ScRange aDirtyRange(0 , aLocalParam.nRow1, nDestTab, MAXCOL, aLocalParam.nRow2, nDestTab);
pDoc->SetSubTotalCellsDirty(aDirtyRange);
2000-09-18 16:07:07 +00:00
if ( bRecord )
{
// create undo action after executing, because of drawing layer undo
rDocShell.GetUndoManager()->AddUndoAction(
new ScUndoQuery( &rDocShell, nTab, rQueryParam, pUndoDoc, pUndoDB,
pOld, bDoSize, pAdvSource ) );
}
2000-09-18 16:07:07 +00:00
if (bCopy)
{
SCCOL nEndX = aLocalParam.nCol2;
SCROW nEndY = aLocalParam.nRow2;
2000-09-18 16:07:07 +00:00
if (pDestData)
{
if ( aOldDest.aEnd.Col() > nEndX )
nEndX = aOldDest.aEnd.Col();
if ( aOldDest.aEnd.Row() > nEndY )
nEndY = aOldDest.aEnd.Row();
}
if (bDoSize)
nEndY = MAXROW;
rDocShell.PostPaint(
ScRange(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab, nEndX, nEndY, nDestTab),
PAINT_GRID);
2000-09-18 16:07:07 +00:00
}
else
rDocShell.PostPaint(
ScRange(0, rQueryParam.nRow1, nTab, MAXCOL, MAXROW, nTab),
PAINT_GRID | PAINT_LEFT);
2000-09-18 16:07:07 +00:00
aModificator.SetDocumentModified();
return sal_True;
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------
sal_Bool ScDBDocFunc::DoSubTotals( SCTAB nTab, const ScSubTotalParam& rParam,
const ScSortParam* pForceNewSort, sal_Bool bRecord, sal_Bool bApi )
2000-09-18 16:07:07 +00:00
{
//! auch fuer ScDBFunc::DoSubTotals benutzen!
// dann bleibt aussen:
// - neuen Bereich (aus DBData) markieren
// - SelectionChanged (?)
sal_Bool bDo = !rParam.bRemoveOnly; // sal_False = nur loeschen
sal_Bool bRet = false;
2000-09-18 16:07:07 +00:00
ScDocument* pDoc = rDocShell.GetDocument();
if (bRecord && !pDoc->IsUndoEnabled())
bRecord = false;
2000-09-18 16:07:07 +00:00
ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1,
rParam.nCol2, rParam.nRow2 );
if (!pDBData)
{
2011-03-01 19:05:02 +01:00
OSL_FAIL( "SubTotals: keine DBData" );
return false;
2000-09-18 16:07:07 +00:00
}
ScEditableTester aTester( pDoc, nTab, 0,rParam.nRow1+1, MAXCOL,MAXROW );
if (!aTester.IsEditable())
2000-09-18 16:07:07 +00:00
{
if (!bApi)
rDocShell.ErrorMessage(aTester.GetMessageId());
return false;
2000-09-18 16:07:07 +00:00
}
if (pDoc->HasAttrib( rParam.nCol1, rParam.nRow1+1, nTab,
rParam.nCol2, rParam.nRow2, nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ))
{
if (!bApi)
rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); // nicht in zusammengefasste einfuegen
return false;
2000-09-18 16:07:07 +00:00
}
sal_Bool bOk = true;
2000-09-18 16:07:07 +00:00
if (rParam.bReplace)
if (pDoc->TestRemoveSubTotals( nTab, rParam ))
{
bOk = ( MessBox( rDocShell.GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
2000-09-18 16:07:07 +00:00
// "StarCalc" "Daten loeschen?"
ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ),
ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_1 ) ).Execute()
== RET_YES );
}
if (bOk)
{
WaitObject aWait( rDocShell.GetActiveDialogParent() );
2000-09-18 16:07:07 +00:00
ScDocShellModificator aModificator( rDocShell );
ScSubTotalParam aNewParam( rParam ); // Bereichsende wird veraendert
ScDocument* pUndoDoc = NULL;
ScOutlineTable* pUndoTab = NULL;
ScRangeName* pUndoRange = NULL;
ScDBCollection* pUndoDB = NULL;
if (bRecord) // alte Daten sichern
{
sal_Bool bOldFilter = bDo && rParam.bDoSort;
2000-09-18 16:07:07 +00:00
SCTAB nTabCount = pDoc->GetTableCount();
2000-09-18 16:07:07 +00:00
pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
if (pTable)
{
pUndoTab = new ScOutlineTable( *pTable );
// column/row state
SCCOLROW nOutStartCol, nOutEndCol;
SCCOLROW nOutStartRow, nOutEndRow;
2000-09-18 16:07:07 +00:00
pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol );
pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow );
pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True );
pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab, IDF_NONE, false, pUndoDoc );
pDoc->CopyToDocument( 0, nOutStartRow, nTab, MAXCOL, nOutEndRow, nTab, IDF_NONE, false, pUndoDoc );
2000-09-18 16:07:07 +00:00
}
else
pUndoDoc->InitUndo( pDoc, nTab, nTab, false, bOldFilter );
2000-09-18 16:07:07 +00:00
// Datenbereich sichern - incl. Filter-Ergebnis
pDoc->CopyToDocument( 0,rParam.nRow1+1,nTab, MAXCOL,rParam.nRow2,nTab,
IDF_ALL, false, pUndoDoc );
2000-09-18 16:07:07 +00:00
// alle Formeln wegen Referenzen
pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
IDF_FORMULA, false, pUndoDoc );
2000-09-18 16:07:07 +00:00
// DB- und andere Bereiche
ScRangeName* pDocRange = pDoc->GetRangeName();
if (!pDocRange->empty())
2000-09-18 16:07:07 +00:00
pUndoRange = new ScRangeName( *pDocRange );
ScDBCollection* pDocDB = pDoc->GetDBCollection();
if (!pDocDB->empty())
2000-09-18 16:07:07 +00:00
pUndoDB = new ScDBCollection( *pDocDB );
}
// pDoc->SetOutlineTable( nTab, NULL );
ScOutlineTable* pOut = pDoc->GetOutlineTable( nTab );
if (pOut)
pOut->GetRowArray()->RemoveAll(); // nur Zeilen-Outlines loeschen
if (rParam.bReplace)
pDoc->RemoveSubTotals( nTab, aNewParam );
sal_Bool bSuccess = sal_True;
2000-09-18 16:07:07 +00:00
if (bDo)
{
// Sortieren
if ( rParam.bDoSort || pForceNewSort )
{
pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
// Teilergebnis-Felder vor die Sortierung setzen
// (doppelte werden weggelassen, kann darum auch wieder aufgerufen werden)
ScSortParam aOldSort;
pDBData->GetSortParam( aOldSort );
ScSortParam aSortParam( aNewParam, pForceNewSort ? *pForceNewSort : aOldSort );
Sort( nTab, aSortParam, false, false, bApi );
2000-09-18 16:07:07 +00:00
}
pDoc->InitializeNoteCaptions(nTab);
2000-09-18 16:07:07 +00:00
bSuccess = pDoc->DoSubTotals( nTab, aNewParam );
pDoc->SetDrawPageSize(nTab);
2000-09-18 16:07:07 +00:00
}
ScRange aDirtyRange( aNewParam.nCol1, aNewParam.nRow1, nTab,
aNewParam.nCol2, aNewParam.nRow2, nTab );
pDoc->SetDirty( aDirtyRange );
if (bRecord)
{
// ScDBData* pUndoDBData = pDBData ? new ScDBData( *pDBData ) : NULL;
rDocShell.GetUndoManager()->AddUndoAction(
new ScUndoSubTotals( &rDocShell, nTab,
rParam, aNewParam.nRow2,
pUndoDoc, pUndoTab, // pUndoDBData,
pUndoRange, pUndoDB ) );
}
if (!bSuccess)
{
// "Kann keine Zeilen einfuegen"
if (!bApi)
rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2);
}
// merken
pDBData->SetSubTotalParam( aNewParam );
pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
pDoc->CompileDBFormula();
rDocShell.PostPaint(ScRange(0, 0, nTab, MAXCOL,MAXROW,nTab),
PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE);
2000-09-18 16:07:07 +00:00
aModificator.SetDocumentModified();
bRet = bSuccess;
}
return bRet;
}
namespace {
2000-09-18 16:07:07 +00:00
bool lcl_EmptyExcept( ScDocument* pDoc, const ScRange& rRange, const ScRange& rExcept )
{
ScCellIterator aIter( pDoc, rRange );
for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
{
if (!aIter.isEmpty()) // real content?
{
if (!rExcept.In(aIter.GetPos()))
return false; // cell found
}
}
return true; // nothing found - empty
}
bool isEditable(ScDocShell& rDocShell, const ScRangeList& rRanges, bool bApi)
{
ScDocument* pDoc = rDocShell.GetDocument();
if (!rDocShell.IsEditable() || pDoc->GetChangeTrack())
{
// not recorded -> disallow
if (!bApi)
rDocShell.ErrorMessage(STR_PROTECTIONERR);
return false;
}
for (size_t i = 0, n = rRanges.size(); i < n; ++i)
{
const ScRange* p = rRanges[i];
ScEditableTester aTester(pDoc, *p);
if (!aTester.IsEditable())
{
if (!bApi)
rDocShell.ErrorMessage(aTester.GetMessageId());
return false;
}
}
return true;
}
SAL_WNODEPRECATED_DECLARATIONS_PUSH
void createUndoDoc(std::auto_ptr<ScDocument>& pUndoDoc, ScDocument* pDoc, const ScRange& rRange)
{
SCTAB nTab = rRange.aStart.Tab();
pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
pUndoDoc->InitUndo(pDoc, nTab, nTab);
pDoc->CopyToDocument(rRange, IDF_ALL, false, pUndoDoc.get());
}
SAL_WNODEPRECATED_DECLARATIONS_POP
bool checkNewOutputRange(ScDPObject& rDPObj, ScDocShell& rDocShell, ScRange& rNewOut, bool bApi)
{
ScDocument* pDoc = rDocShell.GetDocument();
bool bOverflow = false;
rNewOut = rDPObj.GetNewOutputRange(bOverflow);
// Test for overlap with source data range.
// TODO: Check with other pivot tables as well.
const ScSheetSourceDesc* pSheetDesc = rDPObj.GetSheetDesc();
if (pSheetDesc && pSheetDesc->GetSourceRange().Intersects(rNewOut))
{
// New output range intersepts with the source data. Move it up to
// where the old range is and see if that works.
ScRange aOldRange = rDPObj.GetOutRange();
SCsROW nDiff = aOldRange.aStart.Row() - rNewOut.aStart.Row();
rNewOut.aStart.SetRow(aOldRange.aStart.Row());
rNewOut.aEnd.IncRow(nDiff);
if (!ValidRow(rNewOut.aStart.Row()) || !ValidRow(rNewOut.aEnd.Row()))
bOverflow = true;
}
if (bOverflow)
{
if (!bApi)
rDocShell.ErrorMessage(STR_PIVOT_ERROR);
return false;
}
ScEditableTester aTester(pDoc, rNewOut);
if (!aTester.IsEditable())
{
// destination area isn't editable
if (!bApi)
rDocShell.ErrorMessage(aTester.GetMessageId());
return false;
}
return true;
}
}
2012-03-13 11:41:20 -04:00
bool ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewObj,
bool bRecord, bool bApi, bool bAllowMove )
2000-09-18 16:07:07 +00:00
{
if (!pOldObj)
{
if (!pNewObj)
return false;
return CreatePivotTable(*pNewObj, bRecord, bApi);
}
if (pOldObj)
{
if (!pNewObj)
return RemovePivotTable(*pOldObj, bRecord, bApi);
if (pOldObj == pNewObj)
return UpdatePivotTable(*pOldObj, bRecord, bApi);
}
OSL_ASSERT(pOldObj && pNewObj && pOldObj != pNewObj);
2000-09-18 16:07:07 +00:00
ScDocShellModificator aModificator( rDocShell );
WaitObject aWait( rDocShell.GetActiveDialogParent() );
2000-09-18 16:07:07 +00:00
ScRangeList aRanges;
aRanges.Append(pOldObj->GetOutRange());
aRanges.Append(pNewObj->GetOutRange().aStart); // at least one cell in the output position must be editable.
if (!isEditable(rDocShell, aRanges, bApi))
return false;
SAL_WNODEPRECATED_DECLARATIONS_PUSH
std::auto_ptr<ScDocument> pOldUndoDoc;
std::auto_ptr<ScDocument> pNewUndoDoc;
SAL_WNODEPRECATED_DECLARATIONS_POP
2000-09-18 16:07:07 +00:00
ScDPObject aUndoDPObj(*pOldObj); // for undo or revert on failure
2000-09-18 16:07:07 +00:00
ScDocument* pDoc = rDocShell.GetDocument();
if (bRecord && !pDoc->IsUndoEnabled())
bRecord = false;
2000-09-18 16:07:07 +00:00
if (bRecord)
createUndoDoc(pOldUndoDoc, pDoc, pOldObj->GetOutRange());
2000-09-18 16:07:07 +00:00
pNewObj->WriteSourceDataTo(*pOldObj); // copy source data
2000-09-18 16:07:07 +00:00
ScDPSaveData* pData = pNewObj->GetSaveData();
OSL_ENSURE( pData, "no SaveData from living DPObject" );
if (pData)
pOldObj->SetSaveData(*pData); // copy SaveData
2000-09-18 16:07:07 +00:00
pOldObj->SetAllowMove(bAllowMove);
pOldObj->ReloadGroupTableData();
pOldObj->SyncAllDimensionMembers();
pOldObj->InvalidateData(); // before getting the new output area
2000-09-18 16:07:07 +00:00
// make sure the table has a name (not set by dialog)
if (pOldObj->GetName().isEmpty())
pOldObj->SetName( pDoc->GetDPCollection()->CreateNewName() );
2000-09-18 16:07:07 +00:00
ScRange aNewOut;
if (!checkNewOutputRange(*pOldObj, rDocShell, aNewOut, bApi))
{
*pOldObj = aUndoDPObj;
return false;
}
// test if new output area is empty except for old area
if (!bApi)
2000-09-18 16:07:07 +00:00
{
// OutRange of pOldObj (pDestObj) is still old area
if (!lcl_EmptyExcept(pDoc, aNewOut, pOldObj->GetOutRange()))
2000-09-18 16:07:07 +00:00
{
QueryBox aBox( rDocShell.GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
ScGlobal::GetRscString(STR_PIVOT_NOTEMPTY) );
if (aBox.Execute() == RET_NO)
{
//! like above (not editable)
*pOldObj = aUndoDPObj;
return false;
}
2000-09-18 16:07:07 +00:00
}
}
if (bRecord)
createUndoDoc(pNewUndoDoc, pDoc, aNewOut);
2000-09-18 16:07:07 +00:00
pOldObj->Output(aNewOut.aStart);
rDocShell.PostPaintGridAll(); //! only necessary parts
if (bRecord)
{
rDocShell.GetUndoManager()->AddUndoAction(
new ScUndoDataPilot(
&rDocShell, pOldUndoDoc.release(), pNewUndoDoc.release(), &aUndoDPObj, pOldObj, bAllowMove));
}
2000-09-18 16:07:07 +00:00
// notify API objects
pDoc->BroadcastUno( ScDataPilotModifiedHint(pOldObj->GetName()) );
aModificator.SetDocumentModified();
2000-09-18 16:07:07 +00:00
return true;
2000-09-18 16:07:07 +00:00
}
bool ScDBDocFunc::RemovePivotTable(ScDPObject& rDPObj, bool bRecord, bool bApi)
{
ScDocShellModificator aModificator(rDocShell);
WaitObject aWait(rDocShell.GetActiveDialogParent());
if (!isEditable(rDocShell, rDPObj.GetOutRange(), bApi))
return false;
SAL_WNODEPRECATED_DECLARATIONS_PUSH
std::auto_ptr<ScDocument> pOldUndoDoc;
std::auto_ptr<ScDPObject> pUndoDPObj;
SAL_WNODEPRECATED_DECLARATIONS_POP
if (bRecord)
pUndoDPObj.reset(new ScDPObject(rDPObj)); // copy old settings for undo
ScDocument* pDoc = rDocShell.GetDocument();
if (bRecord && !pDoc->IsUndoEnabled())
bRecord = false;
// delete table
ScRange aRange = rDPObj.GetOutRange();
SCTAB nTab = aRange.aStart.Tab();
if (bRecord)
createUndoDoc(pOldUndoDoc, pDoc, aRange);
pDoc->DeleteAreaTab( aRange.aStart.Col(), aRange.aStart.Row(),
aRange.aEnd.Col(), aRange.aEnd.Row(),
nTab, IDF_ALL );
pDoc->RemoveFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(),
aRange.aEnd.Col(), aRange.aEnd.Row(),
nTab, SC_MF_AUTO );
pDoc->GetDPCollection()->FreeTable(&rDPObj); // object is deleted here
rDocShell.PostPaintGridAll(); //! only necessary parts
rDocShell.PostPaint(aRange, PAINT_GRID);
if (bRecord)
{
rDocShell.GetUndoManager()->AddUndoAction(
new ScUndoDataPilot(
&rDocShell, pOldUndoDoc.release(), NULL, pUndoDPObj.get(), NULL, false));
// pUndoDPObj is copied
}
aModificator.SetDocumentModified();
return true;
}
bool ScDBDocFunc::CreatePivotTable(const ScDPObject& rDPObj, bool bRecord, bool bApi)
{
ScDocShellModificator aModificator(rDocShell);
WaitObject aWait(rDocShell.GetActiveDialogParent());
// At least one cell in the output range should be editable. Check in advance.
if (!isEditable(rDocShell, ScRange(rDPObj.GetOutRange().aStart), bApi))
return false;
SAL_WNODEPRECATED_DECLARATIONS_PUSH
std::auto_ptr<ScDocument> pNewUndoDoc;
SAL_WNODEPRECATED_DECLARATIONS_POP
ScDocument* pDoc = rDocShell.GetDocument();
if (bRecord && !pDoc->IsUndoEnabled())
bRecord = false;
// output range must be set at pNewObj
SAL_WNODEPRECATED_DECLARATIONS_PUSH
std::auto_ptr<ScDPObject> pDestObj(new ScDPObject(rDPObj));
SAL_WNODEPRECATED_DECLARATIONS_POP
ScDPObject& rDestObj = *pDestObj;
// #i94570# When changing the output position in the dialog, a new table is created
// with the settings from the old table, including the name.
// So we have to check for duplicate names here (before inserting).
if (pDoc->GetDPCollection()->GetByName(rDestObj.GetName()))
rDestObj.SetName(OUString()); // ignore the invalid name, create a new name below
if (!pDoc->GetDPCollection()->InsertNewTable(pDestObj.release()))
// Insertion into collection failed.
return false;
rDestObj.ReloadGroupTableData();
rDestObj.SyncAllDimensionMembers();
rDestObj.InvalidateData(); // before getting the new output area
// make sure the table has a name (not set by dialog)
if (rDestObj.GetName().isEmpty())
rDestObj.SetName(pDoc->GetDPCollection()->CreateNewName());
bool bOverflow = false;
ScRange aNewOut = rDestObj.GetNewOutputRange(bOverflow);
if (bOverflow)
{
if (!bApi)
rDocShell.ErrorMessage(STR_PIVOT_ERROR);
return false;
}
{
ScEditableTester aTester(pDoc, aNewOut);
if (!aTester.IsEditable())
{
// destination area isn't editable
if (!bApi)
rDocShell.ErrorMessage(aTester.GetMessageId());
return false;
}
}
// test if new output area is empty except for old area
if (!bApi)
{
bool bEmpty = pDoc->IsBlockEmpty(
aNewOut.aStart.Tab(), aNewOut.aStart.Col(), aNewOut.aStart.Row(),
aNewOut.aEnd.Col(), aNewOut.aEnd.Row());
if (!bEmpty)
{
QueryBox aBox(
rDocShell.GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
ScGlobal::GetRscString(STR_PIVOT_NOTEMPTY));
if (aBox.Execute() == RET_NO)
{
//! like above (not editable)
return false;
}
}
}
if (bRecord)
createUndoDoc(pNewUndoDoc, pDoc, aNewOut);
rDestObj.Output(aNewOut.aStart);
rDocShell.PostPaintGridAll(); //! only necessary parts
if (bRecord)
{
rDocShell.GetUndoManager()->AddUndoAction(
new ScUndoDataPilot(&rDocShell, NULL, pNewUndoDoc.release(), NULL, &rDestObj, false));
}
// notify API objects
pDoc->BroadcastUno(ScDataPilotModifiedHint(rDestObj.GetName()));
aModificator.SetDocumentModified();
return true;
}
bool ScDBDocFunc::UpdatePivotTable(ScDPObject& rDPObj, bool bRecord, bool bApi)
{
ScDocShellModificator aModificator( rDocShell );
WaitObject aWait( rDocShell.GetActiveDialogParent() );
if (!isEditable(rDocShell, rDPObj.GetOutRange(), bApi))
return false;
SAL_WNODEPRECATED_DECLARATIONS_PUSH
std::auto_ptr<ScDocument> pOldUndoDoc;
std::auto_ptr<ScDocument> pNewUndoDoc;
SAL_WNODEPRECATED_DECLARATIONS_POP
ScDPObject aUndoDPObj(rDPObj); // For undo or revert on failure.
ScDocument* pDoc = rDocShell.GetDocument();
if (bRecord && !pDoc->IsUndoEnabled())
bRecord = false;
if (bRecord)
createUndoDoc(pOldUndoDoc, pDoc, rDPObj.GetOutRange());
rDPObj.SetAllowMove(false);
rDPObj.ReloadGroupTableData();
if (!rDPObj.SyncAllDimensionMembers())
return false;
rDPObj.InvalidateData(); // before getting the new output area
// make sure the table has a name (not set by dialog)
if (rDPObj.GetName().isEmpty())
rDPObj.SetName( pDoc->GetDPCollection()->CreateNewName() );
ScRange aNewOut;
if (!checkNewOutputRange(rDPObj, rDocShell, aNewOut, bApi))
{
rDPObj = aUndoDPObj;
return false;
}
// test if new output area is empty except for old area
if (!bApi)
{
if (!lcl_EmptyExcept(pDoc, aNewOut, rDPObj.GetOutRange()))
{
QueryBox aBox( rDocShell.GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
ScGlobal::GetRscString(STR_PIVOT_NOTEMPTY) );
if (aBox.Execute() == RET_NO)
{
rDPObj = aUndoDPObj;
return false;
}
}
}
if (bRecord)
createUndoDoc(pNewUndoDoc, pDoc, aNewOut);
rDPObj.Output(aNewOut.aStart);
rDocShell.PostPaintGridAll(); //! only necessary parts
if (bRecord)
{
rDocShell.GetUndoManager()->AddUndoAction(
new ScUndoDataPilot(
&rDocShell, pOldUndoDoc.release(), pNewUndoDoc.release(), &aUndoDPObj, &rDPObj, false));
}
// notify API objects
pDoc->BroadcastUno( ScDataPilotModifiedHint(rDPObj.GetName()) );
aModificator.SetDocumentModified();
return true;
}
sal_uLong ScDBDocFunc::RefreshPivotTables(ScDPObject* pDPObj, bool bApi)
{
ScDPCollection* pDPs = rDocShell.GetDocument()->GetDPCollection();
if (!pDPs)
return 0;
std::set<ScDPObject*> aRefs;
sal_uLong nErrId = pDPs->ReloadCache(pDPObj, aRefs);
if (nErrId)
return nErrId;
std::set<ScDPObject*>::iterator it = aRefs.begin(), itEnd = aRefs.end();
for (; it != itEnd; ++it)
{
ScDPObject* pObj = *it;
// This action is intentionally not undoable since it modifies cache.
UpdatePivotTable(*pObj, false, bApi);
}
return 0;
}
void ScDBDocFunc::RefreshPivotTableGroups(ScDPObject* pDPObj)
{
if (!pDPObj)
return;
ScDPCollection* pDPs = rDocShell.GetDocument()->GetDPCollection();
if (!pDPs)
return;
ScDPSaveData* pSaveData = pDPObj->GetSaveData();
if (!pSaveData)
return;
std::set<ScDPObject*> aRefs;
if (!pDPs->ReloadGroupsInCache(pDPObj, aRefs))
return;
// We allow pDimData being NULL.
const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData();
std::set<ScDPObject*>::iterator it = aRefs.begin(), itEnd = aRefs.end();
for (; it != itEnd; ++it)
{
ScDPObject* pObj = *it;
if (pObj != pDPObj)
{
pSaveData = pObj->GetSaveData();
if (pSaveData)
pSaveData->SetDimensionData(pDimData);
}
// This action is intentionally not undoable since it modifies cache.
UpdatePivotTable(*pObj, false, false);
}
}
2000-09-18 16:07:07 +00:00
//==================================================================
//
// database import
2000-09-18 16:07:07 +00:00
void ScDBDocFunc::UpdateImport( const OUString& rTarget, const svx::ODataAccessDescriptor& rDescriptor )
2000-09-18 16:07:07 +00:00
{
// rTarget is the name of a database range
2000-09-18 16:07:07 +00:00
ScDocument* pDoc = rDocShell.GetDocument();
ScDBCollection& rDBColl = *pDoc->GetDBCollection();
const ScDBData* pData = rDBColl.getNamedDBs().findByUpperName(ScGlobal::pCharClass->uppercase(rTarget));
if (!pData)
2000-09-18 16:07:07 +00:00
{
InfoBox aInfoBox(rDocShell.GetActiveDialogParent(),
2000-09-18 16:07:07 +00:00
ScGlobal::GetRscString( STR_TARGETNOTFOUND ) );
aInfoBox.Execute();
return;
}
SCTAB nTab;
SCCOL nDummyCol;
SCROW nDummyRow;
pData->GetArea( nTab, nDummyCol,nDummyRow,nDummyCol,nDummyRow );
ScImportParam aImportParam;
2000-09-18 16:07:07 +00:00
pData->GetImportParam( aImportParam );
OUString sDBName;
OUString sDBTable;
sal_Int32 nCommandType = 0;
sDBName = rDescriptor.getDataSource();
rDescriptor[svx::daCommand] >>= sDBTable;
rDescriptor[svx::daCommandType] >>= nCommandType;
aImportParam.aDBName = sDBName;
aImportParam.bSql = ( nCommandType == sdb::CommandType::COMMAND );
aImportParam.aStatement = sDBTable;
aImportParam.bNative = false;
aImportParam.nType = static_cast<sal_uInt8>( ( nCommandType == sdb::CommandType::QUERY ) ? ScDbQuery : ScDbTable );
2011-05-10 11:57:13 -04:00
aImportParam.bImport = true;
bool bContinue = DoImport( nTab, aImportParam, &rDescriptor, true );
2000-09-18 16:07:07 +00:00
// DB-Operationen wiederholen
ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
if (pViewSh)
{
ScRange aRange;
pData->GetArea(aRange);
pViewSh->MarkRange(aRange); // selektieren
2011-03-01 14:29:24 +01:00
if ( bContinue ) // Fehler beim Import -> Abbruch
2000-09-18 16:07:07 +00:00
{
// interne Operationen, wenn welche gespeichert
if ( pData->HasQueryParam() || pData->HasSortParam() || pData->HasSubTotalParam() )
pViewSh->RepeatDB();
// Pivottabellen die den Bereich als Quelldaten haben
rDocShell.RefreshPivotTables(aRange);
}
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */