Files
libreoffice/sc/source/ui/view/dbfunc.cxx
Rüdiger Timm 6a0f97d3dc INTEGRATION: CWS ooo19126 (1.10.328); FILE MERGED
2005/09/05 15:09:25 rt 1.10.328.1: #i54170# Change license header: remove SISSL
2005-09-08 21:54:18 +00:00

461 lines
14 KiB
C++

/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: dbfunc.cxx,v $
*
* $Revision: 1.11 $
*
* last change: $Author: rt $ $Date: 2005-09-08 22:54:18 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 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
*
************************************************************************/
#ifdef PCH
#include "ui_pch.hxx"
#endif
#pragma hdrstop
// INCLUDE ---------------------------------------------------------------
#include "scitems.hxx"
#include <sfx2/app.hxx>
#include <sfx2/bindings.hxx>
#include <vcl/msgbox.hxx>
#include <com/sun/star/sdbc/XResultSet.hpp>
#include "dbfunc.hxx"
#include "docsh.hxx"
#include "attrib.hxx"
#include "sc.hrc"
#include "undodat.hxx"
#include "dbcolect.hxx"
#include "globstr.hrc"
#include "global.hxx"
#include "dbdocfun.hxx"
#include "editable.hxx"
//==================================================================
ScDBFunc::ScDBFunc( Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ) :
ScViewFunc( pParent, rDocSh, pViewShell )
{
}
ScDBFunc::ScDBFunc( Window* pParent, const ScDBFunc& rDBFunc, ScTabViewShell* pViewShell ) :
ScViewFunc( pParent, rDBFunc, pViewShell )
{
}
ScDBFunc::~ScDBFunc()
{
}
//
// Hilfsfunktionen
//
void ScDBFunc::GotoDBArea( const String& rDBName )
{
ScDocument* pDoc = GetViewData()->GetDocument();
ScDBCollection* pDBCol = pDoc->GetDBCollection();
USHORT nFoundAt = 0;
if ( pDBCol->SearchName( rDBName, nFoundAt ) )
{
ScDBData* pData = (*pDBCol)[nFoundAt];
DBG_ASSERT( pData, "GotoDBArea: Datenbankbereich nicht gefunden!" );
if ( pData )
{
SCTAB nTab = 0;
SCCOL nStartCol = 0;
SCROW nStartRow = 0;
SCCOL nEndCol = 0;
SCROW nEndRow = 0;
pData->GetArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow );
SetTabNo( nTab );
MoveCursorAbs( nStartCol, nStartRow, ScFollowMode( SC_FOLLOW_JUMP ),
FALSE, FALSE ); // bShift,bControl
DoneBlockMode();
InitBlockMode( nStartCol, nStartRow, nTab );
MarkCursor( nEndCol, nEndRow, nTab );
SelectionChanged();
}
}
}
// aktuellen Datenbereich fuer Sortieren / Filtern suchen
ScDBData* ScDBFunc::GetDBData( BOOL bMark, ScGetDBMode eMode )
{
ScDocShell* pDocSh = GetViewData()->GetDocShell();
ScDBData* pData = NULL;
ScRange aRange;
if ( GetViewData()->GetSimpleArea(aRange) )
pData = pDocSh->GetDBData( aRange, eMode, FALSE );
else if ( eMode != SC_DB_OLD )
pData = pDocSh->GetDBData(
ScRange( GetViewData()->GetCurX(), GetViewData()->GetCurY(),
GetViewData()->GetTabNo() ),
eMode, FALSE );
if ( pData && bMark )
{
ScRange aFound;
pData->GetArea(aFound);
MarkRange( aFound, FALSE );
}
return pData;
}
// Datenbankbereiche aendern (Dialog)
void ScDBFunc::NotifyCloseDbNameDlg( const ScDBCollection& rNewColl, const List& rDelAreaList )
{
ScDocShell* pDocShell = GetViewData()->GetDocShell();
ScDocShellModificator aModificator( *pDocShell );
ScDocument* pDoc = pDocShell->GetDocument();
ScDBCollection* pOldColl = pDoc->GetDBCollection();
ScDBCollection* pUndoColl = NULL;
ScDBCollection* pRedoColl = NULL;
const BOOL bRecord (pDoc->IsUndoEnabled());
long nDelCount = rDelAreaList.Count();
for (long nDelPos=0; nDelPos<nDelCount; nDelPos++)
{
ScRange* pEntry = (ScRange*) rDelAreaList.GetObject(nDelPos);
if ( pEntry )
{
ScAddress& rStart = pEntry->aStart;
ScAddress& rEnd = pEntry->aEnd;
pDocShell->DBAreaDeleted( rStart.Tab(),
rStart.Col(), rStart.Row(),
rEnd.Col(), rEnd.Row() );
// Targets am SBA abmelden nicht mehr noetig
}
}
if (bRecord)
pUndoColl = new ScDBCollection( *pOldColl );
// neue Targets am SBA anmelden nicht mehr noetig
pDoc->CompileDBFormula( TRUE ); // CreateFormulaString
pDoc->SetDBCollection( new ScDBCollection( rNewColl ) );
pDoc->CompileDBFormula( FALSE ); // CompileFormulaString
pOldColl = NULL;
pDocShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID );
aModificator.SetDocumentModified();
SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
if (bRecord)
{
pRedoColl = new ScDBCollection( rNewColl );
pDocShell->GetUndoManager()->AddUndoAction(
new ScUndoDBData( pDocShell, pUndoColl, pRedoColl ) );
}
}
//
// wirkliche Funktionen
//
// Sortieren
void ScDBFunc::UISort( const ScSortParam& rSortParam, BOOL bRecord )
{
ScDocShell* pDocSh = GetViewData()->GetDocShell();
ScDocument* pDoc = pDocSh->GetDocument();
SCTAB nTab = GetViewData()->GetTabNo();
ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rSortParam.nCol1, rSortParam.nRow1,
rSortParam.nCol2, rSortParam.nRow2 );
if (!pDBData)
{
DBG_ERROR( "Sort: keine DBData" );
return;
}
ScSubTotalParam aSubTotalParam;
pDBData->GetSubTotalParam( aSubTotalParam );
if (aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly)
{
// Subtotals wiederholen, mit neuer Sortierung
ScSubTotalParam aSubTotalParam;
pDBData->GetSubTotalParam( aSubTotalParam );
DoSubTotals( aSubTotalParam, bRecord, &rSortParam );
}
else
{
Sort( rSortParam, bRecord ); // nur sortieren
}
}
void ScDBFunc::Sort( const ScSortParam& rSortParam, BOOL bRecord, BOOL bPaint )
{
ScDocShell* pDocSh = GetViewData()->GetDocShell();
SCTAB nTab = GetViewData()->GetTabNo();
ScDBDocFunc aDBDocFunc( *pDocSh );
BOOL bSuccess = aDBDocFunc.Sort( nTab, rSortParam, bRecord, bPaint, FALSE );
if ( bSuccess && !rSortParam.bInplace )
{
// Ziel markieren
ScRange aDestRange( rSortParam.nDestCol, rSortParam.nDestRow, rSortParam.nDestTab,
rSortParam.nDestCol + rSortParam.nCol2 - rSortParam.nCol1,
rSortParam.nDestRow + rSortParam.nRow2 - rSortParam.nRow1,
rSortParam.nDestTab );
MarkRange( aDestRange );
}
}
// Filtern
void ScDBFunc::Query( const ScQueryParam& rQueryParam, const ScRange* pAdvSource, BOOL bRecord )
{
ScDocShell* pDocSh = GetViewData()->GetDocShell();
SCTAB nTab = GetViewData()->GetTabNo();
ScDBDocFunc aDBDocFunc( *pDocSh );
BOOL bSuccess = aDBDocFunc.Query( nTab, rQueryParam, pAdvSource, bRecord, FALSE );
if (bSuccess)
{
BOOL bCopy = !rQueryParam.bInplace;
if (bCopy)
{
// Zielbereich markieren (DB-Bereich wurde ggf. angelegt)
ScDocument* pDoc = pDocSh->GetDocument();
ScDBData* pDestData = pDoc->GetDBAtCursor(
rQueryParam.nDestCol, rQueryParam.nDestRow,
rQueryParam.nDestTab, TRUE );
if (pDestData)
{
ScRange aDestRange;
pDestData->GetArea(aDestRange);
MarkRange( aDestRange );
}
}
if (!bCopy)
{
UpdateScrollBars();
SelectionChanged(); // for attribute states (filtered rows are ignored)
}
GetViewData()->GetBindings().Invalidate( SID_UNFILTER );
}
}
// Autofilter-Knoepfe ein-/ausblenden
void ScDBFunc::ToggleAutoFilter()
{
ScDocShell* pDocSh = GetViewData()->GetDocShell();
ScDocShellModificator aModificator( *pDocSh );
ScQueryParam aParam;
ScDocument* pDoc = GetViewData()->GetDocument();
ScDBData* pDBData = GetDBData( FALSE );
pDBData->SetByRow( TRUE ); //! Undo, vorher abfragen ??
pDBData->GetQueryParam( aParam );
SCCOL nCol;
SCROW nRow = aParam.nRow1;
SCTAB nTab = GetViewData()->GetTabNo();
INT16 nFlag;
BOOL bHasAuto = TRUE;
BOOL bHeader = pDBData->HasHeader();
BOOL bPaint = FALSE;
//! stattdessen aus DB-Bereich abfragen?
for (nCol=aParam.nCol1; nCol<=aParam.nCol2 && bHasAuto; nCol++)
{
nFlag = ((ScMergeFlagAttr*) pDoc->
GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ))->GetValue();
if ( (nFlag & SC_MF_AUTO) == 0 )
bHasAuto = FALSE;
}
if (bHasAuto) // aufheben
{
// Filterknoepfe ausblenden
for (nCol=aParam.nCol1; nCol<=aParam.nCol2; nCol++)
{
nFlag = ((ScMergeFlagAttr*) pDoc->
GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ))->GetValue();
pDoc->ApplyAttr( nCol, nRow, nTab, ScMergeFlagAttr( nFlag & ~SC_MF_AUTO ) );
}
// use a list action for the AutoFilter buttons (ScUndoAutoFilter) and the filter operation
String aUndo = ScGlobal::GetRscString( STR_UNDO_QUERY );
pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
ScRange aRange;
pDBData->GetArea( aRange );
pDocSh->GetUndoManager()->AddUndoAction(
new ScUndoAutoFilter( pDocSh, aRange, pDBData->GetName(), FALSE ) );
pDBData->SetAutoFilter(FALSE);
// Filter aufheben (incl. Paint / Undo)
SCSIZE nEC = aParam.GetEntryCount();
for (SCSIZE i=0; i<nEC; i++)
aParam.GetEntry(i).bDoQuery = FALSE;
aParam.bDuplicate = TRUE;
Query( aParam, NULL, TRUE );
pDocSh->GetUndoManager()->LeaveListAction();
bPaint = TRUE;
}
else // Filterknoepfe einblenden
{
if ( !pDoc->IsBlockEmpty( nTab,
aParam.nCol1, aParam.nRow1,
aParam.nCol2, aParam.nRow2 ) )
{
if (!bHeader)
{
if ( MessBox( GetViewData()->GetDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ), // "StarCalc"
ScGlobal::GetRscString( STR_MSSG_MAKEAUTOFILTER_0 ) // Koepfe aus erster Zeile?
).Execute() == RET_YES )
{
pDBData->SetHeader( TRUE ); //! Undo ??
bHeader = TRUE;
}
}
ScRange aRange;
pDBData->GetArea( aRange );
pDocSh->GetUndoManager()->AddUndoAction(
new ScUndoAutoFilter( pDocSh, aRange, pDBData->GetName(), TRUE ) );
pDBData->SetAutoFilter(TRUE);
for (nCol=aParam.nCol1; nCol<=aParam.nCol2; nCol++)
{
nFlag = ((ScMergeFlagAttr*) pDoc->
GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ))->GetValue();
pDoc->ApplyAttr( nCol, nRow, nTab, ScMergeFlagAttr( nFlag | SC_MF_AUTO ) );
}
pDocSh->PostPaint( aParam.nCol1, nRow, nTab, aParam.nCol2, nRow, nTab,
PAINT_GRID );
bPaint = TRUE;
}
else
{
ErrorBox aErrorBox( GetViewData()->GetDialogParent(), WinBits( WB_OK | WB_DEF_OK ),
ScGlobal::GetRscString( STR_ERR_AUTOFILTER ) );
aErrorBox.Execute();
}
}
if ( bPaint )
{
aModificator.SetDocumentModified();
SfxBindings& rBindings = GetViewData()->GetBindings();
rBindings.Invalidate( SID_AUTO_FILTER );
rBindings.Invalidate( SID_AUTOFILTER_HIDE );
}
}
// nur ausblenden, keine Daten veraendern
void ScDBFunc::HideAutoFilter()
{
ScDocShell* pDocSh = GetViewData()->GetDocShell();
ScDocShellModificator aModificator( *pDocSh );
ScDocument* pDoc = pDocSh->GetDocument();
ScQueryParam aParam;
ScDBData* pDBData = GetDBData( FALSE );
SCTAB nTab;
SCCOL nCol1, nCol2;
SCROW nRow1, nRow2;
pDBData->GetArea(nTab, nCol1, nRow1, nCol2, nRow2);
for (SCCOL nCol=nCol1; nCol<=nCol2; nCol++)
{
INT16 nFlag = ((ScMergeFlagAttr*) pDoc->
GetAttr( nCol, nRow1, nTab, ATTR_MERGE_FLAG ))->GetValue();
pDoc->ApplyAttr( nCol, nRow1, nTab, ScMergeFlagAttr( nFlag & ~SC_MF_AUTO ) );
}
ScRange aRange;
pDBData->GetArea( aRange );
pDocSh->GetUndoManager()->AddUndoAction(
new ScUndoAutoFilter( pDocSh, aRange, pDBData->GetName(), FALSE ) );
pDBData->SetAutoFilter(FALSE);
pDocSh->PostPaint( nCol1,nRow1,nTab, nCol2,nRow1,nTab, PAINT_GRID );
aModificator.SetDocumentModified();
SfxBindings& rBindings = GetViewData()->GetBindings();
rBindings.Invalidate( SID_AUTO_FILTER );
rBindings.Invalidate( SID_AUTOFILTER_HIDE );
}
// Re-Import
BOOL ScDBFunc::ImportData( const ScImportParam& rParam, BOOL bRecord )
{
BOOL bSuccess = FALSE;
ScDocument* pDoc = GetViewData()->GetDocument();
ScEditableTester aTester( pDoc, GetViewData()->GetTabNo(), rParam.nCol1,rParam.nRow1,
rParam.nCol2,rParam.nRow2 );
if ( !aTester.IsEditable() )
{
ErrorMessage(aTester.GetMessageId());
return FALSE;
}
ScDBDocFunc aDBDocFunc( *GetViewData()->GetDocShell() );
::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > xResultSet;
return aDBDocFunc.DoImport( GetViewData()->GetTabNo(), rParam, xResultSet, NULL, bRecord );
}