merge the formfield patch from ooo-build
[ooovba.git] / sc / source / filter / excel / xichart.cxx
blob3b0243622710a2dfb30bc4f5d896b143cae1740b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xichart.cxx,v $
10 * $Revision: 1.20.62.14 $
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 "xichart.hxx"
36 #include <algorithm>
37 #include <memory>
39 #include <com/sun/star/frame/XModel.hpp>
40 #include <com/sun/star/drawing/Direction3D.hpp>
41 #include <com/sun/star/drawing/ProjectionMode.hpp>
42 #include <com/sun/star/drawing/ShadeMode.hpp>
43 #include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp>
44 #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
45 #include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
46 #include <com/sun/star/chart/ChartAxisPosition.hpp>
47 #include <com/sun/star/chart/XChartDocument.hpp>
48 #include <com/sun/star/chart2/XChartDocument.hpp>
49 #include <com/sun/star/chart2/XDiagram.hpp>
50 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
51 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
52 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
53 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
54 #include <com/sun/star/chart2/XTitled.hpp>
55 #include <com/sun/star/chart2/data/XDataProvider.hpp>
56 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
57 #include <com/sun/star/chart2/data/XDataSink.hpp>
58 #include <com/sun/star/chart2/AxisType.hpp>
59 #include <com/sun/star/chart2/CurveStyle.hpp>
60 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
61 #include <com/sun/star/chart2/DataPointLabel.hpp>
62 #include <com/sun/star/chart2/StackingDirection.hpp>
63 #include <com/sun/star/chart2/TickmarkStyle.hpp>
64 #include <com/sun/star/chart/DataLabelPlacement.hpp>
65 #include <com/sun/star/chart/ErrorBarStyle.hpp>
66 #include <com/sun/star/chart/MissingValueTreatment.hpp>
68 #include <sfx2/objsh.hxx>
70 #include "document.hxx"
71 #include "drwlayer.hxx"
72 #include "rangeutl.hxx"
73 #include "tokenarray.hxx"
74 #include "token.hxx"
75 #include "compiler.hxx"
76 #include "reftokenhelper.hxx"
77 #include "chartlis.hxx"
78 #include "fprogressbar.hxx"
79 #include "xltracer.hxx"
80 #include "xistream.hxx"
81 #include "xiformula.hxx"
82 #include "xistyle.hxx"
83 #include "xipage.hxx"
84 #include "xiview.hxx"
85 #include "xiescher.hxx"
87 using ::rtl::OUString;
88 using ::rtl::OUStringBuffer;
89 using ::com::sun::star::uno::Any;
90 using ::com::sun::star::uno::Reference;
91 using ::com::sun::star::uno::Sequence;
92 using ::com::sun::star::uno::UNO_QUERY;
93 using ::com::sun::star::uno::UNO_QUERY_THROW;
94 using ::com::sun::star::uno::Exception;
95 using ::com::sun::star::beans::XPropertySet;
96 using ::com::sun::star::lang::XMultiServiceFactory;
97 using ::com::sun::star::frame::XModel;
98 using ::com::sun::star::util::XNumberFormatsSupplier;
100 using ::com::sun::star::chart2::XChartDocument;
101 using ::com::sun::star::chart2::XDiagram;
102 using ::com::sun::star::chart2::XCoordinateSystemContainer;
103 using ::com::sun::star::chart2::XCoordinateSystem;
104 using ::com::sun::star::chart2::XChartTypeContainer;
105 using ::com::sun::star::chart2::XChartType;
106 using ::com::sun::star::chart2::XDataSeriesContainer;
107 using ::com::sun::star::chart2::XDataSeries;
108 using ::com::sun::star::chart2::XRegressionCurve;
109 using ::com::sun::star::chart2::XRegressionCurveContainer;
110 using ::com::sun::star::chart2::XAxis;
111 using ::com::sun::star::chart2::XScaling;
112 using ::com::sun::star::chart2::ScaleData;
113 using ::com::sun::star::chart2::IncrementData;
114 using ::com::sun::star::chart2::SubIncrement;
115 using ::com::sun::star::chart2::XLegend;
116 using ::com::sun::star::chart2::XTitled;
117 using ::com::sun::star::chart2::XTitle;
118 using ::com::sun::star::chart2::XFormattedString;
120 using ::com::sun::star::chart2::data::XDataProvider;
121 using ::com::sun::star::chart2::data::XDataReceiver;
122 using ::com::sun::star::chart2::data::XDataSink;
123 using ::com::sun::star::chart2::data::XLabeledDataSequence;
124 using ::com::sun::star::chart2::data::XDataSequence;
126 using ::formula::FormulaToken;
127 using ::formula::StackVar;
129 using ::std::vector;
131 // Helpers ====================================================================
133 namespace {
135 XclImpStream& operator>>( XclImpStream& rStrm, XclChRectangle& rRect )
137 return rStrm >> rRect.mnX >> rRect.mnY >> rRect.mnWidth >> rRect.mnHeight;
140 template< typename Type >
141 void lclSetValueOrClearAny( Any& rAny, const Type& rValue, bool bClear )
143 if( bClear )
144 rAny.clear();
145 else
146 rAny <<= rValue;
149 void lclSetExpValueOrClearAny( Any& rAny, double fValue, bool bLogScale, bool bClear )
151 if( !bClear && bLogScale )
152 fValue = pow( 10.0, fValue );
153 lclSetValueOrClearAny( rAny, fValue, bClear );
156 } // namespace
158 // Common =====================================================================
160 /** Stores global data needed in various classes of the Chart import filter. */
161 class XclImpChRootData : public XclChRootData
163 public:
164 explicit XclImpChRootData( XclImpChChart* pChartData );
166 /** Returns a reference to the parent chart data object. */
167 inline XclImpChChart& GetChartData() const { return *mpChartData; }
169 private:
170 XclImpChChart* mpChartData; /// Pointer to the chart data object.
173 XclImpChRootData::XclImpChRootData( XclImpChChart* pChartData ) :
174 mpChartData( pChartData )
178 // ----------------------------------------------------------------------------
180 XclImpChRoot::XclImpChRoot( const XclImpRoot& rRoot, XclImpChChart* pChartData ) :
181 XclImpRoot( rRoot ),
182 mxChData( new XclImpChRootData( pChartData ) )
186 XclImpChRoot::~XclImpChRoot()
190 XclImpChChart& XclImpChRoot::GetChartData() const
192 return mxChData->GetChartData();
195 const XclChTypeInfo& XclImpChRoot::GetChartTypeInfo( XclChTypeId eType ) const
197 return mxChData->GetTypeInfoProvider().GetTypeInfo( eType );
200 const XclChTypeInfo& XclImpChRoot::GetChartTypeInfo( sal_uInt16 nRecId ) const
202 return mxChData->GetTypeInfoProvider().GetTypeInfoFromRecId( nRecId );
205 const XclChFormatInfo& XclImpChRoot::GetFormatInfo( XclChObjectType eObjType ) const
207 return mxChData->GetFormatInfoProvider().GetFormatInfo( eObjType );
210 Color XclImpChRoot::GetFontAutoColor() const
212 return GetPalette().GetColor( EXC_COLOR_CHWINDOWTEXT );
215 Color XclImpChRoot::GetSeriesLineAutoColor( sal_uInt16 nFormatIdx ) const
217 return GetPalette().GetColor( XclChartHelper::GetSeriesLineAutoColorIdx( nFormatIdx ) );
220 Color XclImpChRoot::GetSeriesFillAutoColor( sal_uInt16 nFormatIdx ) const
222 const XclImpPalette& rPal = GetPalette();
223 Color aColor = rPal.GetColor( XclChartHelper::GetSeriesFillAutoColorIdx( nFormatIdx ) );
224 sal_uInt8 nTrans = XclChartHelper::GetSeriesFillAutoTransp( nFormatIdx );
225 return ScfTools::GetMixedColor( aColor, rPal.GetColor( EXC_COLOR_CHWINDOWBACK ), nTrans );
228 void XclImpChRoot::InitConversion( Reference< XChartDocument > xChartDoc ) const
230 // create formatting object tables
231 mxChData->InitConversion( xChartDoc );
233 // lock the model to suppress any internal updates
234 Reference< XModel > xModel( xChartDoc, UNO_QUERY );
235 if( xModel.is() )
236 xModel->lockControllers();
238 SfxObjectShell* pDocShell = GetDocShell();
239 Reference< XDataReceiver > xDataRec( xChartDoc, UNO_QUERY );
240 if( pDocShell && xDataRec.is() )
242 // create and register a data provider
243 Reference< XDataProvider > xDataProv(
244 ScfApiHelper::CreateInstance( pDocShell, SERVICE_CHART2_DATAPROVIDER ), UNO_QUERY );
245 if( xDataProv.is() )
246 xDataRec->attachDataProvider( xDataProv );
247 // attach the number formatter
248 Reference< XNumberFormatsSupplier > xNumFmtSupp( pDocShell->GetModel(), UNO_QUERY );
249 if( xNumFmtSupp.is() )
250 xDataRec->attachNumberFormatsSupplier( xNumFmtSupp );
254 void XclImpChRoot::FinishConversion( ScfProgressBar& rProgress ) const
256 rProgress.Progress( EXC_CHART_PROGRESS_SIZE );
257 // unlock the model
258 Reference< XModel > xModel( mxChData->GetChartDoc(), UNO_QUERY );
259 if( xModel.is() )
260 xModel->unlockControllers();
261 rProgress.Progress( EXC_CHART_PROGRESS_SIZE );
263 mxChData->FinishConversion();
266 Reference< XDataProvider > XclImpChRoot::GetDataProvider() const
268 return mxChData->GetChartDoc()->getDataProvider();
271 void XclImpChRoot::ConvertLineFormat( ScfPropertySet& rPropSet,
272 const XclChLineFormat& rLineFmt, XclChPropertyMode ePropMode ) const
274 GetChartPropSetHelper().WriteLineProperties(
275 rPropSet, mxChData->GetLineDashTable(), rLineFmt, ePropMode );
278 void XclImpChRoot::ConvertAreaFormat( ScfPropertySet& rPropSet,
279 const XclChAreaFormat& rAreaFmt, XclChPropertyMode ePropMode ) const
281 GetChartPropSetHelper().WriteAreaProperties( rPropSet, rAreaFmt, ePropMode );
284 void XclImpChRoot::ConvertEscherFormat( ScfPropertySet& rPropSet,
285 const XclChEscherFormat& rEscherFmt, const XclChPicFormat& rPicFmt,
286 XclChPropertyMode ePropMode ) const
288 GetChartPropSetHelper().WriteEscherProperties( rPropSet,
289 mxChData->GetGradientTable(), mxChData->GetHatchTable(), mxChData->GetBitmapTable(),
290 rEscherFmt, rPicFmt, ePropMode );
293 void XclImpChRoot::ConvertFont( ScfPropertySet& rPropSet,
294 sal_uInt16 nFontIdx, const Color* pFontColor ) const
296 GetFontBuffer().WriteFontProperties( rPropSet, EXC_FONTPROPSET_CHART, nFontIdx, pFontColor );
299 void XclImpChRoot::ConvertPieRotation( ScfPropertySet& rPropSet, sal_uInt16 nAngle )
301 sal_Int32 nApiRot = (450 - (nAngle % 360)) % 360;
302 rPropSet.SetProperty( EXC_CHPROP_STARTINGANGLE, nApiRot );
305 // ----------------------------------------------------------------------------
307 XclImpChGroupBase::~XclImpChGroupBase()
311 void XclImpChGroupBase::ReadRecordGroup( XclImpStream& rStrm )
313 // read contents of the header record
314 ReadHeaderRecord( rStrm );
316 // only read sub records, if the next record is a CHBEGIN
317 if( rStrm.GetNextRecId() == EXC_ID_CHBEGIN )
319 // read the CHBEGIN record, may be used for special initial processing
320 rStrm.StartNextRecord();
321 ReadSubRecord( rStrm );
323 // read the nested records
324 bool bLoop = true;
325 while( bLoop && rStrm.StartNextRecord() )
327 sal_uInt16 nRecId = rStrm.GetRecId();
328 bLoop = nRecId != EXC_ID_CHEND;
329 // skip unsupported nested blocks
330 if( nRecId == EXC_ID_CHBEGIN )
331 SkipBlock( rStrm );
332 else
333 ReadSubRecord( rStrm );
336 /* Returns with current CHEND record or unchanged stream, if no record
337 group present. In every case another call to StartNextRecord() will go
338 to next record of interest. */
341 void XclImpChGroupBase::SkipBlock( XclImpStream& rStrm )
343 DBG_ASSERT( rStrm.GetRecId() == EXC_ID_CHBEGIN, "XclImpChGroupBase::SkipBlock - no CHBEGIN record" );
344 // do nothing if current record is not CHBEGIN
345 bool bLoop = rStrm.GetRecId() == EXC_ID_CHBEGIN;
346 while( bLoop && rStrm.StartNextRecord() )
348 sal_uInt16 nRecId = rStrm.GetRecId();
349 bLoop = nRecId != EXC_ID_CHEND;
350 // skip nested record groups
351 if( nRecId == EXC_ID_CHBEGIN )
352 SkipBlock( rStrm );
356 // Frame formatting ===========================================================
358 void XclImpChFramePos::ReadChFramePos( XclImpStream& rStrm )
360 rStrm >> maData.mnObjType >> maData.mnSizeMode >> maData.maRect;
363 // ----------------------------------------------------------------------------
365 void XclImpChLineFormat::ReadChLineFormat( XclImpStream& rStrm )
367 rStrm >> maData.maColor >> maData.mnPattern >> maData.mnWeight >> maData.mnFlags;
369 const XclImpRoot& rRoot = rStrm.GetRoot();
370 if( rRoot.GetBiff() == EXC_BIFF8 )
371 // #116397# BIFF8: index into palette used instead of RGB data
372 maData.maColor = rRoot.GetPalette().GetColor( rStrm.ReaduInt16() );
375 void XclImpChLineFormat::Convert( const XclImpChRoot& rRoot,
376 ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx ) const
378 const XclChFormatInfo& rFmtInfo = rRoot.GetFormatInfo( eObjType );
379 if( IsAuto() )
381 XclChLineFormat aLineFmt;
382 aLineFmt.maColor = (eObjType == EXC_CHOBJTYPE_LINEARSERIES) ?
383 rRoot.GetSeriesLineAutoColor( nFormatIdx ) :
384 rRoot.GetPalette().GetColor( rFmtInfo.mnAutoLineColorIdx );
385 aLineFmt.mnPattern = EXC_CHLINEFORMAT_SOLID;
386 aLineFmt.mnWeight = rFmtInfo.mnAutoLineWeight;
387 rRoot.ConvertLineFormat( rPropSet, aLineFmt, rFmtInfo.mePropMode );
389 else
391 rRoot.ConvertLineFormat( rPropSet, maData, rFmtInfo.mePropMode );
395 // ----------------------------------------------------------------------------
397 void XclImpChAreaFormat::ReadChAreaFormat( XclImpStream& rStrm )
399 rStrm >> maData.maPattColor >> maData.maBackColor >> maData.mnPattern >> maData.mnFlags;
401 const XclImpRoot& rRoot = rStrm.GetRoot();
402 if( rRoot.GetBiff() == EXC_BIFF8 )
404 // #116397# BIFF8: index into palette used instead of RGB data
405 const XclImpPalette& rPal = rRoot.GetPalette();
406 maData.maPattColor = rPal.GetColor( rStrm.ReaduInt16() );
407 maData.maBackColor = rPal.GetColor( rStrm.ReaduInt16());
411 void XclImpChAreaFormat::Convert( const XclImpChRoot& rRoot,
412 ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx ) const
414 const XclChFormatInfo& rFmtInfo = rRoot.GetFormatInfo( eObjType );
415 if( IsAuto() )
417 XclChAreaFormat aAreaFmt;
418 aAreaFmt.maPattColor = (eObjType == EXC_CHOBJTYPE_FILLEDSERIES) ?
419 rRoot.GetSeriesFillAutoColor( nFormatIdx ) :
420 rRoot.GetPalette().GetColor( rFmtInfo.mnAutoPattColorIdx );
421 aAreaFmt.mnPattern = EXC_PATT_SOLID;
422 rRoot.ConvertAreaFormat( rPropSet, aAreaFmt, rFmtInfo.mePropMode );
424 else
426 rRoot.ConvertAreaFormat( rPropSet, maData, rFmtInfo.mePropMode );
430 // ----------------------------------------------------------------------------
432 XclImpChEscherFormat::XclImpChEscherFormat( const XclImpRoot& rRoot )
434 maData.mxItemSet.reset(
435 new SfxItemSet( rRoot.GetDoc().GetDrawLayer()->GetItemPool() ) );
438 void XclImpChEscherFormat::ReadHeaderRecord( XclImpStream& rStrm )
440 // read from stream - CHESCHERFORMAT uses own ID for record continuation
441 XclImpDffPropSet aPropSet( rStrm.GetRoot() );
442 rStrm.ResetRecord( true, rStrm.GetRecId() );
443 rStrm >> aPropSet;
444 // get the data
445 aPropSet.FillToItemSet( *maData.mxItemSet );
446 // get bitmap mode from DFF item set
447 sal_uInt32 nType = aPropSet.GetPropertyValue( DFF_Prop_fillType, mso_fillSolid );
448 maPicFmt.mnBmpMode = (nType == mso_fillPicture) ? EXC_CHPICFORMAT_STRETCH : EXC_CHPICFORMAT_STACK;
451 void XclImpChEscherFormat::ReadSubRecord( XclImpStream& rStrm )
453 switch( rStrm.GetRecId() )
455 case EXC_ID_CHPICFORMAT:
456 rStrm >> maPicFmt.mnBmpMode >> maPicFmt.mnFormat >> maPicFmt.mnFlags >> maPicFmt.mfScale;
457 break;
461 void XclImpChEscherFormat::Convert( const XclImpChRoot& rRoot,
462 ScfPropertySet& rPropSet, XclChObjectType eObjType ) const
464 const XclChFormatInfo& rFmtInfo = rRoot.GetFormatInfo( eObjType );
465 rRoot.ConvertEscherFormat( rPropSet, maData, maPicFmt, rFmtInfo.mePropMode );
468 // ----------------------------------------------------------------------------
470 XclImpChFrameBase::XclImpChFrameBase( const XclChFormatInfo& rFmtInfo )
472 if( rFmtInfo.mbCreateDefFrame ) switch( rFmtInfo.meDefFrameType )
474 case EXC_CHFRAMETYPE_AUTO:
475 mxLineFmt.reset( new XclImpChLineFormat );
476 if( rFmtInfo.mbIsFrame )
477 mxAreaFmt.reset( new XclImpChAreaFormat );
478 break;
479 case EXC_CHFRAMETYPE_INVISIBLE:
481 XclChLineFormat aLineFmt;
482 ::set_flag( aLineFmt.mnFlags, EXC_CHLINEFORMAT_AUTO, false );
483 aLineFmt.mnPattern = EXC_CHLINEFORMAT_NONE;
484 mxLineFmt.reset( new XclImpChLineFormat( aLineFmt ) );
485 if( rFmtInfo.mbIsFrame )
487 XclChAreaFormat aAreaFmt;
488 ::set_flag( aAreaFmt.mnFlags, EXC_CHAREAFORMAT_AUTO, false );
489 aAreaFmt.mnPattern = EXC_PATT_NONE;
490 mxAreaFmt.reset( new XclImpChAreaFormat( aAreaFmt ) );
493 break;
494 default:
495 DBG_ERRORFILE( "XclImpChFrameBase::XclImpChFrameBase - unknown frame type" );
499 void XclImpChFrameBase::ReadSubRecord( XclImpStream& rStrm )
501 switch( rStrm.GetRecId() )
503 case EXC_ID_CHLINEFORMAT:
504 mxLineFmt.reset( new XclImpChLineFormat );
505 mxLineFmt->ReadChLineFormat( rStrm );
506 break;
507 case EXC_ID_CHAREAFORMAT:
508 mxAreaFmt.reset( new XclImpChAreaFormat );
509 mxAreaFmt->ReadChAreaFormat( rStrm );
510 break;
511 case EXC_ID_CHESCHERFORMAT:
512 mxEscherFmt.reset( new XclImpChEscherFormat( rStrm.GetRoot() ) );
513 mxEscherFmt->ReadRecordGroup( rStrm );
514 break;
518 void XclImpChFrameBase::ConvertLineBase( const XclImpChRoot& rRoot,
519 ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx ) const
521 if( mxLineFmt.is() )
522 mxLineFmt->Convert( rRoot, rPropSet, eObjType, nFormatIdx );
525 void XclImpChFrameBase::ConvertAreaBase( const XclImpChRoot& rRoot,
526 ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx ) const
528 if( rRoot.GetFormatInfo( eObjType ).mbIsFrame )
530 // CHESCHERFORMAT overrides CHAREAFORMAT (even if it is auto)
531 if( mxEscherFmt.is() )
532 mxEscherFmt->Convert( rRoot, rPropSet, eObjType );
533 else if( mxAreaFmt.is() )
534 mxAreaFmt->Convert( rRoot, rPropSet, eObjType, nFormatIdx );
538 void XclImpChFrameBase::ConvertFrameBase( const XclImpChRoot& rRoot,
539 ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx ) const
541 ConvertLineBase( rRoot, rPropSet, eObjType, nFormatIdx );
542 ConvertAreaBase( rRoot, rPropSet, eObjType, nFormatIdx );
545 // ----------------------------------------------------------------------------
547 XclImpChFrame::XclImpChFrame( const XclImpChRoot& rRoot, XclChObjectType eObjType ) :
548 XclImpChFrameBase( rRoot.GetFormatInfo( eObjType ) ),
549 XclImpChRoot( rRoot ),
550 meObjType( eObjType )
554 void XclImpChFrame::ReadHeaderRecord( XclImpStream& rStrm )
556 rStrm >> maData.mnFormat >> maData.mnFlags;
559 void XclImpChFrame::UpdateObjFrame( const XclObjLineData& rLineData, const XclObjFillData& rFillData )
561 const XclImpPalette& rPal = GetPalette();
563 if( rLineData.IsVisible() && (!mxLineFmt || !mxLineFmt->HasLine()) )
565 // line formatting
566 XclChLineFormat aLineFmt;
567 aLineFmt.maColor = rPal.GetColor( rLineData.mnColorIdx );
568 switch( rLineData.mnStyle )
570 case EXC_OBJ_LINE_SOLID: aLineFmt.mnPattern = EXC_CHLINEFORMAT_SOLID; break;
571 case EXC_OBJ_LINE_DASH: aLineFmt.mnPattern = EXC_CHLINEFORMAT_DASH; break;
572 case EXC_OBJ_LINE_DOT: aLineFmt.mnPattern = EXC_CHLINEFORMAT_DOT; break;
573 case EXC_OBJ_LINE_DASHDOT: aLineFmt.mnPattern = EXC_CHLINEFORMAT_DASHDOT; break;
574 case EXC_OBJ_LINE_DASHDOTDOT: aLineFmt.mnPattern = EXC_CHLINEFORMAT_DASHDOTDOT; break;
575 case EXC_OBJ_LINE_MEDTRANS: aLineFmt.mnPattern = EXC_CHLINEFORMAT_MEDTRANS; break;
576 case EXC_OBJ_LINE_DARKTRANS: aLineFmt.mnPattern = EXC_CHLINEFORMAT_DARKTRANS; break;
577 case EXC_OBJ_LINE_LIGHTTRANS: aLineFmt.mnPattern = EXC_CHLINEFORMAT_LIGHTTRANS; break;
578 case EXC_OBJ_LINE_NONE: aLineFmt.mnPattern = EXC_CHLINEFORMAT_NONE; break;
579 default: aLineFmt.mnPattern = EXC_CHLINEFORMAT_SOLID;
581 switch( rLineData.mnWidth )
583 case EXC_OBJ_LINE_HAIR: aLineFmt.mnWeight = EXC_CHLINEFORMAT_HAIR; break;
584 case EXC_OBJ_LINE_THIN: aLineFmt.mnWeight = EXC_CHLINEFORMAT_SINGLE; break;
585 case EXC_OBJ_LINE_MEDIUM: aLineFmt.mnWeight = EXC_CHLINEFORMAT_DOUBLE; break;
586 case EXC_OBJ_LINE_THICK: aLineFmt.mnWeight = EXC_CHLINEFORMAT_TRIPLE; break;
587 default: aLineFmt.mnWeight = EXC_CHLINEFORMAT_HAIR;
589 ::set_flag( aLineFmt.mnFlags, EXC_CHLINEFORMAT_AUTO, rLineData.IsAuto() );
590 mxLineFmt.reset( new XclImpChLineFormat( aLineFmt ) );
593 if( rFillData.IsFilled() && (!mxAreaFmt || !mxAreaFmt->HasArea()) && !mxEscherFmt )
595 // area formatting
596 XclChAreaFormat aAreaFmt;
597 aAreaFmt.maPattColor = rPal.GetColor( rFillData.mnPattColorIdx );
598 aAreaFmt.maBackColor = rPal.GetColor( rFillData.mnBackColorIdx );
599 aAreaFmt.mnPattern = rFillData.mnPattern;
600 ::set_flag( aAreaFmt.mnFlags, EXC_CHAREAFORMAT_AUTO, rFillData.IsAuto() );
601 mxAreaFmt.reset( new XclImpChAreaFormat( aAreaFmt ) );
605 void XclImpChFrame::Convert( ScfPropertySet& rPropSet ) const
607 ConvertFrameBase( GetChRoot(), rPropSet, meObjType );
610 // Source links ===============================================================
612 namespace {
614 /** Creates a labeled data sequence object, adds link for series title if present. */
615 Reference< XLabeledDataSequence > lclCreateLabeledDataSequence(
616 XclImpChSourceLinkRef xValueLink, const OUString& rValueRole,
617 const XclImpChSourceLink* pTitleLink = 0 )
619 // create data sequence for values and title
620 Reference< XDataSequence > xValueSeq;
621 if( xValueLink.is() )
622 xValueSeq = xValueLink->CreateDataSequence( rValueRole );
623 Reference< XDataSequence > xTitleSeq;
624 if( pTitleLink )
625 xTitleSeq = pTitleLink->CreateDataSequence( EXC_CHPROP_ROLE_LABEL );
627 // create the labeled data sequence, if values or title are present
628 Reference< XLabeledDataSequence > xLabeledSeq;
629 if( xValueSeq.is() || xTitleSeq.is() )
630 xLabeledSeq.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_LABELEDDATASEQ ), UNO_QUERY );
631 if( xLabeledSeq.is() )
633 if( xValueSeq.is() )
634 xLabeledSeq->setValues( xValueSeq );
635 if( xTitleSeq.is() )
636 xLabeledSeq->setLabel( xTitleSeq );
638 return xLabeledSeq;
641 } // namespace
643 // ----------------------------------------------------------------------------
645 XclImpChSourceLink::XclImpChSourceLink( const XclImpChRoot& rRoot ) :
646 XclImpChRoot( rRoot )
650 XclImpChSourceLink::~XclImpChSourceLink()
654 void XclImpChSourceLink::ReadChSourceLink( XclImpStream& rStrm )
656 rStrm >> maData.mnDestType
657 >> maData.mnLinkType
658 >> maData.mnFlags
659 >> maData.mnNumFmtIdx;
661 mxTokenArray.reset();
662 if( GetLinkType() == EXC_CHSRCLINK_WORKSHEET )
664 // read token array
665 XclTokenArray aXclTokArr;
666 rStrm >> aXclTokArr;
668 // convert BIFF formula tokens to Calc token array
669 if( const ScTokenArray* pTokens = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CHART, aXclTokArr ) )
670 mxTokenArray.reset( pTokens->Clone() );
673 // try to read a following CHSTRING record
674 if( (rStrm.GetNextRecId() == EXC_ID_CHSTRING) && rStrm.StartNextRecord() )
676 mxString.reset( new XclImpString );
677 rStrm.Ignore( 2 );
678 mxString->Read( rStrm, EXC_STR_8BITLENGTH | EXC_STR_SEPARATEFORMATS );
682 void XclImpChSourceLink::SetString( const String& rString )
684 if( !mxString )
685 mxString.reset( new XclImpString );
686 mxString->SetText( rString );
689 void XclImpChSourceLink::SetTextFormats( const XclFormatRunVec& rFormats )
691 if( mxString.is() )
692 mxString->SetFormats( rFormats );
695 sal_uInt16 XclImpChSourceLink::GetCellCount() const
697 sal_uInt32 nCellCount = 0;
698 if( mxTokenArray.is() )
700 mxTokenArray->Reset();
701 for( const FormulaToken* pToken = mxTokenArray->First(); pToken; pToken = mxTokenArray->Next() )
703 switch( pToken->GetType() )
705 case ::formula::svSingleRef:
706 case ::formula::svExternalSingleRef:
707 // single cell
708 ++nCellCount;
709 break;
710 case ::formula::svDoubleRef:
711 case ::formula::svExternalDoubleRef:
713 // cell range
714 const ScComplexRefData& rComplexRef = static_cast< const ScToken* >( pToken )->GetDoubleRef();
715 const ScSingleRefData& rRef1 = rComplexRef.Ref1;
716 const ScSingleRefData& rRef2 = rComplexRef.Ref2;
717 sal_uInt32 nTabs = static_cast< sal_uInt32 >( rRef2.nTab - rRef1.nTab + 1 );
718 sal_uInt32 nCols = static_cast< sal_uInt32 >( rRef2.nCol - rRef1.nCol + 1 );
719 sal_uInt32 nRows = static_cast< sal_uInt32 >( rRef2.nRow - rRef1.nRow + 1 );
720 nCellCount += nCols * nRows * nTabs;
722 break;
723 default: ;
727 return limit_cast< sal_uInt16 >( nCellCount );
730 void XclImpChSourceLink::ConvertNumFmt( ScfPropertySet& rPropSet, bool bPercent ) const
732 bool bLinkToSource = ::get_flag( maData.mnFlags, EXC_CHSRCLINK_NUMFMT );
733 sal_uInt32 nScNumFmt = bLinkToSource ? GetNumFmtBuffer().GetScFormat( maData.mnNumFmtIdx ) : NUMBERFORMAT_ENTRY_NOT_FOUND;
734 OUString aPropName = bPercent ? EXC_CHPROP_PERCENTAGENUMFMT : EXC_CHPROP_NUMBERFORMAT;
735 if( nScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND )
736 rPropSet.SetProperty( aPropName, static_cast< sal_Int32 >( nScNumFmt ) );
737 else
738 // restore 'link to source' at data point (series may contain manual number format)
739 rPropSet.SetAnyProperty( aPropName, Any() );
742 Reference< XDataSequence > XclImpChSourceLink::CreateDataSequence( const OUString& rRole ) const
744 Reference< XDataSequence > xDataSeq;
745 Reference< XDataProvider > xDataProv = GetDataProvider();
746 if( xDataProv.is() && mxTokenArray.is() )
748 ScCompiler aComp( GetDocPtr(), ScAddress(), *mxTokenArray );
749 aComp.SetGrammar( ::formula::FormulaGrammar::GRAM_ENGLISH );
750 OUStringBuffer aRangeRep;
751 aComp.CreateStringFromTokenArray( aRangeRep );
754 xDataSeq = xDataProv->createDataSequenceByRangeRepresentation( aRangeRep.makeStringAndClear() );
755 // set sequence role
756 ScfPropertySet aSeqProp( xDataSeq );
757 aSeqProp.SetProperty( EXC_CHPROP_ROLE, rRole );
759 catch( Exception& )
761 // DBG_ERRORFILE( "XclImpChSourceLink::CreateDataSequence - cannot create data sequence" );
764 return xDataSeq;
767 Sequence< Reference< XFormattedString > > XclImpChSourceLink::CreateStringSequence(
768 const XclImpChRoot& rRoot, sal_uInt16 nLeadFontIdx, const Color& rLeadFontColor ) const
770 ::std::vector< Reference< XFormattedString > > aStringVec;
771 if( mxString.is() )
773 for( XclImpStringIterator aIt( *mxString ); aIt.Is(); ++aIt )
775 Reference< XFormattedString > xFmtStr(
776 ScfApiHelper::CreateInstance( SERVICE_CHART2_FORMATTEDSTRING ), UNO_QUERY );
777 if( xFmtStr.is() )
779 // set text data
780 xFmtStr->setString( aIt.GetPortionText() );
782 // set font formatting and font color
783 ScfPropertySet aStringProp( xFmtStr );
784 sal_uInt16 nFontIdx = aIt.GetPortionFont();
785 if( (nFontIdx == EXC_FONT_NOTFOUND) && (aIt.GetPortionIndex() == 0) )
786 // leading unformatted portion - use passed font settings
787 rRoot.ConvertFont( aStringProp, nLeadFontIdx, &rLeadFontColor );
788 else
789 rRoot.ConvertFont( aStringProp, nFontIdx );
791 // add string to vector of strings
792 aStringVec.push_back( xFmtStr );
796 return ScfApiHelper::VectorToSequence( aStringVec );
799 void XclImpChSourceLink::FillSourceLink(vector<ScSharedTokenRef>& rTokens) const
801 if (!mxTokenArray.is())
802 // no links to fill.
803 return;
805 mxTokenArray->Reset();
806 for (FormulaToken* p = mxTokenArray->First(); p; p = mxTokenArray->Next())
808 ScSharedTokenRef pToken(static_cast<ScToken*>(p->Clone()));
809 if (ScRefTokenHelper::isRef(pToken))
810 // This is a reference token. Store it.
811 ScRefTokenHelper::join(rTokens, pToken);
815 // Text =======================================================================
817 XclImpChFontBase::~XclImpChFontBase()
821 void XclImpChFontBase::ConvertFontBase( const XclImpChRoot& rRoot, ScfPropertySet& rPropSet ) const
823 Color aFontColor = GetFontColor();
824 rRoot.ConvertFont( rPropSet, GetFontIndex(), &aFontColor );
827 void XclImpChFontBase::ConvertRotationBase( const XclImpChRoot& rRoot, ScfPropertySet& rPropSet, bool bSupportsStacked ) const
829 rRoot.GetChartPropSetHelper().WriteRotationProperties( rPropSet, GetRotation(), bSupportsStacked );
832 // ----------------------------------------------------------------------------
834 XclImpChFont::XclImpChFont() :
835 mnFontIdx( EXC_FONT_NOTFOUND )
839 void XclImpChFont::ReadChFont( XclImpStream& rStrm )
841 rStrm >> mnFontIdx;
844 // ----------------------------------------------------------------------------
846 XclImpChText::XclImpChText( const XclImpChRoot& rRoot ) :
847 XclImpChRoot( rRoot )
851 void XclImpChText::ReadHeaderRecord( XclImpStream& rStrm )
853 rStrm >> maData.mnHAlign
854 >> maData.mnVAlign
855 >> maData.mnBackMode
856 >> maData.maTextColor
857 >> maData.maRect
858 >> maData.mnFlags;
860 if( GetBiff() == EXC_BIFF8 )
862 // #116397# BIFF8: index into palette used instead of RGB data
863 maData.maTextColor = GetPalette().GetColor( rStrm.ReaduInt16() );
864 // placement and rotation
865 rStrm >> maData.mnPlacement >> maData.mnRotation;
866 // lower 4 bits used for placement, other bits contain garbage
867 maData.mnPlacement &= 0x000F;
869 else
871 // BIFF2-BIFF7: get rotation from text orientation
872 sal_uInt8 nOrient = ::extract_value< sal_uInt8 >( maData.mnFlags, 8, 3 );
873 maData.mnRotation = XclTools::GetXclRotFromOrient( nOrient );
877 void XclImpChText::ReadSubRecord( XclImpStream& rStrm )
879 switch( rStrm.GetRecId() )
881 case EXC_ID_CHFONT:
882 mxFont.reset( new XclImpChFont );
883 mxFont->ReadChFont( rStrm );
884 break;
885 case EXC_ID_CHFORMATRUNS:
886 if( GetBiff() == EXC_BIFF8 )
887 XclImpString::ReadFormats( rStrm, maFormats );
888 break;
889 case EXC_ID_CHSOURCELINK:
890 mxSrcLink.reset( new XclImpChSourceLink( GetChRoot() ) );
891 mxSrcLink->ReadChSourceLink( rStrm );
892 break;
893 case EXC_ID_CHFRAME:
894 mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_TEXT ) );
895 mxFrame->ReadRecordGroup( rStrm );
896 break;
897 case EXC_ID_CHOBJECTLINK:
898 rStrm >> maObjLink.mnTarget >> maObjLink.maPointPos.mnSeriesIdx >> maObjLink.maPointPos.mnPointIdx;
899 break;
900 case EXC_ID_CHFRLABELPROPS:
901 ReadChFrLabelProps( rStrm );
902 break;
903 case EXC_ID_CHEND:
904 if( mxSrcLink.is() && !maFormats.empty() )
905 mxSrcLink->SetTextFormats( maFormats );
906 break;
910 sal_uInt16 XclImpChText::GetFontIndex() const
912 return mxFont.is() ? mxFont->GetFontIndex() : EXC_FONT_NOTFOUND;
915 Color XclImpChText::GetFontColor() const
917 return ::get_flag( maData.mnFlags, EXC_CHTEXT_AUTOCOLOR ) ? GetFontAutoColor() : maData.maTextColor;
920 sal_uInt16 XclImpChText::GetRotation() const
922 return maData.mnRotation;
925 void XclImpChText::SetString( const String& rString )
927 if( !mxSrcLink )
928 mxSrcLink.reset( new XclImpChSourceLink( GetChRoot() ) );
929 mxSrcLink->SetString( rString );
932 void XclImpChText::UpdateText( const XclImpChText* pParentText )
934 if( pParentText )
936 // update missing members
937 if( !mxFrame )
938 mxFrame = pParentText->mxFrame;
939 if( !mxFont )
941 mxFont = pParentText->mxFont;
942 // text color is taken from CHTEXT record, not from font in CHFONT
943 ::set_flag( maData.mnFlags, EXC_CHTEXT_AUTOCOLOR, ::get_flag( pParentText->maData.mnFlags, EXC_CHTEXT_AUTOCOLOR ) );
944 maData.maTextColor = pParentText->maData.maTextColor;
949 void XclImpChText::UpdateDataLabel( bool bCateg, bool bValue, bool bPercent )
951 ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWCATEG, bCateg );
952 ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWVALUE, bValue );
953 ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWPERCENT, bPercent );
954 ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWCATEGPERC, bCateg && bPercent );
955 ::set_flag( maData.mnFlags, EXC_CHTEXT_DELETED, !bCateg && !bValue && !bPercent );
958 void XclImpChText::ConvertFont( ScfPropertySet& rPropSet ) const
960 ConvertFontBase( GetChRoot(), rPropSet );
963 void XclImpChText::ConvertRotation( ScfPropertySet& rPropSet, bool bSupportsStacked ) const
965 ConvertRotationBase( GetChRoot(), rPropSet, bSupportsStacked );
968 void XclImpChText::ConvertFrame( ScfPropertySet& rPropSet ) const
970 if( mxFrame.is() )
971 mxFrame->Convert( rPropSet );
974 void XclImpChText::ConvertNumFmt( ScfPropertySet& rPropSet, bool bPercent ) const
976 if( mxSrcLink.is() )
977 mxSrcLink->ConvertNumFmt( rPropSet, bPercent );
980 void XclImpChText::ConvertDataLabel( ScfPropertySet& rPropSet, const XclChTypeInfo& rTypeInfo ) const
982 // existing CHFRLABELPROPS record wins over flags from CHTEXT
983 sal_uInt16 nShowFlags = mxLabelProps.is() ? mxLabelProps->mnFlags : maData.mnFlags;
984 sal_uInt16 SHOWANYCATEG = mxLabelProps.is() ? EXC_CHFRLABELPROPS_SHOWCATEG : (EXC_CHTEXT_SHOWCATEGPERC | EXC_CHTEXT_SHOWCATEG);
985 sal_uInt16 SHOWANYVALUE = mxLabelProps.is() ? EXC_CHFRLABELPROPS_SHOWVALUE : EXC_CHTEXT_SHOWVALUE;
986 sal_uInt16 SHOWANYPERCENT = mxLabelProps.is() ? EXC_CHFRLABELPROPS_SHOWPERCENT : (EXC_CHTEXT_SHOWPERCENT | EXC_CHTEXT_SHOWCATEGPERC);
987 sal_uInt16 SHOWANYBUBBLE = mxLabelProps.is() ? EXC_CHFRLABELPROPS_SHOWBUBBLE : EXC_CHTEXT_SHOWBUBBLE;
989 // get raw flags for label values
990 bool bShowNone = IsDeleted();
991 bool bShowCateg = !bShowNone && ::get_flag( nShowFlags, SHOWANYCATEG );
992 bool bShowPercent = !bShowNone && ::get_flag( nShowFlags, SHOWANYPERCENT );
993 bool bShowValue = !bShowNone && ::get_flag( nShowFlags, SHOWANYVALUE );
994 bool bShowBubble = !bShowNone && ::get_flag( nShowFlags, SHOWANYBUBBLE );
996 // adjust to Chart2 behaviour
997 if( rTypeInfo.meTypeId == EXC_CHTYPEID_BUBBLES )
998 bShowValue = bShowBubble; // Chart2 bubble charts show bubble size if 'ShowValue' is set
1000 // other flags
1001 bool bShowAny = bShowValue || bShowPercent || bShowCateg;
1002 bool bShowSymbol = bShowAny && ::get_flag( maData.mnFlags, EXC_CHTEXT_SHOWSYMBOL );
1004 // create API struct for label values, set API label separator
1005 namespace cssc = ::com::sun::star::chart2;
1006 cssc::DataPointLabel aPointLabel( bShowValue, bShowPercent, bShowCateg, bShowSymbol );
1007 rPropSet.SetProperty( EXC_CHPROP_LABEL, aPointLabel );
1008 String aSep = mxLabelProps.is() ? mxLabelProps->maSeparator : String( sal_Unicode( '\n' ) );
1009 if( aSep.Len() == 0 )
1010 aSep = CREATE_STRING( "; " );
1011 rPropSet.SetStringProperty( EXC_CHPROP_LABELSEPARATOR, aSep );
1013 // text properties of attached label
1014 if( bShowAny )
1016 ConvertFont( rPropSet );
1017 ConvertRotation( rPropSet, false );
1018 // label placement
1019 using namespace ::com::sun::star::chart::DataLabelPlacement;
1020 sal_Int32 nPlacement = rTypeInfo.mnDefaultLabelPos;
1021 switch( maData.mnPlacement )
1023 case EXC_CHTEXT_POS_DEFAULT: nPlacement = rTypeInfo.mnDefaultLabelPos; break;
1024 case EXC_CHTEXT_POS_OUTSIDE: nPlacement = OUTSIDE; break;
1025 case EXC_CHTEXT_POS_INSIDE: nPlacement = INSIDE; break;
1026 case EXC_CHTEXT_POS_CENTER: nPlacement = CENTER; break;
1027 case EXC_CHTEXT_POS_AXIS: nPlacement = NEAR_ORIGIN; break;
1028 case EXC_CHTEXT_POS_ABOVE: nPlacement = TOP; break;
1029 case EXC_CHTEXT_POS_BELOW: nPlacement = BOTTOM; break;
1030 case EXC_CHTEXT_POS_LEFT: nPlacement = LEFT; break;
1031 case EXC_CHTEXT_POS_RIGHT: nPlacement = RIGHT; break;
1032 case EXC_CHTEXT_POS_AUTO: nPlacement = AVOID_OVERLAP; break;
1034 rPropSet.SetProperty( EXC_CHPROP_LABELPLACEMENT, nPlacement );
1035 // label number format (percentage format wins over value format)
1036 if( bShowPercent || bShowValue )
1037 ConvertNumFmt( rPropSet, bShowPercent );
1041 Reference< XTitle > XclImpChText::CreateTitle() const
1043 Reference< XTitle > xTitle;
1044 if( mxSrcLink.is() && mxSrcLink->HasString() )
1046 // create the formatted strings
1047 Sequence< Reference< XFormattedString > > aStringSeq(
1048 mxSrcLink->CreateStringSequence( GetChRoot(), GetFontIndex(), GetFontColor() ) );
1049 if( aStringSeq.hasElements() )
1051 // create the title object
1052 xTitle.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_TITLE ), UNO_QUERY );
1053 if( xTitle.is() )
1055 // set the formatted strings
1056 xTitle->setText( aStringSeq );
1057 // more title formatting properties
1058 ScfPropertySet aTitleProp( xTitle );
1059 ConvertFrame( aTitleProp );
1060 ConvertRotation( aTitleProp, true );
1064 return xTitle;
1067 void XclImpChText::ReadChFrLabelProps( XclImpStream& rStrm )
1069 if( GetBiff() == EXC_BIFF8 )
1071 mxLabelProps.reset( new XclChFrLabelProps );
1072 sal_uInt16 nSepLen;
1073 rStrm.Ignore( 12 );
1074 rStrm >> mxLabelProps->mnFlags >> nSepLen;
1075 if( nSepLen > 0 )
1076 mxLabelProps->maSeparator = rStrm.ReadUniString( nSepLen );
1080 namespace {
1082 void lclUpdateText( XclImpChTextRef& rxText, XclImpChTextRef xDefText )
1084 if( rxText.is() )
1085 rxText->UpdateText( xDefText.get() );
1086 else
1087 rxText = xDefText;
1090 void lclFinalizeTitle( XclImpChTextRef& rxTitle, XclImpChTextRef xDefText )
1092 /* Do not update a title, if it is not visible (if rxTitle is null).
1093 Existing reference indicates enabled title. */
1094 if( rxTitle.is() )
1096 if( rxTitle->HasString() )
1097 rxTitle->UpdateText( xDefText.get() );
1098 else
1099 rxTitle.reset();
1103 } // namespace
1105 // Data series ================================================================
1107 void XclImpChMarkerFormat::ReadChMarkerFormat( XclImpStream& rStrm )
1109 rStrm >> maData.maLineColor >> maData.maFillColor >> maData.mnMarkerType >> maData.mnFlags;
1111 const XclImpRoot& rRoot = rStrm.GetRoot();
1112 if( rRoot.GetBiff() == EXC_BIFF8 )
1114 // #116397# BIFF8: index into palette used instead of RGB data
1115 const XclImpPalette& rPal = rRoot.GetPalette();
1116 maData.maLineColor = rPal.GetColor( rStrm.ReaduInt16() );
1117 maData.maFillColor = rPal.GetColor( rStrm.ReaduInt16() );
1118 // marker size
1119 rStrm >> maData.mnMarkerSize;
1123 void XclImpChMarkerFormat::Convert( const XclImpChRoot& rRoot,
1124 ScfPropertySet& rPropSet, sal_uInt16 nFormatIdx, sal_Int16 nLineWeight ) const
1126 if( IsAuto() )
1128 XclChMarkerFormat aMarkerFmt;
1129 // line and fill color of the symbol are equal to series line color
1130 //! TODO: Excel sets no fill color for specific symbols (e.g. cross)
1131 aMarkerFmt.maLineColor = aMarkerFmt.maFillColor = rRoot.GetSeriesLineAutoColor( nFormatIdx );
1132 switch( nLineWeight )
1134 case EXC_CHLINEFORMAT_HAIR: aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_HAIRSIZE; break;
1135 case EXC_CHLINEFORMAT_SINGLE: aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_SINGLESIZE; break;
1136 case EXC_CHLINEFORMAT_DOUBLE: aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_DOUBLESIZE; break;
1137 case EXC_CHLINEFORMAT_TRIPLE: aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_TRIPLESIZE; break;
1138 default: aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_SINGLESIZE;
1140 aMarkerFmt.mnMarkerType = XclChartHelper::GetAutoMarkerType( nFormatIdx );
1141 rRoot.GetChartPropSetHelper().WriteMarkerProperties( rPropSet, aMarkerFmt );
1143 else
1145 rRoot.GetChartPropSetHelper().WriteMarkerProperties( rPropSet, maData );
1149 void XclImpChMarkerFormat::ConvertColor( const XclImpChRoot& rRoot,
1150 ScfPropertySet& rPropSet, sal_uInt16 nFormatIdx ) const
1152 Color aLineColor = IsAuto() ? rRoot.GetSeriesLineAutoColor( nFormatIdx ) : maData.maFillColor;
1153 rPropSet.SetColorProperty( EXC_CHPROP_COLOR, aLineColor );
1156 // ----------------------------------------------------------------------------
1158 XclImpChPieFormat::XclImpChPieFormat() :
1159 mnPieDist( 0 )
1163 void XclImpChPieFormat::ReadChPieFormat( XclImpStream& rStrm )
1165 rStrm >> mnPieDist;
1168 void XclImpChPieFormat::Convert( ScfPropertySet& rPropSet ) const
1170 double fApiDist = ::std::min< double >( mnPieDist / 100.0, 1.0 );
1171 rPropSet.SetProperty( EXC_CHPROP_OFFSET, fApiDist );
1174 // ----------------------------------------------------------------------------
1176 XclImpChSeriesFormat::XclImpChSeriesFormat() :
1177 mnFlags( 0 )
1181 void XclImpChSeriesFormat::ReadChSeriesFormat( XclImpStream& rStrm )
1183 rStrm >> mnFlags;
1186 // ----------------------------------------------------------------------------
1188 void XclImpCh3dDataFormat::ReadCh3dDataFormat( XclImpStream& rStrm )
1190 rStrm >> maData.mnBase >> maData.mnTop;
1193 void XclImpCh3dDataFormat::Convert( ScfPropertySet& rPropSet ) const
1195 using namespace ::com::sun::star::chart2::DataPointGeometry3D;
1196 sal_Int32 nApiType = (maData.mnBase == EXC_CH3DDATAFORMAT_RECT) ?
1197 ((maData.mnTop == EXC_CH3DDATAFORMAT_STRAIGHT) ? CUBOID : PYRAMID) :
1198 ((maData.mnTop == EXC_CH3DDATAFORMAT_STRAIGHT) ? CYLINDER : CONE);
1199 rPropSet.SetProperty( EXC_CHPROP_GEOMETRY3D, nApiType );
1202 // ----------------------------------------------------------------------------
1204 XclImpChAttachedLabel::XclImpChAttachedLabel( const XclImpChRoot& rRoot ) :
1205 XclImpChRoot( rRoot ),
1206 mnFlags( 0 )
1210 void XclImpChAttachedLabel::ReadChAttachedLabel( XclImpStream& rStrm )
1212 rStrm >> mnFlags;
1215 XclImpChTextRef XclImpChAttachedLabel::CreateDataLabel( XclImpChTextRef xParent ) const
1217 const sal_uInt16 EXC_CHATTLABEL_SHOWANYVALUE = EXC_CHATTLABEL_SHOWVALUE;
1218 const sal_uInt16 EXC_CHATTLABEL_SHOWANYPERCENT = EXC_CHATTLABEL_SHOWPERCENT | EXC_CHATTLABEL_SHOWCATEGPERC;
1219 const sal_uInt16 EXC_CHATTLABEL_SHOWANYCATEG = EXC_CHATTLABEL_SHOWCATEG | EXC_CHATTLABEL_SHOWCATEGPERC;
1221 XclImpChTextRef xLabel( xParent.is() ? new XclImpChText( *xParent ) : new XclImpChText( GetChRoot() ) );
1222 xLabel->UpdateDataLabel(
1223 ::get_flag( mnFlags, EXC_CHATTLABEL_SHOWANYCATEG ),
1224 ::get_flag( mnFlags, EXC_CHATTLABEL_SHOWANYVALUE ),
1225 ::get_flag( mnFlags, EXC_CHATTLABEL_SHOWANYPERCENT ) );
1226 return xLabel;
1229 // ----------------------------------------------------------------------------
1231 XclImpChDataFormat::XclImpChDataFormat( const XclImpChRoot& rRoot ) :
1232 XclImpChRoot( rRoot )
1236 void XclImpChDataFormat::ReadHeaderRecord( XclImpStream& rStrm )
1238 rStrm >> maData.maPointPos.mnPointIdx
1239 >> maData.maPointPos.mnSeriesIdx
1240 >> maData.mnFormatIdx
1241 >> maData.mnFlags;
1244 void XclImpChDataFormat::ReadSubRecord( XclImpStream& rStrm )
1246 switch( rStrm.GetRecId() )
1248 case EXC_ID_CHMARKERFORMAT:
1249 mxMarkerFmt.reset( new XclImpChMarkerFormat );
1250 mxMarkerFmt->ReadChMarkerFormat( rStrm );
1251 break;
1252 case EXC_ID_CHPIEFORMAT:
1253 mxPieFmt.reset( new XclImpChPieFormat );
1254 mxPieFmt->ReadChPieFormat( rStrm );
1255 break;
1256 case EXC_ID_CHSERIESFORMAT:
1257 mxSeriesFmt.reset( new XclImpChSeriesFormat );
1258 mxSeriesFmt->ReadChSeriesFormat( rStrm );
1259 break;
1260 case EXC_ID_CH3DDATAFORMAT:
1261 mx3dDataFmt.reset( new XclImpCh3dDataFormat );
1262 mx3dDataFmt->ReadCh3dDataFormat( rStrm );
1263 break;
1264 case EXC_ID_CHATTACHEDLABEL:
1265 mxAttLabel.reset( new XclImpChAttachedLabel( GetChRoot() ) );
1266 mxAttLabel->ReadChAttachedLabel( rStrm );
1267 break;
1268 default:
1269 XclImpChFrameBase::ReadSubRecord( rStrm );
1273 void XclImpChDataFormat::SetPointPos( const XclChDataPointPos& rPointPos, sal_uInt16 nFormatIdx )
1275 maData.maPointPos = rPointPos;
1276 maData.mnFormatIdx = nFormatIdx;
1279 void XclImpChDataFormat::UpdateGroupFormat( const XclChExtTypeInfo& rTypeInfo )
1281 // remove formats not used for the current chart type
1282 RemoveUnusedFormats( rTypeInfo );
1285 void XclImpChDataFormat::UpdateSeriesFormat( const XclChExtTypeInfo& rTypeInfo, const XclImpChDataFormat* pGroupFmt )
1287 // update missing formats from passed chart type group format
1288 if( pGroupFmt )
1290 if( !mxLineFmt )
1291 mxLineFmt = pGroupFmt->mxLineFmt;
1292 if( !mxAreaFmt && !mxEscherFmt )
1294 mxAreaFmt = pGroupFmt->mxAreaFmt;
1295 mxEscherFmt = pGroupFmt->mxEscherFmt;
1297 if( !mxMarkerFmt )
1298 mxMarkerFmt = pGroupFmt->mxMarkerFmt;
1299 if( !mxPieFmt )
1300 mxPieFmt = pGroupFmt->mxPieFmt;
1301 if( !mxSeriesFmt )
1302 mxSeriesFmt = pGroupFmt->mxSeriesFmt;
1303 if( !mx3dDataFmt )
1304 mx3dDataFmt = pGroupFmt->mx3dDataFmt;
1305 if( !mxAttLabel )
1306 mxAttLabel = pGroupFmt->mxAttLabel;
1309 /* Create missing but required formats. Existing line, area, and marker
1310 format objects are needed to create automatic series formatting. */
1311 if( !mxLineFmt )
1312 mxLineFmt.reset( new XclImpChLineFormat );
1313 if( !mxAreaFmt && !mxEscherFmt )
1314 mxAreaFmt.reset( new XclImpChAreaFormat );
1315 if( !mxMarkerFmt )
1316 mxMarkerFmt.reset( new XclImpChMarkerFormat );
1318 // remove formats not used for the current chart type
1319 RemoveUnusedFormats( rTypeInfo );
1320 // update data label
1321 UpdateDataLabel( pGroupFmt );
1324 void XclImpChDataFormat::UpdatePointFormat( const XclChExtTypeInfo& rTypeInfo, const XclImpChDataFormat* pSeriesFmt )
1326 // remove formats if they are automatic in this and in the passed series format
1327 if( pSeriesFmt )
1329 if( IsAutoLine() && pSeriesFmt->IsAutoLine() )
1330 mxLineFmt.reset();
1331 if( IsAutoArea() && pSeriesFmt->IsAutoArea() )
1332 mxAreaFmt.reset();
1333 if( IsAutoMarker() && pSeriesFmt->IsAutoMarker() )
1334 mxMarkerFmt.reset();
1335 mxSeriesFmt.reset();
1338 // Excel ignores 3D bar format for single data points
1339 mx3dDataFmt.reset();
1340 // remove point line formats for linear chart types, TODO: implement in OOChart
1341 if( !rTypeInfo.IsSeriesFrameFormat() )
1342 mxLineFmt.reset();
1344 // remove formats not used for the current chart type
1345 RemoveUnusedFormats( rTypeInfo );
1346 // update data label
1347 UpdateDataLabel( pSeriesFmt );
1350 void XclImpChDataFormat::UpdateTrendLineFormat()
1352 if( !mxLineFmt )
1353 mxLineFmt.reset( new XclImpChLineFormat );
1354 mxAreaFmt.reset();
1355 mxEscherFmt.reset();
1356 mxMarkerFmt.reset();
1357 mxPieFmt.reset();
1358 mxSeriesFmt.reset();
1359 mx3dDataFmt.reset();
1360 mxAttLabel.reset();
1361 // update data label
1362 UpdateDataLabel( 0 );
1365 void XclImpChDataFormat::Convert( ScfPropertySet& rPropSet, const XclChExtTypeInfo& rTypeInfo ) const
1367 // line and area format
1368 ConvertFrameBase( GetChRoot(), rPropSet, rTypeInfo.GetSeriesObjectType(), maData.mnFormatIdx );
1369 #if EXC_CHART2_3DBAR_HAIRLINES_ONLY
1370 // #i83151# only hair lines in 3D charts with filled data points
1371 if( rTypeInfo.mb3dChart && rTypeInfo.IsSeriesFrameFormat() && mxLineFmt.is() && mxLineFmt->HasLine() )
1372 rPropSet.SetProperty< sal_Int32 >( CREATE_OUSTRING( "BorderWidth" ), 0 );
1373 #endif
1375 // other formatting
1376 if( mxMarkerFmt.is() )
1377 mxMarkerFmt->Convert( GetChRoot(), rPropSet, maData.mnFormatIdx, GetLineWeight() );
1378 if( mxPieFmt.is() )
1379 mxPieFmt->Convert( rPropSet );
1380 if( mx3dDataFmt.is() )
1381 mx3dDataFmt->Convert( rPropSet );
1382 if( mxLabel.is() )
1383 mxLabel->ConvertDataLabel( rPropSet, rTypeInfo );
1385 // 3D settings
1386 rPropSet.SetProperty< sal_Int16 >( EXC_CHPROP_PERCENTDIAGONAL, 0 );
1388 /* Special case: set marker color as line color, if series line is not
1389 visible. This makes the color visible in the marker area.
1390 TODO: remove this if OOChart supports own colors in markers. */
1391 if( !rTypeInfo.IsSeriesFrameFormat() && !HasLine() && mxMarkerFmt.is() )
1392 mxMarkerFmt->ConvertColor( GetChRoot(), rPropSet, maData.mnFormatIdx );
1395 void XclImpChDataFormat::ConvertLine( ScfPropertySet& rPropSet, XclChObjectType eObjType ) const
1397 ConvertLineBase( GetChRoot(), rPropSet, eObjType );
1400 void XclImpChDataFormat::ConvertArea( ScfPropertySet& rPropSet, sal_uInt16 nFormatIdx ) const
1402 ConvertAreaBase( GetChRoot(), rPropSet, EXC_CHOBJTYPE_FILLEDSERIES, nFormatIdx );
1405 void XclImpChDataFormat::RemoveUnusedFormats( const XclChExtTypeInfo& rTypeInfo )
1407 // data point marker only in linear 2D charts
1408 if( rTypeInfo.IsSeriesFrameFormat() )
1409 mxMarkerFmt.reset();
1410 // pie format only in pie/donut charts
1411 if( rTypeInfo.meTypeCateg != EXC_CHTYPECATEG_PIE )
1412 mxPieFmt.reset();
1413 // 3D format only in 3D bar charts
1414 if( !rTypeInfo.mb3dChart || (rTypeInfo.meTypeCateg != EXC_CHTYPECATEG_BAR) )
1415 mx3dDataFmt.reset();
1418 void XclImpChDataFormat::UpdateDataLabel( const XclImpChDataFormat* pParentFmt )
1420 /* CHTEXT groups linked to data labels override existing CHATTACHEDLABEL
1421 records. Only if there is a CHATTACHEDLABEL record without a CHTEXT
1422 group, the contents of the CHATTACHEDLABEL record are used. In this
1423 case a new CHTEXT group is created and filled with the settings from
1424 the CHATTACHEDLABEL record. */
1425 XclImpChTextRef xDefText;
1426 if( pParentFmt )
1427 xDefText = pParentFmt->GetDataLabel();
1428 if( !xDefText )
1429 xDefText = GetChartData().GetDefaultText( EXC_CHTEXTTYPE_DATALABEL );
1430 if( mxLabel.is() )
1431 mxLabel->UpdateText( xDefText.get() );
1432 else if( mxAttLabel.is() )
1433 mxLabel = mxAttLabel->CreateDataLabel( xDefText );
1436 // ----------------------------------------------------------------------------
1438 XclImpChSerTrendLine::XclImpChSerTrendLine( const XclImpChRoot& rRoot ) :
1439 XclImpChRoot( rRoot )
1443 void XclImpChSerTrendLine::ReadChSerTrendLine( XclImpStream& rStrm )
1445 rStrm >> maData.mnLineType
1446 >> maData.mnOrder
1447 >> maData.mfIntercept
1448 >> maData.mnShowEquation
1449 >> maData.mnShowRSquared
1450 >> maData.mfForecastFor
1451 >> maData.mfForecastBack;
1454 Reference< XRegressionCurve > XclImpChSerTrendLine::CreateRegressionCurve() const
1456 // trend line type
1457 OUString aService;
1458 switch( maData.mnLineType )
1460 case EXC_CHSERTREND_POLYNOMIAL:
1461 // TODO: only linear trend lines are supported by OOChart (#i20819#)
1462 if( maData.mnOrder == 1 )
1463 aService = SERVICE_CHART2_LINEARREGCURVE;
1464 break;
1465 case EXC_CHSERTREND_EXPONENTIAL:
1466 aService = SERVICE_CHART2_EXPREGCURVE;
1467 break;
1468 case EXC_CHSERTREND_LOGARITHMIC:
1469 aService = SERVICE_CHART2_LOGREGCURVE;
1470 break;
1471 case EXC_CHSERTREND_POWER:
1472 aService = SERVICE_CHART2_POTREGCURVE;
1473 break;
1475 Reference< XRegressionCurve > xRegCurve;
1476 if( aService.getLength() > 0 )
1477 xRegCurve.set( ScfApiHelper::CreateInstance( aService ), UNO_QUERY );
1479 // trend line formatting
1480 if( xRegCurve.is() && mxDataFmt.is() )
1482 ScfPropertySet aPropSet( xRegCurve );
1483 mxDataFmt->ConvertLine( aPropSet, EXC_CHOBJTYPE_TRENDLINE );
1485 // #i83100# show equation and correlation coefficient
1486 ScfPropertySet aLabelProp( xRegCurve->getEquationProperties() );
1487 aLabelProp.SetBoolProperty( EXC_CHPROP_SHOWEQUATION, maData.mnShowEquation != 0 );
1488 aLabelProp.SetBoolProperty( EXC_CHPROP_SHOWCORRELATION, maData.mnShowRSquared != 0 );
1490 // #i83100# formatting of the equation text box
1491 if( const XclImpChText* pLabel = mxDataFmt->GetDataLabel().get() )
1493 pLabel->ConvertFont( aLabelProp );
1494 pLabel->ConvertFrame( aLabelProp );
1495 pLabel->ConvertNumFmt( aLabelProp, false );
1499 // missing features
1500 // #i20819# polynomial trend lines
1501 // #i66819# moving average trend lines
1502 // #i5085# manual trend line size
1503 // #i34093# manual crossing point
1505 return xRegCurve;
1508 // ----------------------------------------------------------------------------
1510 XclImpChSerErrorBar::XclImpChSerErrorBar( const XclImpChRoot& rRoot ) :
1511 XclImpChRoot( rRoot )
1515 void XclImpChSerErrorBar::ReadChSerErrorBar( XclImpStream& rStrm )
1517 rStrm >> maData.mnBarType >> maData.mnSourceType >> maData.mnLineEnd;
1518 rStrm.Ignore( 1 );
1519 rStrm >> maData.mfValue >> maData.mnValueCount;
1522 void XclImpChSerErrorBar::SetSeriesData( XclImpChSourceLinkRef xValueLink, XclImpChDataFormatRef xDataFmt )
1524 mxValueLink = xValueLink;
1525 mxDataFmt = xDataFmt;
1528 Reference< XLabeledDataSequence > XclImpChSerErrorBar::CreateValueSequence() const
1530 return lclCreateLabeledDataSequence( mxValueLink, XclChartHelper::GetErrorBarValuesRole( maData.mnBarType ) );
1533 Reference< XPropertySet > XclImpChSerErrorBar::CreateErrorBar( const XclImpChSerErrorBar* pPosBar, const XclImpChSerErrorBar* pNegBar )
1535 Reference< XPropertySet > xErrorBar;
1537 if( const XclImpChSerErrorBar* pPrimaryBar = pPosBar ? pPosBar : pNegBar )
1539 xErrorBar.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_ERRORBAR ), UNO_QUERY );
1540 ScfPropertySet aBarProp( xErrorBar );
1542 // plus/minus bars visible?
1543 aBarProp.SetBoolProperty( EXC_CHPROP_SHOWPOSITIVEERROR, pPosBar != 0 );
1544 aBarProp.SetBoolProperty( EXC_CHPROP_SHOWNEGATIVEERROR, pNegBar != 0 );
1546 // type of displayed error
1547 namespace cssc = ::com::sun::star::chart;
1548 switch( pPrimaryBar->maData.mnSourceType )
1550 case EXC_CHSERERR_PERCENT:
1551 aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::RELATIVE );
1552 aBarProp.SetProperty( EXC_CHPROP_POSITIVEERROR, pPrimaryBar->maData.mfValue );
1553 aBarProp.SetProperty( EXC_CHPROP_NEGATIVEERROR, pPrimaryBar->maData.mfValue );
1554 break;
1555 case EXC_CHSERERR_FIXED:
1556 aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::ABSOLUTE );
1557 aBarProp.SetProperty( EXC_CHPROP_POSITIVEERROR, pPrimaryBar->maData.mfValue );
1558 aBarProp.SetProperty( EXC_CHPROP_NEGATIVEERROR, pPrimaryBar->maData.mfValue );
1559 break;
1560 case EXC_CHSERERR_STDDEV:
1561 aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::STANDARD_DEVIATION );
1562 aBarProp.SetProperty( EXC_CHPROP_WEIGHT, pPrimaryBar->maData.mfValue );
1563 break;
1564 case EXC_CHSERERR_STDERR:
1565 aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::STANDARD_ERROR );
1566 break;
1567 case EXC_CHSERERR_CUSTOM:
1569 aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::FROM_DATA );
1570 // attach data sequences to erorr bar
1571 Reference< XDataSink > xDataSink( xErrorBar, UNO_QUERY );
1572 if( xDataSink.is() )
1574 // create vector of all value sequences
1575 ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
1576 // add positive values
1577 if( pPosBar )
1579 Reference< XLabeledDataSequence > xValueSeq = pPosBar->CreateValueSequence();
1580 if( xValueSeq.is() )
1581 aLabeledSeqVec.push_back( xValueSeq );
1583 // add negative values
1584 if( pNegBar )
1586 Reference< XLabeledDataSequence > xValueSeq = pNegBar->CreateValueSequence();
1587 if( xValueSeq.is() )
1588 aLabeledSeqVec.push_back( xValueSeq );
1590 // attach labeled data sequences to series
1591 if( aLabeledSeqVec.empty() )
1592 xErrorBar.clear();
1593 else
1594 xDataSink->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec ) );
1597 break;
1598 default:
1599 xErrorBar.clear();
1602 // error bar formatting
1603 if( pPrimaryBar->mxDataFmt.is() && xErrorBar.is() )
1604 pPrimaryBar->mxDataFmt->ConvertLine( aBarProp, EXC_CHOBJTYPE_ERRORBAR );
1607 return xErrorBar;
1610 // ----------------------------------------------------------------------------
1612 XclImpChSeries::XclImpChSeries( const XclImpChRoot& rRoot, sal_uInt16 nSeriesIdx ) :
1613 XclImpChRoot( rRoot ),
1614 mnGroupIdx( EXC_CHSERGROUP_NONE ),
1615 mnSeriesIdx( nSeriesIdx ),
1616 mnParentIdx( EXC_CHSERIES_INVALID )
1620 void XclImpChSeries::ReadHeaderRecord( XclImpStream& rStrm )
1622 rStrm >> maData.mnCategType >> maData.mnValueType >> maData.mnCategCount >> maData.mnValueCount;
1623 if( GetBiff() == EXC_BIFF8 )
1624 rStrm >> maData.mnBubbleType >> maData.mnBubbleCount;
1627 void XclImpChSeries::ReadSubRecord( XclImpStream& rStrm )
1629 switch( rStrm.GetRecId() )
1631 case EXC_ID_CHSOURCELINK:
1632 ReadChSourceLink( rStrm );
1633 break;
1634 case EXC_ID_CHDATAFORMAT:
1635 ReadChDataFormat( rStrm );
1636 break;
1637 case EXC_ID_CHSERGROUP:
1638 rStrm >> mnGroupIdx;
1639 break;
1640 case EXC_ID_CHSERPARENT:
1641 ReadChSerParent( rStrm );
1642 break;
1643 case EXC_ID_CHSERTRENDLINE:
1644 ReadChSerTrendLine( rStrm );
1645 break;
1646 case EXC_ID_CHSERERRORBAR:
1647 ReadChSerErrorBar( rStrm );
1648 break;
1652 void XclImpChSeries::SetDataFormat( XclImpChDataFormatRef xDataFmt )
1654 if( xDataFmt.is() )
1656 XclImpChDataFormatRef* pxDataFmt = GetDataFormatRef( xDataFmt->GetPointPos().mnPointIdx );
1657 // do not overwrite existing data format
1658 if( pxDataFmt && !*pxDataFmt )
1660 *pxDataFmt = xDataFmt;
1661 // #i51639# register series format index at chart type group
1662 if( (pxDataFmt == &mxSeriesFmt) && !HasParentSeries() )
1663 if( XclImpChTypeGroup* pTypeGroup = GetChartData().GetTypeGroup( mnGroupIdx ).get() )
1664 pTypeGroup->SetUsedFormatIndex( xDataFmt->GetFormatIdx() );
1669 void XclImpChSeries::SetDataLabel( XclImpChTextRef xLabel )
1671 if( xLabel.is() )
1673 XclImpChTextRef* pxLabel = GetDataLabelRef( xLabel->GetPointPos().mnPointIdx );
1674 if( pxLabel && !*pxLabel )
1675 *pxLabel = xLabel;
1679 void XclImpChSeries::AddChildSeries( const XclImpChSeries& rSeries )
1681 DBG_ASSERT( !HasParentSeries(), "XclImpChSeries::AddChildSeries - not allowed for child series" );
1683 /* In Excel, trend lines and error bars are stored as own series. In Calc,
1684 these are properties of the parent series. This function adds the
1685 settings of the passed series to this series. */
1686 maTrendLines.insert( maTrendLines.end(), rSeries.maTrendLines.begin(), rSeries.maTrendLines.end() );
1687 maErrorBars.insert( rSeries.maErrorBars.begin(), rSeries.maErrorBars.end() );
1690 void XclImpChSeries::FinalizeDataFormats()
1692 if( HasParentSeries() )
1694 // *** series is a child series, e.g. trend line or error bar ***
1696 // create missing series format
1697 if( !mxSeriesFmt )
1698 mxSeriesFmt = CreateDataFormat( EXC_CHDATAFORMAT_ALLPOINTS, 0 );
1700 if( mxSeriesFmt.is() )
1702 // #i83100# set text label format, e.g. for trend line equations
1703 mxSeriesFmt->SetDataLabel( maLabels.get( EXC_CHDATAFORMAT_ALLPOINTS ) );
1704 // create missing automatic formats
1705 mxSeriesFmt->UpdateTrendLineFormat();
1708 // copy series formatting to child objects
1709 for( XclImpChSerTrendLineList::iterator aLIt = maTrendLines.begin(), aLEnd = maTrendLines.end(); aLIt != aLEnd; ++aLIt )
1710 (*aLIt)->SetDataFormat( mxSeriesFmt );
1711 for( XclImpChSerErrorBarMap::iterator aMIt = maErrorBars.begin(), aMEnd = maErrorBars.end(); aMIt != aMEnd; ++aMIt )
1712 aMIt->second->SetSeriesData( mxValueLink, mxSeriesFmt );
1714 else if( XclImpChTypeGroup* pTypeGroup = GetChartData().GetTypeGroup( mnGroupIdx ).get() )
1716 // *** series is a regular data series ***
1718 // create missing series format
1719 if( !mxSeriesFmt )
1721 // #i51639# use a new unused format index to create series default format
1722 sal_uInt16 nFormatIdx = pTypeGroup->PopUnusedFormatIndex();
1723 mxSeriesFmt = CreateDataFormat( EXC_CHDATAFORMAT_ALLPOINTS, nFormatIdx );
1726 // set text labels to data formats
1727 for( XclImpChTextMap::iterator aTIt = maLabels.begin(), aTEnd = maLabels.end(); aTIt != aTEnd; ++aTIt )
1729 if( XclImpChDataFormatRef* pxDataFmt = GetDataFormatRef( aTIt->first ) )
1731 if( !*pxDataFmt )
1732 *pxDataFmt = CreateDataFormat( aTIt->first, EXC_CHDATAFORMAT_DEFAULT );
1733 (*pxDataFmt)->SetDataLabel( aTIt->second );
1737 // update series format (copy missing formatting from group default format)
1738 if( mxSeriesFmt.is() )
1739 mxSeriesFmt->UpdateSeriesFormat( pTypeGroup->GetTypeInfo(), pTypeGroup->GetGroupFormat().get() );
1741 // update data point formats (removes unchanged automatic formatting)
1742 for( XclImpChDataFormatMap::iterator aFIt = maPointFmts.begin(), aFEnd = maPointFmts.end(); aFIt != aFEnd; ++aFIt )
1743 aFIt->second->UpdatePointFormat( pTypeGroup->GetTypeInfo(), mxSeriesFmt.get() );
1747 namespace {
1749 /** Returns the property set of the specified data point. */
1750 ScfPropertySet lclGetPointPropSet( Reference< XDataSeries > xDataSeries, sal_uInt16 nPointIdx )
1752 ScfPropertySet aPropSet;
1755 aPropSet.Set( xDataSeries->getDataPointByIndex( static_cast< sal_Int32 >( nPointIdx ) ) );
1757 catch( Exception& )
1759 DBG_ERRORFILE( "lclGetPointPropSet - no data point property set" );
1761 return aPropSet;
1764 } // namespace
1766 Reference< XLabeledDataSequence > XclImpChSeries::CreateValueSequence( const OUString& rValueRole ) const
1768 return lclCreateLabeledDataSequence( mxValueLink, rValueRole, mxTitleLink.get() );
1771 Reference< XLabeledDataSequence > XclImpChSeries::CreateCategSequence( const OUString& rCategRole ) const
1773 return lclCreateLabeledDataSequence( mxCategLink, rCategRole );
1776 Reference< XDataSeries > XclImpChSeries::CreateDataSeries() const
1778 Reference< XDataSeries > xDataSeries;
1779 if( const XclImpChTypeGroup* pTypeGroup = GetChartData().GetTypeGroup( mnGroupIdx ).get() )
1781 const XclChExtTypeInfo& rTypeInfo = pTypeGroup->GetTypeInfo();
1783 // create the data series object
1784 xDataSeries.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_DATASERIES ), UNO_QUERY );
1786 // attach data and title sequences to series
1787 Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY );
1788 if( xDataSink.is() )
1790 // create vector of all value sequences
1791 ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
1792 // add Y values
1793 Reference< XLabeledDataSequence > xYValueSeq =
1794 CreateValueSequence( EXC_CHPROP_ROLE_YVALUES );
1795 if( xYValueSeq.is() )
1796 aLabeledSeqVec.push_back( xYValueSeq );
1797 // add X values
1798 if( !rTypeInfo.mbCategoryAxis )
1800 Reference< XLabeledDataSequence > xXValueSeq =
1801 CreateCategSequence( EXC_CHPROP_ROLE_XVALUES );
1802 if( xXValueSeq.is() )
1803 aLabeledSeqVec.push_back( xXValueSeq );
1804 // add size values of bubble charts
1805 if( rTypeInfo.meTypeId == EXC_CHTYPEID_BUBBLES )
1807 Reference< XLabeledDataSequence > xSizeValueSeq =
1808 lclCreateLabeledDataSequence( mxBubbleLink, EXC_CHPROP_ROLE_SIZEVALUES, mxTitleLink.get() );
1809 if( xSizeValueSeq.is() )
1810 aLabeledSeqVec.push_back( xSizeValueSeq );
1813 // attach labeled data sequences to series
1814 if( !aLabeledSeqVec.empty() )
1815 xDataSink->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec ) );
1818 // series formatting
1819 ScfPropertySet aSeriesProp( xDataSeries );
1820 if( mxSeriesFmt.is() )
1821 mxSeriesFmt->Convert( aSeriesProp, rTypeInfo );
1823 // trend lines
1824 ConvertTrendLines( xDataSeries );
1826 // error bars
1827 Reference< XPropertySet > xErrorBarX = CreateErrorBar( EXC_CHSERERR_XPLUS, EXC_CHSERERR_XMINUS );
1828 if( xErrorBarX.is() )
1829 aSeriesProp.SetProperty( EXC_CHPROP_ERRORBARX, xErrorBarX );
1830 Reference< XPropertySet > xErrorBarY = CreateErrorBar( EXC_CHSERERR_YPLUS, EXC_CHSERERR_YMINUS );
1831 if( xErrorBarY.is() )
1832 aSeriesProp.SetProperty( EXC_CHPROP_ERRORBARY, xErrorBarY );
1834 // own area formatting for every data point (TODO: varying line color not supported)
1835 bool bVarPointFmt = pTypeGroup->HasVarPointFormat() && rTypeInfo.IsSeriesFrameFormat();
1836 #if EXC_CHART2_VARYCOLORSBY_PROP
1837 aSeriesProp.SetBoolProperty( EXC_CHPROP_VARYCOLORSBY, bVarPointFmt );
1838 #else
1839 aSeriesProp.SetBoolProperty( EXC_CHPROP_VARYCOLORSBY, rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE );
1840 #endif
1841 // #i91271# always set area formatting for every point in pie/doughnut charts
1842 if( mxSeriesFmt.is() && ((bVarPointFmt && mxSeriesFmt->IsAutoArea()) || (rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE)) )
1844 for( sal_uInt16 nPointIdx = 0, nPointCount = mxValueLink->GetCellCount(); nPointIdx < nPointCount; ++nPointIdx )
1846 ScfPropertySet aPointProp = lclGetPointPropSet( xDataSeries, nPointIdx );
1847 mxSeriesFmt->ConvertArea( aPointProp, bVarPointFmt ? nPointIdx : mnSeriesIdx );
1851 // data point formatting
1852 for( XclImpChDataFormatMap::const_iterator aIt = maPointFmts.begin(), aEnd = maPointFmts.end(); aIt != aEnd; ++aIt )
1854 ScfPropertySet aPointProp = lclGetPointPropSet( xDataSeries, aIt->first );
1855 aIt->second->Convert( aPointProp, rTypeInfo );
1858 return xDataSeries;
1861 void XclImpChSeries::FillAllSourceLinks(vector<ScSharedTokenRef>& rTokens) const
1863 mxValueLink->FillSourceLink(rTokens);
1864 mxCategLink->FillSourceLink(rTokens);
1865 mxTitleLink->FillSourceLink(rTokens);
1866 mxBubbleLink->FillSourceLink(rTokens);
1869 void XclImpChSeries::ReadChSourceLink( XclImpStream& rStrm )
1871 XclImpChSourceLinkRef xSrcLink( new XclImpChSourceLink( GetChRoot() ) );
1872 xSrcLink->ReadChSourceLink( rStrm );
1873 switch( xSrcLink->GetDestType() )
1875 case EXC_CHSRCLINK_TITLE: mxTitleLink = xSrcLink; break;
1876 case EXC_CHSRCLINK_VALUES: mxValueLink = xSrcLink; break;
1877 case EXC_CHSRCLINK_CATEGORY: mxCategLink = xSrcLink; break;
1878 case EXC_CHSRCLINK_BUBBLES: mxBubbleLink = xSrcLink; break;
1882 void XclImpChSeries::ReadChDataFormat( XclImpStream& rStrm )
1884 // #i51639# chart stores all data formats and assigns them later to the series
1885 GetChartData().ReadChDataFormat( rStrm );
1888 void XclImpChSeries::ReadChSerParent( XclImpStream& rStrm )
1890 rStrm >> mnParentIdx;
1891 // index to parent series is 1-based, convert it to 0-based
1892 if( mnParentIdx > 0 )
1893 --mnParentIdx;
1894 else
1895 mnParentIdx = EXC_CHSERIES_INVALID;
1898 void XclImpChSeries::ReadChSerTrendLine( XclImpStream& rStrm )
1900 XclImpChSerTrendLineRef xTrendLine( new XclImpChSerTrendLine( GetChRoot() ) );
1901 xTrendLine->ReadChSerTrendLine( rStrm );
1902 maTrendLines.push_back( xTrendLine );
1905 void XclImpChSeries::ReadChSerErrorBar( XclImpStream& rStrm )
1907 XclImpChSerErrorBarRef xErrorBar( new XclImpChSerErrorBar( GetChRoot() ) );
1908 xErrorBar->ReadChSerErrorBar( rStrm );
1909 maErrorBars[ xErrorBar->GetBarType() ] = xErrorBar;
1912 XclImpChDataFormatRef XclImpChSeries::CreateDataFormat( sal_uInt16 nPointIdx, sal_uInt16 nFormatIdx )
1914 XclImpChDataFormatRef xDataFmt( new XclImpChDataFormat( GetChRoot() ) );
1915 xDataFmt->SetPointPos( XclChDataPointPos( mnSeriesIdx, nPointIdx ), nFormatIdx );
1916 return xDataFmt;
1919 XclImpChDataFormatRef* XclImpChSeries::GetDataFormatRef( sal_uInt16 nPointIdx )
1921 if( nPointIdx == EXC_CHDATAFORMAT_ALLPOINTS )
1922 return &mxSeriesFmt;
1923 if( nPointIdx < EXC_CHDATAFORMAT_MAXPOINTCOUNT )
1924 return &maPointFmts[ nPointIdx ];
1925 return 0;
1928 XclImpChTextRef* XclImpChSeries::GetDataLabelRef( sal_uInt16 nPointIdx )
1930 if( (nPointIdx == EXC_CHDATAFORMAT_ALLPOINTS) || (nPointIdx < EXC_CHDATAFORMAT_MAXPOINTCOUNT) )
1931 return &maLabels[ nPointIdx ];
1932 return 0;
1935 void XclImpChSeries::ConvertTrendLines( Reference< XDataSeries > xDataSeries ) const
1937 Reference< XRegressionCurveContainer > xRegCurveCont( xDataSeries, UNO_QUERY );
1938 if( xRegCurveCont.is() )
1940 for( XclImpChSerTrendLineList::const_iterator aIt = maTrendLines.begin(), aEnd = maTrendLines.end(); aIt != aEnd; ++aIt )
1944 Reference< XRegressionCurve > xRegCurve = (*aIt)->CreateRegressionCurve();
1945 if( xRegCurve.is() )
1946 xRegCurveCont->addRegressionCurve( xRegCurve );
1948 catch( Exception& )
1950 DBG_ERRORFILE( "XclImpChSeries::ConvertTrendLines - cannot add regression curve" );
1956 Reference< XPropertySet > XclImpChSeries::CreateErrorBar( sal_uInt8 nPosBarId, sal_uInt8 nNegBarId ) const
1958 return XclImpChSerErrorBar::CreateErrorBar( maErrorBars.get( nPosBarId ).get(), maErrorBars.get( nNegBarId ).get() );
1961 // Chart type groups ==========================================================
1963 XclImpChType::XclImpChType( const XclImpChRoot& rRoot ) :
1964 XclImpChRoot( rRoot ),
1965 mnRecId( EXC_ID_CHUNKNOWN ),
1966 maTypeInfo( rRoot.GetChartTypeInfo( EXC_CHTYPEID_UNKNOWN ) )
1970 void XclImpChType::ReadChType( XclImpStream& rStrm )
1972 sal_uInt16 nRecId = rStrm.GetRecId();
1973 bool bKnownType = true;
1975 switch( nRecId )
1977 case EXC_ID_CHBAR:
1978 rStrm >> maData.mnOverlap >> maData.mnGap >> maData.mnFlags;
1979 break;
1981 case EXC_ID_CHLINE:
1982 case EXC_ID_CHAREA:
1983 case EXC_ID_CHRADARLINE:
1984 case EXC_ID_CHRADARAREA:
1985 rStrm >> maData.mnFlags;
1986 break;
1988 case EXC_ID_CHPIE:
1989 rStrm >> maData.mnRotation >> maData.mnPieHole;
1990 if( GetBiff() == EXC_BIFF8 )
1991 rStrm >> maData.mnFlags;
1992 else
1993 maData.mnFlags = 0;
1994 break;
1996 case EXC_ID_CHPIEEXT:
1997 maData.mnRotation = 0;
1998 maData.mnPieHole = 0;
1999 maData.mnFlags = 0;
2000 break;
2002 case EXC_ID_CHSCATTER:
2003 if( GetBiff() == EXC_BIFF8 )
2004 rStrm >> maData.mnBubbleSize >> maData.mnBubbleType >> maData.mnFlags;
2005 else
2006 maData.mnFlags = 0;
2007 break;
2009 case EXC_ID_CHSURFACE:
2010 rStrm >> maData.mnFlags;
2011 break;
2013 default:
2014 bKnownType = false;
2017 if( bKnownType )
2018 mnRecId = nRecId;
2021 void XclImpChType::Finalize( bool bStockChart )
2023 switch( mnRecId )
2025 case EXC_ID_CHLINE:
2026 maTypeInfo = GetChartTypeInfo( bStockChart ?
2027 EXC_CHTYPEID_STOCK : EXC_CHTYPEID_LINE );
2028 break;
2029 case EXC_ID_CHBAR:
2030 maTypeInfo = GetChartTypeInfo( ::get_flagvalue(
2031 maData.mnFlags, EXC_CHBAR_HORIZONTAL,
2032 EXC_CHTYPEID_HORBAR, EXC_CHTYPEID_BAR ) );
2033 break;
2034 case EXC_ID_CHPIE:
2035 maTypeInfo = GetChartTypeInfo( (maData.mnPieHole > 0) ?
2036 EXC_CHTYPEID_DONUT : EXC_CHTYPEID_PIE );
2037 break;
2038 case EXC_ID_CHSCATTER:
2039 maTypeInfo = GetChartTypeInfo( ::get_flagvalue(
2040 maData.mnFlags, EXC_CHSCATTER_BUBBLES,
2041 EXC_CHTYPEID_BUBBLES, EXC_CHTYPEID_SCATTER ) );
2042 break;
2043 default:
2044 maTypeInfo = GetChartTypeInfo( mnRecId );
2047 switch( maTypeInfo.meTypeId )
2049 case EXC_CHTYPEID_PIEEXT:
2050 case EXC_CHTYPEID_BUBBLES:
2051 case EXC_CHTYPEID_SURFACE:
2052 case EXC_CHTYPEID_UNKNOWN:
2053 GetTracer().TraceChartUnKnownType();
2054 break;
2055 default:;
2059 bool XclImpChType::IsStacked() const
2061 bool bStacked = false;
2062 if( maTypeInfo.mbSupportsStacking ) switch( maTypeInfo.meTypeCateg )
2064 case EXC_CHTYPECATEG_LINE:
2065 bStacked =
2066 ::get_flag( maData.mnFlags, EXC_CHLINE_STACKED ) &&
2067 !::get_flag( maData.mnFlags, EXC_CHLINE_PERCENT );
2068 break;
2069 case EXC_CHTYPECATEG_BAR:
2070 bStacked =
2071 ::get_flag( maData.mnFlags, EXC_CHBAR_STACKED ) &&
2072 !::get_flag( maData.mnFlags, EXC_CHBAR_PERCENT );
2073 break;
2074 default:;
2076 return bStacked;
2079 bool XclImpChType::IsPercent() const
2081 bool bPercent = false;
2082 if( maTypeInfo.mbSupportsStacking ) switch( maTypeInfo.meTypeCateg )
2084 case EXC_CHTYPECATEG_LINE:
2085 bPercent =
2086 ::get_flag( maData.mnFlags, EXC_CHLINE_STACKED ) &&
2087 ::get_flag( maData.mnFlags, EXC_CHLINE_PERCENT );
2088 break;
2089 case EXC_CHTYPECATEG_BAR:
2090 bPercent =
2091 ::get_flag( maData.mnFlags, EXC_CHBAR_STACKED ) &&
2092 ::get_flag( maData.mnFlags, EXC_CHBAR_PERCENT );
2093 break;
2094 default:;
2096 return bPercent;
2099 bool XclImpChType::HasCategoryLabels() const
2101 // radar charts disable category labels in chart type, not in CHTICK of X axis
2102 return (maTypeInfo.meTypeCateg != EXC_CHTYPECATEG_RADAR) || ::get_flag( maData.mnFlags, EXC_CHRADAR_AXISLABELS );
2105 Reference< XCoordinateSystem > XclImpChType::CreateCoordSystem( bool b3dChart ) const
2107 // service name
2108 OUString aCoordSysService;
2109 if( maTypeInfo.mbPolarCoordSystem )
2111 if( b3dChart )
2112 aCoordSysService = SERVICE_CHART2_POLARCOORDSYS3D;
2113 else
2114 aCoordSysService = SERVICE_CHART2_POLARCOORDSYS2D;
2116 else
2118 if( b3dChart )
2119 aCoordSysService = SERVICE_CHART2_CARTESIANCOORDSYS3D;
2120 else
2121 aCoordSysService = SERVICE_CHART2_CARTESIANCOORDSYS2D;
2124 // create the coordinate system object
2125 Reference< XCoordinateSystem > xCoordSystem( ScfApiHelper::CreateInstance( aCoordSysService ), UNO_QUERY );
2127 // swap X and Y axis
2128 if( maTypeInfo.mbSwappedAxesSet )
2130 ScfPropertySet aCoordSysProp( xCoordSystem );
2131 aCoordSysProp.SetBoolProperty( EXC_CHPROP_SWAPXANDYAXIS, true );
2134 return xCoordSystem;
2137 Reference< XChartType > XclImpChType::CreateChartType( Reference< XDiagram > xDiagram, bool b3dChart ) const
2139 OUString aService = OUString::createFromAscii( maTypeInfo.mpcServiceName );
2140 Reference< XChartType > xChartType( ScfApiHelper::CreateInstance( aService ), UNO_QUERY );
2142 // additional properties
2143 switch( maTypeInfo.meTypeCateg )
2145 case EXC_CHTYPECATEG_LINE:
2147 ScfPropertySet aTypeProp(xChartType);
2148 bool bStacked = (maData.mnFlags & EXC_CHLINE_STACKED);
2149 bool bPercent = (maData.mnFlags & EXC_CHLINE_PERCENT);
2150 aTypeProp.SetBoolProperty(EXC_CHPROP_STACKED, bStacked);
2151 aTypeProp.SetBoolProperty(EXC_CHPROP_PERCENT, bPercent);
2153 break;
2154 case EXC_CHTYPECATEG_BAR:
2156 ScfPropertySet aTypeProp( xChartType );
2157 Sequence< sal_Int32 > aInt32Seq( 2 );
2158 aInt32Seq[ 0 ] = aInt32Seq[ 1 ] = -maData.mnOverlap;
2159 aTypeProp.SetProperty( EXC_CHPROP_OVERLAPSEQ, aInt32Seq );
2160 aInt32Seq[ 0 ] = aInt32Seq[ 1 ] = maData.mnGap;
2161 aTypeProp.SetProperty( EXC_CHPROP_GAPWIDTHSEQ, aInt32Seq );
2162 bool bStacked = (maData.mnFlags & EXC_CHBAR_STACKED);
2163 bool bPercent = (maData.mnFlags & EXC_CHBAR_PERCENT);
2164 aTypeProp.SetBoolProperty(EXC_CHPROP_STACKED, bStacked);
2165 aTypeProp.SetBoolProperty(EXC_CHPROP_PERCENT, bPercent);
2167 break;
2168 case EXC_CHTYPECATEG_PIE:
2170 ScfPropertySet aTypeProp( xChartType );
2171 aTypeProp.SetBoolProperty( EXC_CHPROP_USERINGS, maTypeInfo.meTypeId == EXC_CHTYPEID_DONUT );
2172 /* #i85166# starting angle of first pie slice. 3D pie charts use Y
2173 rotation setting in view3D element. Of-pie charts do not
2174 support pie rotation. */
2175 if( !b3dChart && (maTypeInfo.meTypeId != EXC_CHTYPEID_PIEEXT) )
2177 ScfPropertySet aDiaProp( xDiagram );
2178 XclImpChRoot::ConvertPieRotation( aDiaProp, maData.mnRotation );
2181 break;
2182 default:;
2185 return xChartType;
2188 // ----------------------------------------------------------------------------
2190 void XclImpChChart3d::ReadChChart3d( XclImpStream& rStrm )
2192 rStrm >> maData.mnRotation
2193 >> maData.mnElevation
2194 >> maData.mnEyeDist
2195 >> maData.mnRelHeight
2196 >> maData.mnRelDepth
2197 >> maData.mnDepthGap
2198 >> maData.mnFlags;
2201 void XclImpChChart3d::Convert( ScfPropertySet& rPropSet, bool b3dWallChart ) const
2203 namespace cssd = ::com::sun::star::drawing;
2205 // #i104057# do not assert this, written by broken external generators
2206 // DBG_ASSERT( ::get_flag( maData.mnFlags, EXC_CHCHART3D_HASWALLS ) == b3dWallChart, "XclImpChChart3d::Convert - wrong wall flag" );
2208 sal_Int32 nRotationY = 0;
2209 sal_Int32 nRotationX = 0;
2210 sal_Int32 nPerspective = 15;
2211 bool bRightAngled = false;
2212 cssd::ProjectionMode eProjMode = cssd::ProjectionMode_PERSPECTIVE;
2213 Color aAmbientColor, aLightColor;
2215 if( b3dWallChart )
2217 // Y rotation (Excel [0..359], Chart2 [-179,180])
2218 nRotationY = maData.mnRotation % 360;
2219 if( nRotationY > 180 ) nRotationY -= 360;
2220 // X rotation a.k.a. elevation (Excel [-90..90], Chart2 [-179,180])
2221 nRotationX = limit_cast< sal_Int32, sal_Int32 >( maData.mnElevation, -90, 90 );
2222 // perspective (Excel and Chart2 [0,100])
2223 nPerspective = limit_cast< sal_Int32, sal_Int32 >( maData.mnEyeDist, 0, 100 );
2224 // right-angled axes
2225 bRightAngled = !::get_flag( maData.mnFlags, EXC_CHCHART3D_REAL3D );
2226 // projection mode (parallel axes, if right-angled, #i90360# or if perspective is at 0%)
2227 bool bParallel = bRightAngled || (nPerspective == 0);
2228 eProjMode = bParallel ? cssd::ProjectionMode_PARALLEL : cssd::ProjectionMode_PERSPECTIVE;
2229 // ambient color (Gray 20%)
2230 aAmbientColor.SetColor( RGB_COLORDATA( 204, 204, 204 ) );
2231 // light color (Gray 60%)
2232 aLightColor.SetColor( RGB_COLORDATA( 102, 102, 102 ) );
2234 else
2236 // Y rotation not used in pie charts, but 'first pie slice angle'
2237 nRotationY = 0;
2238 XclImpChRoot::ConvertPieRotation( rPropSet, maData.mnRotation );
2239 // X rotation a.k.a. elevation (map Excel [10..80] to Chart2 [-80,-10])
2240 nRotationX = limit_cast< sal_Int32, sal_Int32 >( maData.mnElevation, 10, 80 ) - 90;
2241 // perspective (Excel and Chart2 [0,100])
2242 nPerspective = limit_cast< sal_Int32, sal_Int32 >( maData.mnEyeDist, 0, 100 );
2243 // no right-angled axes in pie charts, but parallel projection
2244 bRightAngled = false;
2245 eProjMode = cssd::ProjectionMode_PARALLEL;
2246 // ambient color (Gray 30%)
2247 aAmbientColor.SetColor( RGB_COLORDATA( 179, 179, 179 ) );
2248 // light color (Gray 70%)
2249 aLightColor.SetColor( RGB_COLORDATA( 76, 76, 76 ) );
2252 // properties
2253 rPropSet.SetProperty( EXC_CHPROP_ROTATIONVERTICAL, nRotationY );
2254 rPropSet.SetProperty( EXC_CHPROP_ROTATIONHORIZONTAL, nRotationX );
2255 rPropSet.SetProperty( EXC_CHPROP_PERSPECTIVE, nPerspective );
2256 rPropSet.SetBoolProperty( EXC_CHPROP_RIGHTANGLEDAXES, bRightAngled );
2257 rPropSet.SetProperty( EXC_CHPROP_D3DSCENEPERSPECTIVE, eProjMode );
2259 // light settings
2260 rPropSet.SetProperty( EXC_CHPROP_D3DSCENESHADEMODE, cssd::ShadeMode_FLAT );
2261 rPropSet.SetColorProperty( EXC_CHPROP_D3DSCENEAMBIENTCOLOR, aAmbientColor );
2262 rPropSet.SetBoolProperty( EXC_CHPROP_D3DSCENELIGHTON1, false );
2263 rPropSet.SetBoolProperty( EXC_CHPROP_D3DSCENELIGHTON2, true );
2264 rPropSet.SetColorProperty( EXC_CHPROP_D3DSCENELIGHTCOLOR2, aLightColor );
2265 rPropSet.SetProperty( EXC_CHPROP_D3DSCENELIGHTDIR2, cssd::Direction3D( 0.2, 0.4, 1.0 ) );
2268 // ----------------------------------------------------------------------------
2270 XclImpChLegend::XclImpChLegend( const XclImpChRoot& rRoot ) :
2271 XclImpChRoot( rRoot )
2275 void XclImpChLegend::ReadHeaderRecord( XclImpStream& rStrm )
2277 rStrm >> maData.maRect >> maData.mnDockMode >> maData.mnSpacing >> maData.mnFlags;
2279 // trace unsupported features
2280 if( GetTracer().IsEnabled() )
2282 if( maData.mnDockMode == EXC_CHLEGEND_NOTDOCKED )
2283 GetTracer().TraceChartLegendPosition();
2284 if( ::get_flag( maData.mnFlags, EXC_CHLEGEND_DATATABLE ) )
2285 GetTracer().TraceChartDataTable();
2289 void XclImpChLegend::ReadSubRecord( XclImpStream& rStrm )
2291 switch( rStrm.GetRecId() )
2293 case EXC_ID_CHTEXT:
2294 mxText.reset( new XclImpChText( GetChRoot() ) );
2295 mxText->ReadRecordGroup( rStrm );
2296 break;
2297 case EXC_ID_CHFRAME:
2298 mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_LEGEND ) );
2299 mxFrame->ReadRecordGroup( rStrm );
2300 break;
2304 void XclImpChLegend::Finalize()
2306 // legend default formatting differs in OOChart and Excel, missing frame means automatic
2307 if( !mxFrame )
2308 mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_LEGEND ) );
2309 // Update text formatting. If mxText is empty, the passed default text is used.
2310 lclUpdateText( mxText, GetChartData().GetDefaultText( EXC_CHTEXTTYPE_LEGEND ) );
2313 Reference< XLegend > XclImpChLegend::CreateLegend() const
2315 Reference< XLegend > xLegend( ScfApiHelper::CreateInstance( SERVICE_CHART2_LEGEND ), UNO_QUERY );
2316 if( xLegend.is() )
2318 ScfPropertySet aLegendProp( xLegend );
2320 // frame properties
2321 if( mxFrame.is() )
2322 mxFrame->Convert( aLegendProp );
2323 // text properties
2324 if( mxText.is() )
2325 mxText->ConvertFont( aLegendProp );
2326 // special legend properties
2327 GetChartPropSetHelper().WriteLegendProperties( aLegendProp, maData );
2329 return xLegend;
2332 // ----------------------------------------------------------------------------
2334 XclImpChDropBar::XclImpChDropBar( sal_uInt16 nDropBar ) :
2335 mnDropBar( nDropBar ),
2336 mnBarDist( 0 )
2340 void XclImpChDropBar::ReadHeaderRecord( XclImpStream& rStrm )
2342 rStrm >> mnBarDist;
2345 void XclImpChDropBar::Convert( const XclImpChRoot& rRoot, ScfPropertySet& rPropSet ) const
2347 XclChObjectType eObjType = EXC_CHOBJTYPE_BACKGROUND;
2348 switch( mnDropBar )
2350 case EXC_CHDROPBAR_UP: eObjType = EXC_CHOBJTYPE_WHITEDROPBAR; break;
2351 case EXC_CHDROPBAR_DOWN: eObjType = EXC_CHOBJTYPE_BLACKDROPBAR; break;
2353 ConvertFrameBase( rRoot, rPropSet, eObjType );
2356 // ----------------------------------------------------------------------------
2358 XclImpChTypeGroup::XclImpChTypeGroup( const XclImpChRoot& rRoot ) :
2359 XclImpChRoot( rRoot ),
2360 maType( rRoot ),
2361 maTypeInfo( maType.GetTypeInfo() )
2363 // Initialize unused format indexes set. At this time, all formats are unused.
2364 for( sal_uInt16 nFormatIdx = 0; nFormatIdx <= EXC_CHSERIES_MAXSERIES; ++nFormatIdx )
2365 maUnusedFormats.insert( maUnusedFormats.end(), nFormatIdx );
2368 void XclImpChTypeGroup::ReadHeaderRecord( XclImpStream& rStrm )
2370 rStrm >> maData.maRect >> maData.mnFlags >> maData.mnGroupIdx;
2373 void XclImpChTypeGroup::ReadSubRecord( XclImpStream& rStrm )
2375 switch( rStrm.GetRecId() )
2377 case EXC_ID_CHCHART3D:
2378 mxChart3d.reset( new XclImpChChart3d );
2379 mxChart3d->ReadChChart3d( rStrm );
2380 break;
2381 case EXC_ID_CHLEGEND:
2382 mxLegend.reset( new XclImpChLegend( GetChRoot() ) );
2383 mxLegend->ReadRecordGroup( rStrm );
2384 break;
2385 case EXC_ID_CHDEFAULTTEXT:
2386 GetChartData().ReadChDefaultText( rStrm );
2387 break;
2388 case EXC_ID_CHDROPBAR:
2389 ReadChDropBar( rStrm );
2390 break;
2391 case EXC_ID_CHCHARTLINE:
2392 ReadChChartLine( rStrm );
2393 break;
2394 case EXC_ID_CHDATAFORMAT:
2395 ReadChDataFormat( rStrm );
2396 break;
2397 default:
2398 maType.ReadChType( rStrm );
2402 void XclImpChTypeGroup::Finalize()
2404 // check and set valid chart type
2405 bool bStockChart =
2406 (maType.GetRecId() == EXC_ID_CHLINE) && // must be a line chart
2407 !mxChart3d && // must be a 2d chart
2408 HasHiLoLine() && // must contain hi-lo lines
2409 (maSeries.size() == static_cast<XclImpChSeriesVec::size_type>(HasDropBars() ? 4 : 3)); // correct series count
2410 maType.Finalize( bStockChart );
2412 // extended type info
2413 maTypeInfo.Set( maType.GetTypeInfo(), mxChart3d.is(), false );
2415 // reverse series order for some unstacked 2D chart types
2416 if( maTypeInfo.mbReverseSeries && !Is3dChart() && !maType.IsStacked() && !maType.IsPercent() )
2417 ::std::reverse( maSeries.begin(), maSeries.end() );
2419 // update chart type group format, may depend on chart type finalized above
2420 if( mxGroupFmt.is() )
2421 mxGroupFmt->UpdateGroupFormat( maTypeInfo );
2424 void XclImpChTypeGroup::AddSeries( XclImpChSeriesRef xSeries )
2426 if( xSeries.is() )
2427 maSeries.push_back( xSeries );
2428 // store first inserted series separately, series order may be reversed later
2429 if( !mxFirstSeries )
2430 mxFirstSeries = xSeries;
2433 void XclImpChTypeGroup::SetUsedFormatIndex( sal_uInt16 nFormatIdx )
2435 maUnusedFormats.erase( nFormatIdx );
2438 sal_uInt16 XclImpChTypeGroup::PopUnusedFormatIndex()
2440 DBG_ASSERT( !maUnusedFormats.empty(), "XclImpChTypeGroup::PopUnusedFormatIndex - no more format indexes available" );
2441 sal_uInt16 nFormatIdx = maUnusedFormats.empty() ? 0 : *maUnusedFormats.begin();
2442 SetUsedFormatIndex( nFormatIdx );
2443 return nFormatIdx;
2446 bool XclImpChTypeGroup::HasVarPointFormat() const
2448 return ::get_flag( maData.mnFlags, EXC_CHTYPEGROUP_VARIEDCOLORS ) &&
2449 ((maTypeInfo.meVarPointMode == EXC_CHVARPOINT_MULTI) || // multiple series allowed
2450 ((maTypeInfo.meVarPointMode == EXC_CHVARPOINT_SINGLE) && // or exactly 1 series?
2451 (maSeries.size() == 1)));
2454 bool XclImpChTypeGroup::HasConnectorLines() const
2456 // existence of connector lines (only in stacked bar charts)
2457 bool bAnyStacked = maType.IsStacked() || maType.IsPercent();
2458 XclImpChLineFormatRef xConnLine = maChartLines.get( EXC_CHCHARTLINE_CONNECT );
2459 return bAnyStacked && (maTypeInfo.meTypeCateg == EXC_CHTYPECATEG_BAR) && xConnLine.is() && xConnLine->HasLine();
2462 const String& XclImpChTypeGroup::GetSingleSeriesTitle() const
2464 // no automatic title for series with trendlines or error bars
2465 // pie charts always show an automatic title, even if more series exist
2466 return (mxFirstSeries.is() && !mxFirstSeries->HasChildSeries() && (maTypeInfo.mbSingleSeriesVis || (maSeries.size() == 1))) ?
2467 mxFirstSeries->GetTitle() : String::EmptyString();
2470 void XclImpChTypeGroup::ConvertChart3d( ScfPropertySet& rPropSet ) const
2472 if( mxChart3d.is() )
2473 mxChart3d->Convert( rPropSet, Is3dWallChart() );
2476 Reference< XCoordinateSystem > XclImpChTypeGroup::CreateCoordSystem() const
2478 return maType.CreateCoordSystem( Is3dChart() );
2481 Reference< XChartType > XclImpChTypeGroup::CreateChartType( Reference< XDiagram > xDiagram, sal_Int32 nApiAxesSetIdx ) const
2483 DBG_ASSERT( IsValidGroup(), "XclImpChTypeGroup::CreateChartType - type group without series" );
2485 // create the chart type object
2486 Reference< XChartType > xChartType = maType.CreateChartType( xDiagram, Is3dChart() );
2488 // bar chart connector lines
2489 if( HasConnectorLines() )
2491 ScfPropertySet aDiaProp( xDiagram );
2492 aDiaProp.SetBoolProperty( EXC_CHPROP_CONNECTBARS, true );
2495 /* Stock chart needs special processing. Create one 'big' series with
2496 data sequences of different roles. */
2497 if( maTypeInfo.meTypeId == EXC_CHTYPEID_STOCK )
2498 CreateStockSeries( xChartType, nApiAxesSetIdx );
2499 else
2500 CreateDataSeries( xChartType, nApiAxesSetIdx );
2502 return xChartType;
2505 Reference< XLabeledDataSequence > XclImpChTypeGroup::CreateCategSequence() const
2507 Reference< XLabeledDataSequence > xLabeledSeq;
2508 // create category sequence from first visible series
2509 if( mxFirstSeries.is() )
2510 xLabeledSeq = mxFirstSeries->CreateCategSequence( EXC_CHPROP_ROLE_CATEG );
2511 return xLabeledSeq;
2514 void XclImpChTypeGroup::ReadChDropBar( XclImpStream& rStrm )
2516 sal_uInt16 nDropBar = EXC_CHDROPBAR_NONE;
2517 if( !maDropBars.has( EXC_CHDROPBAR_UP ) )
2518 nDropBar = EXC_CHDROPBAR_UP;
2519 else if( !maDropBars.has( EXC_CHDROPBAR_DOWN ) )
2520 nDropBar = EXC_CHDROPBAR_DOWN;
2522 if( nDropBar != EXC_CHDROPBAR_NONE )
2524 XclImpChDropBarRef xDropBar( new XclImpChDropBar( nDropBar ) );
2525 xDropBar->ReadRecordGroup( rStrm );
2526 maDropBars[ nDropBar ] = xDropBar;
2530 void XclImpChTypeGroup::ReadChChartLine( XclImpStream& rStrm )
2532 sal_uInt16 nLineId = rStrm.ReaduInt16();
2533 if( (rStrm.GetNextRecId() == EXC_ID_CHLINEFORMAT) && rStrm.StartNextRecord() )
2535 XclImpChLineFormatRef xLineFmt( new XclImpChLineFormat );
2536 xLineFmt->ReadChLineFormat( rStrm );
2537 maChartLines[ nLineId ] = xLineFmt;
2541 void XclImpChTypeGroup::ReadChDataFormat( XclImpStream& rStrm )
2543 // global series and data point format
2544 XclImpChDataFormatRef xDataFmt( new XclImpChDataFormat( GetChRoot() ) );
2545 xDataFmt->ReadRecordGroup( rStrm );
2546 const XclChDataPointPos& rPos = xDataFmt->GetPointPos();
2547 if( (rPos.mnSeriesIdx == 0) && (rPos.mnPointIdx == 0) &&
2548 (xDataFmt->GetFormatIdx() == EXC_CHDATAFORMAT_DEFAULT) )
2549 mxGroupFmt = xDataFmt;
2553 void XclImpChTypeGroup::InsertDataSeries( Reference< XChartType > xChartType,
2554 Reference< XDataSeries > xSeries, sal_Int32 nApiAxesSetIdx ) const
2556 Reference< XDataSeriesContainer > xSeriesCont( xChartType, UNO_QUERY );
2557 if( xSeriesCont.is() && xSeries.is() )
2559 // series stacking mode
2560 namespace cssc = ::com::sun::star::chart2;
2561 cssc::StackingDirection eStacking = cssc::StackingDirection_NO_STACKING;
2562 // stacked overrides deep-3d
2563 if( maType.IsStacked() || maType.IsPercent() )
2564 eStacking = cssc::StackingDirection_Y_STACKING;
2565 else if( Is3dDeepChart() )
2566 eStacking = cssc::StackingDirection_Z_STACKING;
2568 // additional series properties
2569 ScfPropertySet aSeriesProp( xSeries );
2570 aSeriesProp.SetProperty( EXC_CHPROP_STACKINGDIR, eStacking );
2571 aSeriesProp.SetProperty( EXC_CHPROP_ATTAXISINDEX, nApiAxesSetIdx );
2573 // insert series into container
2576 xSeriesCont->addDataSeries( xSeries );
2578 catch( Exception& )
2580 DBG_ERRORFILE( "XclImpChTypeGroup::InsertDataSeries - cannot add data series" );
2585 void XclImpChTypeGroup::CreateDataSeries( Reference< XChartType > xChartType, sal_Int32 nApiAxesSetIdx ) const
2587 bool bSpline = false;
2588 for( XclImpChSeriesVec::const_iterator aIt = maSeries.begin(), aEnd = maSeries.end(); aIt != aEnd; ++aIt )
2590 Reference< XDataSeries > xDataSeries = (*aIt)->CreateDataSeries();
2591 InsertDataSeries( xChartType, xDataSeries, nApiAxesSetIdx );
2592 bSpline |= (*aIt)->HasSpline();
2594 // spline - TODO: set at single series (#i66858#)
2595 if( bSpline && !maTypeInfo.IsSeriesFrameFormat() && (maTypeInfo.meTypeCateg != EXC_CHTYPECATEG_RADAR) )
2597 ScfPropertySet aTypeProp( xChartType );
2598 aTypeProp.SetProperty( EXC_CHPROP_CURVESTYLE, ::com::sun::star::chart2::CurveStyle_CUBIC_SPLINES );
2602 void XclImpChTypeGroup::CreateStockSeries( Reference< XChartType > xChartType, sal_Int32 nApiAxesSetIdx ) const
2604 // create the data series object
2605 Reference< XDataSeries > xDataSeries( ScfApiHelper::CreateInstance( SERVICE_CHART2_DATASERIES ), UNO_QUERY );
2606 Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY );
2607 if( xDataSink.is() )
2609 // create a list of data sequences from all series
2610 ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
2611 DBG_ASSERT( maSeries.size() >= 3, "XclImpChTypeGroup::CreateChartType - missing stock series" );
2612 int nRoleIdx = (maSeries.size() == 3) ? 1 : 0;
2613 for( XclImpChSeriesVec::const_iterator aIt = maSeries.begin(), aEnd = maSeries.end();
2614 (nRoleIdx < 4) && (aIt != aEnd); ++nRoleIdx, ++aIt )
2616 // create a data sequence with a specific role
2617 OUString aRole;
2618 switch( nRoleIdx )
2620 case 0: aRole = EXC_CHPROP_ROLE_OPENVALUES; break;
2621 case 1: aRole = EXC_CHPROP_ROLE_HIGHVALUES; break;
2622 case 2: aRole = EXC_CHPROP_ROLE_LOWVALUES; break;
2623 case 3: aRole = EXC_CHPROP_ROLE_CLOSEVALUES; break;
2625 Reference< XLabeledDataSequence > xDataSeq = (*aIt)->CreateValueSequence( aRole );
2626 if( xDataSeq.is() )
2627 aLabeledSeqVec.push_back( xDataSeq );
2630 // attach labeled data sequences to series and insert series into chart type
2631 xDataSink->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec ) );
2633 // formatting of special stock chart elements
2634 ScfPropertySet aTypeProp( xChartType );
2635 aTypeProp.SetBoolProperty( EXC_CHPROP_JAPANESE, HasDropBars() );
2636 aTypeProp.SetBoolProperty( EXC_CHPROP_SHOWFIRST, HasDropBars() );
2637 aTypeProp.SetBoolProperty( EXC_CHPROP_SHOWHIGHLOW, true );
2638 // hi-lo line format
2639 XclImpChLineFormatRef xHiLoLine = maChartLines.get( EXC_CHCHARTLINE_HILO );
2640 if( xHiLoLine.is() )
2642 ScfPropertySet aSeriesProp( xDataSeries );
2643 xHiLoLine->Convert( GetChRoot(), aSeriesProp, EXC_CHOBJTYPE_HILOLINE );
2645 // white dropbar format
2646 XclImpChDropBarRef xUpBar = maDropBars.get( EXC_CHDROPBAR_UP );
2647 Reference< XPropertySet > xWhitePropSet;
2648 if( xUpBar.is() && aTypeProp.GetProperty( xWhitePropSet, EXC_CHPROP_WHITEDAY ) )
2650 ScfPropertySet aBarProp( xWhitePropSet );
2651 xUpBar->Convert( GetChRoot(), aBarProp );
2653 // black dropbar format
2654 XclImpChDropBarRef xDownBar = maDropBars.get( EXC_CHDROPBAR_DOWN );
2655 Reference< XPropertySet > xBlackPropSet;
2656 if( xDownBar.is() && aTypeProp.GetProperty( xBlackPropSet, EXC_CHPROP_BLACKDAY ) )
2658 ScfPropertySet aBarProp( xBlackPropSet );
2659 xDownBar->Convert( GetChRoot(), aBarProp );
2662 // insert the series into the chart type object
2663 InsertDataSeries( xChartType, xDataSeries, nApiAxesSetIdx );
2667 // Axes =======================================================================
2669 XclImpChLabelRange::XclImpChLabelRange( const XclImpChRoot& rRoot ) :
2670 XclImpChRoot( rRoot )
2674 void XclImpChLabelRange::ReadChLabelRange( XclImpStream& rStrm )
2676 rStrm >> maData.mnCross >> maData.mnLabelFreq >> maData.mnTickFreq >> maData.mnFlags;
2679 void XclImpChLabelRange::Convert( ScfPropertySet& rPropSet, ScaleData& rScaleData, bool bMirrorOrient ) const
2681 // do not overlap text unless all labels are visible
2682 rPropSet.SetBoolProperty( EXC_CHPROP_TEXTOVERLAP, maData.mnLabelFreq == 1 );
2683 // do not break text into several lines unless all labels are visible
2684 rPropSet.SetBoolProperty( EXC_CHPROP_TEXTBREAK, maData.mnLabelFreq == 1 );
2685 // do not stagger labels in two lines
2686 namespace cssc = ::com::sun::star::chart;
2687 rPropSet.SetProperty( EXC_CHPROP_ARRANGEORDER, cssc::ChartAxisArrangeOrderType_SIDE_BY_SIDE );
2689 // reverse order
2690 namespace cssc2 = ::com::sun::star::chart2;
2691 bool bReverse = ::get_flag( maData.mnFlags, EXC_CHLABELRANGE_REVERSE ) != bMirrorOrient;
2692 rScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL;
2694 //! TODO #i58731# show n-th category
2697 void XclImpChLabelRange::ConvertAxisPosition( ScfPropertySet& rPropSet, bool b3dChart ) const
2699 /* Crossing mode (max-cross flag overrides other crossing settings). Excel
2700 does not move the Y axis in 3D charts, regardless of actual settings.
2701 But: the Y axis has to be moved to "end", if the X axis is mirrored,
2702 to keep it at the left end of the chart. */
2703 bool bMaxCross = ::get_flag( maData.mnFlags, b3dChart ? EXC_CHLABELRANGE_REVERSE : EXC_CHLABELRANGE_MAXCROSS );
2704 namespace cssc = ::com::sun::star::chart;
2705 cssc::ChartAxisPosition eAxisPos = bMaxCross ? cssc::ChartAxisPosition_END : cssc::ChartAxisPosition_VALUE;
2706 rPropSet.SetProperty( EXC_CHPROP_CROSSOVERPOSITION, eAxisPos );
2708 // crossing position
2709 double fCrossingPos = b3dChart ? 1.0 : maData.mnCross;
2710 rPropSet.SetProperty( EXC_CHPROP_CROSSOVERVALUE, fCrossingPos );
2713 // ----------------------------------------------------------------------------
2715 XclImpChValueRange::XclImpChValueRange( const XclImpChRoot& rRoot ) :
2716 XclImpChRoot( rRoot )
2720 void XclImpChValueRange::ReadChValueRange( XclImpStream& rStrm )
2722 rStrm >> maData.mfMin
2723 >> maData.mfMax
2724 >> maData.mfMajorStep
2725 >> maData.mfMinorStep
2726 >> maData.mfCross
2727 >> maData.mnFlags;
2730 void XclImpChValueRange::Convert( ScaleData& rScaleData, bool bMirrorOrient, bool bPercent ) const
2732 // scaling algorithm
2733 bool bLogScale = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_LOGSCALE );
2734 OUString aScalingService = bLogScale ? SERVICE_CHART2_LOGSCALING : SERVICE_CHART2_LINEARSCALING;
2735 rScaleData.Scaling.set( ScfApiHelper::CreateInstance( aScalingService ), UNO_QUERY );
2737 // min/max
2738 double fMinVal = bPercent ? maData.mfMin/100.0 : maData.mfMin;
2739 double fMaxVal = bPercent ? maData.mfMax/100.0 : maData.mfMax;
2740 lclSetExpValueOrClearAny( rScaleData.Minimum, fMinVal, bLogScale, ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMIN ) );
2741 lclSetExpValueOrClearAny( rScaleData.Maximum, fMaxVal, bLogScale, ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMAX ) );
2743 // increment
2744 bool bAutoMajor = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMAJOR );
2745 bool bAutoMinor = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMINOR );
2746 // major increment
2747 IncrementData& rIncrementData = rScaleData.IncrementData;
2748 double fMajorStep = bPercent ? maData.mfMajorStep/100.0 : maData.mfMajorStep;
2749 lclSetValueOrClearAny( rIncrementData.Distance, fMajorStep, bAutoMajor );
2750 // minor increment
2751 Sequence< SubIncrement >& rSubIncrementSeq = rIncrementData.SubIncrements;
2752 rSubIncrementSeq.realloc( 1 );
2753 Any& rIntervalCount = rSubIncrementSeq[ 0 ].IntervalCount;
2754 if( bLogScale )
2756 rIntervalCount <<= sal_Int32( 10 );
2758 else
2760 sal_Int32 nCount = 0;
2761 if( !bAutoMajor && !bAutoMinor && (0.0 < maData.mfMinorStep) && (maData.mfMinorStep <= maData.mfMajorStep) )
2763 double fCount = maData.mfMajorStep / maData.mfMinorStep + 0.5;
2764 if( fCount < 1001.0 )
2765 nCount = static_cast< sal_Int32 >( fCount );
2767 lclSetValueOrClearAny( rIntervalCount, nCount, nCount == 0 );
2770 // reverse order
2771 namespace cssc2 = ::com::sun::star::chart2;
2772 bool bReverse = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_REVERSE ) != bMirrorOrient;
2773 rScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL;
2776 void XclImpChValueRange::ConvertAxisPosition( ScfPropertySet& rPropSet ) const
2778 bool bMaxCross = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_MAXCROSS );
2779 bool bAutoCross = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOCROSS );
2780 bool bLogScale = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_LOGSCALE );
2782 // crossing mode (max-cross flag overrides other crossing settings)
2783 namespace cssc = ::com::sun::star::chart;
2784 cssc::ChartAxisPosition eAxisPos = bMaxCross ? cssc::ChartAxisPosition_END : cssc::ChartAxisPosition_VALUE;
2785 rPropSet.SetProperty( EXC_CHPROP_CROSSOVERPOSITION, eAxisPos );
2787 // crossing position
2788 double fCrossingPos = bAutoCross ? 0.0 : maData.mfCross;
2789 if( bLogScale ) fCrossingPos = pow( 10.0, fCrossingPos );
2790 rPropSet.SetProperty( EXC_CHPROP_CROSSOVERVALUE, fCrossingPos );
2793 // ----------------------------------------------------------------------------
2795 namespace {
2797 sal_Int32 lclGetApiTickmarks( sal_uInt8 nXclTickPos )
2799 using namespace ::com::sun::star::chart2::TickmarkStyle;
2800 sal_Int32 nApiTickmarks = NONE;
2801 ::set_flag( nApiTickmarks, INNER, ::get_flag( nXclTickPos, EXC_CHTICK_INSIDE ) );
2802 ::set_flag( nApiTickmarks, OUTER, ::get_flag( nXclTickPos, EXC_CHTICK_OUTSIDE ) );
2803 return nApiTickmarks;
2806 ::com::sun::star::chart::ChartAxisLabelPosition lclGetApiLabelPosition( sal_Int8 nXclLabelPos )
2808 using namespace ::com::sun::star::chart;
2809 switch( nXclLabelPos )
2811 case EXC_CHTICK_LOW: return ChartAxisLabelPosition_OUTSIDE_START;
2812 case EXC_CHTICK_HIGH: return ChartAxisLabelPosition_OUTSIDE_END;
2813 case EXC_CHTICK_NEXT: return ChartAxisLabelPosition_NEAR_AXIS;
2815 return ChartAxisLabelPosition_NEAR_AXIS;
2818 } // namespace
2820 XclImpChTick::XclImpChTick( const XclImpChRoot& rRoot ) :
2821 XclImpChRoot( rRoot )
2825 void XclImpChTick::ReadChTick( XclImpStream& rStrm )
2827 rStrm >> maData.mnMajor
2828 >> maData.mnMinor
2829 >> maData.mnLabelPos
2830 >> maData.mnBackMode
2831 >> maData.maRect
2832 >> maData.maTextColor
2833 >> maData.mnFlags;
2835 if( GetBiff() == EXC_BIFF8 )
2837 // #116397# BIFF8: index into palette used instead of RGB data
2838 maData.maTextColor = GetPalette().GetColor( rStrm.ReaduInt16() );
2839 // rotation
2840 rStrm >> maData.mnRotation;
2842 else
2844 // BIFF2-BIFF7: get rotation from text orientation
2845 sal_uInt8 nOrient = ::extract_value< sal_uInt8 >( maData.mnFlags, 2, 3 );
2846 maData.mnRotation = XclTools::GetXclRotFromOrient( nOrient );
2850 Color XclImpChTick::GetFontColor() const
2852 return ::get_flag( maData.mnFlags, EXC_CHTICK_AUTOCOLOR ) ? GetFontAutoColor() : maData.maTextColor;
2855 sal_uInt16 XclImpChTick::GetRotation() const
2857 return ::get_flag( maData.mnFlags, EXC_CHTICK_AUTOROT ) ? EXC_CHART_AUTOROTATION : maData.mnRotation;
2860 void XclImpChTick::Convert( ScfPropertySet& rPropSet ) const
2862 rPropSet.SetProperty( EXC_CHPROP_MAJORTICKS, lclGetApiTickmarks( maData.mnMajor ) );
2863 rPropSet.SetProperty( EXC_CHPROP_MINORTICKS, lclGetApiTickmarks( maData.mnMinor ) );
2864 rPropSet.SetProperty( EXC_CHPROP_LABELPOSITION, lclGetApiLabelPosition( maData.mnLabelPos ) );
2865 rPropSet.SetProperty( EXC_CHPROP_MARKPOSITION, ::com::sun::star::chart::ChartAxisMarkPosition_AT_AXIS );
2868 // ----------------------------------------------------------------------------
2870 XclImpChAxis::XclImpChAxis( const XclImpChRoot& rRoot, sal_uInt16 nAxisType ) :
2871 XclImpChRoot( rRoot ),
2872 mnNumFmtIdx( EXC_FORMAT_NOTFOUND )
2874 maData.mnType = nAxisType;
2877 void XclImpChAxis::ReadHeaderRecord( XclImpStream& rStrm )
2879 rStrm >> maData.mnType >> maData.maRect;
2882 void XclImpChAxis::ReadSubRecord( XclImpStream& rStrm )
2884 switch( rStrm.GetRecId() )
2886 case EXC_ID_CHLABELRANGE:
2887 mxLabelRange.reset( new XclImpChLabelRange( GetChRoot() ) );
2888 mxLabelRange->ReadChLabelRange( rStrm );
2889 break;
2890 case EXC_ID_CHVALUERANGE:
2891 mxValueRange.reset( new XclImpChValueRange( GetChRoot() ) );
2892 mxValueRange->ReadChValueRange( rStrm );
2893 break;
2894 case EXC_ID_CHFORMAT:
2895 rStrm >> mnNumFmtIdx;
2896 break;
2897 case EXC_ID_CHTICK:
2898 mxTick.reset( new XclImpChTick( GetChRoot() ) );
2899 mxTick->ReadChTick( rStrm );
2900 break;
2901 case EXC_ID_CHFONT:
2902 mxFont.reset( new XclImpChFont );
2903 mxFont->ReadChFont( rStrm );
2904 break;
2905 case EXC_ID_CHAXISLINE:
2906 ReadChAxisLine( rStrm );
2907 break;
2911 void XclImpChAxis::Finalize()
2913 // add default scaling, needed e.g. to adjust rotation direction of pie and radar charts
2914 if( !mxLabelRange )
2915 mxLabelRange.reset( new XclImpChLabelRange( GetChRoot() ) );
2916 if( !mxValueRange )
2917 mxValueRange.reset( new XclImpChValueRange( GetChRoot() ) );
2918 // remove invisible grid lines completely
2919 if( mxMajorGrid.is() && !mxMajorGrid->HasLine() )
2920 mxMajorGrid.reset();
2921 if( mxMinorGrid.is() && !mxMinorGrid->HasLine() )
2922 mxMinorGrid.reset();
2923 // default tick settings different in OOChart and Excel
2924 if( !mxTick )
2925 mxTick.reset( new XclImpChTick( GetChRoot() ) );
2926 // #i4140# different default axis line color
2927 if( !mxAxisLine )
2929 XclChLineFormat aLineFmt;
2930 // set "show axis" flag, default if line format record is missing
2931 ::set_flag( aLineFmt.mnFlags, EXC_CHLINEFORMAT_SHOWAXIS );
2932 mxAxisLine.reset( new XclImpChLineFormat( aLineFmt ) );
2934 // add wall/floor frame for 3d charts
2935 if( !mxWallFrame )
2936 CreateWallFrame();
2939 sal_uInt16 XclImpChAxis::GetFontIndex() const
2941 return mxFont.is() ? mxFont->GetFontIndex() : EXC_FONT_NOTFOUND;
2944 Color XclImpChAxis::GetFontColor() const
2946 return mxTick.is() ? mxTick->GetFontColor() : GetFontAutoColor();
2949 sal_uInt16 XclImpChAxis::GetRotation() const
2951 return mxTick.is() ? mxTick->GetRotation() : EXC_CHART_AUTOROTATION;
2954 Reference< XAxis > XclImpChAxis::CreateAxis( const XclImpChTypeGroup& rTypeGroup, const XclImpChAxis* pCrossingAxis ) const
2956 namespace cssc2 = ::com::sun::star::chart2;
2958 // create the axis object (always)
2959 Reference< XAxis > xAxis( ScfApiHelper::CreateInstance( SERVICE_CHART2_AXIS ), UNO_QUERY );
2960 if( xAxis.is() )
2962 ScfPropertySet aAxisProp( xAxis );
2963 // #i58688# axis enabled
2964 aAxisProp.SetBoolProperty( EXC_CHPROP_SHOW, IsActivated() );
2966 // axis line properties
2967 if( mxAxisLine.is() )
2968 mxAxisLine->Convert( GetChRoot(), aAxisProp, EXC_CHOBJTYPE_AXISLINE );
2969 // axis ticks properties
2970 if( mxTick.is() )
2971 mxTick->Convert( aAxisProp );
2973 // axis caption text --------------------------------------------------
2975 // radar charts disable their category labels via chart type, not via axis
2976 bool bHasLabels = HasLabels() &&
2977 ((GetAxisType() != EXC_CHAXIS_X) || rTypeGroup.HasCategoryLabels());
2978 aAxisProp.SetBoolProperty( EXC_CHPROP_DISPLAYLABELS, bHasLabels );
2979 if( bHasLabels )
2981 // font settings from CHFONT record or from default text
2982 if( mxFont.is() )
2983 ConvertFontBase( GetChRoot(), aAxisProp );
2984 else if( const XclImpChText* pDefText = GetChartData().GetDefaultText( EXC_CHTEXTTYPE_AXISLABEL ).get() )
2985 pDefText->ConvertFont( aAxisProp );
2986 // label text rotation
2987 ConvertRotationBase( GetChRoot(), aAxisProp, true );
2988 // number format
2989 sal_uInt32 nScNumFmt = GetNumFmtBuffer().GetScFormat( mnNumFmtIdx );
2990 if( nScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND )
2991 aAxisProp.SetProperty( EXC_CHPROP_NUMBERFORMAT, static_cast< sal_Int32 >( nScNumFmt ) );
2994 // axis scaling and increment -----------------------------------------
2996 const XclChExtTypeInfo& rTypeInfo = rTypeGroup.GetTypeInfo();
2997 ScaleData aScaleData = xAxis->getScaleData();
2998 // set axis type
2999 switch( GetAxisType() )
3001 case EXC_CHAXIS_X:
3002 if( rTypeInfo.mbCategoryAxis )
3004 aScaleData.AxisType = cssc2::AxisType::CATEGORY;
3005 aScaleData.Categories = rTypeGroup.CreateCategSequence();
3007 else
3008 aScaleData.AxisType = cssc2::AxisType::REALNUMBER;
3009 break;
3010 case EXC_CHAXIS_Y:
3011 aScaleData.AxisType = rTypeGroup.IsPercent() ?
3012 cssc2::AxisType::PERCENT : cssc2::AxisType::REALNUMBER;
3013 break;
3014 case EXC_CHAXIS_Z:
3015 aScaleData.AxisType = cssc2::AxisType::SERIES;
3016 break;
3018 // axis scaling settings, dependent on axis type
3019 switch( aScaleData.AxisType )
3021 case cssc2::AxisType::CATEGORY:
3022 case cssc2::AxisType::SERIES:
3023 // #i71684# radar charts have reversed rotation direction
3024 mxLabelRange->Convert( aAxisProp, aScaleData, rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_RADAR );
3025 break;
3026 case cssc2::AxisType::REALNUMBER:
3027 case cssc2::AxisType::PERCENT:
3029 bool bPercent = (aScaleData.AxisType == cssc2::AxisType::PERCENT);
3030 // #i85167# pie/donut charts have reversed rotation direction (at Y axis!)
3031 mxValueRange->Convert( aScaleData, rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE, bPercent );
3033 break;
3034 default:
3035 DBG_ERRORFILE( "XclImpChAxis::CreateAxis - unknown axis type" );
3038 /* Do not set a value to the Origin member anymore (will be done via
3039 new axis properties 'CrossoverPosition' and 'CrossoverValue'). */
3040 aScaleData.Origin.clear();
3042 // write back
3043 xAxis->setScaleData( aScaleData );
3045 // grid ---------------------------------------------------------------
3047 // main grid
3048 ScfPropertySet aGridProp( xAxis->getGridProperties() );
3049 aGridProp.SetBoolProperty( EXC_CHPROP_SHOW, HasMajorGrid() );
3050 if( mxMajorGrid.is() )
3051 mxMajorGrid->Convert( GetChRoot(), aGridProp, EXC_CHOBJTYPE_GRIDLINE );
3052 // sub grid
3053 Sequence< Reference< XPropertySet > > aSubGridPropSeq = xAxis->getSubGridProperties();
3054 if( aSubGridPropSeq.hasElements() )
3056 ScfPropertySet aSubGridProp( aSubGridPropSeq[ 0 ] );
3057 aSubGridProp.SetBoolProperty( EXC_CHPROP_SHOW, HasMinorGrid() );
3058 if( mxMinorGrid.is() )
3059 mxMinorGrid->Convert( GetChRoot(), aSubGridProp, EXC_CHOBJTYPE_GRIDLINE );
3062 // position of crossing axis ------------------------------------------
3064 if( pCrossingAxis )
3065 pCrossingAxis->ConvertAxisPosition( aAxisProp, rTypeGroup );
3067 return xAxis;
3070 void XclImpChAxis::ConvertWall( ScfPropertySet& rPropSet ) const
3072 if( mxWallFrame.is() )
3073 mxWallFrame->Convert( rPropSet );
3076 void XclImpChAxis::ConvertAxisPosition( ScfPropertySet& rPropSet, const XclImpChTypeGroup& rTypeGroup ) const
3078 if( ((GetAxisType() == EXC_CHAXIS_X) && rTypeGroup.GetTypeInfo().mbCategoryAxis) || (GetAxisType() == EXC_CHAXIS_Z) )
3079 mxLabelRange->ConvertAxisPosition( rPropSet, rTypeGroup.Is3dChart() );
3080 else
3081 mxValueRange->ConvertAxisPosition( rPropSet );
3084 void XclImpChAxis::ReadChAxisLine( XclImpStream& rStrm )
3086 XclImpChLineFormatRef* pxLineFmt = 0;
3087 bool bWallFrame = false;
3088 switch( rStrm.ReaduInt16() )
3090 case EXC_CHAXISLINE_AXISLINE: pxLineFmt = &mxAxisLine; break;
3091 case EXC_CHAXISLINE_MAJORGRID: pxLineFmt = &mxMajorGrid; break;
3092 case EXC_CHAXISLINE_MINORGRID: pxLineFmt = &mxMinorGrid; break;
3093 case EXC_CHAXISLINE_WALLS: bWallFrame = true; break;
3095 if( bWallFrame )
3096 CreateWallFrame();
3098 bool bLoop = pxLineFmt || bWallFrame;
3099 while( bLoop )
3101 sal_uInt16 nRecId = rStrm.GetNextRecId();
3102 bLoop = ((nRecId == EXC_ID_CHLINEFORMAT) ||
3103 (nRecId == EXC_ID_CHAREAFORMAT) ||
3104 (nRecId == EXC_ID_CHESCHERFORMAT))
3105 && rStrm.StartNextRecord();
3106 if( bLoop )
3108 if( pxLineFmt && (nRecId == EXC_ID_CHLINEFORMAT) )
3110 pxLineFmt->reset( new XclImpChLineFormat );
3111 (*pxLineFmt)->ReadChLineFormat( rStrm );
3113 else if( bWallFrame && mxWallFrame.is() )
3115 mxWallFrame->ReadSubRecord( rStrm );
3121 void XclImpChAxis::CreateWallFrame()
3123 switch( GetAxisType() )
3125 case EXC_CHAXIS_X:
3126 mxWallFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_WALL3D ) );
3127 break;
3128 case EXC_CHAXIS_Y:
3129 mxWallFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_FLOOR3D ) );
3130 break;
3131 default:
3132 mxWallFrame.reset();
3136 // ----------------------------------------------------------------------------
3138 XclImpChAxesSet::XclImpChAxesSet( const XclImpChRoot& rRoot, sal_uInt16 nAxesSetId ) :
3139 XclImpChRoot( rRoot )
3141 maData.mnAxesSetId = nAxesSetId;
3144 void XclImpChAxesSet::ReadHeaderRecord( XclImpStream& rStrm )
3146 rStrm >> maData.mnAxesSetId >> maData.maRect;
3149 void XclImpChAxesSet::ReadSubRecord( XclImpStream& rStrm )
3151 switch( rStrm.GetRecId() )
3153 case EXC_ID_CHFRAMEPOS:
3154 mxPos.reset( new XclImpChFramePos );
3155 mxPos->ReadChFramePos( rStrm );
3156 break;
3157 case EXC_ID_CHAXIS:
3158 ReadChAxis( rStrm );
3159 break;
3160 case EXC_ID_CHTEXT:
3161 ReadChText( rStrm );
3162 break;
3163 case EXC_ID_CHPLOTFRAME:
3164 ReadChPlotFrame( rStrm );
3165 break;
3166 case EXC_ID_CHTYPEGROUP:
3167 ReadChTypeGroup( rStrm );
3168 break;
3172 void XclImpChAxesSet::Finalize()
3174 if( IsValidAxesSet() )
3176 // finalize chart type groups, erase empty groups without series
3177 XclImpChTypeGroupMap aValidGroups;
3178 for( XclImpChTypeGroupMap::const_iterator aIt = maTypeGroups.begin(), aEnd = maTypeGroups.end(); aIt != aEnd; ++aIt )
3180 XclImpChTypeGroupRef xTypeGroup = aIt->second;
3181 xTypeGroup->Finalize();
3182 if( xTypeGroup->IsValidGroup() )
3183 aValidGroups[ aIt->first ] = xTypeGroup;
3185 maTypeGroups.swap( aValidGroups );
3188 // invalid chart type groups are deleted now, check again with IsValidAxesSet()
3189 if( IsValidAxesSet() )
3191 // always create missing axis objects
3192 if( !mxXAxis )
3193 mxXAxis.reset( new XclImpChAxis( GetChRoot(), EXC_CHAXIS_X ) );
3194 if( !mxYAxis )
3195 mxYAxis.reset( new XclImpChAxis( GetChRoot(), EXC_CHAXIS_Y ) );
3196 if( !mxZAxis && GetFirstTypeGroup()->Is3dDeepChart() )
3197 mxZAxis.reset( new XclImpChAxis( GetChRoot(), EXC_CHAXIS_Z ) );
3199 // finalize axes
3200 if( mxXAxis.is() ) mxXAxis->Finalize();
3201 if( mxYAxis.is() ) mxYAxis->Finalize();
3202 if( mxZAxis.is() ) mxZAxis->Finalize();
3204 // finalize axis titles
3205 XclImpChTextRef xDefText = GetChartData().GetDefaultText( EXC_CHTEXTTYPE_AXISTITLE );
3206 lclFinalizeTitle( mxXAxisTitle, xDefText );
3207 lclFinalizeTitle( mxYAxisTitle, xDefText );
3208 lclFinalizeTitle( mxZAxisTitle, xDefText );
3210 // #i47745# missing plot frame -> invisible border and area
3211 if( !mxPlotFrame )
3212 mxPlotFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_PLOTFRAME ) );
3216 XclImpChTypeGroupRef XclImpChAxesSet::GetFirstTypeGroup() const
3218 XclImpChTypeGroupRef xTypeGroup;
3219 if( !maTypeGroups.empty() )
3220 xTypeGroup = maTypeGroups.begin()->second;
3221 return xTypeGroup;
3224 XclImpChLegendRef XclImpChAxesSet::GetLegend() const
3226 XclImpChLegendRef xLegend;
3227 for( XclImpChTypeGroupMap::const_iterator aIt = maTypeGroups.begin(), aEnd = maTypeGroups.end(); !xLegend && (aIt != aEnd); ++aIt )
3228 xLegend = aIt->second->GetLegend();
3229 return xLegend;
3232 const String& XclImpChAxesSet::GetSingleSeriesTitle() const
3234 return (maTypeGroups.size() == 1) ? maTypeGroups.begin()->second->GetSingleSeriesTitle() : String::EmptyString();
3237 void XclImpChAxesSet::Convert( Reference< XDiagram > xDiagram ) const
3239 if( IsValidAxesSet() && xDiagram.is() )
3241 // diagram background formatting
3242 if( GetAxesSetId() == EXC_CHAXESSET_PRIMARY )
3243 ConvertBackground( xDiagram );
3245 // create the coordinate system, this inserts all chart types and series
3246 Reference< XCoordinateSystem > xCoordSystem = CreateCoordSystem( xDiagram );
3247 if( xCoordSystem.is() )
3249 // insert coordinate system, if not already done
3252 Reference< XCoordinateSystemContainer > xCoordSystemCont( xDiagram, UNO_QUERY_THROW );
3253 Sequence< Reference< XCoordinateSystem > > aCoordSystems = xCoordSystemCont->getCoordinateSystems();
3254 if( aCoordSystems.getLength() == 0 )
3255 xCoordSystemCont->addCoordinateSystem( xCoordSystem );
3257 catch( Exception& )
3259 DBG_ERRORFILE( "XclImpChAxesSet::Convert - cannot insert coordinate system" );
3262 // create the axes with grids and axis titles and insert them into the diagram
3263 ConvertAxis( mxXAxis, mxXAxisTitle, xCoordSystem, mxYAxis.get() );
3264 ConvertAxis( mxYAxis, mxYAxisTitle, xCoordSystem, mxXAxis.get() );
3265 ConvertAxis( mxZAxis, mxZAxisTitle, xCoordSystem, 0 );
3270 void XclImpChAxesSet::ReadChAxis( XclImpStream& rStrm )
3272 XclImpChAxisRef xAxis( new XclImpChAxis( GetChRoot() ) );
3273 xAxis->ReadRecordGroup( rStrm );
3275 switch( xAxis->GetAxisType() )
3277 case EXC_CHAXIS_X: mxXAxis = xAxis; break;
3278 case EXC_CHAXIS_Y: mxYAxis = xAxis; break;
3279 case EXC_CHAXIS_Z: mxZAxis = xAxis; break;
3283 void XclImpChAxesSet::ReadChText( XclImpStream& rStrm )
3285 XclImpChTextRef xText( new XclImpChText( GetChRoot() ) );
3286 xText->ReadRecordGroup( rStrm );
3288 switch( xText->GetLinkTarget() )
3290 case EXC_CHOBJLINK_XAXIS: mxXAxisTitle = xText; break;
3291 case EXC_CHOBJLINK_YAXIS: mxYAxisTitle = xText; break;
3292 case EXC_CHOBJLINK_ZAXIS: mxZAxisTitle = xText; break;
3296 void XclImpChAxesSet::ReadChPlotFrame( XclImpStream& rStrm )
3298 if( (rStrm.GetNextRecId() == EXC_ID_CHFRAME) && rStrm.StartNextRecord() )
3300 mxPlotFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_PLOTFRAME ) );
3301 mxPlotFrame->ReadRecordGroup( rStrm );
3305 void XclImpChAxesSet::ReadChTypeGroup( XclImpStream& rStrm )
3307 XclImpChTypeGroupRef xTypeGroup( new XclImpChTypeGroup( GetChRoot() ) );
3308 xTypeGroup->ReadRecordGroup( rStrm );
3309 maTypeGroups[ xTypeGroup->GetGroupIdx() ] = xTypeGroup;
3312 Reference< XCoordinateSystem > XclImpChAxesSet::CreateCoordSystem( Reference< XDiagram > xDiagram ) const
3314 Reference< XCoordinateSystem > xCoordSystem;
3316 /* Try to get existing ccordinate system. For now, all series from primary
3317 and secondary axes sets are inserted into one coordinate system. Later,
3318 this should be changed to use one coordinate system for each axes set. */
3319 Reference< XCoordinateSystemContainer > xCoordSystemCont( xDiagram, UNO_QUERY );
3320 if( xCoordSystemCont.is() )
3322 Sequence< Reference< XCoordinateSystem > > aCoordSystems = xCoordSystemCont->getCoordinateSystems();
3323 DBG_ASSERT( aCoordSystems.getLength() <= 1, "XclImpChAxesSet::CreateCoordSystem - too many existing coordinate systems" );
3324 if( aCoordSystems.getLength() > 0 )
3325 xCoordSystem = aCoordSystems[ 0 ];
3328 // create the coordinate system according to the first chart type
3329 if( !xCoordSystem.is() )
3331 XclImpChTypeGroupRef xTypeGroup = GetFirstTypeGroup();
3332 if( xTypeGroup.is() )
3334 xCoordSystem = xTypeGroup->CreateCoordSystem();
3335 // convert 3d chart settings
3336 ScfPropertySet aDiaProp( xDiagram );
3337 xTypeGroup->ConvertChart3d( aDiaProp );
3341 /* Create XChartType objects for all chart type groups. Each group will
3342 add its series to the data provider attached to the chart document. */
3343 Reference< XChartTypeContainer > xChartTypeCont( xCoordSystem, UNO_QUERY );
3344 if( xChartTypeCont.is() )
3346 sal_Int32 nApiAxesSetIdx = GetApiAxesSetIndex();
3347 for( XclImpChTypeGroupMap::const_iterator aIt = maTypeGroups.begin(), aEnd = maTypeGroups.end(); aIt != aEnd; ++aIt )
3351 Reference< XChartType > xChartType = aIt->second->CreateChartType( xDiagram, nApiAxesSetIdx );
3352 if( xChartType.is() )
3353 xChartTypeCont->addChartType( xChartType );
3355 catch( Exception& )
3357 DBG_ERRORFILE( "XclImpChAxesSet::CreateCoordSystem - cannot add chart type" );
3362 return xCoordSystem;
3365 void XclImpChAxesSet::ConvertAxis(
3366 XclImpChAxisRef xChAxis, XclImpChTextRef xChAxisTitle,
3367 Reference< XCoordinateSystem > xCoordSystem, const XclImpChAxis* pCrossingAxis ) const
3369 if( xChAxis.is() )
3371 // create and attach the axis object
3372 Reference< XAxis > xAxis = CreateAxis( *xChAxis, pCrossingAxis );
3373 if( xAxis.is() )
3375 // create and attach the axis title
3376 if( xChAxisTitle.is() )
3378 Reference< XTitled > xTitled( xAxis, UNO_QUERY );
3379 if( xTitled.is() )
3380 xTitled->setTitleObject( xChAxisTitle->CreateTitle() );
3383 // insert axis into coordinate system
3386 sal_Int32 nApiAxisDim = xChAxis->GetApiAxisDimension();
3387 sal_Int32 nApiAxesSetIdx = GetApiAxesSetIndex();
3388 xCoordSystem->setAxisByDimension( nApiAxisDim, xAxis, nApiAxesSetIdx );
3390 catch( Exception& )
3392 DBG_ERRORFILE( "XclImpChAxesSet::ConvertAxis - cannot set axis" );
3398 Reference< XAxis > XclImpChAxesSet::CreateAxis( const XclImpChAxis& rChAxis, const XclImpChAxis* pCrossingAxis ) const
3400 Reference< XAxis > xAxis;
3401 if( const XclImpChTypeGroup* pTypeGroup = GetFirstTypeGroup().get() )
3402 xAxis = rChAxis.CreateAxis( *pTypeGroup, pCrossingAxis );
3403 return xAxis;
3406 void XclImpChAxesSet::ConvertBackground( Reference< XDiagram > xDiagram ) const
3408 XclImpChTypeGroupRef xTypeGroup = GetFirstTypeGroup();
3409 if( xTypeGroup.is() && xTypeGroup->Is3dWallChart() )
3411 // wall/floor formatting (3D charts)
3412 if( mxXAxis.is() )
3414 ScfPropertySet aWallProp( xDiagram->getWall() );
3415 mxXAxis->ConvertWall( aWallProp );
3417 if( mxYAxis.is() )
3419 ScfPropertySet aFloorProp( xDiagram->getFloor() );
3420 mxYAxis->ConvertWall( aFloorProp );
3423 else if( mxPlotFrame.is() )
3425 // diagram background formatting
3426 ScfPropertySet aWallProp( xDiagram->getWall() );
3427 mxPlotFrame->Convert( aWallProp );
3431 // The chart object ===========================================================
3433 XclImpChChart::XclImpChChart( const XclImpRoot& rRoot ) :
3434 XclImpChRoot( rRoot, this )
3436 mxPrimAxesSet.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_PRIMARY ) );
3437 mxSecnAxesSet.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_SECONDARY ) );
3440 XclImpChChart::~XclImpChChart()
3444 void XclImpChChart::ReadHeaderRecord( XclImpStream& rStrm )
3446 // coordinates are stored as 16.16 fixed point
3447 rStrm >> maRect;
3450 void XclImpChChart::ReadSubRecord( XclImpStream& rStrm )
3452 switch( rStrm.GetRecId() )
3454 case EXC_ID_CHFRAME:
3455 mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND ) );
3456 mxFrame->ReadRecordGroup( rStrm );
3457 break;
3458 case EXC_ID_CHSERIES:
3459 ReadChSeries( rStrm );
3460 break;
3461 case EXC_ID_CHPROPERTIES:
3462 ReadChProperties( rStrm );
3463 break;
3464 case EXC_ID_CHDEFAULTTEXT:
3465 ReadChDefaultText( rStrm );
3466 break;
3467 case EXC_ID_CHAXESSET:
3468 ReadChAxesSet( rStrm );
3469 break;
3470 case EXC_ID_CHTEXT:
3471 ReadChText( rStrm );
3472 break;
3473 case EXC_ID_CHEND:
3474 Finalize(); // finalize the entire chart object
3475 break;
3479 void XclImpChChart::ReadChDefaultText( XclImpStream& rStrm )
3481 sal_uInt16 nTextId = rStrm.ReaduInt16();
3482 if( (rStrm.GetNextRecId() == EXC_ID_CHTEXT) && rStrm.StartNextRecord() )
3484 XclImpChTextRef xText( new XclImpChText( GetChRoot() ) );
3485 xText->ReadRecordGroup( rStrm );
3486 maDefTexts[ nTextId ] = xText;
3490 void XclImpChChart::ReadChDataFormat( XclImpStream& rStrm )
3492 XclImpChDataFormatRef xDataFmt( new XclImpChDataFormat( GetChRoot() ) );
3493 xDataFmt->ReadRecordGroup( rStrm );
3494 if( xDataFmt->GetPointPos().mnSeriesIdx <= EXC_CHSERIES_MAXSERIES )
3496 XclImpChDataFormatRef& rxMapFmt = maDataFmts[ xDataFmt->GetPointPos() ];
3497 /* Do not overwrite existing data format group, Excel always uses the
3498 first data format group occuring in any CHSERIES group. */
3499 if( !rxMapFmt )
3500 rxMapFmt = xDataFmt;
3504 void XclImpChChart::UpdateObjFrame( const XclObjLineData& rLineData, const XclObjFillData& rFillData )
3506 if( !mxFrame )
3507 mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND ) );
3508 mxFrame->UpdateObjFrame( rLineData, rFillData );
3511 XclImpChTypeGroupRef XclImpChChart::GetTypeGroup( sal_uInt16 nGroupIdx ) const
3513 XclImpChTypeGroupRef xTypeGroup = mxPrimAxesSet->GetTypeGroup( nGroupIdx );
3514 if( !xTypeGroup ) xTypeGroup = mxSecnAxesSet->GetTypeGroup( nGroupIdx );
3515 if( !xTypeGroup ) xTypeGroup = mxPrimAxesSet->GetFirstTypeGroup();
3516 return xTypeGroup;
3519 XclImpChTextRef XclImpChChart::GetDefaultText( XclChTextType eTextType ) const
3521 sal_uInt16 nDefTextId = EXC_CHDEFTEXT_GLOBAL;
3522 bool bBiff8 = GetBiff() == EXC_BIFF8;
3523 switch( eTextType )
3525 case EXC_CHTEXTTYPE_TITLE: nDefTextId = EXC_CHDEFTEXT_GLOBAL; break;
3526 case EXC_CHTEXTTYPE_LEGEND: nDefTextId = EXC_CHDEFTEXT_GLOBAL; break;
3527 case EXC_CHTEXTTYPE_AXISTITLE: nDefTextId = bBiff8 ? EXC_CHDEFTEXT_AXESSET : EXC_CHDEFTEXT_GLOBAL; break;
3528 case EXC_CHTEXTTYPE_AXISLABEL: nDefTextId = bBiff8 ? EXC_CHDEFTEXT_AXESSET : EXC_CHDEFTEXT_GLOBAL; break;
3529 case EXC_CHTEXTTYPE_DATALABEL: nDefTextId = bBiff8 ? EXC_CHDEFTEXT_AXESSET : EXC_CHDEFTEXT_GLOBAL; break;
3531 return maDefTexts.get( nDefTextId );
3534 void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, ScfProgressBar& rProgress, const OUString& rObjName ) const
3536 // initialize conversion (locks the model to suppress any internal updates)
3537 InitConversion( xChartDoc );
3539 // chart frame and title
3540 if( mxFrame.is() )
3542 ScfPropertySet aFrameProp( xChartDoc->getPageBackground() );
3543 mxFrame->Convert( aFrameProp );
3545 if( mxTitle.is() )
3547 Reference< XTitled > xTitled( xChartDoc, UNO_QUERY );
3548 Reference< XTitle > xTitle = mxTitle->CreateTitle();
3549 if( xTitled.is() && xTitle.is() )
3550 xTitled->setTitleObject( xTitle );
3553 /* Create the diagram object and attach it to the chart document. Currently,
3554 one diagram is used to carry all coordinate systems and data series. */
3555 Reference< XDiagram > xDiagram = CreateDiagram();
3556 xChartDoc->setFirstDiagram( xDiagram );
3558 // coordinate systems and chart types, convert axis settings
3559 mxPrimAxesSet->Convert( xDiagram );
3560 mxSecnAxesSet->Convert( xDiagram );
3562 // legend
3563 if( xDiagram.is() && mxLegend.is() )
3564 xDiagram->setLegend( mxLegend->CreateLegend() );
3566 // set the IncludeHiddenCells property via the old API as only this ensures that the data provider and al created sequences get this flag correctly
3567 Reference< com::sun::star::chart::XChartDocument > xStandardApiChartDoc( xChartDoc, UNO_QUERY );
3568 if( xStandardApiChartDoc.is() )
3570 ScfPropertySet aDiagramProp( xStandardApiChartDoc->getDiagram() );
3571 bool bShowVisCells = (maProps.mnFlags & EXC_CHPROPS_SHOWVISIBLEONLY);
3572 aDiagramProp.SetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS, !bShowVisCells );
3575 // unlock the model
3576 FinishConversion( rProgress );
3578 ScDocument* pDoc = &GetRoot().GetDoc();
3579 ScChartListenerCollection* pChartCollection = pDoc->GetChartListenerCollection();
3580 if (pChartCollection)
3582 // Now, start listening to this chart.
3583 ::std::auto_ptr< vector<ScSharedTokenRef> > pRefTokens(new vector<ScSharedTokenRef>);
3584 for (XclImpChSeriesVec::const_iterator itr = maSeries.begin(), itrEnd = maSeries.end(); itr != itrEnd; ++itr)
3586 const XclImpChSeriesRef& rSeries = *itr;
3587 rSeries->FillAllSourceLinks(*pRefTokens);
3589 if (!pRefTokens->empty())
3591 ::std::auto_ptr<ScChartListener> pListener(
3592 new ScChartListener(rObjName, pDoc, pRefTokens.release()));
3593 pListener->SetDirty(true);
3594 pListener->StartListeningTo();
3595 pChartCollection->Insert(pListener.release());
3601 void XclImpChChart::ReadChSeries( XclImpStream& rStrm )
3603 sal_uInt16 nNewSeriesIdx = static_cast< sal_uInt16 >( maSeries.size() );
3604 XclImpChSeriesRef xSeries( new XclImpChSeries( GetChRoot(), nNewSeriesIdx ) );
3605 xSeries->ReadRecordGroup( rStrm );
3606 maSeries.push_back( xSeries );
3609 void XclImpChChart::ReadChProperties( XclImpStream& rStrm )
3611 rStrm >> maProps.mnFlags >> maProps.mnEmptyMode;
3614 void XclImpChChart::ReadChAxesSet( XclImpStream& rStrm )
3616 XclImpChAxesSetRef xAxesSet( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_NONE ) );
3617 xAxesSet->ReadRecordGroup( rStrm );
3618 switch( xAxesSet->GetAxesSetId() )
3620 case EXC_CHAXESSET_PRIMARY: mxPrimAxesSet = xAxesSet; break;
3621 case EXC_CHAXESSET_SECONDARY: mxSecnAxesSet = xAxesSet; break;
3625 void XclImpChChart::ReadChText( XclImpStream& rStrm )
3627 XclImpChTextRef xText( new XclImpChText( GetChRoot() ) );
3628 xText->ReadRecordGroup( rStrm );
3629 switch( xText->GetLinkTarget() )
3631 case EXC_CHOBJLINK_TITLE:
3632 mxTitle = xText;
3633 break;
3634 case EXC_CHOBJLINK_DATA:
3636 sal_uInt16 nSeriesIdx = xText->GetPointPos().mnSeriesIdx;
3637 if( nSeriesIdx < maSeries.size() )
3638 maSeries[ nSeriesIdx ]->SetDataLabel( xText );
3640 break;
3644 void XclImpChChart::Finalize()
3646 // finalize series (must be done first)
3647 FinalizeSeries();
3648 // #i49218# legend may be attached to primary or secondary axes set
3649 mxLegend = mxPrimAxesSet->GetLegend();
3650 if( !mxLegend )
3651 mxLegend = mxSecnAxesSet->GetLegend();
3652 if( mxLegend.is() )
3653 mxLegend->Finalize();
3654 // axes sets, updates chart type group default formats -> must be called before FinalizeDataFormats()
3655 mxPrimAxesSet->Finalize();
3656 mxSecnAxesSet->Finalize();
3657 // formatting of all series
3658 FinalizeDataFormats();
3659 // #i47745# missing frame -> invisible border and area
3660 if( !mxFrame )
3661 mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND ) );
3662 // chart title
3663 FinalizeTitle();
3666 void XclImpChChart::FinalizeSeries()
3668 for( XclImpChSeriesVec::iterator aSIt = maSeries.begin(), aSEnd = maSeries.end(); aSIt != aSEnd; ++aSIt )
3670 XclImpChSeriesRef xSeries = *aSIt;
3671 if( xSeries->HasParentSeries() )
3673 /* Process child series (trend lines and error bars). Data of
3674 child series will be set at the connected parent series. */
3675 if( xSeries->GetParentIdx() < maSeries.size() )
3676 maSeries[ xSeries->GetParentIdx() ]->AddChildSeries( *xSeries );
3678 else
3680 // insert the series into the related chart type group
3681 if( XclImpChTypeGroup* pTypeGroup = GetTypeGroup( xSeries->GetGroupIdx() ).get() )
3682 pTypeGroup->AddSeries( xSeries );
3687 void XclImpChChart::FinalizeDataFormats()
3689 /* #i51639# (part 1): CHDATAFORMAT groups are part of CHSERIES groups.
3690 Each CHDATAFORMAT group specifies the series and data point it is
3691 assigned to. This makes it possible to have a data format that is
3692 related to another series, e.g. a CHDATAFORMAT group for series 2 is
3693 part of a CHSERIES group that describes series 1. Therefore the chart
3694 itself has collected all CHDATAFORMAT groups to be able to store data
3695 format groups for series that have not been imported at that time. This
3696 loop finally assigns these groups to the related series. */
3697 for( XclImpChDataFormatMap::const_iterator aMIt = maDataFmts.begin(), aMEnd = maDataFmts.end(); aMIt != aMEnd; ++aMIt )
3699 sal_uInt16 nSeriesIdx = aMIt->first.mnSeriesIdx;
3700 if( nSeriesIdx < maSeries.size() )
3701 maSeries[ nSeriesIdx ]->SetDataFormat( aMIt->second );
3704 /* #i51639# (part 2): Finalize data formats of all series. This adds for
3705 example missing CHDATAFORMAT groups for entire series that are needed
3706 for automatic colors of lines and areas. */
3707 for( XclImpChSeriesVec::iterator aVIt = maSeries.begin(), aVEnd = maSeries.end(); aVIt != aVEnd; ++aVIt )
3708 (*aVIt)->FinalizeDataFormats();
3711 void XclImpChChart::FinalizeTitle()
3713 if( (!mxTitle || (!mxTitle->IsDeleted() && !mxTitle->HasString())) && !mxSecnAxesSet->IsValidAxesSet() )
3715 /* Chart title is auto-generated from series title, if there is only
3716 one series with title in the chart. */
3717 const String& rSerTitle = mxPrimAxesSet->GetSingleSeriesTitle();
3718 if( rSerTitle.Len() > 0 )
3720 if( !mxTitle )
3721 mxTitle.reset( new XclImpChText( GetChRoot() ) );
3722 mxTitle->SetString( rSerTitle );
3726 // will reset mxTitle, if it does not contain a string
3727 lclFinalizeTitle( mxTitle, GetDefaultText( EXC_CHTEXTTYPE_TITLE ) );
3730 Reference< XDiagram > XclImpChChart::CreateDiagram() const
3732 // create a diagram object
3733 Reference< XDiagram > xDiagram( ScfApiHelper::CreateInstance( SERVICE_CHART2_DIAGRAM ), UNO_QUERY );
3735 // convert global chart settings
3736 ScfPropertySet aDiaProp( xDiagram );
3738 // treatment of missing values
3739 using namespace ::com::sun::star::chart::MissingValueTreatment;
3740 sal_Int32 nMissingValues = LEAVE_GAP;
3741 switch( maProps.mnEmptyMode )
3743 case EXC_CHPROPS_EMPTY_SKIP: nMissingValues = LEAVE_GAP; break;
3744 case EXC_CHPROPS_EMPTY_ZERO: nMissingValues = USE_ZERO; break;
3745 case EXC_CHPROPS_EMPTY_INTERPOLATE: nMissingValues = CONTINUE; break;
3747 aDiaProp.SetProperty( EXC_CHPROP_MISSINGVALUETREATMENT, nMissingValues );
3749 return xDiagram;
3752 // ----------------------------------------------------------------------------
3754 XclImpChart::XclImpChart( const XclImpRoot& rRoot, bool bOwnTab ) :
3755 XclImpRoot( rRoot ),
3756 mbOwnTab( bOwnTab ),
3757 mbIsPivotChart( false )
3761 void XclImpChart::ReadChartSubStream( XclImpStream& rStrm )
3763 XclImpPageSettings& rPageSett = GetPageSettings();
3764 XclImpTabViewSettings& rTabViewSett = GetTabViewSettings();
3766 bool bLoop = true;
3767 while( bLoop && rStrm.StartNextRecord() )
3769 // page settings - only for charts in entire sheet
3770 if( mbOwnTab ) switch( rStrm.GetRecId() )
3772 case EXC_ID_HORPAGEBREAKS:
3773 case EXC_ID_VERPAGEBREAKS: rPageSett.ReadPageBreaks( rStrm ); break;
3774 case EXC_ID_HEADER:
3775 case EXC_ID_FOOTER: rPageSett.ReadHeaderFooter( rStrm ); break;
3776 case EXC_ID_LEFTMARGIN:
3777 case EXC_ID_RIGHTMARGIN:
3778 case EXC_ID_TOPMARGIN:
3779 case EXC_ID_BOTTOMMARGIN: rPageSett.ReadMargin( rStrm ); break;
3780 case EXC_ID_PRINTHEADERS: rPageSett.ReadPrintHeaders( rStrm ); break;
3781 case EXC_ID_PRINTGRIDLINES: rPageSett.ReadPrintGridLines( rStrm ); break;
3782 case EXC_ID_HCENTER:
3783 case EXC_ID_VCENTER: rPageSett.ReadCenter( rStrm ); break;
3784 case EXC_ID_SETUP: rPageSett.ReadSetup( rStrm ); break;
3785 case EXC_ID8_IMGDATA: rPageSett.ReadImgData( rStrm ); break;
3787 case EXC_ID_WINDOW2: rTabViewSett.ReadWindow2( rStrm, true );break;
3788 case EXC_ID_SCL: rTabViewSett.ReadScl( rStrm ); break;
3789 case EXC_ID_SHEETEXT: //0x0862
3791 XclImpPalette& rPal = GetPalette();
3792 rTabViewSett.ReadTabBgColor( rStrm, rPal);
3794 break;
3797 switch( rStrm.GetRecId() )
3799 case EXC_ID_EOF: bLoop = false; break;
3801 // #i31882# ignore embedded chart objects
3802 case EXC_ID2_BOF:
3803 case EXC_ID3_BOF:
3804 case EXC_ID4_BOF:
3805 case EXC_ID5_BOF: XclTools::SkipSubStream( rStrm ); break;
3807 case EXC_ID_CHCHART: ReadChChart( rStrm ); break;
3808 case EXC_ID_OBJ: GetTracer().TraceChartEmbeddedObj(); break;
3810 case EXC_ID8_CHPIVOTREF:
3811 GetTracer().TracePivotChartExists();
3812 mbIsPivotChart = true;
3813 break;
3818 void XclImpChart::UpdateObjFrame( const XclObjLineData& rLineData, const XclObjFillData& rFillData )
3820 if( !mxChartData )
3821 mxChartData.reset( new XclImpChChart( GetRoot() ) );
3822 mxChartData->UpdateObjFrame( rLineData, rFillData );
3825 sal_Size XclImpChart::GetProgressSize() const
3827 return mxChartData.is() ? mxChartData->GetProgressSize() : 0;
3830 void XclImpChart::Convert( Reference< XModel > xModel, ScfProgressBar& rProgress, const OUString& rObjName ) const
3832 Reference< XChartDocument > xChartDoc( xModel, UNO_QUERY );
3833 if( mxChartData.is() && xChartDoc.is() )
3834 mxChartData->Convert( xChartDoc, rProgress, rObjName );
3837 void XclImpChart::ReadChChart( XclImpStream& rStrm )
3839 mxChartData.reset( new XclImpChChart( GetRoot() ) );
3840 mxChartData->ReadRecordGroup( rStrm );
3843 // ============================================================================