diff options
Diffstat (limited to 'sc/source/ui/docshell/docsh5.cxx')
-rw-r--r-- | sc/source/ui/docshell/docsh5.cxx | 995 |
1 files changed, 995 insertions, 0 deletions
diff --git a/sc/source/ui/docshell/docsh5.cxx b/sc/source/ui/docshell/docsh5.cxx new file mode 100644 index 000000000000..013511ab0acb --- /dev/null +++ b/sc/source/ui/docshell/docsh5.cxx @@ -0,0 +1,995 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// System - Includes ----------------------------------------------------- + + + + +#include "scitems.hxx" +#include <vcl/svapp.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/waitobj.hxx> +#include <sfx2/app.hxx> +#include <sfx2/bindings.hxx> +#include <svl/smplhint.hxx> + +#include <com/sun/star/sdbc/XResultSet.hpp> + +// INCLUDE --------------------------------------------------------------- + +#include "docsh.hxx" +#include "global.hxx" +#include "globstr.hrc" +#include "undodat.hxx" +#include "undotab.hxx" +#include "undoblk.hxx" +//#include "pivot.hxx" +#include "dpobject.hxx" +#include "dpshttab.hxx" +#include "dbdocfun.hxx" +#include "consoli.hxx" +#include "dbcolect.hxx" +#include "olinetab.hxx" +#include "patattr.hxx" +#include "attrib.hxx" +#include "docpool.hxx" +#include "uiitems.hxx" +#include "sc.hrc" +#include "waitoff.hxx" +#include "sizedev.hxx" +#include <basic/sbstar.hxx> +#include <basic/basmgr.hxx> + +// defined in docfunc.cxx +void VBA_InsertModule( ScDocument& rDoc, SCTAB nTab, String& sModuleName, String& sModuleSource ); + +// --------------------------------------------------------------------------- + +// +// ehemalige viewfunc/dbfunc Methoden +// + +void ScDocShell::ErrorMessage( USHORT nGlobStrId ) +{ + //! StopMarking an der (aktiven) View? + + Window* pParent = GetActiveDialogParent(); + ScWaitCursorOff aWaitOff( pParent ); + BOOL bFocus = pParent && pParent->HasFocus(); + + if(nGlobStrId==STR_PROTECTIONERR) + { + if(IsReadOnly()) + { + nGlobStrId=STR_READONLYERR; + } + } + + InfoBox aBox( pParent, ScGlobal::GetRscString( nGlobStrId ) ); + aBox.Execute(); + if (bFocus) + pParent->GrabFocus(); +} + +BOOL ScDocShell::IsEditable() const +{ + // import into read-only document is possible - must be extended if other filters use api + // #i108547# MSOOXML filter uses "IsChangeReadOnlyEnabled" property + + return !IsReadOnly() || aDocument.IsImportingXML() || aDocument.IsChangeReadOnlyEnabled(); +} + +void ScDocShell::DBAreaDeleted( SCTAB nTab, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW /* nY2 */ ) +{ + ScDocShellModificator aModificator( *this ); + aDocument.RemoveFlagsTab( nX1, nY1, nX2, nY1, nTab, SC_MF_AUTO ); + PostPaint( nX1, nY1, nTab, nX2, nY1, nTab, PAINT_GRID ); + // No SetDocumentModified, as the unnamed database range might have to be restored later. + // The UNO hint is broadcast directly instead, to keep UNO objects in valid state. + aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) ); +} + +ScDBData* lcl_GetDBNearCursor( ScDBCollection* pColl, SCCOL nCol, SCROW nRow, SCTAB nTab ) +{ + //! nach document/dbcolect verschieben + + if (!pColl) + return NULL; + + ScDBData* pNoNameData = NULL; + ScDBData* pNearData = NULL; + USHORT nCount = pColl->GetCount(); + String aNoName = ScGlobal::GetRscString( STR_DB_NONAME ); + SCTAB nAreaTab; + SCCOL nStartCol, nEndCol; + SCROW nStartRow, nEndRow; + for (USHORT i = 0; i < nCount; i++) + { + ScDBData* pDB = (*pColl)[i]; + pDB->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow ); + if ( nTab == nAreaTab && nCol+1 >= nStartCol && nCol <= nEndCol+1 && + nRow+1 >= nStartRow && nRow <= nEndRow+1 ) + { + if ( pDB->GetName() == aNoName ) + pNoNameData = pDB; + else if ( nCol < nStartCol || nCol > nEndCol || nRow < nStartRow || nRow > nEndRow ) + { + if (!pNearData) + pNearData = pDB; // ersten angrenzenden Bereich merken + } + else + return pDB; // nicht "unbenannt" und Cursor steht wirklich drin + } + } + if (pNearData) + return pNearData; // angrenzender, wenn nichts direkt getroffen + return pNoNameData; // "unbenannt" nur zurueck, wenn sonst nichts gefunden +} + +ScDBData* ScDocShell::GetDBData( const ScRange& rMarked, ScGetDBMode eMode, ScGetDBSelection eSel ) +{ + SCCOL nCol = rMarked.aStart.Col(); + SCROW nRow = rMarked.aStart.Row(); + SCTAB nTab = rMarked.aStart.Tab(); + + SCCOL nStartCol = nCol; + SCROW nStartRow = nRow; + SCTAB nStartTab = nTab; + SCCOL nEndCol = rMarked.aEnd.Col(); + SCROW nEndRow = rMarked.aEnd.Row(); + SCTAB nEndTab = rMarked.aEnd.Tab(); + + // Wegen #49655# nicht einfach GetDBAtCursor: Der zusammenhaengende Datenbereich + // fuer "unbenannt" (GetDataArea) kann neben dem Cursor legen, also muss auch ein + // benannter DB-Bereich dort gesucht werden. + + ScDBData* pData = aDocument.GetDBAtArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow ); + if (!pData) + pData = lcl_GetDBNearCursor( aDocument.GetDBCollection(), nCol, nRow, nTab ); + + BOOL bSelected = ( eSel == SC_DBSEL_FORCE_MARK || + (rMarked.aStart != rMarked.aEnd && eSel != SC_DBSEL_ROW_DOWN) ); + bool bOnlyDown = (!bSelected && eSel == SC_DBSEL_ROW_DOWN && rMarked.aStart.Row() == rMarked.aEnd.Row()); + + BOOL bUseThis = FALSE; + if (pData) + { + // Bereich nehmen, wenn nichts anderes markiert + + SCTAB nDummy; + SCCOL nOldCol1; + SCROW nOldRow1; + SCCOL nOldCol2; + SCROW nOldRow2; + pData->GetArea( nDummy, nOldCol1,nOldRow1, nOldCol2,nOldRow2 ); + BOOL bIsNoName = ( pData->GetName() == ScGlobal::GetRscString( STR_DB_NONAME ) ); + + if (!bSelected) + { + bUseThis = TRUE; + if ( bIsNoName && eMode == SC_DB_MAKE ) + { + // If nothing marked or only one row marked, adapt + // "unbenannt"/"unnamed" to contiguous area. + nStartCol = nCol; + nStartRow = nRow; + if (bOnlyDown) + { + nEndCol = rMarked.aEnd.Col(); + nEndRow = rMarked.aEnd.Row(); + } + else + { + nEndCol = nStartCol; + nEndRow = nStartRow; + } + aDocument.GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow, FALSE, bOnlyDown ); + if ( nOldCol1 != nStartCol || nOldCol2 != nEndCol || nOldRow1 != nStartRow ) + bUseThis = FALSE; // passt gar nicht + else if ( nOldRow2 != nEndRow ) + { + // Bereich auf neue End-Zeile erweitern + pData->SetArea( nTab, nOldCol1,nOldRow1, nOldCol2,nEndRow ); + } + } + } + else + { + if ( nOldCol1 == nStartCol && nOldRow1 == nStartRow && + nOldCol2 == nEndCol && nOldRow2 == nEndRow ) // genau markiert? + bUseThis = TRUE; + else + bUseThis = FALSE; // immer Markierung nehmen (Bug 11964) + } + + // fuer Import nie "unbenannt" nehmen + + if ( bUseThis && eMode == SC_DB_IMPORT && bIsNoName ) + bUseThis = FALSE; + } + + if ( bUseThis ) + { + pData->GetArea( nStartTab, nStartCol,nStartRow, nEndCol,nEndRow ); + nEndTab = nStartTab; + } + else if ( eMode == SC_DB_OLD ) + { + pData = NULL; // nichts gefunden + nStartCol = nEndCol = nCol; + nStartRow = nEndRow = nRow; + nStartTab = nEndTab = nTab; +// bMark = FALSE; // nichts zu markieren + } + else + { + if ( bSelected ) + { +// bMark = FALSE; + } + else + { // zusammenhaengender Bereich + nStartCol = nCol; + nStartRow = nRow; + if (bOnlyDown) + { + nEndCol = rMarked.aEnd.Col(); + nEndRow = rMarked.aEnd.Row(); + } + else + { + nEndCol = nStartCol; + nEndRow = nStartRow; + } + aDocument.GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow, FALSE, bOnlyDown ); + } + + BOOL bHasHeader = aDocument.HasColHeader( nStartCol,nStartRow, nEndCol,nEndRow, nTab ); + + ScDBData* pNoNameData; + USHORT nNoNameIndex; + ScDBCollection* pColl = aDocument.GetDBCollection(); + if ( eMode != SC_DB_IMPORT && + pColl->SearchName( ScGlobal::GetRscString( STR_DB_NONAME ), nNoNameIndex ) ) + { + pNoNameData = (*pColl)[nNoNameIndex]; + + if ( !pOldAutoDBRange ) + { + // store the old unnamed database range with its settings for undo + // (store at the first change, get the state before all changes) + pOldAutoDBRange = new ScDBData( *pNoNameData ); + } + + SCCOL nOldX1; // alten Bereich sauber wegnehmen + SCROW nOldY1; //! (UNDO ???) + SCCOL nOldX2; + SCROW nOldY2; + SCTAB nOldTab; + pNoNameData->GetArea( nOldTab, nOldX1, nOldY1, nOldX2, nOldY2 ); + DBAreaDeleted( nOldTab, nOldX1, nOldY1, nOldX2, nOldY2 ); + + pNoNameData->SetSortParam( ScSortParam() ); // Parameter zuruecksetzen + pNoNameData->SetQueryParam( ScQueryParam() ); + pNoNameData->SetSubTotalParam( ScSubTotalParam() ); + + pNoNameData->SetArea( nTab, nStartCol,nStartRow, nEndCol,nEndRow ); // neu setzen + pNoNameData->SetByRow( TRUE ); + pNoNameData->SetHeader( bHasHeader ); + pNoNameData->SetAutoFilter( FALSE ); + } + else + { + ScDBCollection* pUndoColl = NULL; + + String aNewName; + if (eMode==SC_DB_IMPORT) + { + aDocument.CompileDBFormula( TRUE ); // CreateFormulaString + pUndoColl = new ScDBCollection( *pColl ); // Undo fuer Import1-Bereich + + String aImport = ScGlobal::GetRscString( STR_DBNAME_IMPORT ); + long nCount = 0; + USHORT nDummy; + do + { + ++nCount; + aNewName = aImport; + aNewName += String::CreateFromInt32( nCount ); + } + while (pColl->SearchName( aNewName, nDummy )); + } + else + aNewName = ScGlobal::GetRscString( STR_DB_NONAME ); + pNoNameData = new ScDBData( aNewName, nTab, + nStartCol,nStartRow, nEndCol,nEndRow, + TRUE, bHasHeader ); + pColl->Insert( pNoNameData ); + + if ( pUndoColl ) + { + aDocument.CompileDBFormula( FALSE ); // CompileFormulaString + + ScDBCollection* pRedoColl = new ScDBCollection( *pColl ); + GetUndoManager()->AddUndoAction( new ScUndoDBData( this, pUndoColl, pRedoColl ) ); + } + + // neuen Bereich am Sba anmelden nicht mehr noetig + + // "Import1" etc am Navigator bekanntmachen + if (eMode==SC_DB_IMPORT) + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) ); + } + pData = pNoNameData; + } + +// if (bMark) +// MarkRange( ScRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ), FALSE ); + + return pData; +} + +ScDBData* ScDocShell::GetOldAutoDBRange() +{ + ScDBData* pRet = pOldAutoDBRange; + pOldAutoDBRange = NULL; + return pRet; // has to be deleted by caller! +} + +void ScDocShell::CancelAutoDBRange() +{ + // called when dialog is cancelled + if ( pOldAutoDBRange ) + { + USHORT nNoNameIndex; + ScDBCollection* pColl = aDocument.GetDBCollection(); + if ( pColl->SearchName( ScGlobal::GetRscString( STR_DB_NONAME ), nNoNameIndex ) ) + { + ScDBData* pNoNameData = (*pColl)[nNoNameIndex]; + + SCCOL nRangeX1; + SCROW nRangeY1; + SCCOL nRangeX2; + SCROW nRangeY2; + SCTAB nRangeTab; + pNoNameData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); + DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); + + *pNoNameData = *pOldAutoDBRange; // restore old settings + + if ( pOldAutoDBRange->HasAutoFilter() ) + { + // restore AutoFilter buttons + pOldAutoDBRange->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); + aDocument.ApplyFlagsTab( nRangeX1, nRangeY1, nRangeX2, nRangeY1, nRangeTab, SC_MF_AUTO ); + PostPaint( nRangeX1, nRangeY1, nRangeTab, nRangeX2, nRangeY1, nRangeTab, PAINT_GRID ); + } + } + + delete pOldAutoDBRange; + pOldAutoDBRange = NULL; + } +} + + + // Hoehen anpassen + //! mit docfunc zusammenfassen + +BOOL ScDocShell::AdjustRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) +{ + ScSizeDeviceProvider aProv(this); + Fraction aZoom(1,1); + BOOL bChange = aDocument.SetOptimalHeight( nStartRow,nEndRow, nTab, 0, aProv.GetDevice(), + aProv.GetPPTX(),aProv.GetPPTY(), aZoom,aZoom, FALSE ); + if (bChange) + PostPaint( 0,nStartRow,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID|PAINT_LEFT ); + + return bChange; +} + +void ScDocShell::UpdateAllRowHeights( const ScMarkData* pTabMark ) +{ + // update automatic row heights + + ScSizeDeviceProvider aProv(this); + Fraction aZoom(1,1); + aDocument.UpdateAllRowHeights( aProv.GetDevice(), aProv.GetPPTX(), aProv.GetPPTY(), aZoom, aZoom, pTabMark ); +} + +void ScDocShell::UpdatePendingRowHeights( SCTAB nUpdateTab, bool bBefore ) +{ + BOOL bIsUndoEnabled = aDocument.IsUndoEnabled(); + aDocument.EnableUndo( FALSE ); + aDocument.LockStreamValid( true ); // ignore draw page size (but not formula results) + if ( bBefore ) // check all sheets up to nUpdateTab + { + SCTAB nTabCount = aDocument.GetTableCount(); + if ( nUpdateTab >= nTabCount ) + nUpdateTab = nTabCount-1; // nUpdateTab is inclusive + + ScMarkData aUpdateSheets; + SCTAB nTab; + for (nTab=0; nTab<=nUpdateTab; ++nTab) + if ( aDocument.IsPendingRowHeights( nTab ) ) + aUpdateSheets.SelectTable( nTab, TRUE ); + + if (aUpdateSheets.GetSelectCount()) + UpdateAllRowHeights(&aUpdateSheets); // update with a single progress bar + + for (nTab=0; nTab<=nUpdateTab; ++nTab) + if ( aUpdateSheets.GetTableSelect( nTab ) ) + { + aDocument.UpdatePageBreaks( nTab ); + aDocument.SetPendingRowHeights( nTab, FALSE ); + } + } + else // only nUpdateTab + { + if ( aDocument.IsPendingRowHeights( nUpdateTab ) ) + { + AdjustRowHeight( 0, MAXROW, nUpdateTab ); + aDocument.UpdatePageBreaks( nUpdateTab ); + aDocument.SetPendingRowHeights( nUpdateTab, FALSE ); + } + } + aDocument.LockStreamValid( false ); + aDocument.EnableUndo( bIsUndoEnabled ); +} + +void ScDocShell::RefreshPivotTables( const ScRange& rSource ) +{ + //! rename to RefreshDataPilotTables? + + ScDPCollection* pColl = aDocument.GetDPCollection(); + if ( pColl ) + { + // DataPilotUpdate doesn't modify the collection order like PivotUpdate did, + // so a simple loop can be used. + + USHORT nCount = pColl->GetCount(); + for ( USHORT i=0; i<nCount; i++ ) + { + ScDPObject* pOld = (*pColl)[i]; + if ( pOld ) + { + const ScSheetSourceDesc* pSheetDesc = pOld->GetSheetDesc(); + if ( pSheetDesc && pSheetDesc->aSourceRange.Intersects( rSource ) ) + { + ScDPObject* pNew = new ScDPObject( *pOld ); + ScDBDocFunc aFunc( *this ); + aFunc.DataPilotUpdate( pOld, pNew, TRUE, FALSE ); + delete pNew; // DataPilotUpdate copies settings from "new" object + } + } + } + } +} + +String lcl_GetAreaName( ScDocument* pDoc, ScArea* pArea ) +{ + String aName; + BOOL bOk = FALSE; + ScDBData* pData = pDoc->GetDBAtArea( pArea->nTab, pArea->nColStart, pArea->nRowStart, + pArea->nColEnd, pArea->nRowEnd ); + if (pData) + { + pData->GetName( aName ); + if ( aName != ScGlobal::GetRscString( STR_DB_NONAME ) ) + bOk = TRUE; + } + + if (!bOk) + pDoc->GetName( pArea->nTab, aName ); + + return aName; +} + +void ScDocShell::DoConsolidate( const ScConsolidateParam& rParam, BOOL bRecord ) +{ + ScConsData aData; + + USHORT nPos; + SCCOL nColSize = 0; + SCROW nRowSize = 0; + BOOL bErr = FALSE; + for (nPos=0; nPos<rParam.nDataAreaCount; nPos++) + { + ScArea* pArea = rParam.ppDataAreas[nPos]; + nColSize = Max( nColSize, SCCOL( pArea->nColEnd - pArea->nColStart + 1 ) ); + nRowSize = Max( nRowSize, SCROW( pArea->nRowEnd - pArea->nRowStart + 1 ) ); + + // Test, ob Quelldaten verschoben wuerden + if (rParam.bReferenceData) + if (pArea->nTab == rParam.nTab && pArea->nRowEnd >= rParam.nRow) + bErr = TRUE; + } + + if (bErr) + { + InfoBox aBox( GetActiveDialogParent(), + ScGlobal::GetRscString( STR_CONSOLIDATE_ERR1 ) ); + aBox.Execute(); + return; + } + + // ausfuehren + + WaitObject aWait( GetActiveDialogParent() ); + ScDocShellModificator aModificator( *this ); + + ScRange aOldDest; + ScDBData* pDestData = aDocument.GetDBAtCursor( rParam.nCol, rParam.nRow, rParam.nTab, TRUE ); + if (pDestData) + pDestData->GetArea(aOldDest); + + aData.SetSize( nColSize, nRowSize ); + aData.SetFlags( rParam.eFunction, rParam.bByCol, rParam.bByRow, rParam.bReferenceData ); + if ( rParam.bByCol || rParam.bByRow ) + for (nPos=0; nPos<rParam.nDataAreaCount; nPos++) + { + ScArea* pArea = rParam.ppDataAreas[nPos]; + aData.AddFields( &aDocument, pArea->nTab, pArea->nColStart, pArea->nRowStart, + pArea->nColEnd, pArea->nRowEnd ); + } + aData.DoneFields(); + for (nPos=0; nPos<rParam.nDataAreaCount; nPos++) + { + ScArea* pArea = rParam.ppDataAreas[nPos]; + aData.AddData( &aDocument, pArea->nTab, pArea->nColStart, pArea->nRowStart, + pArea->nColEnd, pArea->nRowEnd ); + aData.AddName( lcl_GetAreaName(&aDocument,pArea) ); + } + + aData.GetSize( nColSize, nRowSize ); + if (bRecord && nColSize > 0 && nRowSize > 0) + { + ScDBData* pUndoData = pDestData ? new ScDBData(*pDestData) : NULL; + + SCTAB nDestTab = rParam.nTab; + ScArea aDestArea( rParam.nTab, rParam.nCol, rParam.nRow, + rParam.nCol+nColSize-1, rParam.nRow+nRowSize-1 ); + if (rParam.bByCol) ++aDestArea.nColEnd; + if (rParam.bByRow) ++aDestArea.nRowEnd; + + if (rParam.bReferenceData) + { + SCTAB nTabCount = aDocument.GetTableCount(); + SCROW nInsertCount = aData.GetInsertCount(); + + // alte Outlines + ScOutlineTable* pTable = aDocument.GetOutlineTable( nDestTab ); + ScOutlineTable* pUndoTab = pTable ? new ScOutlineTable( *pTable ) : NULL; + + ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( &aDocument, 0, nTabCount-1, FALSE, TRUE ); + + // Zeilenstatus + aDocument.CopyToDocument( 0,0,nDestTab, MAXCOL,MAXROW,nDestTab, + IDF_NONE, FALSE, pUndoDoc ); + + // alle Formeln + aDocument.CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, + IDF_FORMULA, FALSE, pUndoDoc ); + + // komplette Ausgangszeilen + aDocument.CopyToDocument( 0,aDestArea.nRowStart,nDestTab, + MAXCOL,aDestArea.nRowEnd,nDestTab, + IDF_ALL, FALSE, pUndoDoc ); + + // alten Ausgabebereich + if (pDestData) + aDocument.CopyToDocument( aOldDest, IDF_ALL, FALSE, pUndoDoc ); + + GetUndoManager()->AddUndoAction( + new ScUndoConsolidate( this, aDestArea, rParam, pUndoDoc, + TRUE, nInsertCount, pUndoTab, pUndoData ) ); + } + else + { + ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( &aDocument, aDestArea.nTab, aDestArea.nTab ); + + aDocument.CopyToDocument( aDestArea.nColStart, aDestArea.nRowStart, aDestArea.nTab, + aDestArea.nColEnd, aDestArea.nRowEnd, aDestArea.nTab, + IDF_ALL, FALSE, pUndoDoc ); + + // alten Ausgabebereich + if (pDestData) + aDocument.CopyToDocument( aOldDest, IDF_ALL, FALSE, pUndoDoc ); + + GetUndoManager()->AddUndoAction( + new ScUndoConsolidate( this, aDestArea, rParam, pUndoDoc, + FALSE, 0, NULL, pUndoData ) ); + } + } + + if (pDestData) // Zielbereich loeschen / anpassen + { + aDocument.DeleteAreaTab(aOldDest, IDF_CONTENTS); + pDestData->SetArea( rParam.nTab, rParam.nCol, rParam.nRow, + rParam.nCol + nColSize - 1, rParam.nRow + nRowSize - 1 ); + pDestData->SetHeader( rParam.bByRow ); + } + + aData.OutputToDocument( &aDocument, rParam.nCol, rParam.nRow, rParam.nTab ); + + SCCOL nPaintStartCol = rParam.nCol; + SCROW nPaintStartRow = rParam.nRow; + SCCOL nPaintEndCol = nPaintStartCol + nColSize - 1; + SCROW nPaintEndRow = nPaintStartRow + nRowSize - 1; + USHORT nPaintFlags = PAINT_GRID; + if (rParam.bByCol) + ++nPaintEndRow; + if (rParam.bByRow) + ++nPaintEndCol; + if (rParam.bReferenceData) + { + nPaintStartCol = 0; + nPaintEndCol = MAXCOL; + nPaintEndRow = MAXROW; + nPaintFlags |= PAINT_LEFT | PAINT_SIZE; + } + if (pDestData) + { + if ( aOldDest.aEnd.Col() > nPaintEndCol ) + nPaintEndCol = aOldDest.aEnd.Col(); + if ( aOldDest.aEnd.Row() > nPaintEndRow ) + nPaintEndRow = aOldDest.aEnd.Row(); + } + PostPaint( nPaintStartCol, nPaintStartRow, rParam.nTab, + nPaintEndCol, nPaintEndRow, rParam.nTab, nPaintFlags ); + aModificator.SetDocumentModified(); +} + +void ScDocShell::UseScenario( SCTAB nTab, const String& rName, BOOL bRecord ) +{ + if (!aDocument.IsScenario(nTab)) + { + SCTAB nTabCount = aDocument.GetTableCount(); + SCTAB nSrcTab = SCTAB_MAX; + SCTAB nEndTab = nTab; + String aCompare; + while ( nEndTab+1 < nTabCount && aDocument.IsScenario(nEndTab+1) ) + { + ++nEndTab; + if (nSrcTab > MAXTAB) // noch auf der Suche nach dem Szenario? + { + aDocument.GetName( nEndTab, aCompare ); + if (aCompare == rName) + nSrcTab = nEndTab; // gefunden + } + } + if (ValidTab(nSrcTab)) + { + if ( aDocument.TestCopyScenario( nSrcTab, nTab ) ) // Zellschutz testen + { + ScDocShellModificator aModificator( *this ); + ScMarkData aScenMark; + aDocument.MarkScenario( nSrcTab, nTab, aScenMark ); + ScRange aMultiRange; + aScenMark.GetMultiMarkArea( aMultiRange ); + SCCOL nStartCol = aMultiRange.aStart.Col(); + SCROW nStartRow = aMultiRange.aStart.Row(); + SCCOL nEndCol = aMultiRange.aEnd.Col(); + SCROW nEndRow = aMultiRange.aEnd.Row(); + + if (bRecord) + { + ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( &aDocument, nTab,nEndTab ); // auch alle Szenarien + // angezeigte Tabelle: + aDocument.CopyToDocument( nStartCol,nStartRow,nTab, + nEndCol,nEndRow,nTab, IDF_ALL,TRUE, pUndoDoc, &aScenMark ); + // Szenarien + for (SCTAB i=nTab+1; i<=nEndTab; i++) + { + pUndoDoc->SetScenario( i, TRUE ); + String aComment; + Color aColor; + USHORT nScenFlags; + aDocument.GetScenarioData( i, aComment, aColor, nScenFlags ); + pUndoDoc->SetScenarioData( i, aComment, aColor, nScenFlags ); + BOOL bActive = aDocument.IsActiveScenario( i ); + pUndoDoc->SetActiveScenario( i, bActive ); + // Bei Zurueckkopier-Szenarios auch Inhalte + if ( nScenFlags & SC_SCENARIO_TWOWAY ) + aDocument.CopyToDocument( 0,0,i, MAXCOL,MAXROW,i, + IDF_ALL,FALSE, pUndoDoc ); + } + + GetUndoManager()->AddUndoAction( + new ScUndoUseScenario( this, aScenMark, + ScArea( nTab,nStartCol,nStartRow,nEndCol,nEndRow ), + pUndoDoc, rName ) ); + } + + aDocument.CopyScenario( nSrcTab, nTab ); + aDocument.SetDirty(); + + // alles painten, weil in anderen Bereichen das aktive Szenario + // geaendert sein kann + //! nur, wenn sichtbare Rahmen vorhanden? + PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID ); + aModificator.SetDocumentModified(); + } + else + { + InfoBox aBox(GetActiveDialogParent(), + ScGlobal::GetRscString( STR_PROTECTIONERR ) ); + aBox.Execute(); + } + } + else + { + InfoBox aBox(GetActiveDialogParent(), + ScGlobal::GetRscString( STR_SCENARIO_NOTFOUND ) ); + aBox.Execute(); + } + } + else + { + DBG_ERROR( "UseScenario auf Szenario-Blatt" ); + } +} + +void ScDocShell::ModifyScenario( SCTAB nTab, const String& rName, const String& rComment, + const Color& rColor, USHORT nFlags ) +{ + // Undo + String aOldName; + aDocument.GetName( nTab, aOldName ); + String aOldComment; + Color aOldColor; + USHORT nOldFlags; + aDocument.GetScenarioData( nTab, aOldComment, aOldColor, nOldFlags ); + GetUndoManager()->AddUndoAction( + new ScUndoScenarioFlags( this, nTab, + aOldName, rName, aOldComment, rComment, + aOldColor, rColor, nOldFlags, nFlags ) ); + + // ausfuehren + ScDocShellModificator aModificator( *this ); + aDocument.RenameTab( nTab, rName ); + aDocument.SetScenarioData( nTab, rComment, rColor, nFlags ); + PostPaintGridAll(); + aModificator.SetDocumentModified(); + + if ( rName != aOldName ) + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + + SfxBindings* pBindings = GetViewBindings(); + if (pBindings) + pBindings->Invalidate( SID_SELECT_SCENARIO ); +} + +SCTAB ScDocShell::MakeScenario( SCTAB nTab, const String& rName, const String& rComment, + const Color& rColor, USHORT nFlags, + ScMarkData& rMark, BOOL bRecord ) +{ + rMark.MarkToMulti(); + if (rMark.IsMultiMarked()) + { + SCTAB nNewTab = nTab + 1; + while (aDocument.IsScenario(nNewTab)) + ++nNewTab; + + BOOL bCopyAll = ( (nFlags & SC_SCENARIO_COPYALL) != 0 ); + const ScMarkData* pCopyMark = NULL; + if (!bCopyAll) + pCopyMark = &rMark; + + ScDocShellModificator aModificator( *this ); + + if (bRecord) + aDocument.BeginDrawUndo(); // drawing layer must do its own undo actions + + if (aDocument.CopyTab( nTab, nNewTab, pCopyMark )) + { + if (bRecord) + { + GetUndoManager()->AddUndoAction( + new ScUndoMakeScenario( this, nTab, nNewTab, + rName, rComment, rColor, nFlags, rMark )); + } + + aDocument.RenameTab( nNewTab, rName, FALSE ); // ohne Formel-Update + aDocument.SetScenario( nNewTab, TRUE ); + aDocument.SetScenarioData( nNewTab, rComment, rColor, nFlags ); + + ScMarkData aDestMark = rMark; + aDestMark.SelectOneTable( nNewTab ); + + //! auf Filter / Buttons / Merging testen ! + + ScPatternAttr aProtPattern( aDocument.GetPool() ); + aProtPattern.GetItemSet().Put( ScProtectionAttr( TRUE ) ); + aDocument.ApplyPatternAreaTab( 0,0, MAXCOL,MAXROW, nNewTab, aProtPattern ); + + ScPatternAttr aPattern( aDocument.GetPool() ); + aPattern.GetItemSet().Put( ScMergeFlagAttr( SC_MF_SCENARIO ) ); + aPattern.GetItemSet().Put( ScProtectionAttr( TRUE ) ); + aDocument.ApplySelectionPattern( aPattern, aDestMark ); + + if (!bCopyAll) + aDocument.SetVisible( nNewTab, FALSE ); + + // dies ist dann das aktive Szenario + aDocument.CopyScenario( nNewTab, nTab, TRUE ); // TRUE - nicht aus Szenario kopieren + + if (nFlags & SC_SCENARIO_SHOWFRAME) + PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID ); // Rahmen painten + PostPaintExtras(); // Tabellenreiter + aModificator.SetDocumentModified(); + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + + return nNewTab; + } + } + return nTab; +} + +BOOL ScDocShell::MoveTable( SCTAB nSrcTab, SCTAB nDestTab, BOOL bCopy, BOOL bRecord ) +{ + ScDocShellModificator aModificator( *this ); + + // #i92477# be consistent with ScDocFunc::InsertTable: any index past the last sheet means "append" + // #i101139# nDestTab must be the target position, not APPEND (for CopyTabProtection etc.) + if ( nDestTab >= aDocument.GetTableCount() ) + nDestTab = aDocument.GetTableCount(); + + if (bCopy) + { + if (bRecord) + aDocument.BeginDrawUndo(); // drawing layer must do its own undo actions + + String sSrcCodeName; + aDocument.GetCodeName( nSrcTab, sSrcCodeName ); + if (!aDocument.CopyTab( nSrcTab, nDestTab )) + { + //! EndDrawUndo? + return FALSE; + } + else + { + SCTAB nAdjSource = nSrcTab; + if ( nDestTab <= nSrcTab ) + ++nAdjSource; // new position of source table after CopyTab + + if ( aDocument.IsTabProtected( nAdjSource ) ) + aDocument.CopyTabProtection(nAdjSource, nDestTab); + + if (bRecord) + { + SvShorts aSrcList; + SvShorts aDestList; + aSrcList.push_front(nSrcTab); + aDestList.push_front(nDestTab); + GetUndoManager()->AddUndoAction( + new ScUndoCopyTab( this, aSrcList, aDestList ) ); + } + + BOOL bVbaEnabled = aDocument.IsInVBAMode(); + if ( bVbaEnabled ) + { + StarBASIC* pStarBASIC = GetBasic(); + String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); + if ( GetBasicManager()->GetName().Len() > 0 ) + { + aLibName = GetBasicManager()->GetName(); + pStarBASIC = GetBasicManager()->GetLib( aLibName ); + } + SCTAB nTabToUse = nDestTab; + if ( nDestTab == SC_TAB_APPEND ) + nTabToUse = aDocument.GetMaxTableNumber() - 1; + String sCodeName; + String sSource; + com::sun::star::uno::Reference< com::sun::star::script::XLibraryContainer > xLibContainer = GetBasicContainer(); + com::sun::star::uno::Reference< com::sun::star::container::XNameContainer > xLib; + if( xLibContainer.is() ) + { + com::sun::star::uno::Any aLibAny = xLibContainer->getByName( aLibName ); + aLibAny >>= xLib; + } + if( xLib.is() ) + { + rtl::OUString sRTLSource; + xLib->getByName( sSrcCodeName ) >>= sRTLSource; + sSource = sRTLSource; + } + VBA_InsertModule( aDocument, nTabToUse, sCodeName, sSource ); + } + } + Broadcast( ScTablesHint( SC_TAB_COPIED, nSrcTab, nDestTab ) ); + } + else + { + if ( aDocument.GetChangeTrack() ) + return FALSE; + + if ( nSrcTab<nDestTab && nDestTab!=SC_TAB_APPEND ) + nDestTab--; + + if ( nSrcTab == nDestTab ) + { + //! allow only for api calls? + return TRUE; // nothing to do, but valid + } + + if (!aDocument.MoveTab( nSrcTab, nDestTab )) + return FALSE; + else if (bRecord) + { + SvShorts aSrcList; + SvShorts aDestList; + aSrcList.push_front(nSrcTab); + aDestList.push_front(nDestTab); + GetUndoManager()->AddUndoAction( + new ScUndoMoveTab( this, aSrcList, aDestList ) ); + } + + Broadcast( ScTablesHint( SC_TAB_MOVED, nSrcTab, nDestTab ) ); + } + + PostPaintGridAll(); + PostPaintExtras(); + aModificator.SetDocumentModified(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + + return TRUE; +} + + +IMPL_LINK( ScDocShell, RefreshDBDataHdl, ScRefreshTimer*, pRefreshTimer ) +{ + ScDBDocFunc aFunc(*this); + + BOOL bContinue = TRUE; + ScDBData* pDBData = static_cast<ScDBData*>(pRefreshTimer); + ScImportParam aImportParam; + pDBData->GetImportParam( aImportParam ); + if (aImportParam.bImport && !pDBData->HasImportSelection()) + { + ScRange aRange; + pDBData->GetArea( aRange ); + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet> xResultSet; + bContinue = aFunc.DoImport( aRange.aStart.Tab(), aImportParam, xResultSet, NULL, TRUE, FALSE ); //! Api-Flag as parameter + // internal operations (sort, query, subtotal) only if no error + if (bContinue) + { + aFunc.RepeatDB( pDBData->GetName(), TRUE, TRUE ); + RefreshPivotTables(aRange); + } + } + + return bContinue != 0; +} + |