merge the formfield patch from ooo-build
[ooovba.git] / sc / source / core / data / documen5.cxx
blob24cbf48646b63e223521bd00bc8a9ae50ffa9f3f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: documen5.cxx,v $
10 * $Revision: 1.34 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 #include <com/sun/star/util/XModifiable.hpp>
35 #include <com/sun/star/chart/ChartDataRowSource.hpp>
36 #include <com/sun/star/chart2/XChartDocument.hpp>
37 #include <com/sun/star/chart2/data/XDataProvider.hpp>
38 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
39 #include <com/sun/star/embed/EmbedStates.hpp>
40 #include <com/sun/star/embed/XEmbeddedObject.hpp>
43 #ifdef _MSC_VER
44 #pragma optimize("",off)
45 #endif
47 // INCLUDE ---------------------------------------------------------------
49 #include <sfx2/objsh.hxx>
50 #include <svx/svditer.hxx>
51 #include <svx/svdoole2.hxx>
52 #include <svx/svdpage.hxx>
54 //REMOVE #ifndef SO2_DECL_SVINPLACEOBJECT_DEFINED
55 //REMOVE #define SO2_DECL_SVINPLACEOBJECT_DEFINED
56 //REMOVE SO2_DECL_REF(SvInPlaceObject)
57 //REMOVE #endif
59 #include "document.hxx"
60 #include "drwlayer.hxx"
61 #include "chartarr.hxx"
62 #include "chartlis.hxx"
63 #include "chartlock.hxx"
64 #include "refupdat.hxx"
65 #include <tools/globname.hxx>
66 #include <sot/exchange.hxx>
68 #include "miscuno.hxx"
69 #include "chart2uno.hxx"
71 using namespace ::com::sun::star;
73 // -----------------------------------------------------------------------
75 void lcl_GetChartRanges( const uno::Reference< chart2::XChartDocument >& xChartDoc,
76 uno::Sequence< rtl::OUString >& rRanges )
78 rRanges.realloc(0);
79 uno::Reference< chart2::data::XDataSource > xDataSource( xChartDoc, uno::UNO_QUERY );
80 if( !xDataSource.is() )
81 return;
82 //uno::Reference< chart2::data::XDataProvider > xProvider = xChartDoc->getDataProvider();
84 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aLabeledDataSequences( xDataSource->getDataSequences() );
85 rRanges.realloc(2*aLabeledDataSequences.getLength());
86 sal_Int32 nRealCount=0;
87 for( sal_Int32 nN=0;nN<aLabeledDataSequences.getLength();nN++)
89 uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSequence( aLabeledDataSequences[nN] );
90 if(!xLabeledSequence.is())
91 continue;
92 uno::Reference< chart2::data::XDataSequence > xLabel( xLabeledSequence->getLabel());
93 uno::Reference< chart2::data::XDataSequence > xValues( xLabeledSequence->getValues());
95 if( xLabel.is())
96 rRanges[nRealCount++] = xLabel->getSourceRangeRepresentation();
97 if( xValues.is())
98 rRanges[nRealCount++] = xValues->getSourceRangeRepresentation();
100 rRanges.realloc(nRealCount);
103 void lcl_SetChartRanges( const uno::Reference< chart2::XChartDocument >& xChartDoc,
104 const uno::Sequence< rtl::OUString >& rRanges )
106 uno::Reference< chart2::data::XDataSource > xDataSource( xChartDoc, uno::UNO_QUERY );
107 if( !xDataSource.is() )
108 return;
109 uno::Reference< chart2::data::XDataProvider > xDataProvider = xChartDoc->getDataProvider();
110 if( !xDataProvider.is() )
111 return;
113 uno::Reference< frame::XModel > xModel( xChartDoc, uno::UNO_QUERY );
114 if( xModel.is() )
115 xModel->lockControllers();
119 rtl::OUString aPropertyNameRole( ::rtl::OUString::createFromAscii("Role") );
121 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aLabeledDataSequences( xDataSource->getDataSequences() );
122 sal_Int32 nRange=0;
123 for( sal_Int32 nN=0; (nN<aLabeledDataSequences.getLength()) && (nRange<rRanges.getLength()); nN++ )
125 uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSequence( aLabeledDataSequences[nN] );
126 if(!xLabeledSequence.is())
127 continue;
128 uno::Reference< beans::XPropertySet > xLabel( xLabeledSequence->getLabel(), uno::UNO_QUERY );
129 uno::Reference< beans::XPropertySet > xValues( xLabeledSequence->getValues(), uno::UNO_QUERY );
131 if( xLabel.is())
133 // the range string must be in Calc A1 format.
134 uno::Reference< chart2::data::XDataSequence > xNewSeq(
135 xDataProvider->createDataSequenceByRangeRepresentation( rRanges[nRange++] ));
137 uno::Reference< beans::XPropertySet > xNewProps( xNewSeq, uno::UNO_QUERY );
138 if( xNewProps.is() )
139 xNewProps->setPropertyValue( aPropertyNameRole, xLabel->getPropertyValue( aPropertyNameRole ) );
141 xLabeledSequence->setLabel( xNewSeq );
144 if( !(nRange<rRanges.getLength()) )
145 break;
147 if( xValues.is())
149 // the range string must be in Calc A1 format.
150 uno::Reference< chart2::data::XDataSequence > xNewSeq(
151 xDataProvider->createDataSequenceByRangeRepresentation( rRanges[nRange++] ));
153 uno::Reference< beans::XPropertySet > xNewProps( xNewSeq, uno::UNO_QUERY );
154 if( xNewProps.is() )
155 xNewProps->setPropertyValue( aPropertyNameRole, xValues->getPropertyValue( aPropertyNameRole ) );
157 xLabeledSequence->setValues( xNewSeq );
161 catch ( uno::Exception& ex )
163 (void)ex;
164 DBG_ERROR("Exception in lcl_SetChartRanges - invalid range string?");
167 if( xModel.is() )
168 xModel->unlockControllers();
171 void lcl_GetChartParameters( const uno::Reference< chart2::XChartDocument >& xChartDoc,
172 rtl::OUString& rRanges, chart::ChartDataRowSource& rDataRowSource,
173 bool& rHasCategories, bool& rFirstCellAsLabel )
175 rHasCategories = rFirstCellAsLabel = false; // default if not in sequence
177 uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY );
179 uno::Reference< chart2::data::XDataSource > xDataSource = xReceiver->getUsedData();
180 uno::Reference< chart2::data::XDataProvider > xProvider = xChartDoc->getDataProvider();
182 if ( xProvider.is() )
184 uno::Sequence< beans::PropertyValue > aArgs( xProvider->detectArguments( xDataSource ) );
186 const beans::PropertyValue* pPropArray = aArgs.getConstArray();
187 long nPropCount = aArgs.getLength();
188 for (long i = 0; i < nPropCount; i++)
190 const beans::PropertyValue& rProp = pPropArray[i];
191 String aPropName(rProp.Name);
193 if (aPropName.EqualsAscii( "CellRangeRepresentation" ))
194 rProp.Value >>= rRanges;
195 else if (aPropName.EqualsAscii( "DataRowSource" ))
196 rDataRowSource = (chart::ChartDataRowSource)ScUnoHelpFunctions::GetEnumFromAny( rProp.Value );
197 else if (aPropName.EqualsAscii( "HasCategories" ))
198 rHasCategories = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
199 else if (aPropName.EqualsAscii( "FirstCellAsLabel" ))
200 rFirstCellAsLabel = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
205 void lcl_SetChartParameters( const uno::Reference< chart2::data::XDataReceiver >& xReceiver,
206 const rtl::OUString& rRanges, chart::ChartDataRowSource eDataRowSource,
207 bool bHasCategories, bool bFirstCellAsLabel )
209 if ( xReceiver.is() )
211 uno::Sequence< beans::PropertyValue > aArgs( 4 );
212 aArgs[0] = beans::PropertyValue(
213 ::rtl::OUString::createFromAscii("CellRangeRepresentation"), -1,
214 uno::makeAny( rRanges ), beans::PropertyState_DIRECT_VALUE );
215 aArgs[1] = beans::PropertyValue(
216 ::rtl::OUString::createFromAscii("HasCategories"), -1,
217 uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE );
218 aArgs[2] = beans::PropertyValue(
219 ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1,
220 uno::makeAny( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE );
221 aArgs[3] = beans::PropertyValue(
222 ::rtl::OUString::createFromAscii("DataRowSource"), -1,
223 uno::makeAny( eDataRowSource ), beans::PropertyState_DIRECT_VALUE );
224 xReceiver->setArguments( aArgs );
228 // update charts after loading old document
230 void ScDocument::UpdateAllCharts()
232 if ( !pDrawLayer || !pShell )
233 return;
235 USHORT nDataCount = pChartCollection->GetCount();
236 if ( !nDataCount )
237 return ; // nothing to do
239 USHORT nPos;
241 for (SCTAB nTab=0; nTab<=MAXTAB; nTab++)
243 if (pTab[nTab])
245 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
246 DBG_ASSERT(pPage,"Page ?");
248 ScRange aRange;
249 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
250 SdrObject* pObject = aIter.Next();
251 while (pObject)
253 if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
255 uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
256 if ( xIPObj.is() )
258 String aIPName = ((SdrOle2Obj*)pObject)->GetPersistName();
260 for (nPos=0; nPos<nDataCount; nPos++)
262 ScChartArray* pChartObj = (*pChartCollection)[nPos];
263 if (pChartObj->GetName() == aIPName)
265 ScRangeListRef aRanges = pChartObj->GetRangeList();
266 String sRangeStr;
267 aRanges->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() );
269 chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
270 bool bHasCategories = pChartObj->HasRowHeaders();
271 bool bFirstCellAsLabel = pChartObj->HasColHeaders();
273 // Calc -> DataProvider
274 uno::Reference< chart2::data::XDataProvider > xDataProvider =
275 new ScChart2DataProvider( this );
276 // Chart -> DataReceiver
277 uno::Reference< chart2::data::XDataReceiver > xReceiver;
278 uno::Reference< embed::XComponentSupplier > xCompSupp( xIPObj, uno::UNO_QUERY );
279 if( xCompSupp.is())
280 xReceiver.set( xCompSupp->getComponent(), uno::UNO_QUERY );
281 if( xReceiver.is())
283 // connect
284 xReceiver->attachDataProvider( xDataProvider );
285 uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier(
286 pShell->GetModel(), uno::UNO_QUERY );
287 xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier );
289 lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource,
290 bHasCategories, bFirstCellAsLabel );
293 ScChartListener* pCL = new ScChartListener(
294 aIPName, this, pChartObj->GetRangeList() );
295 pChartListenerCollection->Insert( pCL );
296 pCL->StartListeningTo();
301 pObject = aIter.Next();
306 pChartCollection->FreeAll();
309 BOOL ScDocument::HasChartAtPoint( SCTAB nTab, const Point& rPos, String* pName )
311 if (pDrawLayer && pTab[nTab])
313 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
314 DBG_ASSERT(pPage,"Page ?");
316 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
317 SdrObject* pObject = aIter.Next();
318 while (pObject)
320 if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
321 pObject->GetCurrentBoundRect().IsInside(rPos) )
323 // auch Chart-Objekte die nicht in der Collection sind
325 if (IsChart(pObject))
327 if (pName)
328 *pName = ((SdrOle2Obj*)pObject)->GetPersistName();
329 return TRUE;
332 pObject = aIter.Next();
336 if (pName)
337 pName->Erase();
338 return FALSE; // nix gefunden
341 void ScDocument::UpdateChartArea( const String& rChartName,
342 const ScRange& rNewArea, BOOL bColHeaders, BOOL bRowHeaders,
343 BOOL bAdd )
345 ScRangeListRef aRLR( new ScRangeList );
346 aRLR->Append( rNewArea );
347 UpdateChartArea( rChartName, aRLR, bColHeaders, bRowHeaders, bAdd );
350 uno::Reference< chart2::XChartDocument > ScDocument::GetChartByName( const String& rChartName )
352 uno::Reference< chart2::XChartDocument > xReturn;
354 if (pDrawLayer)
356 sal_uInt16 nCount = pDrawLayer->GetPageCount();
357 for (sal_uInt16 nTab=0; nTab<nCount; nTab++)
359 SdrPage* pPage = pDrawLayer->GetPage(nTab);
360 DBG_ASSERT(pPage,"Page ?");
362 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
363 SdrObject* pObject = aIter.Next();
364 while (pObject)
366 if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
367 ((SdrOle2Obj*)pObject)->GetPersistName() == rChartName )
369 uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
370 if ( xIPObj.is() )
372 svt::EmbeddedObjectRef::TryRunningState( xIPObj );
374 uno::Reference< util::XCloseable > xComponent = xIPObj->getComponent();
375 xReturn.set( uno::Reference< chart2::XChartDocument >( xComponent, uno::UNO_QUERY ) );
377 return xReturn;
379 pObject = aIter.Next();
383 return xReturn;
385 void ScDocument::GetChartRanges( const String& rChartName, ::std::vector< ScRangeList >& rRangesVector, ScDocument* pSheetNameDoc )
387 rRangesVector.clear();
388 uno::Reference< chart2::XChartDocument > xChartDoc( GetChartByName( rChartName ) );
389 if ( xChartDoc.is() )
391 uno::Sequence< rtl::OUString > aRangeStrings;
392 lcl_GetChartRanges( xChartDoc, aRangeStrings );
393 for( sal_Int32 nN=0; nN<aRangeStrings.getLength(); nN++ )
395 ScRangeList aRanges;
396 aRanges.Parse( aRangeStrings[nN], pSheetNameDoc, SCA_VALID, pSheetNameDoc->GetAddressConvention() );
397 rRangesVector.push_back(aRanges);
402 void ScDocument::SetChartRanges( const String& rChartName, const ::std::vector< ScRangeList >& rRangesVector )
404 uno::Reference< chart2::XChartDocument > xChartDoc( GetChartByName( rChartName ) );
405 if ( xChartDoc.is() )
407 sal_Int32 nCount = static_cast<sal_Int32>( rRangesVector.size() );
408 uno::Sequence< rtl::OUString > aRangeStrings(nCount);
409 for( sal_Int32 nN=0; nN<nCount; nN++ )
411 ScRangeList aScRangeList( rRangesVector[nN] );
412 String sRangeStr; // This range must be in Calc A1 format.
413 aScRangeList.Format( sRangeStr, SCR_ABS_3D, this );
414 aRangeStrings[nN]=sRangeStr;
416 lcl_SetChartRanges( xChartDoc, aRangeStrings );
420 void ScDocument::GetOldChartParameters( const String& rName,
421 ScRangeList& rRanges, BOOL& rColHeaders, BOOL& rRowHeaders )
423 // used for undo of changing chart source area
425 if (!pDrawLayer)
426 return;
428 sal_uInt16 nCount = pDrawLayer->GetPageCount();
429 for (sal_uInt16 nTab=0; nTab<nCount; nTab++)
431 SdrPage* pPage = pDrawLayer->GetPage(nTab);
432 DBG_ASSERT(pPage,"Page ?");
434 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
435 SdrObject* pObject = aIter.Next();
436 while (pObject)
438 if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
439 ((SdrOle2Obj*)pObject)->GetPersistName() == rName )
441 uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
442 if ( xIPObj.is() )
444 svt::EmbeddedObjectRef::TryRunningState( xIPObj );
446 uno::Reference< util::XCloseable > xComponent = xIPObj->getComponent();
447 uno::Reference< chart2::XChartDocument > xChartDoc( xComponent, uno::UNO_QUERY );
448 if ( xChartDoc.is() )
450 chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
451 bool bHasCategories = false;
452 bool bFirstCellAsLabel = false;
453 rtl::OUString aRangesStr;
454 lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
456 rRanges.Parse( aRangesStr, this );
457 if ( eDataRowSource == chart::ChartDataRowSource_COLUMNS )
459 rRowHeaders = bHasCategories;
460 rColHeaders = bFirstCellAsLabel;
462 else
464 rColHeaders = bHasCategories;
465 rRowHeaders = bFirstCellAsLabel;
469 return;
471 pObject = aIter.Next();
476 void ScDocument::UpdateChartArea( const String& rChartName,
477 const ScRangeListRef& rNewList, BOOL bColHeaders, BOOL bRowHeaders,
478 BOOL bAdd )
480 if (!pDrawLayer)
481 return;
483 for (SCTAB nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++)
485 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
486 DBG_ASSERT(pPage,"Page ?");
488 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
489 SdrObject* pObject = aIter.Next();
490 while (pObject)
492 if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
493 ((SdrOle2Obj*)pObject)->GetPersistName() == rChartName )
495 uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
496 if ( xIPObj.is() )
498 svt::EmbeddedObjectRef::TryRunningState( xIPObj );
500 uno::Reference< util::XCloseable > xComponent = xIPObj->getComponent();
501 uno::Reference< chart2::XChartDocument > xChartDoc( xComponent, uno::UNO_QUERY );
502 uno::Reference< chart2::data::XDataReceiver > xReceiver( xComponent, uno::UNO_QUERY );
503 if ( xChartDoc.is() && xReceiver.is() )
505 ScRangeListRef aNewRanges;
506 chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
507 bool bHasCategories = false;
508 bool bFirstCellAsLabel = false;
509 rtl::OUString aRangesStr;
510 lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
512 sal_Bool bInternalData = xChartDoc->hasInternalDataProvider();
514 if ( bAdd && !bInternalData )
516 // append to old ranges, keep other settings
518 aNewRanges = new ScRangeList;
519 aNewRanges->Parse( aRangesStr, this );
521 ULONG nAddCount = rNewList->Count();
522 for ( ULONG nAdd=0; nAdd<nAddCount; nAdd++ )
523 aNewRanges->Append( *rNewList->GetObject(nAdd) );
525 else
527 // directly use new ranges (only eDataRowSource is used from old settings)
529 if ( eDataRowSource == chart::ChartDataRowSource_COLUMNS )
531 bHasCategories = bRowHeaders;
532 bFirstCellAsLabel = bColHeaders;
534 else
536 bHasCategories = bColHeaders;
537 bFirstCellAsLabel = bRowHeaders;
539 aNewRanges = rNewList;
542 if ( bInternalData && pShell )
544 // Calc -> DataProvider
545 uno::Reference< chart2::data::XDataProvider > xDataProvider = new ScChart2DataProvider( this );
546 xReceiver->attachDataProvider( xDataProvider );
547 uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier(
548 pShell->GetModel(), uno::UNO_QUERY );
549 xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier );
552 String sRangeStr;
553 aNewRanges->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() );
555 lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
557 pChartListenerCollection->ChangeListening( rChartName, aNewRanges );
559 // ((SdrOle2Obj*)pObject)->GetNewReplacement();
560 // pObject->ActionChanged();
562 return; // nicht weitersuchen
566 pObject = aIter.Next();
571 void ScDocument::UpdateChart( const String& rChartName )
573 if (!pDrawLayer || bInDtorClear)
574 return;
576 for (SCTAB nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++)
578 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
579 DBG_ASSERT(pPage,"Page ?");
581 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
582 SdrObject* pObject = aIter.Next();
583 while (pObject)
585 if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
586 ((SdrOle2Obj*)pObject)->GetPersistName() == rChartName )
588 //@todo?: maybe we need a notification
589 //from the calc to the chart in future
590 //that calc content has changed
591 // ((SdrOle2Obj*)pObject)->GetNewReplacement();
593 // Load the object and set modified
595 uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
596 if ( xIPObj.is() )
598 svt::EmbeddedObjectRef::TryRunningState( xIPObj );
602 uno::Reference< util::XModifiable > xModif( xIPObj->getComponent(), uno::UNO_QUERY_THROW );
603 if( apTemporaryChartLock.get() )
604 apTemporaryChartLock->AlsoLockThisChart( uno::Reference< frame::XModel >( xModif, uno::UNO_QUERY ) );
605 xModif->setModified( sal_True );
607 catch ( uno::Exception& )
612 // repaint
614 pObject->ActionChanged();
616 // After the update, chart keeps track of its own data source ranges,
617 // the listener doesn't need to listen anymore.
619 pChartListenerCollection->ChangeListening( rChartName, new ScRangeList );
621 return;
623 /* old chart:
624 uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
625 if ( xIPObj.is() )
627 const SchMemChart* pChartData = SchDLL::GetChartData(xIPObj);
628 if ( pChartData )
630 ScChartArray aArray( this, *pChartData );
632 SchMemChart* pMemChart = aArray.CreateMemChart();
633 ScChartArray::CopySettings( *pMemChart, *pChartData );
635 // #57655# Chart-Update ohne geaenderte Einstellungen (MemChart)
636 // soll das Dokument nicht auf modified setzen (z.B. in frisch
637 // geladenem Dokument durch initiales Recalc)
639 // #72576# disable SetModified for readonly documents only
641 sal_Bool bEnabled = ( (pShell && pShell->IsReadOnly()) || IsImportingXML() );
642 sal_Bool bModified = sal_False;
643 uno::Reference< util::XModifiable > xModif;
645 if ( bEnabled )
649 xModif =
650 uno::Reference< util::XModifiable >( xIPObj->getComponent(), uno::UNO_QUERY_THROW );
651 bModified = xModif->isModified();
653 catch( uno::Exception& )
655 bEnabled = sal_False;
659 SchDLL::Update( xIPObj, pMemChart, pWindow );
660 ((SdrOle2Obj*)pObject)->GetNewReplacement();
661 delete pMemChart;
663 // Dies veranlaesst Chart zum sofortigen Update
664 //SvData aEmpty;
665 //aIPObj->SendDataChanged( aEmpty );
667 // the method below did nothing in SO7
668 //REMOVE aIPObj->SendViewChanged();
670 // redraw only
671 pObject->ActionChanged();
672 // pObject->SendRepaintBroadcast();
674 if ( bEnabled && xModif.is() )
678 if ( xModif->isModified() != bModified )
679 xModif->setModified( bModified );
681 catch ( uno::Exception& )
685 return; // nicht weitersuchen
690 pObject = aIter.Next();
695 void ScDocument::RestoreChartListener( const String& rName )
697 // Read the data ranges from the chart object, and start listening to those ranges again
698 // (called when a chart is saved, because then it might be swapped out and stop listening itself).
700 uno::Reference< embed::XEmbeddedObject > xObject = FindOleObjectByName( rName );
701 if ( xObject.is() )
703 uno::Reference< util::XCloseable > xComponent = xObject->getComponent();
704 uno::Reference< chart2::XChartDocument > xChartDoc( xComponent, uno::UNO_QUERY );
705 uno::Reference< chart2::data::XDataReceiver > xReceiver( xComponent, uno::UNO_QUERY );
706 if ( xChartDoc.is() && xReceiver.is() && !xChartDoc->hasInternalDataProvider())
708 uno::Sequence<rtl::OUString> aRepresentations( xReceiver->getUsedRangeRepresentations() );
709 ScRangeListRef aRanges = new ScRangeList;
710 sal_Int32 nRangeCount = aRepresentations.getLength();
711 for ( sal_Int32 i=0; i<nRangeCount; i++ )
713 ScRange aRange;
714 ScAddress::Details aDetails(GetAddressConvention(), 0, 0);
715 if ( aRange.ParseAny( aRepresentations[i], this, aDetails ) & SCA_VALID )
716 aRanges->Append( aRange );
719 pChartListenerCollection->ChangeListening( rName, aRanges );
724 void ScDocument::UpdateChartRef( UpdateRefMode eUpdateRefMode,
725 SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
726 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
727 SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
729 if (!pDrawLayer)
730 return;
732 USHORT nChartCount = pChartListenerCollection->GetCount();
733 for ( USHORT nIndex = 0; nIndex < nChartCount; nIndex++ )
735 ScChartListener* pChartListener =
736 (ScChartListener*) (pChartListenerCollection->At(nIndex));
737 ScRangeListRef aRLR( pChartListener->GetRangeList() );
738 ScRangeListRef aNewRLR( new ScRangeList );
739 BOOL bChanged = FALSE;
740 BOOL bDataChanged = FALSE;
741 for ( ScRangePtr pR = aRLR->First(); pR; pR = aRLR->Next() )
743 SCCOL theCol1 = pR->aStart.Col();
744 SCROW theRow1 = pR->aStart.Row();
745 SCTAB theTab1 = pR->aStart.Tab();
746 SCCOL theCol2 = pR->aEnd.Col();
747 SCROW theRow2 = pR->aEnd.Row();
748 SCTAB theTab2 = pR->aEnd.Tab();
749 ScRefUpdateRes eRes = ScRefUpdate::Update(
750 this, eUpdateRefMode,
751 nCol1,nRow1,nTab1, nCol2,nRow2,nTab2,
752 nDx,nDy,nDz,
753 theCol1,theRow1,theTab1,
754 theCol2,theRow2,theTab2 );
755 if ( eRes != UR_NOTHING )
757 bChanged = TRUE;
758 aNewRLR->Append( ScRange(
759 theCol1, theRow1, theTab1,
760 theCol2, theRow2, theTab2 ));
761 if ( eUpdateRefMode == URM_INSDEL
762 && !bDataChanged
763 && (eRes == UR_INVALID ||
764 ((pR->aEnd.Col() - pR->aStart.Col()
765 != theCol2 - theCol1)
766 || (pR->aEnd.Row() - pR->aStart.Row()
767 != theRow2 - theRow1)
768 || (pR->aEnd.Tab() - pR->aStart.Tab()
769 != theTab2 - theTab1))) )
771 bDataChanged = TRUE;
774 else
775 aNewRLR->Append( *pR );
777 if ( bChanged )
779 #if 0
780 if ( nDz != 0 )
781 { // #81844# sheet to be deleted or inserted or moved
782 // => no valid sheet names for references right now
783 pChartListener->ChangeListening( aNewRLR, bDataChanged );
784 pChartListener->ScheduleSeriesRanges();
786 else
787 #endif
789 // SetChartRangeList( pChartListener->GetString(), aNewRLR );
790 // pChartListener->ChangeListening( aNewRLR, bDataChanged );
792 // Force the chart to be loaded now, so it registers itself for UNO events.
793 // UNO broadcasts are done after UpdateChartRef, so the chart will get this
794 // reference change.
796 uno::Reference< embed::XEmbeddedObject > xIPObj = FindOleObjectByName( pChartListener->GetString() );
797 svt::EmbeddedObjectRef::TryRunningState( xIPObj );
799 // After the change, chart keeps track of its own data source ranges,
800 // the listener doesn't need to listen anymore.
802 pChartListener->ChangeListening( new ScRangeList, bDataChanged );
809 void ScDocument::SetChartRangeList( const String& rChartName,
810 const ScRangeListRef& rNewRangeListRef )
812 // called from ChartListener
814 if (!pDrawLayer)
815 return;
817 for (SCTAB nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++)
819 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
820 DBG_ASSERT(pPage,"Page ?");
822 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
823 SdrObject* pObject = aIter.Next();
824 while (pObject)
826 if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
827 ((SdrOle2Obj*)pObject)->GetPersistName() == rChartName )
829 uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
830 if ( xIPObj.is() )
832 svt::EmbeddedObjectRef::TryRunningState( xIPObj );
834 uno::Reference< util::XCloseable > xComponent = xIPObj->getComponent();
835 uno::Reference< chart2::XChartDocument > xChartDoc( xComponent, uno::UNO_QUERY );
836 uno::Reference< chart2::data::XDataReceiver > xReceiver( xComponent, uno::UNO_QUERY );
837 if ( xChartDoc.is() && xReceiver.is() )
839 ScRangeListRef aNewRanges;
840 chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
841 bool bHasCategories = false;
842 bool bFirstCellAsLabel = false;
843 rtl::OUString aRangesStr;
844 lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
846 String sRangeStr;
847 rNewRangeListRef->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() );
849 lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
851 // don't modify pChartListenerCollection here, called from there
852 return;
856 pObject = aIter.Next();
862 BOOL ScDocument::HasData( SCCOL nCol, SCROW nRow, SCTAB nTab )
864 if (pTab[nTab])
865 return pTab[nTab]->HasData( nCol, nRow );
866 else
867 return FALSE;
870 uno::Reference< embed::XEmbeddedObject >
871 ScDocument::FindOleObjectByName( const String& rName )
873 if (!pDrawLayer)
874 return uno::Reference< embed::XEmbeddedObject >();
876 // die Seiten hier vom Draw-Layer nehmen,
877 // weil sie evtl. nicht mit den Tabellen uebereinstimmen
878 // (z.B. Redo von Tabelle loeschen, Draw-Redo passiert vor DeleteTab).
880 sal_uInt16 nCount = pDrawLayer->GetPageCount();
881 for (sal_uInt16 nTab=0; nTab<nCount; nTab++)
883 SdrPage* pPage = pDrawLayer->GetPage(nTab);
884 DBG_ASSERT(pPage,"Page ?");
886 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
887 SdrObject* pObject = aIter.Next();
888 while (pObject)
890 if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
892 SdrOle2Obj * pOleObject ( dynamic_cast< SdrOle2Obj * >( pObject ));
893 if( pOleObject &&
894 pOleObject->GetPersistName() == rName )
896 return pOleObject->GetObjRef();
899 pObject = aIter.Next();
903 return uno::Reference< embed::XEmbeddedObject >();
906 BOOL lcl_StringInCollection( const ScStrCollection* pColl, const String& rStr )
908 if ( !pColl )
909 return FALSE;
911 StrData aData( rStr );
912 USHORT nDummy;
913 return pColl->Search( &aData, nDummy );
916 void ScDocument::UpdateChartListenerCollection()
918 bChartListenerCollectionNeedsUpdate = FALSE;
919 if (!pDrawLayer)
920 return;
921 else
923 ScRange aRange;
924 // Range fuer Suche unwichtig
925 ScChartListener aCLSearcher( EMPTY_STRING, this, aRange );
926 for (SCTAB nTab=0; nTab<=MAXTAB; nTab++)
928 if (pTab[nTab])
930 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
931 DBG_ASSERT(pPage,"Page ?");
933 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
934 SdrObject* pObject = aIter.Next();
935 while (pObject)
937 if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
939 String aObjName = ((SdrOle2Obj*)pObject)->GetPersistName();
940 aCLSearcher.SetString( aObjName );
941 USHORT nIndex;
942 if ( pChartListenerCollection->Search( &aCLSearcher, nIndex ) )
944 ((ScChartListener*) (pChartListenerCollection->
945 At( nIndex )))->SetUsed( TRUE );
947 else if ( lcl_StringInCollection( pOtherObjects, aObjName ) )
949 // non-chart OLE object -> don't touch
951 else
953 bool bIsChart = false;
955 uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
956 DBG_ASSERT( xIPObj.is(), "No embedded object is given!");
957 uno::Reference< ::com::sun::star::chart2::data::XDataReceiver > xReceiver;
958 uno::Reference< embed::XComponentSupplier > xCompSupp( xIPObj, uno::UNO_QUERY );
959 if( xCompSupp.is())
960 xReceiver.set( xCompSupp->getComponent(), uno::UNO_QUERY );
962 // if the object is a chart2::XDataReceiver, we must attach as XDataProvider
963 if( xReceiver.is() &&
964 !PastingDrawFromOtherDoc())
966 // NOTE: this currently does not work as we are
967 // unable to set the data. So a chart from the
968 // same document is treated like a chart with
969 // own data for the time being.
970 #if 0
971 // data provider
972 uno::Reference< chart2::data::XDataProvider > xDataProvider = new
973 ScChart2DataProvider( this );
974 xReceiver->attachDataProvider( xDataProvider );
975 // number formats supplier
976 uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( pShell->GetModel(), uno::UNO_QUERY );
977 xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier );
978 // data ?
979 // how to set?? Defined in XML-file, which is already loaded!!!
980 // => we have to do this stuff here, BEFORE the chart is actually loaded
982 bIsChart = true;
983 #endif
986 if (!bIsChart)
988 // put into list of other ole objects, so the object doesn't have to
989 // be swapped in the next time UpdateChartListenerCollection is called
990 //! remove names when objects are no longer there?
991 // (object names aren't used again before reloading the document)
993 if (!pOtherObjects)
994 pOtherObjects = new ScStrCollection;
995 pOtherObjects->Insert( new StrData( aObjName ) );
999 pObject = aIter.Next();
1003 // alle nicht auf SetUsed gesetzten loeschen
1004 pChartListenerCollection->FreeUnused();
1008 void ScDocument::AddOLEObjectToCollection(const String& rName)
1010 if (!pOtherObjects)
1011 pOtherObjects = new ScStrCollection;
1012 pOtherObjects->Insert( new StrData( rName ) );