xref: /trunk/main/sc/source/core/data/documen5.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 #include <com/sun/star/util/XModifiable.hpp>
32 #include <com/sun/star/chart/ChartDataRowSource.hpp>
33 #include <com/sun/star/chart2/XChartDocument.hpp>
34 #include <com/sun/star/chart2/data/XDataProvider.hpp>
35 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
36 #include <com/sun/star/embed/EmbedStates.hpp>
37 #include <com/sun/star/embed/XEmbeddedObject.hpp>
38 
39 
40 #ifdef _MSC_VER
41 #pragma optimize("",off)
42 #endif
43 
44 // INCLUDE ---------------------------------------------------------------
45 
46 #include <sfx2/objsh.hxx>
47 #include <svx/svditer.hxx>
48 #include <svx/svdoole2.hxx>
49 #include <svx/svdpage.hxx>
50 
51 //REMOVE	#ifndef SO2_DECL_SVINPLACEOBJECT_DEFINED
52 //REMOVE	#define SO2_DECL_SVINPLACEOBJECT_DEFINED
53 //REMOVE	SO2_DECL_REF(SvInPlaceObject)
54 //REMOVE	#endif
55 
56 #include "document.hxx"
57 #include "drwlayer.hxx"
58 #include "chartarr.hxx"
59 #include "chartlis.hxx"
60 #include "chartlock.hxx"
61 #include "refupdat.hxx"
62 #include <tools/globname.hxx>
63 #include <sot/exchange.hxx>
64 
65 #include "miscuno.hxx"
66 #include "chart2uno.hxx"
67 #include "charthelper.hxx"
68 
69 using namespace ::com::sun::star;
70 
71 // -----------------------------------------------------------------------
72 
73 void lcl_GetChartParameters( const uno::Reference< chart2::XChartDocument >& xChartDoc,
74             rtl::OUString& rRanges, chart::ChartDataRowSource& rDataRowSource,
75             bool& rHasCategories, bool& rFirstCellAsLabel )
76 {
77     rHasCategories = rFirstCellAsLabel = false;     // default if not in sequence
78 
79     uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY );
80 
81     uno::Reference< chart2::data::XDataSource > xDataSource = xReceiver->getUsedData();
82     uno::Reference< chart2::data::XDataProvider > xProvider = xChartDoc->getDataProvider();
83 
84     if ( xProvider.is() )
85     {
86         uno::Sequence< beans::PropertyValue > aArgs( xProvider->detectArguments( xDataSource ) );
87 
88         const beans::PropertyValue* pPropArray = aArgs.getConstArray();
89         long nPropCount = aArgs.getLength();
90         for (long i = 0; i < nPropCount; i++)
91         {
92             const beans::PropertyValue& rProp = pPropArray[i];
93             String aPropName(rProp.Name);
94 
95             if (aPropName.EqualsAscii( "CellRangeRepresentation" ))
96                 rProp.Value >>= rRanges;
97             else if (aPropName.EqualsAscii( "DataRowSource" ))
98                 rDataRowSource = (chart::ChartDataRowSource)ScUnoHelpFunctions::GetEnumFromAny( rProp.Value );
99             else if (aPropName.EqualsAscii( "HasCategories" ))
100                 rHasCategories = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
101             else if (aPropName.EqualsAscii( "FirstCellAsLabel" ))
102                 rFirstCellAsLabel = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
103         }
104     }
105 }
106 
107 void lcl_SetChartParameters( const uno::Reference< chart2::data::XDataReceiver >& xReceiver,
108             const rtl::OUString& rRanges, chart::ChartDataRowSource eDataRowSource,
109             bool bHasCategories, bool bFirstCellAsLabel )
110 {
111     if ( xReceiver.is() )
112     {
113         uno::Sequence< beans::PropertyValue > aArgs( 4 );
114         aArgs[0] = beans::PropertyValue(
115             ::rtl::OUString::createFromAscii("CellRangeRepresentation"), -1,
116             uno::makeAny( rRanges ), beans::PropertyState_DIRECT_VALUE );
117         aArgs[1] = beans::PropertyValue(
118             ::rtl::OUString::createFromAscii("HasCategories"), -1,
119             uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE );
120         aArgs[2] = beans::PropertyValue(
121             ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1,
122             uno::makeAny( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE );
123         aArgs[3] = beans::PropertyValue(
124             ::rtl::OUString::createFromAscii("DataRowSource"), -1,
125             uno::makeAny( eDataRowSource ), beans::PropertyState_DIRECT_VALUE );
126         xReceiver->setArguments( aArgs );
127     }
128 }
129 
130 // update charts after loading old document
131 
132 void ScDocument::UpdateAllCharts()
133 {
134     if ( !pDrawLayer || !pShell )
135 		return;
136 
137 	sal_uInt16 nDataCount = pChartCollection->GetCount();
138 	if ( !nDataCount )
139 		return ;		// nothing to do
140 
141 	sal_uInt16 nPos;
142 
143 	for (SCTAB nTab=0; nTab<=MAXTAB; nTab++)
144 	{
145 		if (pTab[nTab])
146 		{
147 			SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
148 			DBG_ASSERT(pPage,"Page ?");
149 
150 			ScRange aRange;
151 			SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
152 			SdrObject* pObject = aIter.Next();
153 			while (pObject)
154 			{
155 				if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
156 				{
157 					uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
158 					if ( xIPObj.is() )
159 					{
160 						String aIPName = ((SdrOle2Obj*)pObject)->GetPersistName();
161 
162 						for (nPos=0; nPos<nDataCount; nPos++)
163 						{
164 							ScChartArray* pChartObj = (*pChartCollection)[nPos];
165 							if (pChartObj->GetName() == aIPName)
166 							{
167                                 ScRangeListRef aRanges = pChartObj->GetRangeList();
168                                 String sRangeStr;
169                                 aRanges->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() );
170 
171                                 chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
172                                 bool bHasCategories = pChartObj->HasRowHeaders();
173                                 bool bFirstCellAsLabel = pChartObj->HasColHeaders();
174 
175                                 // Calc -> DataProvider
176                                 uno::Reference< chart2::data::XDataProvider > xDataProvider =
177                                         new ScChart2DataProvider( this );
178                                 // Chart -> DataReceiver
179                                 uno::Reference< chart2::data::XDataReceiver > xReceiver;
180                                 uno::Reference< embed::XComponentSupplier > xCompSupp( xIPObj, uno::UNO_QUERY );
181                                 if( xCompSupp.is())
182                                     xReceiver.set( xCompSupp->getComponent(), uno::UNO_QUERY );
183                                 if( xReceiver.is())
184                                 {
185                                     // connect
186                                     xReceiver->attachDataProvider( xDataProvider );
187                                     uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier(
188                                             pShell->GetModel(), uno::UNO_QUERY );
189                                     xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier );
190 
191                                     lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource,
192                                                             bHasCategories, bFirstCellAsLabel );
193                                 }
194 
195 								ScChartListener* pCL = new ScChartListener(
196 									aIPName, this, pChartObj->GetRangeList() );
197 								pChartListenerCollection->Insert( pCL );
198 								pCL->StartListeningTo();
199 							}
200 						}
201 					}
202 				}
203 				pObject = aIter.Next();
204 			}
205 		}
206 	}
207 
208 	pChartCollection->FreeAll();
209 }
210 
211 sal_Bool ScDocument::HasChartAtPoint( SCTAB nTab, const Point& rPos, String* pName )
212 {
213 	if (pDrawLayer && pTab[nTab])
214 	{
215 		SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
216 		DBG_ASSERT(pPage,"Page ?");
217 
218 		SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
219 		SdrObject* pObject = aIter.Next();
220 		while (pObject)
221 		{
222 			if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
223 				 pObject->GetCurrentBoundRect().IsInside(rPos) )
224 			{
225 						// auch Chart-Objekte die nicht in der Collection sind
226 
227 				if (IsChart(pObject))
228 				{
229 					if (pName)
230 						*pName = ((SdrOle2Obj*)pObject)->GetPersistName();
231 					return sal_True;
232 				}
233 			}
234 			pObject = aIter.Next();
235 		}
236 	}
237 
238 	if (pName)
239 		pName->Erase();
240 	return sal_False;					// nix gefunden
241 }
242 
243 void ScDocument::UpdateChartArea( const String& rChartName,
244 			const ScRange& rNewArea, sal_Bool bColHeaders, sal_Bool bRowHeaders,
245 			sal_Bool bAdd )
246 {
247 	ScRangeListRef aRLR( new ScRangeList );
248 	aRLR->Append( rNewArea );
249 	UpdateChartArea( rChartName, aRLR, bColHeaders, bRowHeaders, bAdd );
250 }
251 
252 uno::Reference< chart2::XChartDocument > ScDocument::GetChartByName( const String& rChartName )
253 {
254     uno::Reference< chart2::XChartDocument > xReturn;
255 
256     if (pDrawLayer)
257     {
258         sal_uInt16 nCount = pDrawLayer->GetPageCount();
259         for (sal_uInt16 nTab=0; nTab<nCount; nTab++)
260         {
261             SdrPage* pPage = pDrawLayer->GetPage(nTab);
262             DBG_ASSERT(pPage,"Page ?");
263 
264             SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
265             SdrObject* pObject = aIter.Next();
266             while (pObject)
267             {
268                 if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
269                         ((SdrOle2Obj*)pObject)->GetPersistName() == rChartName )
270                 {
271                     xReturn.set( ScChartHelper::GetChartFromSdrObject( pObject ) );
272                     return xReturn;
273                 }
274                 pObject = aIter.Next();
275             }
276         }
277     }
278     return xReturn;
279 }
280 void ScDocument::GetChartRanges( const String& rChartName, ::std::vector< ScRangeList >& rRangesVector, ScDocument* pSheetNameDoc )
281 {
282     rRangesVector.clear();
283     uno::Reference< chart2::XChartDocument > xChartDoc( GetChartByName( rChartName ) );
284     if ( xChartDoc.is() )
285     {
286         uno::Sequence< rtl::OUString > aRangeStrings;
287         ScChartHelper::GetChartRanges( xChartDoc, aRangeStrings );
288         for( sal_Int32 nN=0; nN<aRangeStrings.getLength(); nN++ )
289         {
290             ScRangeList aRanges;
291             aRanges.Parse( aRangeStrings[nN], pSheetNameDoc, SCA_VALID, pSheetNameDoc->GetAddressConvention() );
292             rRangesVector.push_back(aRanges);
293         }
294     }
295 }
296 
297 void ScDocument::SetChartRanges( const String& rChartName, const ::std::vector< ScRangeList >& rRangesVector )
298 {
299     uno::Reference< chart2::XChartDocument > xChartDoc( GetChartByName( rChartName ) );
300     if ( xChartDoc.is() )
301     {
302         sal_Int32 nCount = static_cast<sal_Int32>( rRangesVector.size() );
303         uno::Sequence< rtl::OUString > aRangeStrings(nCount);
304         for( sal_Int32 nN=0; nN<nCount; nN++ )
305         {
306             ScRangeList aScRangeList( rRangesVector[nN] );
307             String sRangeStr; // This range must be in Calc A1 format.
308             aScRangeList.Format( sRangeStr, SCR_ABS_3D, this );
309             aRangeStrings[nN]=sRangeStr;
310         }
311         ScChartHelper::SetChartRanges( xChartDoc, aRangeStrings );
312     }
313 }
314 
315 void ScDocument::GetOldChartParameters( const String& rName,
316             ScRangeList& rRanges, sal_Bool& rColHeaders, sal_Bool& rRowHeaders )
317 {
318     // used for undo of changing chart source area
319 
320     if (!pDrawLayer)
321         return;
322 
323     sal_uInt16 nCount = pDrawLayer->GetPageCount();
324     for (sal_uInt16 nTab=0; nTab<nCount; nTab++)
325     {
326         SdrPage* pPage = pDrawLayer->GetPage(nTab);
327         DBG_ASSERT(pPage,"Page ?");
328 
329         SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
330         SdrObject* pObject = aIter.Next();
331         while (pObject)
332         {
333             if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
334                     ((SdrOle2Obj*)pObject)->GetPersistName() == rName )
335             {
336                 uno::Reference< chart2::XChartDocument > xChartDoc( ScChartHelper::GetChartFromSdrObject( pObject ) );
337                 if ( xChartDoc.is() )
338                 {
339                     chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
340                     bool bHasCategories = false;
341                     bool bFirstCellAsLabel = false;
342                     rtl::OUString aRangesStr;
343                     lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
344 
345                     rRanges.Parse( aRangesStr, this );
346                     if ( eDataRowSource == chart::ChartDataRowSource_COLUMNS )
347                     {
348                         rRowHeaders = bHasCategories;
349                         rColHeaders = bFirstCellAsLabel;
350                     }
351                     else
352                     {
353                         rColHeaders = bHasCategories;
354                         rRowHeaders = bFirstCellAsLabel;
355                     }
356                 }
357                 return;
358             }
359             pObject = aIter.Next();
360         }
361     }
362 }
363 
364 void ScDocument::UpdateChartArea( const String& rChartName,
365 			const ScRangeListRef& rNewList, sal_Bool bColHeaders, sal_Bool bRowHeaders,
366 			sal_Bool bAdd )
367 {
368 	if (!pDrawLayer)
369 		return;
370 
371 	for (SCTAB nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++)
372 	{
373 		SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
374 		DBG_ASSERT(pPage,"Page ?");
375 
376 		SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
377 		SdrObject* pObject = aIter.Next();
378 		while (pObject)
379 		{
380 			if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
381 					((SdrOle2Obj*)pObject)->GetPersistName() == rChartName )
382 			{
383                 uno::Reference< chart2::XChartDocument > xChartDoc( ScChartHelper::GetChartFromSdrObject( pObject ) );
384                 uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY );
385                 if ( xChartDoc.is() && xReceiver.is() )
386                 {
387                     ScRangeListRef aNewRanges;
388                     chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
389                     bool bHasCategories = false;
390                     bool bFirstCellAsLabel = false;
391                     rtl::OUString aRangesStr;
392                     lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
393 
394                     sal_Bool bInternalData = xChartDoc->hasInternalDataProvider();
395 
396                     if ( bAdd && !bInternalData )
397                     {
398                         // append to old ranges, keep other settings
399 
400                         aNewRanges = new ScRangeList;
401                         aNewRanges->Parse( aRangesStr, this );
402 
403                         sal_uLong nAddCount = rNewList->Count();
404                         for ( sal_uLong nAdd=0; nAdd<nAddCount; nAdd++ )
405                             aNewRanges->Append( *rNewList->GetObject(nAdd) );
406                     }
407                     else
408                     {
409                         // directly use new ranges (only eDataRowSource is used from old settings)
410 
411                         if ( eDataRowSource == chart::ChartDataRowSource_COLUMNS )
412                         {
413                             bHasCategories = bRowHeaders;
414                             bFirstCellAsLabel = bColHeaders;
415                         }
416                         else
417                         {
418                             bHasCategories = bColHeaders;
419                             bFirstCellAsLabel = bRowHeaders;
420                         }
421                         aNewRanges = rNewList;
422                     }
423 
424                     if ( bInternalData && pShell )
425                     {
426                         // Calc -> DataProvider
427                         uno::Reference< chart2::data::XDataProvider > xDataProvider = new ScChart2DataProvider( this );
428                         xReceiver->attachDataProvider( xDataProvider );
429                         uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier(
430                                 pShell->GetModel(), uno::UNO_QUERY );
431                         xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier );
432                     }
433 
434                     String sRangeStr;
435                     aNewRanges->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() );
436 
437                     lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
438 
439                     pChartListenerCollection->ChangeListening( rChartName, aNewRanges );
440 
441                     // ((SdrOle2Obj*)pObject)->GetNewReplacement();
442                     // pObject->ActionChanged();
443 
444 					return;			// nicht weitersuchen
445 				}
446 			}
447 			pObject = aIter.Next();
448 		}
449 	}
450 }
451 
452 void ScDocument::UpdateChart( const String& rChartName )
453 {
454 	if (!pDrawLayer || bInDtorClear)
455 		return;
456     uno::Reference< chart2::XChartDocument > xChartDoc( GetChartByName( rChartName ) );
457     if( xChartDoc.is() )
458     {
459         try
460         {
461             uno::Reference< util::XModifiable > xModif( xChartDoc, uno::UNO_QUERY_THROW );
462             if( apTemporaryChartLock.get() )
463                 apTemporaryChartLock->AlsoLockThisChart( uno::Reference< frame::XModel >( xModif, uno::UNO_QUERY ) );
464             xModif->setModified( sal_True );
465         }
466         catch ( uno::Exception& )
467         {
468         }
469     }
470 
471     // After the update, chart keeps track of its own data source ranges,
472     // the listener doesn't need to listen anymore, except the chart has
473     // an internal data provider.
474     if ( !( xChartDoc.is() && xChartDoc->hasInternalDataProvider() ) && pChartListenerCollection )
475     {
476         pChartListenerCollection->ChangeListening( rChartName, new ScRangeList );
477 	}
478 }
479 
480 void ScDocument::RestoreChartListener( const String& rName )
481 {
482     // Read the data ranges from the chart object, and start listening to those ranges again
483     // (called when a chart is saved, because then it might be swapped out and stop listening itself).
484 
485     uno::Reference< embed::XEmbeddedObject > xObject = FindOleObjectByName( rName );
486     if ( xObject.is() )
487     {
488         uno::Reference< util::XCloseable > xComponent = xObject->getComponent();
489         uno::Reference< chart2::XChartDocument > xChartDoc( xComponent, uno::UNO_QUERY );
490         uno::Reference< chart2::data::XDataReceiver > xReceiver( xComponent, uno::UNO_QUERY );
491         if ( xChartDoc.is() && xReceiver.is() && !xChartDoc->hasInternalDataProvider())
492         {
493             uno::Sequence<rtl::OUString> aRepresentations( xReceiver->getUsedRangeRepresentations() );
494             ScRangeListRef aRanges = new ScRangeList;
495             sal_Int32 nRangeCount = aRepresentations.getLength();
496             for ( sal_Int32 i=0; i<nRangeCount; i++ )
497             {
498                 ScRange aRange;
499                 ScAddress::Details aDetails(GetAddressConvention(), 0, 0);
500                 if ( aRange.ParseAny( aRepresentations[i], this, aDetails ) & SCA_VALID )
501                     aRanges->Append( aRange );
502             }
503 
504             pChartListenerCollection->ChangeListening( rName, aRanges );
505         }
506     }
507 }
508 
509 void ScDocument::UpdateChartRef( UpdateRefMode eUpdateRefMode,
510 									SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
511 									SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
512 									SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
513 {
514 	if (!pDrawLayer)
515 		return;
516 
517 	sal_uInt16 nChartCount = pChartListenerCollection->GetCount();
518 	for ( sal_uInt16 nIndex = 0; nIndex < nChartCount; nIndex++ )
519 	{
520 		ScChartListener* pChartListener =
521 			(ScChartListener*) (pChartListenerCollection->At(nIndex));
522 		ScRangeListRef aRLR( pChartListener->GetRangeList() );
523 		ScRangeListRef aNewRLR( new ScRangeList );
524 		sal_Bool bChanged = sal_False;
525 		sal_Bool bDataChanged = sal_False;
526 		for ( ScRangePtr pR = aRLR->First(); pR; pR = aRLR->Next() )
527 		{
528 			SCCOL theCol1 = pR->aStart.Col();
529 			SCROW theRow1 = pR->aStart.Row();
530 			SCTAB theTab1 = pR->aStart.Tab();
531 			SCCOL theCol2 = pR->aEnd.Col();
532 			SCROW theRow2 = pR->aEnd.Row();
533 			SCTAB theTab2 = pR->aEnd.Tab();
534 			ScRefUpdateRes eRes = ScRefUpdate::Update(
535 				this, eUpdateRefMode,
536 				nCol1,nRow1,nTab1, nCol2,nRow2,nTab2,
537 				nDx,nDy,nDz,
538 				theCol1,theRow1,theTab1,
539 				theCol2,theRow2,theTab2 );
540 			if ( eRes != UR_NOTHING )
541 			{
542 				bChanged = sal_True;
543 				aNewRLR->Append( ScRange(
544 					theCol1, theRow1, theTab1,
545 					theCol2, theRow2, theTab2 ));
546 				if ( eUpdateRefMode == URM_INSDEL
547 					&& !bDataChanged
548 					&& (eRes == UR_INVALID ||
549 						((pR->aEnd.Col() - pR->aStart.Col()
550 						!= theCol2 - theCol1)
551 					|| (pR->aEnd.Row() - pR->aStart.Row()
552 						!= theRow2 - theRow1)
553 					|| (pR->aEnd.Tab() - pR->aStart.Tab()
554 						!= theTab2 - theTab1))) )
555 				{
556 					bDataChanged = sal_True;
557 				}
558 			}
559 			else
560 				aNewRLR->Append( *pR );
561 		}
562 		if ( bChanged )
563 		{
564 #if 0
565 			if ( nDz != 0 )
566 			{	// #81844# sheet to be deleted or inserted or moved
567 				// => no valid sheet names for references right now
568 				pChartListener->ChangeListening( aNewRLR, bDataChanged );
569 				pChartListener->ScheduleSeriesRanges();
570 			}
571 			else
572 #endif
573 			{
574 //				SetChartRangeList( pChartListener->GetString(), aNewRLR );
575 //				pChartListener->ChangeListening( aNewRLR, bDataChanged );
576 
577                 // Force the chart to be loaded now, so it registers itself for UNO events.
578                 // UNO broadcasts are done after UpdateChartRef, so the chart will get this
579                 // reference change.
580 
581                 uno::Reference< embed::XEmbeddedObject > xIPObj = FindOleObjectByName( pChartListener->GetString() );
582                 svt::EmbeddedObjectRef::TryRunningState( xIPObj );
583 
584                 // After the change, chart keeps track of its own data source ranges,
585                 // the listener doesn't need to listen anymore, except the chart has
586                 // an internal data provider.
587                 bool bInternalDataProvider = false;
588                 if ( xIPObj.is() )
589                 {
590                     try
591                     {
592                         uno::Reference< chart2::XChartDocument > xChartDoc( xIPObj->getComponent(), uno::UNO_QUERY_THROW );
593                         bInternalDataProvider = xChartDoc->hasInternalDataProvider();
594                     }
595                     catch ( uno::Exception& )
596                     {
597                     }
598                 }
599                 if ( bInternalDataProvider )
600                 {
601                     pChartListener->ChangeListening( aNewRLR, bDataChanged );
602                 }
603                 else
604                 {
605                     pChartListener->ChangeListening( new ScRangeList, bDataChanged );
606                 }
607 			}
608 		}
609 	}
610 }
611 
612 
613 void ScDocument::SetChartRangeList( const String& rChartName,
614 			const ScRangeListRef& rNewRangeListRef )
615 {
616     // called from ChartListener
617 
618     if (!pDrawLayer)
619         return;
620 
621     for (SCTAB nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++)
622     {
623         SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
624         DBG_ASSERT(pPage,"Page ?");
625 
626         SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
627         SdrObject* pObject = aIter.Next();
628         while (pObject)
629         {
630             if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
631                     ((SdrOle2Obj*)pObject)->GetPersistName() == rChartName )
632             {
633                 uno::Reference< chart2::XChartDocument > xChartDoc( ScChartHelper::GetChartFromSdrObject( pObject ) );
634                 uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY );
635                 if ( xChartDoc.is() && xReceiver.is() )
636                 {
637                     ScRangeListRef aNewRanges;
638                     chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
639                     bool bHasCategories = false;
640                     bool bFirstCellAsLabel = false;
641                     rtl::OUString aRangesStr;
642                     lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
643 
644                     String sRangeStr;
645                     rNewRangeListRef->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() );
646 
647                     lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
648 
649                     // don't modify pChartListenerCollection here, called from there
650                     return;
651                 }
652             }
653             pObject = aIter.Next();
654         }
655     }
656 }
657 
658 
659 sal_Bool ScDocument::HasData( SCCOL nCol, SCROW nRow, SCTAB nTab )
660 {
661 	if (pTab[nTab])
662 		return pTab[nTab]->HasData( nCol, nRow );
663 	else
664 		return sal_False;
665 }
666 
667 uno::Reference< embed::XEmbeddedObject >
668     ScDocument::FindOleObjectByName( const String& rName )
669 {
670     if (!pDrawLayer)
671 		return uno::Reference< embed::XEmbeddedObject >();
672 
673 	//	die Seiten hier vom Draw-Layer nehmen,
674 	//	weil sie evtl. nicht mit den Tabellen uebereinstimmen
675 	//	(z.B. Redo von Tabelle loeschen, Draw-Redo passiert vor DeleteTab).
676 
677 	sal_uInt16 nCount = pDrawLayer->GetPageCount();
678 	for (sal_uInt16 nTab=0; nTab<nCount; nTab++)
679 	{
680 		SdrPage* pPage = pDrawLayer->GetPage(nTab);
681 		DBG_ASSERT(pPage,"Page ?");
682 
683 		SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
684 		SdrObject* pObject = aIter.Next();
685 		while (pObject)
686 		{
687 			if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
688             {
689                 SdrOle2Obj * pOleObject ( dynamic_cast< SdrOle2Obj * >( pObject ));
690                 if( pOleObject &&
691 					pOleObject->GetPersistName() == rName )
692                 {
693                     return pOleObject->GetObjRef();
694                 }
695             }
696 			pObject = aIter.Next();
697         }
698     }
699 
700     return uno::Reference< embed::XEmbeddedObject >();
701 }
702 
703 sal_Bool lcl_StringInCollection( const ScStrCollection* pColl, const String& rStr )
704 {
705 	if ( !pColl )
706 		return sal_False;
707 
708 	StrData aData( rStr );
709 	sal_uInt16 nDummy;
710 	return pColl->Search( &aData, nDummy );
711 }
712 
713 void ScDocument::UpdateChartListenerCollection()
714 {
715 	bChartListenerCollectionNeedsUpdate = sal_False;
716 	if (!pDrawLayer)
717 		return;
718 	else
719 	{
720 		ScRange aRange;
721 		// Range fuer Suche unwichtig
722 		ScChartListener aCLSearcher( EMPTY_STRING, this, aRange );
723 		for (SCTAB nTab=0; nTab<=MAXTAB; nTab++)
724 		{
725 			if (pTab[nTab])
726 			{
727 				SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
728 				DBG_ASSERT(pPage,"Page ?");
729 
730                 if (!pPage)
731                     continue;
732 
733 				SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
734 				SdrObject* pObject = aIter.Next();
735 				while (pObject)
736 				{
737 					if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
738 					{
739 						String aObjName = ((SdrOle2Obj*)pObject)->GetPersistName();
740 						aCLSearcher.SetString( aObjName );
741 						sal_uInt16 nIndex;
742 						if ( pChartListenerCollection->Search( &aCLSearcher, nIndex ) )
743 						{
744 							((ScChartListener*) (pChartListenerCollection->
745 								At( nIndex )))->SetUsed( sal_True );
746 						}
747 						else if ( lcl_StringInCollection( pOtherObjects, aObjName ) )
748 						{
749 							// non-chart OLE object -> don't touch
750 						}
751 						else
752 						{
753 						    bool bIsChart = false;
754 
755 							uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
756                             DBG_ASSERT( xIPObj.is(), "No embedded object is given!");
757                             uno::Reference< ::com::sun::star::chart2::data::XDataReceiver > xReceiver;
758                             uno::Reference< embed::XComponentSupplier > xCompSupp( xIPObj, uno::UNO_QUERY );
759                             if( xCompSupp.is())
760                                 xReceiver.set( xCompSupp->getComponent(), uno::UNO_QUERY );
761 
762                             // if the object is a chart2::XDataReceiver, we must attach as XDataProvider
763                             if( xReceiver.is() &&
764                                 !PastingDrawFromOtherDoc())
765                             {
766                                 // NOTE: this currently does not work as we are
767                                 // unable to set the data. So a chart from the
768                                 // same document is treated like a chart with
769                                 // own data for the time being.
770 #if 0
771                                 // data provider
772                                 uno::Reference< chart2::data::XDataProvider > xDataProvider = new
773                                     ScChart2DataProvider( this );
774                                 xReceiver->attachDataProvider( xDataProvider );
775                                 // number formats supplier
776                                 uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( pShell->GetModel(), uno::UNO_QUERY );
777                                 xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier );
778                                 // data ?
779                                 // how to set?? Defined in XML-file, which is already loaded!!!
780                                 // => we have to do this stuff here, BEFORE the chart is actually loaded
781 
782                                 bIsChart = true;
783 #endif
784                             }
785 
786 						    if (!bIsChart)
787 						    {
788 							    //	put into list of other ole objects, so the object doesn't have to
789 							    //	be swapped in the next time UpdateChartListenerCollection is called
790 							    //!	remove names when objects are no longer there?
791 							    //	(object names aren't used again before reloading the document)
792 
793 							    if (!pOtherObjects)
794 								    pOtherObjects = new ScStrCollection;
795 							    pOtherObjects->Insert( new StrData( aObjName ) );
796 						    }
797 						}
798 					}
799 					pObject = aIter.Next();
800 				}
801 			}
802 		}
803 		// alle nicht auf SetUsed gesetzten loeschen
804 		pChartListenerCollection->FreeUnused();
805 	}
806 }
807 
808 void ScDocument::AddOLEObjectToCollection(const String& rName)
809 {
810 	if (!pOtherObjects)
811 		pOtherObjects = new ScStrCollection;
812 	pOtherObjects->Insert( new StrData( rName ) );
813 }
814 
815 
816 
817