2000-09-18 16:07:07 +00:00
|
|
|
/*************************************************************************
|
|
|
|
*
|
|
|
|
* $RCSfile: dbdocfun.cxx,v $
|
|
|
|
*
|
2004-06-04 10:22:36 +00:00
|
|
|
* $Revision: 1.11 $
|
2000-09-18 16:07:07 +00:00
|
|
|
*
|
2004-06-04 10:22:36 +00:00
|
|
|
* last change: $Author: obo $ $Date: 2004-06-04 11:22:36 $
|
2000-09-18 16:07:07 +00:00
|
|
|
*
|
|
|
|
* The Contents of this file are made available subject to the terms of
|
|
|
|
* either of the following licenses
|
|
|
|
*
|
|
|
|
* - GNU Lesser General Public License Version 2.1
|
|
|
|
* - Sun Industry Standards Source License Version 1.1
|
|
|
|
*
|
|
|
|
* Sun Microsystems Inc., October, 2000
|
|
|
|
*
|
|
|
|
* GNU Lesser General Public License Version 2.1
|
|
|
|
* =============================================
|
|
|
|
* Copyright 2000 by Sun Microsystems, Inc.
|
|
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
|
|
* MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Sun Industry Standards Source License Version 1.1
|
|
|
|
* =================================================
|
|
|
|
* The contents of this file are subject to the Sun Industry Standards
|
|
|
|
* Source License Version 1.1 (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.openoffice.org/license.html.
|
|
|
|
*
|
|
|
|
* Software provided under this License is provided on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
|
|
|
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
|
|
|
|
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
|
|
|
|
* See the License for the specific provisions governing your rights and
|
|
|
|
* obligations concerning the Software.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
|
|
|
|
*
|
|
|
|
* Copyright: 2000 by Sun Microsystems, Inc.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s): _______________________________________
|
|
|
|
*
|
|
|
|
*
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
#ifdef PCH
|
|
|
|
#include "ui_pch.hxx"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#pragma hdrstop
|
|
|
|
|
|
|
|
// INCLUDE ---------------------------------------------------------------
|
|
|
|
|
|
|
|
#include <sfx2/app.hxx>
|
|
|
|
#include <vcl/msgbox.hxx>
|
|
|
|
#include <vcl/waitobj.hxx>
|
|
|
|
|
2002-08-08 12:05:31 +00:00
|
|
|
#include <com/sun/star/sdbc/XResultSet.hpp>
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
#include "dbdocfun.hxx"
|
|
|
|
#include "sc.hrc"
|
|
|
|
#include "dbcolect.hxx"
|
|
|
|
#include "undodat.hxx"
|
|
|
|
#include "docsh.hxx"
|
|
|
|
#include "docfunc.hxx"
|
|
|
|
#include "globstr.hrc"
|
|
|
|
#include "tabvwsh.hxx"
|
|
|
|
#include "patattr.hxx"
|
|
|
|
#include "rangenam.hxx"
|
|
|
|
#include "olinetab.hxx"
|
|
|
|
#include "dpobject.hxx"
|
2001-01-25 18:38:12 +00:00
|
|
|
#include "dociter.hxx" // for lcl_EmptyExcept
|
|
|
|
#include "cell.hxx" // for lcl_EmptyExcept
|
2002-11-20 13:36:29 +00:00
|
|
|
#include "editable.hxx"
|
2004-04-13 11:30:54 +00:00
|
|
|
#include "attrib.hxx"
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
|
|
|
|
|
|
BOOL ScDBDocFunc::AddDBRange( const String& rName, const ScRange& rRange, BOOL bApi )
|
|
|
|
{
|
2001-02-14 14:34:08 +00:00
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
ScDocShellModificator aModificator( rDocShell );
|
|
|
|
|
|
|
|
ScDocument* pDoc = rDocShell.GetDocument();
|
|
|
|
ScDBCollection* pDocColl = pDoc->GetDBCollection();
|
2001-02-14 14:34:08 +00:00
|
|
|
BOOL bUndo (pDoc->IsUndoEnabled());
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2001-02-14 14:34:08 +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() );
|
|
|
|
|
|
|
|
pDoc->CompileDBFormula( TRUE ); // CreateFormulaString
|
|
|
|
BOOL bOk = pDocColl->Insert( pNew );
|
|
|
|
pDoc->CompileDBFormula( FALSE ); // CompileFormulaString
|
|
|
|
if (!bOk)
|
|
|
|
{
|
|
|
|
delete pNew;
|
|
|
|
delete pUndoColl;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2001-02-14 14:34:08 +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;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScDBDocFunc::DeleteDBRange( const String& rName, BOOL bApi )
|
|
|
|
{
|
|
|
|
BOOL bDone = FALSE;
|
|
|
|
ScDocument* pDoc = rDocShell.GetDocument();
|
|
|
|
ScDBCollection* pDocColl = pDoc->GetDBCollection();
|
2001-02-14 14:34:08 +00:00
|
|
|
BOOL bUndo (pDoc->IsUndoEnabled());
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
USHORT nPos = 0;
|
|
|
|
if (pDocColl->SearchName( rName, nPos ))
|
|
|
|
{
|
|
|
|
ScDocShellModificator aModificator( rDocShell );
|
|
|
|
|
2001-02-14 14:34:08 +00:00
|
|
|
ScDBCollection* pUndoColl = NULL;
|
|
|
|
if (bUndo)
|
|
|
|
pUndoColl = new ScDBCollection( *pDocColl );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
pDoc->CompileDBFormula( TRUE ); // CreateFormulaString
|
|
|
|
pDocColl->AtFree( nPos );
|
|
|
|
pDoc->CompileDBFormula( FALSE ); // CompileFormulaString
|
|
|
|
|
2001-02-14 14:34:08 +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;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bDone;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScDBDocFunc::RenameDBRange( const String& rOld, const String& rNew, BOOL bApi )
|
|
|
|
{
|
|
|
|
BOOL bDone = FALSE;
|
|
|
|
ScDocument* pDoc = rDocShell.GetDocument();
|
|
|
|
ScDBCollection* pDocColl = pDoc->GetDBCollection();
|
2001-02-14 14:34:08 +00:00
|
|
|
BOOL bUndo (pDoc->IsUndoEnabled());
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
USHORT nPos = 0;
|
|
|
|
USHORT nDummy = 0;
|
|
|
|
if ( pDocColl->SearchName( rOld, nPos ) &&
|
|
|
|
!pDocColl->SearchName( rNew, nDummy ) )
|
|
|
|
{
|
|
|
|
ScDocShellModificator aModificator( rDocShell );
|
|
|
|
|
|
|
|
ScDBData* pData = (*pDocColl)[nPos];
|
|
|
|
ScDBData* pNewData = new ScDBData(*pData);
|
|
|
|
pNewData->SetName(rNew);
|
|
|
|
|
|
|
|
ScDBCollection* pUndoColl = new ScDBCollection( *pDocColl );
|
|
|
|
|
|
|
|
pDoc->CompileDBFormula( TRUE ); // CreateFormulaString
|
|
|
|
pDocColl->AtFree( nPos );
|
|
|
|
BOOL bInserted = pDocColl->Insert( pNewData );
|
|
|
|
if (!bInserted) // Fehler -> alten Zustand wiederherstellen
|
|
|
|
{
|
|
|
|
delete pNewData;
|
|
|
|
pDoc->SetDBCollection( pUndoColl ); // gehoert dann dem Dokument
|
|
|
|
}
|
|
|
|
pDoc->CompileDBFormula( FALSE ); // CompileFormulaString
|
|
|
|
|
|
|
|
if (bInserted) // Einfuegen hat geklappt
|
|
|
|
{
|
2001-02-14 14:34:08 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bDone;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScDBDocFunc::ModifyDBData( const ScDBData& rNewData, BOOL bApi )
|
|
|
|
{
|
|
|
|
BOOL bDone = FALSE;
|
|
|
|
ScDocument* pDoc = rDocShell.GetDocument();
|
|
|
|
ScDBCollection* pDocColl = pDoc->GetDBCollection();
|
2001-02-14 14:34:08 +00:00
|
|
|
BOOL bUndo (pDoc->IsUndoEnabled());
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
USHORT nPos = 0;
|
|
|
|
if (pDocColl->SearchName( rNewData.GetName(), nPos ))
|
|
|
|
{
|
|
|
|
ScDocShellModificator aModificator( rDocShell );
|
|
|
|
|
|
|
|
ScDBData* pData = (*pDocColl)[nPos];
|
|
|
|
|
|
|
|
ScRange aOldRange, aNewRange;
|
|
|
|
pData->GetArea(aOldRange);
|
|
|
|
rNewData.GetArea(aNewRange);
|
|
|
|
BOOL bAreaChanged = ( aOldRange != aNewRange ); // dann muss neu compiliert werden
|
|
|
|
|
2001-02-14 14:34:08 +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();
|
|
|
|
|
2001-02-14 14:34:08 +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();
|
|
|
|
bDone = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bDone;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
|
|
|
|
|
|
BOOL ScDBDocFunc::RepeatDB( const String& rDBName, BOOL bRecord, BOOL bApi )
|
|
|
|
{
|
|
|
|
//! auch fuer ScDBFunc::RepeatDB benutzen!
|
|
|
|
|
|
|
|
BOOL bDone = FALSE;
|
|
|
|
ScDocument* pDoc = rDocShell.GetDocument();
|
2001-02-14 14:34:08 +00:00
|
|
|
if (bRecord && !pDoc->IsUndoEnabled())
|
|
|
|
bRecord = FALSE;
|
2000-09-18 16:07:07 +00:00
|
|
|
ScDBCollection* pColl = pDoc->GetDBCollection();
|
|
|
|
USHORT nIndex;
|
|
|
|
if ( pColl && pColl->SearchName( rDBName, nIndex ) )
|
|
|
|
{
|
|
|
|
ScDBData* pDBData = (*pColl)[nIndex];
|
|
|
|
|
|
|
|
ScQueryParam aQueryParam;
|
|
|
|
pDBData->GetQueryParam( aQueryParam );
|
|
|
|
BOOL bQuery = aQueryParam.GetEntry(0).bDoQuery;
|
|
|
|
|
|
|
|
ScSortParam aSortParam;
|
|
|
|
pDBData->GetSortParam( aSortParam );
|
|
|
|
BOOL bSort = aSortParam.bDoSort[0];
|
|
|
|
|
|
|
|
ScSubTotalParam aSubTotalParam;
|
|
|
|
pDBData->GetSubTotalParam( aSubTotalParam );
|
|
|
|
BOOL bSubTotal = aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly;
|
|
|
|
|
|
|
|
if ( bQuery || bSort || bSubTotal )
|
|
|
|
{
|
|
|
|
BOOL bQuerySize = FALSE;
|
|
|
|
ScRange aOldQuery;
|
|
|
|
ScRange aNewQuery;
|
|
|
|
if (bQuery && !aQueryParam.bInplace)
|
|
|
|
{
|
|
|
|
ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
|
|
|
|
aQueryParam.nDestTab, TRUE );
|
|
|
|
if (pDest && pDest->IsDoSize())
|
|
|
|
{
|
|
|
|
pDest->GetArea( aOldQuery );
|
|
|
|
bQuerySize = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-06-04 10:22:36 +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)
|
|
|
|
{
|
2004-06-04 10:22:36 +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 );
|
|
|
|
|
2004-06-04 10:22:36 +00:00
|
|
|
// 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, TRUE, TRUE );
|
2004-06-04 10:22:36 +00:00
|
|
|
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, TRUE );
|
|
|
|
|
|
|
|
// Datenbereich sichern - incl. Filter-Ergebnis
|
|
|
|
pDoc->CopyToDocument( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab, IDF_ALL, FALSE, pUndoDoc );
|
|
|
|
|
|
|
|
// alle Formeln wegen Referenzen
|
|
|
|
pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, IDF_FORMULA, FALSE, pUndoDoc );
|
|
|
|
|
|
|
|
// DB- und andere Bereiche
|
|
|
|
ScRangeName* pDocRange = pDoc->GetRangeName();
|
|
|
|
if (pDocRange->GetCount())
|
|
|
|
pUndoRange = new ScRangeName( *pDocRange );
|
|
|
|
ScDBCollection* pDocDB = pDoc->GetDBCollection();
|
|
|
|
if (pDocDB->GetCount())
|
|
|
|
pUndoDB = new ScDBCollection( *pDocDB );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bSort && bSubTotal)
|
|
|
|
{
|
|
|
|
// Sortieren ohne SubTotals
|
|
|
|
|
|
|
|
aSubTotalParam.bRemoveOnly = TRUE; // wird unten wieder zurueckgesetzt
|
|
|
|
DoSubTotals( nTab, aSubTotalParam, NULL, FALSE, bApi );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bSort)
|
|
|
|
{
|
|
|
|
pDBData->GetSortParam( aSortParam ); // Bereich kann sich geaendert haben
|
|
|
|
Sort( nTab, aSortParam, FALSE, FALSE, bApi );
|
|
|
|
}
|
|
|
|
if (bQuery)
|
|
|
|
{
|
|
|
|
pDBData->GetQueryParam( aQueryParam ); // Bereich kann sich geaendert haben
|
|
|
|
ScRange aAdvSource;
|
|
|
|
if (pDBData->GetAdvancedQuerySource(aAdvSource))
|
|
|
|
Query( nTab, aQueryParam, &aAdvSource, FALSE, bApi );
|
|
|
|
else
|
|
|
|
Query( nTab, aQueryParam, NULL, FALSE, bApi );
|
|
|
|
|
|
|
|
// 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 );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bRecord)
|
|
|
|
{
|
|
|
|
USHORT nDummy;
|
2004-06-04 10:22:36 +00:00
|
|
|
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, TRUE );
|
|
|
|
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( 0,0,nTab, MAXCOL,MAXROW,nTab,
|
|
|
|
PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE );
|
|
|
|
bDone = TRUE;
|
|
|
|
}
|
|
|
|
else if (!bApi) // "Keine Operationen auszufuehren"
|
|
|
|
rDocShell.ErrorMessage(STR_MSSG_REPEATDB_0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return bDone;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
|
|
|
2004-06-04 10:22:36 +00:00
|
|
|
BOOL ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam,
|
2000-09-18 16:07:07 +00:00
|
|
|
BOOL bRecord, BOOL bPaint, BOOL bApi )
|
|
|
|
{
|
|
|
|
ScDocShellModificator aModificator( rDocShell );
|
|
|
|
|
|
|
|
ScDocument* pDoc = rDocShell.GetDocument();
|
2001-02-14 14:34:08 +00:00
|
|
|
if (bRecord && !pDoc->IsUndoEnabled())
|
|
|
|
bRecord = FALSE;
|
2004-06-04 10:22:36 +00:00
|
|
|
SCTAB nSrcTab = nTab;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rSortParam.nCol1, rSortParam.nRow1,
|
|
|
|
rSortParam.nCol2, rSortParam.nRow2 );
|
|
|
|
if (!pDBData)
|
|
|
|
{
|
|
|
|
DBG_ERROR( "Sort: keine DBData" );
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ScDBData* pDestData = NULL;
|
|
|
|
ScRange aOldDest;
|
|
|
|
BOOL bCopy = !rSortParam.bInplace;
|
|
|
|
if ( bCopy && rSortParam.nDestCol == rSortParam.nCol1 &&
|
|
|
|
rSortParam.nDestRow == rSortParam.nRow1 && rSortParam.nDestTab == nTab )
|
|
|
|
bCopy = FALSE;
|
|
|
|
ScSortParam aLocalParam( rSortParam );
|
|
|
|
if ( bCopy )
|
|
|
|
{
|
|
|
|
aLocalParam.MoveToDest();
|
|
|
|
nTab = rSortParam.nDestTab;
|
|
|
|
pDestData = pDoc->GetDBAtCursor( rSortParam.nDestCol, rSortParam.nDestRow,
|
|
|
|
rSortParam.nDestTab, TRUE );
|
|
|
|
if (pDestData)
|
|
|
|
pDestData->GetArea(aOldDest);
|
|
|
|
}
|
|
|
|
|
2002-11-20 13:36:29 +00:00
|
|
|
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)
|
2002-11-20 13:36:29 +00:00
|
|
|
rDocShell.ErrorMessage(aTester.GetMessageId());
|
2000-09-18 16:07:07 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ausfuehren
|
|
|
|
|
|
|
|
WaitObject aWait( rDocShell.GetDialogParent() );
|
|
|
|
|
|
|
|
BOOL bRepeatQuery = FALSE; // bestehenden Filter wiederholen?
|
|
|
|
ScQueryParam aQueryParam;
|
|
|
|
pDBData->GetQueryParam( aQueryParam );
|
|
|
|
if ( aQueryParam.GetEntry(0).bDoQuery )
|
|
|
|
bRepeatQuery = TRUE;
|
|
|
|
|
|
|
|
if (bRepeatQuery && bCopy)
|
|
|
|
{
|
|
|
|
if ( aQueryParam.bInplace ||
|
|
|
|
aQueryParam.nDestCol != rSortParam.nDestCol ||
|
|
|
|
aQueryParam.nDestRow != rSortParam.nDestRow ||
|
|
|
|
aQueryParam.nDestTab != rSortParam.nDestTab ) // Query auf selben Zielbereich?
|
|
|
|
bRepeatQuery = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
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, TRUE );
|
|
|
|
pDoc->CopyToDocument( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
|
|
|
|
aLocalParam.nCol2, aLocalParam.nRow2, nTab,
|
|
|
|
IDF_ALL, FALSE, pUndoDoc );
|
|
|
|
|
|
|
|
const ScRange* pR = 0;
|
|
|
|
if (pDestData)
|
|
|
|
{
|
|
|
|
pDoc->CopyToDocument( aOldDest, IDF_ALL, FALSE, pUndoDoc );
|
|
|
|
pR = &aOldDest;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Zeilenhoehen immer (wegen automatischer Anpassung)
|
|
|
|
//! auf ScBlockUndo umstellen
|
|
|
|
// if (bRepeatQuery)
|
|
|
|
pDoc->CopyToDocument( 0, aLocalParam.nRow1, nTab, MAXCOL, aLocalParam.nRow2, nTab,
|
|
|
|
IDF_NONE, FALSE, pUndoDoc );
|
|
|
|
|
|
|
|
ScDBCollection* pUndoDB = NULL;
|
|
|
|
ScDBCollection* pDocDB = pDoc->GetDBCollection();
|
|
|
|
if (pDocDB->GetCount())
|
|
|
|
pUndoDB = new ScDBCollection( *pDocDB );
|
|
|
|
|
|
|
|
|
|
|
|
rDocShell.GetUndoManager()->AddUndoAction(
|
|
|
|
new ScUndoSort( &rDocShell, nTab,
|
|
|
|
rSortParam, bRepeatQuery, pUndoDoc, pUndoDB, pR ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
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, TRUE );
|
|
|
|
}
|
2002-12-02 16:44:59 +00:00
|
|
|
|
|
|
|
// #105780# don't call ScDocument::Sort with an empty SortParam (may be empty here if bCopy is set)
|
|
|
|
if ( aLocalParam.bDoSort[0] )
|
|
|
|
pDoc->Sort( nTab, aLocalParam, bRepeatQuery );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
BOOL bSave = TRUE;
|
|
|
|
if (bCopy)
|
|
|
|
{
|
|
|
|
ScSortParam aOldSortParam;
|
|
|
|
pDBData->GetSortParam( aOldSortParam );
|
|
|
|
if ( aOldSortParam.bDoSort[0] && aOldSortParam.bInplace ) // Inplace-Sortierung gemerkt?
|
|
|
|
{
|
|
|
|
bSave = FALSE;
|
|
|
|
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, TRUE );
|
|
|
|
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
|
|
|
|
DBG_ERROR("Zielbereich nicht da");
|
|
|
|
}
|
|
|
|
|
|
|
|
ScRange aDirtyRange( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
|
|
|
|
aLocalParam.nCol2, aLocalParam.nRow2, nTab );
|
|
|
|
pDoc->SetDirty( aDirtyRange );
|
|
|
|
|
|
|
|
if (bPaint)
|
|
|
|
{
|
|
|
|
USHORT nPaint = PAINT_GRID;
|
2004-06-04 10:22:36 +00:00
|
|
|
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( nStartX, nStartY, nTab, nEndX, nEndY, nTab, nPaint );
|
|
|
|
}
|
|
|
|
|
|
|
|
// AdjustRowHeight( aLocalParam.nRow1, aLocalParam.nRow2, bPaint );
|
|
|
|
rDocShell.AdjustRowHeight( aLocalParam.nRow1, aLocalParam.nRow2, nTab );
|
|
|
|
|
|
|
|
aModificator.SetDocumentModified();
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
|
|
|
2004-06-04 10:22:36 +00:00
|
|
|
BOOL ScDBDocFunc::Query( SCTAB nTab, const ScQueryParam& rQueryParam,
|
2000-09-18 16:07:07 +00:00
|
|
|
const ScRange* pAdvSource, BOOL bRecord, BOOL bApi )
|
|
|
|
{
|
|
|
|
ScDocShellModificator aModificator( rDocShell );
|
|
|
|
|
|
|
|
ScDocument* pDoc = rDocShell.GetDocument();
|
2001-02-14 14:34:08 +00:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
DBG_ERROR( "Query: keine DBData" );
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
2004-06-04 10:22:36 +00:00
|
|
|
SCSIZE nEC = aOldQuery.GetEntryCount();
|
|
|
|
for (SCSIZE i=0; i<nEC; i++)
|
2000-09-18 16:07:07 +00:00
|
|
|
aOldQuery.GetEntry(i).bDoQuery = FALSE;
|
|
|
|
aOldQuery.bDuplicate = TRUE;
|
|
|
|
Query( nTab, aOldQuery, NULL, bRecord, bApi );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ScQueryParam aLocalParam( rQueryParam ); // fuer Paint / Zielbereich
|
|
|
|
BOOL bCopy = !rQueryParam.bInplace; // kopiert wird in Table::Query
|
|
|
|
ScDBData* pDestData = NULL; // Bereich, in den kopiert wird
|
|
|
|
BOOL bDoSize = FALSE; // Zielgroesse anpassen (einf./loeschen)
|
2004-06-04 10:22:36 +00:00
|
|
|
SCCOL nFormulaCols = 0; // nur bei bDoSize
|
2000-09-18 16:07:07 +00:00
|
|
|
BOOL bKeepFmt = FALSE;
|
|
|
|
ScRange aOldDest;
|
|
|
|
ScRange aDestTotal;
|
|
|
|
if ( bCopy && rQueryParam.nDestCol == rQueryParam.nCol1 &&
|
|
|
|
rQueryParam.nDestRow == rQueryParam.nRow1 && rQueryParam.nDestTab == nTab )
|
|
|
|
bCopy = FALSE;
|
2004-06-04 10:22:36 +00:00
|
|
|
SCTAB nDestTab = nTab;
|
2000-09-18 16:07:07 +00:00
|
|
|
if ( bCopy )
|
|
|
|
{
|
|
|
|
aLocalParam.MoveToDest();
|
|
|
|
nDestTab = rQueryParam.nDestTab;
|
|
|
|
|
2002-11-20 13:36:29 +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)
|
2002-11-20 13:36:29 +00:00
|
|
|
rDocShell.ErrorMessage(aTester.GetMessageId());
|
2000-09-18 16:07:07 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pDestData = pDoc->GetDBAtCursor( rQueryParam.nDestCol, rQueryParam.nDestRow,
|
|
|
|
rQueryParam.nDestTab, TRUE );
|
|
|
|
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() )
|
|
|
|
{
|
2004-06-04 10:22:36 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ausfuehren
|
|
|
|
|
|
|
|
WaitObject aWait( rDocShell.GetDialogParent() );
|
|
|
|
|
|
|
|
BOOL bKeepSub = FALSE; // bestehende Teilergebnisse wiederholen?
|
|
|
|
ScSubTotalParam aSubTotalParam;
|
|
|
|
if (rQueryParam.GetEntry(0).bDoQuery) // nicht beim Aufheben
|
|
|
|
{
|
|
|
|
pDBData->GetSubTotalParam( aSubTotalParam ); // Teilergebnisse vorhanden?
|
|
|
|
|
|
|
|
if ( aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly )
|
|
|
|
bKeepSub = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( bRecord )
|
|
|
|
{
|
|
|
|
const ScRange* pOld = 0;
|
|
|
|
ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
|
|
|
|
if (bCopy)
|
|
|
|
{
|
|
|
|
pUndoDoc->InitUndo( pDoc, nDestTab, nDestTab, FALSE, TRUE );
|
|
|
|
pDoc->CopyToDocument( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
|
|
|
|
aLocalParam.nCol2, aLocalParam.nRow2, nDestTab,
|
|
|
|
IDF_ALL, FALSE, pUndoDoc );
|
|
|
|
// Attribute sichern, falls beim Filtern mitkopiert
|
|
|
|
|
|
|
|
if (pDestData)
|
|
|
|
{
|
|
|
|
pDoc->CopyToDocument( aOldDest, IDF_ALL, FALSE, pUndoDoc );
|
|
|
|
pOld = &aOldDest;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pUndoDoc->InitUndo( pDoc, nTab, nTab, FALSE, TRUE );
|
|
|
|
pDoc->CopyToDocument( 0, rQueryParam.nRow1, nTab, MAXCOL, rQueryParam.nRow2, nTab,
|
|
|
|
IDF_NONE, FALSE, pUndoDoc );
|
|
|
|
}
|
|
|
|
|
|
|
|
ScDBCollection* pUndoDB = NULL;
|
|
|
|
ScDBCollection* pDocDB = pDoc->GetDBCollection();
|
|
|
|
if (pDocDB->GetCount())
|
|
|
|
pUndoDB = new ScDBCollection( *pDocDB );
|
|
|
|
|
|
|
|
rDocShell.GetUndoManager()->AddUndoAction(
|
|
|
|
new ScUndoQuery( &rDocShell, nTab, rQueryParam, pUndoDoc, pUndoDB,
|
|
|
|
pOld, bDoSize, pAdvSource ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
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, TRUE );
|
|
|
|
pDoc->CopyToDocument( aAttribRange, IDF_ATTRIB, FALSE, pAttribDoc );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( bDoSize )
|
|
|
|
pDoc->FitBlock( aOldDest, aDestTotal );
|
|
|
|
else
|
|
|
|
pDoc->DeleteAreaTab(aOldDest, IDF_ALL); // einfach loeschen
|
|
|
|
}
|
|
|
|
|
|
|
|
// Filtern am Dokument ausfuehren
|
2004-06-04 10:22:36 +00:00
|
|
|
SCSIZE nCount = pDoc->Query( nTab, rQueryParam, bKeepSub );
|
2000-09-18 16:07:07 +00:00
|
|
|
if (bCopy)
|
|
|
|
{
|
|
|
|
aLocalParam.nRow2 = aLocalParam.nRow1 + nCount;
|
2004-06-04 10:22:36 +00:00
|
|
|
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 ); // FALSE - nicht loeschen
|
|
|
|
|
2004-06-04 10:22:36 +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 );
|
|
|
|
|
|
|
|
ScMarkData aMark;
|
|
|
|
aMark.SelectOneTable(nDestTab);
|
2004-06-04 10:22:36 +00:00
|
|
|
SCROW nFStartY = aLocalParam.nRow1 + ( aLocalParam.bHasHeader ? 1 : 0 );
|
2000-09-18 16:07:07 +00:00
|
|
|
pDoc->Fill( aLocalParam.nCol2+1, nFStartY,
|
|
|
|
aLocalParam.nCol2+nFormulaCols, nFStartY, aMark,
|
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Daten
|
2004-06-04 10:22:36 +00:00
|
|
|
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 );
|
|
|
|
DBG_ASSERT(pSrcPattern,"Pattern ist 0");
|
|
|
|
if (pSrcPattern)
|
|
|
|
pDoc->ApplyPatternAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
|
|
|
|
nDestTab, *pSrcPattern );
|
|
|
|
const ScStyleSheet* pStyle = pSrcPattern->GetStyleSheet();
|
|
|
|
if (pStyle)
|
|
|
|
pDoc->ApplyStyleAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
|
|
|
|
nDestTab, *pStyle );
|
|
|
|
}
|
|
|
|
|
|
|
|
delete pAttribDoc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// speichern: Inplace immer, sonst je nach Einstellung
|
|
|
|
// alter Inplace-Filter ist ggf. schon aufgehoben
|
|
|
|
|
|
|
|
BOOL bSave = rQueryParam.bInplace || rQueryParam.bDestPers;
|
|
|
|
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, TRUE );
|
|
|
|
|
|
|
|
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
|
|
|
|
DBG_ERROR("Zielbereich nicht da");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bCopy)
|
|
|
|
pDoc->UpdatePageBreaks( nTab );
|
|
|
|
|
|
|
|
ScRange aDirtyRange( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
|
|
|
|
aLocalParam.nCol2, aLocalParam.nRow2, nDestTab );
|
|
|
|
pDoc->SetDirty( aDirtyRange );
|
|
|
|
|
|
|
|
if (bCopy)
|
|
|
|
{
|
2004-06-04 10:22:36 +00:00
|
|
|
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( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
|
|
|
|
nEndX, nEndY, nDestTab, PAINT_GRID );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rDocShell.PostPaint( 0, rQueryParam.nRow1, nTab, MAXCOL, MAXROW, nTab,
|
|
|
|
PAINT_GRID | PAINT_LEFT );
|
|
|
|
aModificator.SetDocumentModified();
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
|
|
|
2004-06-04 10:22:36 +00:00
|
|
|
BOOL ScDBDocFunc::DoSubTotals( SCTAB nTab, const ScSubTotalParam& rParam,
|
2000-09-18 16:07:07 +00:00
|
|
|
const ScSortParam* pForceNewSort, BOOL bRecord, BOOL bApi )
|
|
|
|
{
|
|
|
|
//! auch fuer ScDBFunc::DoSubTotals benutzen!
|
|
|
|
// dann bleibt aussen:
|
|
|
|
// - neuen Bereich (aus DBData) markieren
|
|
|
|
// - SelectionChanged (?)
|
|
|
|
|
|
|
|
BOOL bDo = !rParam.bRemoveOnly; // FALSE = nur loeschen
|
|
|
|
BOOL bRet = FALSE;
|
|
|
|
|
|
|
|
ScDocument* pDoc = rDocShell.GetDocument();
|
2001-02-14 14:34:08 +00:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
DBG_ERROR( "SubTotals: keine DBData" );
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2002-11-20 13:36:29 +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)
|
2002-11-20 13:36:29 +00:00
|
|
|
rDocShell.ErrorMessage(aTester.GetMessageId());
|
2000-09-18 16:07:07 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL bOk = TRUE;
|
|
|
|
BOOL bDelete = FALSE;
|
|
|
|
if (rParam.bReplace)
|
|
|
|
if (pDoc->TestRemoveSubTotals( nTab, rParam ))
|
|
|
|
{
|
|
|
|
bDelete = TRUE;
|
|
|
|
bOk = ( MessBox( rDocShell.GetDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
|
|
|
|
// "StarCalc" "Daten loeschen?"
|
|
|
|
ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ),
|
|
|
|
ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_1 ) ).Execute()
|
|
|
|
== RET_YES );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bOk)
|
|
|
|
{
|
|
|
|
WaitObject aWait( rDocShell.GetDialogParent() );
|
|
|
|
ScDocShellModificator aModificator( rDocShell );
|
|
|
|
|
|
|
|
ScSubTotalParam aNewParam( rParam ); // Bereichsende wird veraendert
|
|
|
|
ScDocument* pUndoDoc = NULL;
|
|
|
|
ScOutlineTable* pUndoTab = NULL;
|
|
|
|
ScRangeName* pUndoRange = NULL;
|
|
|
|
ScDBCollection* pUndoDB = NULL;
|
2004-06-04 10:22:36 +00:00
|
|
|
SCTAB nTabCount = 0; // fuer Referenz-Undo
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if (bRecord) // alte Daten sichern
|
|
|
|
{
|
|
|
|
BOOL bOldFilter = bDo && rParam.bDoSort;
|
|
|
|
|
|
|
|
nTabCount = pDoc->GetTableCount();
|
|
|
|
pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
|
|
|
|
ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
|
|
|
|
if (pTable)
|
|
|
|
{
|
|
|
|
pUndoTab = new ScOutlineTable( *pTable );
|
|
|
|
|
2004-06-04 10:22:36 +00:00
|
|
|
// 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, TRUE, TRUE );
|
2004-06-04 10:22:36 +00:00
|
|
|
pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab, IDF_NONE, FALSE, pUndoDoc );
|
2000-09-18 16:07:07 +00:00
|
|
|
pDoc->CopyToDocument( 0, nOutStartRow, nTab, MAXCOL, nOutEndRow, nTab, IDF_NONE, FALSE, pUndoDoc );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pUndoDoc->InitUndo( pDoc, nTab, nTab, FALSE, bOldFilter );
|
|
|
|
|
|
|
|
// Datenbereich sichern - incl. Filter-Ergebnis
|
|
|
|
pDoc->CopyToDocument( 0,rParam.nRow1+1,nTab, MAXCOL,rParam.nRow2,nTab,
|
|
|
|
IDF_ALL, FALSE, pUndoDoc );
|
|
|
|
|
|
|
|
// alle Formeln wegen Referenzen
|
|
|
|
pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
|
|
|
|
IDF_FORMULA, FALSE, pUndoDoc );
|
|
|
|
|
|
|
|
// DB- und andere Bereiche
|
|
|
|
ScRangeName* pDocRange = pDoc->GetRangeName();
|
|
|
|
if (pDocRange->GetCount())
|
|
|
|
pUndoRange = new ScRangeName( *pDocRange );
|
|
|
|
ScDBCollection* pDocDB = pDoc->GetDBCollection();
|
|
|
|
if (pDocDB->GetCount())
|
|
|
|
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 );
|
|
|
|
BOOL bSuccess = TRUE;
|
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
|
|
|
bSuccess = pDoc->DoSubTotals( nTab, aNewParam );
|
|
|
|
}
|
|
|
|
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( 0,0,nTab, MAXCOL,MAXROW,nTab,
|
|
|
|
PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE );
|
|
|
|
aModificator.SetDocumentModified();
|
|
|
|
|
|
|
|
bRet = bSuccess;
|
|
|
|
}
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==================================================================
|
|
|
|
|
2001-01-25 18:38:12 +00:00
|
|
|
BOOL lcl_EmptyExcept( ScDocument* pDoc, const ScRange& rRange, const ScRange& rExcept )
|
|
|
|
{
|
|
|
|
ScCellIterator aIter( pDoc, rRange );
|
|
|
|
ScBaseCell* pCell = aIter.GetFirst();
|
|
|
|
while (pCell)
|
|
|
|
{
|
|
|
|
if ( pCell->GetCellType() != CELLTYPE_NOTE || pCell->GetNotePtr() ) // real content?
|
|
|
|
{
|
|
|
|
if ( !rExcept.In( ScAddress( aIter.GetCol(), aIter.GetRow(), aIter.GetTab() ) ) )
|
|
|
|
return FALSE; // cell found
|
|
|
|
}
|
|
|
|
pCell = aIter.GetNext();
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE; // nothing found - empty
|
|
|
|
}
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
BOOL ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewObj,
|
2004-04-13 11:30:54 +00:00
|
|
|
BOOL bRecord, BOOL bApi, BOOL bAllowMove )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
ScDocShellModificator aModificator( rDocShell );
|
|
|
|
WaitObject aWait( rDocShell.GetDialogParent() );
|
|
|
|
|
|
|
|
BOOL bDone = FALSE;
|
|
|
|
BOOL bUndoSelf = FALSE;
|
|
|
|
USHORT nErrId = 0;
|
|
|
|
|
|
|
|
ScDocument* pOldUndoDoc = NULL;
|
|
|
|
ScDocument* pNewUndoDoc = NULL;
|
|
|
|
ScDPObject* pUndoDPObj = NULL;
|
|
|
|
if ( bRecord && pOldObj )
|
|
|
|
pUndoDPObj = new ScDPObject( *pOldObj ); // copy old settings for undo
|
|
|
|
|
|
|
|
ScDocument* pDoc = rDocShell.GetDocument();
|
2001-02-14 14:34:08 +00:00
|
|
|
if (bRecord && !pDoc->IsUndoEnabled())
|
|
|
|
bRecord = FALSE;
|
2000-10-09 09:32:39 +00:00
|
|
|
if ( !rDocShell.IsEditable() || pDoc->GetChangeTrack() )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
// not recorded -> disallow
|
|
|
|
//! different error messages?
|
|
|
|
|
|
|
|
nErrId = STR_PROTECTIONERR;
|
|
|
|
}
|
|
|
|
if ( pOldObj && !nErrId )
|
|
|
|
{
|
|
|
|
ScRange aOldOut = pOldObj->GetOutRange();
|
2002-11-20 13:36:29 +00:00
|
|
|
ScEditableTester aTester( pDoc, aOldOut );
|
|
|
|
if ( !aTester.IsEditable() )
|
|
|
|
nErrId = aTester.GetMessageId();
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
if ( pNewObj && !nErrId )
|
|
|
|
{
|
|
|
|
// at least one cell at the output position must be editable
|
|
|
|
// -> check in advance
|
|
|
|
// (start of output range in pNewObj is valid)
|
|
|
|
|
|
|
|
ScRange aNewStart( pNewObj->GetOutRange().aStart );
|
2002-11-20 13:36:29 +00:00
|
|
|
ScEditableTester aTester( pDoc, aNewStart );
|
|
|
|
if ( !aTester.IsEditable() )
|
|
|
|
nErrId = aTester.GetMessageId();
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ScDPObject* pDestObj = NULL;
|
|
|
|
if ( !nErrId )
|
|
|
|
{
|
|
|
|
if ( pOldObj && !pNewObj )
|
|
|
|
{
|
|
|
|
// delete table
|
|
|
|
|
|
|
|
ScRange aRange = pOldObj->GetOutRange();
|
2004-06-04 10:22:36 +00:00
|
|
|
SCTAB nTab = aRange.aStart.Tab();
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if ( bRecord )
|
|
|
|
{
|
|
|
|
pOldUndoDoc = new ScDocument( SCDOCMODE_UNDO );
|
|
|
|
pOldUndoDoc->InitUndo( pDoc, nTab, nTab );
|
|
|
|
pDoc->CopyToDocument( aRange, IDF_ALL, FALSE, pOldUndoDoc );
|
|
|
|
}
|
|
|
|
|
|
|
|
pDoc->DeleteAreaTab( aRange.aStart.Col(), aRange.aStart.Row(),
|
|
|
|
aRange.aEnd.Col(), aRange.aEnd.Row(),
|
|
|
|
nTab, IDF_ALL );
|
2004-04-13 11:30:54 +00:00
|
|
|
pDoc->RemoveFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(),
|
|
|
|
aRange.aEnd.Col(), aRange.aEnd.Row(),
|
|
|
|
nTab, SC_MF_AUTO );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
pDoc->GetDPCollection()->Free( pOldObj ); // object is deleted here
|
|
|
|
|
|
|
|
rDocShell.PostPaintGridAll(); //! only necessary parts
|
|
|
|
rDocShell.PostPaint( aRange.aStart.Col(), aRange.aStart.Row(), nTab,
|
|
|
|
aRange.aEnd.Col(), aRange.aEnd.Row(), nTab,
|
|
|
|
PAINT_GRID );
|
|
|
|
bDone = TRUE;
|
|
|
|
}
|
|
|
|
else if ( pNewObj )
|
|
|
|
{
|
|
|
|
if ( pOldObj )
|
|
|
|
{
|
|
|
|
if ( bRecord )
|
|
|
|
{
|
|
|
|
ScRange aRange = pOldObj->GetOutRange();
|
2004-06-04 10:22:36 +00:00
|
|
|
SCTAB nTab = aRange.aStart.Tab();
|
2000-09-18 16:07:07 +00:00
|
|
|
pOldUndoDoc = new ScDocument( SCDOCMODE_UNDO );
|
|
|
|
pOldUndoDoc->InitUndo( pDoc, nTab, nTab );
|
|
|
|
pDoc->CopyToDocument( aRange, IDF_ALL, FALSE, pOldUndoDoc );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( pNewObj == pOldObj )
|
|
|
|
{
|
|
|
|
// refresh only - no settings modified
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pNewObj->WriteSourceDataTo( *pOldObj ); // copy source data
|
|
|
|
|
|
|
|
ScDPSaveData* pData = pNewObj->GetSaveData();
|
|
|
|
DBG_ASSERT( pData, "no SaveData from living DPObject" );
|
|
|
|
if ( pData )
|
|
|
|
pOldObj->SetSaveData( *pData ); // copy SaveData
|
|
|
|
}
|
|
|
|
|
|
|
|
pDestObj = pOldObj;
|
2004-04-13 11:30:54 +00:00
|
|
|
pDestObj->SetAllowMove( bAllowMove );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// output range must be set at pNewObj
|
|
|
|
|
|
|
|
pDestObj = new ScDPObject( *pNewObj );
|
|
|
|
pDestObj->SetAlive(TRUE);
|
|
|
|
if ( !pDoc->GetDPCollection()->Insert(pDestObj) )
|
|
|
|
{
|
|
|
|
DBG_ERROR("cannot insert DPObject");
|
|
|
|
DELETEZ( pDestObj );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( pDestObj )
|
|
|
|
{
|
2000-10-18 15:29:19 +00:00
|
|
|
// #78541# create new database connection for "refresh"
|
|
|
|
// (and re-read column entry collections)
|
|
|
|
// so all changes take effect
|
|
|
|
if ( pNewObj == pOldObj && pDestObj->IsImportData() )
|
|
|
|
pDestObj->InvalidateSource();
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
pDestObj->InvalidateData(); // before getting the new output area
|
|
|
|
|
|
|
|
// make sure the table has a name (not set by dialog)
|
|
|
|
if ( !pDestObj->GetName().Len() )
|
|
|
|
pDestObj->SetName( pDoc->GetDPCollection()->CreateNewName() );
|
|
|
|
|
2001-03-08 13:28:19 +00:00
|
|
|
BOOL bOverflow = FALSE;
|
|
|
|
ScRange aNewOut = pDestObj->GetNewOutputRange( bOverflow );
|
|
|
|
if ( bOverflow )
|
|
|
|
{
|
|
|
|
// like with STR_PROTECTIONERR, use undo to reverse everything
|
|
|
|
DBG_ASSERT( bRecord, "DataPilotUpdate: can't undo" );
|
|
|
|
bUndoSelf = TRUE;
|
|
|
|
nErrId = STR_PIVOT_ERROR;
|
|
|
|
}
|
2002-11-20 13:36:29 +00:00
|
|
|
else
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2002-11-20 13:36:29 +00:00
|
|
|
ScEditableTester aTester( pDoc, aNewOut );
|
|
|
|
if ( !aTester.IsEditable() )
|
|
|
|
{
|
|
|
|
// destination area isn't editable
|
|
|
|
//! reverse everything done so far, don't proceed
|
|
|
|
|
|
|
|
// quick solution: proceed to end, use undo action
|
|
|
|
// to reverse everything:
|
|
|
|
DBG_ASSERT( bRecord, "DataPilotUpdate: can't undo" );
|
|
|
|
bUndoSelf = TRUE;
|
|
|
|
nErrId = aTester.GetMessageId();
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
2001-01-25 18:38:12 +00:00
|
|
|
// test if new output area is empty except for old area
|
|
|
|
if ( !bApi )
|
|
|
|
{
|
|
|
|
BOOL bEmpty;
|
|
|
|
if ( pOldObj ) // OutRange of pOldObj (pDestObj) is still old area
|
|
|
|
bEmpty = lcl_EmptyExcept( pDoc, aNewOut, pOldObj->GetOutRange() );
|
|
|
|
else
|
|
|
|
bEmpty = pDoc->IsBlockEmpty( aNewOut.aStart.Tab(),
|
|
|
|
aNewOut.aStart.Col(), aNewOut.aStart.Row(),
|
|
|
|
aNewOut.aEnd.Col(), aNewOut.aEnd.Row() );
|
|
|
|
|
|
|
|
if ( !bEmpty )
|
|
|
|
{
|
|
|
|
QueryBox aBox( rDocShell.GetDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
|
|
|
|
ScGlobal::GetRscString(STR_PIVOT_NOTEMPTY) );
|
|
|
|
if (aBox.Execute() == RET_NO)
|
|
|
|
{
|
|
|
|
//! like above (not editable), use undo to reverse everything
|
|
|
|
DBG_ASSERT( bRecord, "DataPilotUpdate: can't undo" );
|
|
|
|
bUndoSelf = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
if ( bRecord )
|
|
|
|
{
|
2004-06-04 10:22:36 +00:00
|
|
|
SCTAB nTab = aNewOut.aStart.Tab();
|
2000-09-18 16:07:07 +00:00
|
|
|
pNewUndoDoc = new ScDocument( SCDOCMODE_UNDO );
|
|
|
|
pNewUndoDoc->InitUndo( pDoc, nTab, nTab );
|
|
|
|
pDoc->CopyToDocument( aNewOut, IDF_ALL, FALSE, pNewUndoDoc );
|
|
|
|
}
|
|
|
|
|
|
|
|
//! test for overlap with other data pilot tables
|
|
|
|
|
|
|
|
pDestObj->Output();
|
|
|
|
|
|
|
|
rDocShell.PostPaintGridAll(); //! only necessary parts
|
|
|
|
bDone = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// else nothing (no old, no new)
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( bRecord && bDone )
|
|
|
|
{
|
|
|
|
SfxUndoAction* pAction = new ScUndoDataPilot( &rDocShell,
|
2004-04-13 11:30:54 +00:00
|
|
|
pOldUndoDoc, pNewUndoDoc, pUndoDPObj, pDestObj, bAllowMove );
|
2000-09-18 16:07:07 +00:00
|
|
|
pOldUndoDoc = NULL;
|
|
|
|
pNewUndoDoc = NULL; // pointers are used in undo action
|
|
|
|
// pUndoDPObj is copied
|
|
|
|
|
|
|
|
if (bUndoSelf)
|
|
|
|
{
|
|
|
|
// use undo action to restore original state
|
|
|
|
//! prevent setting the document modified? (ScDocShellModificator)
|
|
|
|
|
|
|
|
pAction->Undo();
|
|
|
|
delete pAction;
|
|
|
|
bDone = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rDocShell.GetUndoManager()->AddUndoAction( pAction );
|
|
|
|
}
|
|
|
|
|
|
|
|
delete pOldUndoDoc; // if not used for undo
|
|
|
|
delete pNewUndoDoc;
|
|
|
|
delete pUndoDPObj;
|
|
|
|
|
|
|
|
if (bDone)
|
|
|
|
aModificator.SetDocumentModified();
|
|
|
|
|
|
|
|
if ( nErrId && !bApi )
|
|
|
|
rDocShell.ErrorMessage( nErrId );
|
|
|
|
|
|
|
|
return bDone;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==================================================================
|
|
|
|
//
|
|
|
|
// Datenbank-Import...
|
|
|
|
|
|
|
|
void ScDBDocFunc::UpdateImport( const String& rTarget, const String& rDBName,
|
2002-08-08 12:05:31 +00:00
|
|
|
const String& rTableName, const String& rStatement, BOOL bNative,
|
|
|
|
BYTE nType, const ::com::sun::star::uno::Reference<
|
|
|
|
::com::sun::star::sdbc::XResultSet >& xResultSet,
|
|
|
|
const SbaSelectionList* pSelection )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
// Target ist jetzt einfach der Bereichsname
|
|
|
|
|
|
|
|
ScDocument* pDoc = rDocShell.GetDocument();
|
|
|
|
ScDBCollection& rDBColl = *pDoc->GetDBCollection();
|
|
|
|
ScDBData* pData;
|
|
|
|
ScImportParam aImportParam;
|
|
|
|
BOOL bFound = FALSE;
|
|
|
|
USHORT nCount = rDBColl.GetCount();
|
|
|
|
for (USHORT i=0; i<nCount && !bFound; i++)
|
|
|
|
{
|
|
|
|
pData = rDBColl[i];
|
|
|
|
if (pData->GetName() == rTarget)
|
|
|
|
bFound = TRUE;
|
|
|
|
}
|
|
|
|
if (!bFound)
|
|
|
|
{
|
|
|
|
InfoBox aInfoBox(rDocShell.GetDialogParent(),
|
|
|
|
ScGlobal::GetRscString( STR_TARGETNOTFOUND ) );
|
|
|
|
aInfoBox.Execute();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-06-04 10:22:36 +00:00
|
|
|
SCTAB nTab;
|
|
|
|
SCCOL nDummyCol;
|
|
|
|
SCROW nDummyRow;
|
|
|
|
pData->GetArea( nTab, nDummyCol,nDummyRow,nDummyCol,nDummyRow );
|
2000-09-18 16:07:07 +00:00
|
|
|
pData->GetImportParam( aImportParam );
|
|
|
|
|
|
|
|
BOOL bSql = ( rStatement.Len() != 0 );
|
|
|
|
|
|
|
|
aImportParam.aDBName = rDBName;
|
|
|
|
aImportParam.bSql = bSql;
|
|
|
|
aImportParam.aStatement = bSql ? rStatement : rTableName;
|
|
|
|
aImportParam.bNative = bNative;
|
|
|
|
aImportParam.nType = nType;
|
|
|
|
aImportParam.bImport = TRUE;
|
2002-08-08 12:05:31 +00:00
|
|
|
BOOL bContinue = DoImport( nTab, aImportParam, xResultSet, pSelection, 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
|
|
|
|
|
|
|
|
if ( bContinue ) // #41905# Fehler beim Import -> Abbruch
|
|
|
|
{
|
|
|
|
// interne Operationen, wenn welche gespeichert
|
|
|
|
|
|
|
|
if ( pData->HasQueryParam() || pData->HasSortParam() || pData->HasSubTotalParam() )
|
|
|
|
pViewSh->RepeatDB();
|
|
|
|
|
|
|
|
// Pivottabellen die den Bereich als Quelldaten haben
|
|
|
|
|
|
|
|
rDocShell.RefreshPivotTables(aRange);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|