diff options
Diffstat (limited to 'sc/source/core/data/documen5.cxx')
-rw-r--r-- | sc/source/core/data/documen5.cxx | 816 |
1 files changed, 816 insertions, 0 deletions
diff --git a/sc/source/core/data/documen5.cxx b/sc/source/core/data/documen5.cxx new file mode 100644 index 000000000000..fd8d9936683f --- /dev/null +++ b/sc/source/core/data/documen5.cxx @@ -0,0 +1,816 @@ +/************************************************************************* + * + * 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" + +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/chart/ChartDataRowSource.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/data/XDataProvider.hpp> +#include <com/sun/star/chart2/data/XDataReceiver.hpp> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/embed/XEmbeddedObject.hpp> + + +#ifdef _MSC_VER +#pragma optimize("",off) +#endif + +// INCLUDE --------------------------------------------------------------- + +#include <sfx2/objsh.hxx> +#include <svx/svditer.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdpage.hxx> + +//REMOVE #ifndef SO2_DECL_SVINPLACEOBJECT_DEFINED +//REMOVE #define SO2_DECL_SVINPLACEOBJECT_DEFINED +//REMOVE SO2_DECL_REF(SvInPlaceObject) +//REMOVE #endif + +#include "document.hxx" +#include "drwlayer.hxx" +#include "chartarr.hxx" +#include "chartlis.hxx" +#include "chartlock.hxx" +#include "refupdat.hxx" +#include <tools/globname.hxx> +#include <sot/exchange.hxx> + +#include "miscuno.hxx" +#include "chart2uno.hxx" +#include "charthelper.hxx" + +using namespace ::com::sun::star; + +// ----------------------------------------------------------------------- + +void lcl_GetChartParameters( const uno::Reference< chart2::XChartDocument >& xChartDoc, + rtl::OUString& rRanges, chart::ChartDataRowSource& rDataRowSource, + bool& rHasCategories, bool& rFirstCellAsLabel ) +{ + rHasCategories = rFirstCellAsLabel = false; // default if not in sequence + + uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY ); + + uno::Reference< chart2::data::XDataSource > xDataSource = xReceiver->getUsedData(); + uno::Reference< chart2::data::XDataProvider > xProvider = xChartDoc->getDataProvider(); + + if ( xProvider.is() ) + { + uno::Sequence< beans::PropertyValue > aArgs( xProvider->detectArguments( xDataSource ) ); + + const beans::PropertyValue* pPropArray = aArgs.getConstArray(); + long nPropCount = aArgs.getLength(); + for (long i = 0; i < nPropCount; i++) + { + const beans::PropertyValue& rProp = pPropArray[i]; + String aPropName(rProp.Name); + + if (aPropName.EqualsAscii( "CellRangeRepresentation" )) + rProp.Value >>= rRanges; + else if (aPropName.EqualsAscii( "DataRowSource" )) + rDataRowSource = (chart::ChartDataRowSource)ScUnoHelpFunctions::GetEnumFromAny( rProp.Value ); + else if (aPropName.EqualsAscii( "HasCategories" )) + rHasCategories = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + else if (aPropName.EqualsAscii( "FirstCellAsLabel" )) + rFirstCellAsLabel = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + } + } +} + +void lcl_SetChartParameters( const uno::Reference< chart2::data::XDataReceiver >& xReceiver, + const rtl::OUString& rRanges, chart::ChartDataRowSource eDataRowSource, + bool bHasCategories, bool bFirstCellAsLabel ) +{ + if ( xReceiver.is() ) + { + uno::Sequence< beans::PropertyValue > aArgs( 4 ); + aArgs[0] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("CellRangeRepresentation"), -1, + uno::makeAny( rRanges ), beans::PropertyState_DIRECT_VALUE ); + aArgs[1] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("HasCategories"), -1, + uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE ); + aArgs[2] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1, + uno::makeAny( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE ); + aArgs[3] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("DataRowSource"), -1, + uno::makeAny( eDataRowSource ), beans::PropertyState_DIRECT_VALUE ); + xReceiver->setArguments( aArgs ); + } +} + +// update charts after loading old document + +void ScDocument::UpdateAllCharts() +{ + if ( !pDrawLayer || !pShell ) + return; + + sal_uInt16 nDataCount = pChartCollection->GetCount(); + if ( !nDataCount ) + return ; // nothing to do + + sal_uInt16 nPos; + + for (SCTAB nTab=0; nTab<=MAXTAB; nTab++) + { + if (pTab[nTab]) + { + SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage,"Page ?"); + + ScRange aRange; + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_OLE2 ) + { + uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef(); + if ( xIPObj.is() ) + { + String aIPName = ((SdrOle2Obj*)pObject)->GetPersistName(); + + for (nPos=0; nPos<nDataCount; nPos++) + { + ScChartArray* pChartObj = (*pChartCollection)[nPos]; + if (pChartObj->GetName() == aIPName) + { + ScRangeListRef aRanges = pChartObj->GetRangeList(); + String sRangeStr; + aRanges->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() ); + + chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS; + bool bHasCategories = pChartObj->HasRowHeaders(); + bool bFirstCellAsLabel = pChartObj->HasColHeaders(); + + // Calc -> DataProvider + uno::Reference< chart2::data::XDataProvider > xDataProvider = + new ScChart2DataProvider( this ); + // Chart -> DataReceiver + uno::Reference< chart2::data::XDataReceiver > xReceiver; + uno::Reference< embed::XComponentSupplier > xCompSupp( xIPObj, uno::UNO_QUERY ); + if( xCompSupp.is()) + xReceiver.set( xCompSupp->getComponent(), uno::UNO_QUERY ); + if( xReceiver.is()) + { + // connect + xReceiver->attachDataProvider( xDataProvider ); + uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( + pShell->GetModel(), uno::UNO_QUERY ); + xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier ); + + lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource, + bHasCategories, bFirstCellAsLabel ); + } + + ScChartListener* pCL = new ScChartListener( + aIPName, this, pChartObj->GetRangeList() ); + pChartListenerCollection->Insert( pCL ); + pCL->StartListeningTo(); + } + } + } + } + pObject = aIter.Next(); + } + } + } + + pChartCollection->FreeAll(); +} + +sal_Bool ScDocument::HasChartAtPoint( SCTAB nTab, const Point& rPos, String* pName ) +{ + if (pDrawLayer && pTab[nTab]) + { + SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage,"Page ?"); + + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_OLE2 && + pObject->GetCurrentBoundRect().IsInside(rPos) ) + { + // auch Chart-Objekte die nicht in der Collection sind + + if (IsChart(pObject)) + { + if (pName) + *pName = ((SdrOle2Obj*)pObject)->GetPersistName(); + return sal_True; + } + } + pObject = aIter.Next(); + } + } + + if (pName) + pName->Erase(); + return sal_False; // nix gefunden +} + +void ScDocument::UpdateChartArea( const String& rChartName, + const ScRange& rNewArea, sal_Bool bColHeaders, sal_Bool bRowHeaders, + sal_Bool bAdd ) +{ + ScRangeListRef aRLR( new ScRangeList ); + aRLR->Append( rNewArea ); + UpdateChartArea( rChartName, aRLR, bColHeaders, bRowHeaders, bAdd ); +} + +uno::Reference< chart2::XChartDocument > ScDocument::GetChartByName( const String& rChartName ) +{ + uno::Reference< chart2::XChartDocument > xReturn; + + if (pDrawLayer) + { + sal_uInt16 nCount = pDrawLayer->GetPageCount(); + for (sal_uInt16 nTab=0; nTab<nCount; nTab++) + { + SdrPage* pPage = pDrawLayer->GetPage(nTab); + DBG_ASSERT(pPage,"Page ?"); + + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_OLE2 && + ((SdrOle2Obj*)pObject)->GetPersistName() == rChartName ) + { + xReturn.set( ScChartHelper::GetChartFromSdrObject( pObject ) ); + return xReturn; + } + pObject = aIter.Next(); + } + } + } + return xReturn; +} +void ScDocument::GetChartRanges( const String& rChartName, ::std::vector< ScRangeList >& rRangesVector, ScDocument* pSheetNameDoc ) +{ + rRangesVector.clear(); + uno::Reference< chart2::XChartDocument > xChartDoc( GetChartByName( rChartName ) ); + if ( xChartDoc.is() ) + { + uno::Sequence< rtl::OUString > aRangeStrings; + ScChartHelper::GetChartRanges( xChartDoc, aRangeStrings ); + for( sal_Int32 nN=0; nN<aRangeStrings.getLength(); nN++ ) + { + ScRangeList aRanges; + aRanges.Parse( aRangeStrings[nN], pSheetNameDoc, SCA_VALID, pSheetNameDoc->GetAddressConvention() ); + rRangesVector.push_back(aRanges); + } + } +} + +void ScDocument::SetChartRanges( const String& rChartName, const ::std::vector< ScRangeList >& rRangesVector ) +{ + uno::Reference< chart2::XChartDocument > xChartDoc( GetChartByName( rChartName ) ); + if ( xChartDoc.is() ) + { + sal_Int32 nCount = static_cast<sal_Int32>( rRangesVector.size() ); + uno::Sequence< rtl::OUString > aRangeStrings(nCount); + for( sal_Int32 nN=0; nN<nCount; nN++ ) + { + ScRangeList aScRangeList( rRangesVector[nN] ); + String sRangeStr; // This range must be in Calc A1 format. + aScRangeList.Format( sRangeStr, SCR_ABS_3D, this ); + aRangeStrings[nN]=sRangeStr; + } + ScChartHelper::SetChartRanges( xChartDoc, aRangeStrings ); + } +} + +void ScDocument::GetOldChartParameters( const String& rName, + ScRangeList& rRanges, sal_Bool& rColHeaders, sal_Bool& rRowHeaders ) +{ + // used for undo of changing chart source area + + if (!pDrawLayer) + return; + + sal_uInt16 nCount = pDrawLayer->GetPageCount(); + for (sal_uInt16 nTab=0; nTab<nCount; nTab++) + { + SdrPage* pPage = pDrawLayer->GetPage(nTab); + DBG_ASSERT(pPage,"Page ?"); + + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_OLE2 && + ((SdrOle2Obj*)pObject)->GetPersistName() == rName ) + { + uno::Reference< chart2::XChartDocument > xChartDoc( ScChartHelper::GetChartFromSdrObject( pObject ) ); + if ( xChartDoc.is() ) + { + chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS; + bool bHasCategories = false; + bool bFirstCellAsLabel = false; + rtl::OUString aRangesStr; + lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel ); + + rRanges.Parse( aRangesStr, this ); + if ( eDataRowSource == chart::ChartDataRowSource_COLUMNS ) + { + rRowHeaders = bHasCategories; + rColHeaders = bFirstCellAsLabel; + } + else + { + rColHeaders = bHasCategories; + rRowHeaders = bFirstCellAsLabel; + } + } + return; + } + pObject = aIter.Next(); + } + } +} + +void ScDocument::UpdateChartArea( const String& rChartName, + const ScRangeListRef& rNewList, sal_Bool bColHeaders, sal_Bool bRowHeaders, + sal_Bool bAdd ) +{ + if (!pDrawLayer) + return; + + for (SCTAB nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++) + { + SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage,"Page ?"); + + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_OLE2 && + ((SdrOle2Obj*)pObject)->GetPersistName() == rChartName ) + { + uno::Reference< chart2::XChartDocument > xChartDoc( ScChartHelper::GetChartFromSdrObject( pObject ) ); + uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY ); + if ( xChartDoc.is() && xReceiver.is() ) + { + ScRangeListRef aNewRanges; + chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS; + bool bHasCategories = false; + bool bFirstCellAsLabel = false; + rtl::OUString aRangesStr; + lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel ); + + sal_Bool bInternalData = xChartDoc->hasInternalDataProvider(); + + if ( bAdd && !bInternalData ) + { + // append to old ranges, keep other settings + + aNewRanges = new ScRangeList; + aNewRanges->Parse( aRangesStr, this ); + + sal_uLong nAddCount = rNewList->Count(); + for ( sal_uLong nAdd=0; nAdd<nAddCount; nAdd++ ) + aNewRanges->Append( *rNewList->GetObject(nAdd) ); + } + else + { + // directly use new ranges (only eDataRowSource is used from old settings) + + if ( eDataRowSource == chart::ChartDataRowSource_COLUMNS ) + { + bHasCategories = bRowHeaders; + bFirstCellAsLabel = bColHeaders; + } + else + { + bHasCategories = bColHeaders; + bFirstCellAsLabel = bRowHeaders; + } + aNewRanges = rNewList; + } + + if ( bInternalData && pShell ) + { + // Calc -> DataProvider + uno::Reference< chart2::data::XDataProvider > xDataProvider = new ScChart2DataProvider( this ); + xReceiver->attachDataProvider( xDataProvider ); + uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( + pShell->GetModel(), uno::UNO_QUERY ); + xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier ); + } + + String sRangeStr; + aNewRanges->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() ); + + lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource, bHasCategories, bFirstCellAsLabel ); + + pChartListenerCollection->ChangeListening( rChartName, aNewRanges ); + + // ((SdrOle2Obj*)pObject)->GetNewReplacement(); + // pObject->ActionChanged(); + + return; // nicht weitersuchen + } + } + pObject = aIter.Next(); + } + } +} + +void ScDocument::UpdateChart( const String& rChartName ) +{ + if (!pDrawLayer || bInDtorClear) + return; + uno::Reference< chart2::XChartDocument > xChartDoc( GetChartByName( rChartName ) ); + if( xChartDoc.is() ) + { + try + { + uno::Reference< util::XModifiable > xModif( xChartDoc, uno::UNO_QUERY_THROW ); + if( apTemporaryChartLock.get() ) + apTemporaryChartLock->AlsoLockThisChart( uno::Reference< frame::XModel >( xModif, uno::UNO_QUERY ) ); + xModif->setModified( sal_True ); + } + catch ( uno::Exception& ) + { + } + } + + // After the update, chart keeps track of its own data source ranges, + // the listener doesn't need to listen anymore, except the chart has + // an internal data provider. + if ( !( xChartDoc.is() && xChartDoc->hasInternalDataProvider() ) && pChartListenerCollection ) + { + pChartListenerCollection->ChangeListening( rChartName, new ScRangeList ); + } +} + +void ScDocument::RestoreChartListener( const String& rName ) +{ + // Read the data ranges from the chart object, and start listening to those ranges again + // (called when a chart is saved, because then it might be swapped out and stop listening itself). + + uno::Reference< embed::XEmbeddedObject > xObject = FindOleObjectByName( rName ); + if ( xObject.is() ) + { + uno::Reference< util::XCloseable > xComponent = xObject->getComponent(); + uno::Reference< chart2::XChartDocument > xChartDoc( xComponent, uno::UNO_QUERY ); + uno::Reference< chart2::data::XDataReceiver > xReceiver( xComponent, uno::UNO_QUERY ); + if ( xChartDoc.is() && xReceiver.is() && !xChartDoc->hasInternalDataProvider()) + { + uno::Sequence<rtl::OUString> aRepresentations( xReceiver->getUsedRangeRepresentations() ); + ScRangeListRef aRanges = new ScRangeList; + sal_Int32 nRangeCount = aRepresentations.getLength(); + for ( sal_Int32 i=0; i<nRangeCount; i++ ) + { + ScRange aRange; + ScAddress::Details aDetails(GetAddressConvention(), 0, 0); + if ( aRange.ParseAny( aRepresentations[i], this, aDetails ) & SCA_VALID ) + aRanges->Append( aRange ); + } + + pChartListenerCollection->ChangeListening( rName, aRanges ); + } + } +} + +void ScDocument::UpdateChartRef( UpdateRefMode eUpdateRefMode, + SCCOL nCol1, SCROW nRow1, SCTAB nTab1, + SCCOL nCol2, SCROW nRow2, SCTAB nTab2, + SCsCOL nDx, SCsROW nDy, SCsTAB nDz ) +{ + if (!pDrawLayer) + return; + + sal_uInt16 nChartCount = pChartListenerCollection->GetCount(); + for ( sal_uInt16 nIndex = 0; nIndex < nChartCount; nIndex++ ) + { + ScChartListener* pChartListener = + (ScChartListener*) (pChartListenerCollection->At(nIndex)); + ScRangeListRef aRLR( pChartListener->GetRangeList() ); + ScRangeListRef aNewRLR( new ScRangeList ); + sal_Bool bChanged = sal_False; + sal_Bool bDataChanged = sal_False; + for ( ScRangePtr pR = aRLR->First(); pR; pR = aRLR->Next() ) + { + SCCOL theCol1 = pR->aStart.Col(); + SCROW theRow1 = pR->aStart.Row(); + SCTAB theTab1 = pR->aStart.Tab(); + SCCOL theCol2 = pR->aEnd.Col(); + SCROW theRow2 = pR->aEnd.Row(); + SCTAB theTab2 = pR->aEnd.Tab(); + ScRefUpdateRes eRes = ScRefUpdate::Update( + this, eUpdateRefMode, + nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, + nDx,nDy,nDz, + theCol1,theRow1,theTab1, + theCol2,theRow2,theTab2 ); + if ( eRes != UR_NOTHING ) + { + bChanged = sal_True; + aNewRLR->Append( ScRange( + theCol1, theRow1, theTab1, + theCol2, theRow2, theTab2 )); + if ( eUpdateRefMode == URM_INSDEL + && !bDataChanged + && (eRes == UR_INVALID || + ((pR->aEnd.Col() - pR->aStart.Col() + != theCol2 - theCol1) + || (pR->aEnd.Row() - pR->aStart.Row() + != theRow2 - theRow1) + || (pR->aEnd.Tab() - pR->aStart.Tab() + != theTab2 - theTab1))) ) + { + bDataChanged = sal_True; + } + } + else + aNewRLR->Append( *pR ); + } + if ( bChanged ) + { +#if 0 + if ( nDz != 0 ) + { // #81844# sheet to be deleted or inserted or moved + // => no valid sheet names for references right now + pChartListener->ChangeListening( aNewRLR, bDataChanged ); + pChartListener->ScheduleSeriesRanges(); + } + else +#endif + { +// SetChartRangeList( pChartListener->GetString(), aNewRLR ); +// pChartListener->ChangeListening( aNewRLR, bDataChanged ); + + // Force the chart to be loaded now, so it registers itself for UNO events. + // UNO broadcasts are done after UpdateChartRef, so the chart will get this + // reference change. + + uno::Reference< embed::XEmbeddedObject > xIPObj = FindOleObjectByName( pChartListener->GetString() ); + svt::EmbeddedObjectRef::TryRunningState( xIPObj ); + + // After the change, chart keeps track of its own data source ranges, + // the listener doesn't need to listen anymore, except the chart has + // an internal data provider. + bool bInternalDataProvider = false; + if ( xIPObj.is() ) + { + try + { + uno::Reference< chart2::XChartDocument > xChartDoc( xIPObj->getComponent(), uno::UNO_QUERY_THROW ); + bInternalDataProvider = xChartDoc->hasInternalDataProvider(); + } + catch ( uno::Exception& ) + { + } + } + if ( bInternalDataProvider ) + { + pChartListener->ChangeListening( aNewRLR, bDataChanged ); + } + else + { + pChartListener->ChangeListening( new ScRangeList, bDataChanged ); + } + } + } + } +} + + +void ScDocument::SetChartRangeList( const String& rChartName, + const ScRangeListRef& rNewRangeListRef ) +{ + // called from ChartListener + + if (!pDrawLayer) + return; + + for (SCTAB nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++) + { + SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage,"Page ?"); + + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_OLE2 && + ((SdrOle2Obj*)pObject)->GetPersistName() == rChartName ) + { + uno::Reference< chart2::XChartDocument > xChartDoc( ScChartHelper::GetChartFromSdrObject( pObject ) ); + uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY ); + if ( xChartDoc.is() && xReceiver.is() ) + { + ScRangeListRef aNewRanges; + chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS; + bool bHasCategories = false; + bool bFirstCellAsLabel = false; + rtl::OUString aRangesStr; + lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel ); + + String sRangeStr; + rNewRangeListRef->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() ); + + lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource, bHasCategories, bFirstCellAsLabel ); + + // don't modify pChartListenerCollection here, called from there + return; + } + } + pObject = aIter.Next(); + } + } +} + + +sal_Bool ScDocument::HasData( SCCOL nCol, SCROW nRow, SCTAB nTab ) +{ + if (pTab[nTab]) + return pTab[nTab]->HasData( nCol, nRow ); + else + return sal_False; +} + +uno::Reference< embed::XEmbeddedObject > + ScDocument::FindOleObjectByName( const String& rName ) +{ + if (!pDrawLayer) + return uno::Reference< embed::XEmbeddedObject >(); + + // die Seiten hier vom Draw-Layer nehmen, + // weil sie evtl. nicht mit den Tabellen uebereinstimmen + // (z.B. Redo von Tabelle loeschen, Draw-Redo passiert vor DeleteTab). + + sal_uInt16 nCount = pDrawLayer->GetPageCount(); + for (sal_uInt16 nTab=0; nTab<nCount; nTab++) + { + SdrPage* pPage = pDrawLayer->GetPage(nTab); + DBG_ASSERT(pPage,"Page ?"); + + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_OLE2 ) + { + SdrOle2Obj * pOleObject ( dynamic_cast< SdrOle2Obj * >( pObject )); + if( pOleObject && + pOleObject->GetPersistName() == rName ) + { + return pOleObject->GetObjRef(); + } + } + pObject = aIter.Next(); + } + } + + return uno::Reference< embed::XEmbeddedObject >(); +} + +sal_Bool lcl_StringInCollection( const ScStrCollection* pColl, const String& rStr ) +{ + if ( !pColl ) + return sal_False; + + StrData aData( rStr ); + sal_uInt16 nDummy; + return pColl->Search( &aData, nDummy ); +} + +void ScDocument::UpdateChartListenerCollection() +{ + bChartListenerCollectionNeedsUpdate = sal_False; + if (!pDrawLayer) + return; + else + { + ScRange aRange; + // Range fuer Suche unwichtig + ScChartListener aCLSearcher( EMPTY_STRING, this, aRange ); + for (SCTAB nTab=0; nTab<=MAXTAB; nTab++) + { + if (pTab[nTab]) + { + SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage,"Page ?"); + + if (!pPage) + continue; + + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_OLE2 ) + { + String aObjName = ((SdrOle2Obj*)pObject)->GetPersistName(); + aCLSearcher.SetString( aObjName ); + sal_uInt16 nIndex; + if ( pChartListenerCollection->Search( &aCLSearcher, nIndex ) ) + { + ((ScChartListener*) (pChartListenerCollection-> + At( nIndex )))->SetUsed( sal_True ); + } + else if ( lcl_StringInCollection( pOtherObjects, aObjName ) ) + { + // non-chart OLE object -> don't touch + } + else + { + bool bIsChart = false; + + uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef(); + DBG_ASSERT( xIPObj.is(), "No embedded object is given!"); + uno::Reference< ::com::sun::star::chart2::data::XDataReceiver > xReceiver; + uno::Reference< embed::XComponentSupplier > xCompSupp( xIPObj, uno::UNO_QUERY ); + if( xCompSupp.is()) + xReceiver.set( xCompSupp->getComponent(), uno::UNO_QUERY ); + + // if the object is a chart2::XDataReceiver, we must attach as XDataProvider + if( xReceiver.is() && + !PastingDrawFromOtherDoc()) + { + // NOTE: this currently does not work as we are + // unable to set the data. So a chart from the + // same document is treated like a chart with + // own data for the time being. +#if 0 + // data provider + uno::Reference< chart2::data::XDataProvider > xDataProvider = new + ScChart2DataProvider( this ); + xReceiver->attachDataProvider( xDataProvider ); + // number formats supplier + uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( pShell->GetModel(), uno::UNO_QUERY ); + xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier ); + // data ? + // how to set?? Defined in XML-file, which is already loaded!!! + // => we have to do this stuff here, BEFORE the chart is actually loaded + + bIsChart = true; +#endif + } + + if (!bIsChart) + { + // put into list of other ole objects, so the object doesn't have to + // be swapped in the next time UpdateChartListenerCollection is called + //! remove names when objects are no longer there? + // (object names aren't used again before reloading the document) + + if (!pOtherObjects) + pOtherObjects = new ScStrCollection; + pOtherObjects->Insert( new StrData( aObjName ) ); + } + } + } + pObject = aIter.Next(); + } + } + } + // alle nicht auf SetUsed gesetzten loeschen + pChartListenerCollection->FreeUnused(); + } +} + +void ScDocument::AddOLEObjectToCollection(const String& rName) +{ + if (!pOtherObjects) + pOtherObjects = new ScStrCollection; + pOtherObjects->Insert( new StrData( rName ) ); +} + + + |