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