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"
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"
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"
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
;
131 // Helpers ====================================================================
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
)
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
);
158 // Common =====================================================================
160 /** Stores global data needed in various classes of the Chart import filter. */
161 class XclImpChRootData
: public XclChRootData
164 explicit XclImpChRootData( XclImpChChart
* pChartData
);
166 /** Returns a reference to the parent chart data object. */
167 inline XclImpChChart
& GetChartData() const { return *mpChartData
; }
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
) :
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
);
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
);
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
);
258 Reference
< XModel
> xModel( mxChData
->GetChartDoc(), UNO_QUERY
);
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
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
)
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
)
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
);
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
);
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
);
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
);
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() );
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
;
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
);
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
) );
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
);
507 case EXC_ID_CHAREAFORMAT
:
508 mxAreaFmt
.reset( new XclImpChAreaFormat
);
509 mxAreaFmt
->ReadChAreaFormat( rStrm
);
511 case EXC_ID_CHESCHERFORMAT
:
512 mxEscherFmt
.reset( new XclImpChEscherFormat( rStrm
.GetRoot() ) );
513 mxEscherFmt
->ReadRecordGroup( rStrm
);
518 void XclImpChFrameBase::ConvertLineBase( const XclImpChRoot
& rRoot
,
519 ScfPropertySet
& rPropSet
, XclChObjectType eObjType
, sal_uInt16 nFormatIdx
) const
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()) )
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
)
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 ===============================================================
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
;
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() )
634 xLabeledSeq
->setValues( xValueSeq
);
636 xLabeledSeq
->setLabel( xTitleSeq
);
643 // ----------------------------------------------------------------------------
645 XclImpChSourceLink::XclImpChSourceLink( const XclImpChRoot
& rRoot
) :
646 XclImpChRoot( rRoot
)
650 XclImpChSourceLink::~XclImpChSourceLink()
654 void XclImpChSourceLink::ReadChSourceLink( XclImpStream
& rStrm
)
656 rStrm
>> maData
.mnDestType
659 >> maData
.mnNumFmtIdx
;
661 mxTokenArray
.reset();
662 if( GetLinkType() == EXC_CHSRCLINK_WORKSHEET
)
665 XclTokenArray 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
);
678 mxString
->Read( rStrm
, EXC_STR_8BITLENGTH
| EXC_STR_SEPARATEFORMATS
);
682 void XclImpChSourceLink::SetString( const String
& rString
)
685 mxString
.reset( new XclImpString
);
686 mxString
->SetText( rString
);
689 void XclImpChSourceLink::SetTextFormats( const XclFormatRunVec
& rFormats
)
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
:
710 case ::formula::svDoubleRef
:
711 case ::formula::svExternalDoubleRef
:
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
;
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
) );
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() );
756 ScfPropertySet
aSeqProp( xDataSeq
);
757 aSeqProp
.SetProperty( EXC_CHPROP_ROLE
, rRole
);
761 // DBG_ERRORFILE( "XclImpChSourceLink::CreateDataSequence - cannot create data sequence" );
767 Sequence
< Reference
< XFormattedString
> > XclImpChSourceLink::CreateStringSequence(
768 const XclImpChRoot
& rRoot
, sal_uInt16 nLeadFontIdx
, const Color
& rLeadFontColor
) const
770 ::std::vector
< Reference
< XFormattedString
> > aStringVec
;
773 for( XclImpStringIterator
aIt( *mxString
); aIt
.Is(); ++aIt
)
775 Reference
< XFormattedString
> xFmtStr(
776 ScfApiHelper::CreateInstance( SERVICE_CHART2_FORMATTEDSTRING
), UNO_QUERY
);
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
);
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())
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
)
844 // ----------------------------------------------------------------------------
846 XclImpChText::XclImpChText( const XclImpChRoot
& rRoot
) :
847 XclImpChRoot( rRoot
)
851 void XclImpChText::ReadHeaderRecord( XclImpStream
& rStrm
)
853 rStrm
>> maData
.mnHAlign
856 >> maData
.maTextColor
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;
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() )
882 mxFont
.reset( new XclImpChFont
);
883 mxFont
->ReadChFont( rStrm
);
885 case EXC_ID_CHFORMATRUNS
:
886 if( GetBiff() == EXC_BIFF8
)
887 XclImpString::ReadFormats( rStrm
, maFormats
);
889 case EXC_ID_CHSOURCELINK
:
890 mxSrcLink
.reset( new XclImpChSourceLink( GetChRoot() ) );
891 mxSrcLink
->ReadChSourceLink( rStrm
);
894 mxFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_TEXT
) );
895 mxFrame
->ReadRecordGroup( rStrm
);
897 case EXC_ID_CHOBJECTLINK
:
898 rStrm
>> maObjLink
.mnTarget
>> maObjLink
.maPointPos
.mnSeriesIdx
>> maObjLink
.maPointPos
.mnPointIdx
;
900 case EXC_ID_CHFRLABELPROPS
:
901 ReadChFrLabelProps( rStrm
);
904 if( mxSrcLink
.is() && !maFormats
.empty() )
905 mxSrcLink
->SetTextFormats( maFormats
);
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
)
928 mxSrcLink
.reset( new XclImpChSourceLink( GetChRoot() ) );
929 mxSrcLink
->SetString( rString
);
932 void XclImpChText::UpdateText( const XclImpChText
* pParentText
)
936 // update missing members
938 mxFrame
= pParentText
->mxFrame
;
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
971 mxFrame
->Convert( rPropSet
);
974 void XclImpChText::ConvertNumFmt( ScfPropertySet
& rPropSet
, bool bPercent
) const
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
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
1016 ConvertFont( rPropSet
);
1017 ConvertRotation( rPropSet
, false );
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
);
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 );
1067 void XclImpChText::ReadChFrLabelProps( XclImpStream
& rStrm
)
1069 if( GetBiff() == EXC_BIFF8
)
1071 mxLabelProps
.reset( new XclChFrLabelProps
);
1074 rStrm
>> mxLabelProps
->mnFlags
>> nSepLen
;
1076 mxLabelProps
->maSeparator
= rStrm
.ReadUniString( nSepLen
);
1082 void lclUpdateText( XclImpChTextRef
& rxText
, XclImpChTextRef xDefText
)
1085 rxText
->UpdateText( xDefText
.get() );
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. */
1096 if( rxTitle
->HasString() )
1097 rxTitle
->UpdateText( xDefText
.get() );
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() );
1119 rStrm
>> maData
.mnMarkerSize
;
1123 void XclImpChMarkerFormat::Convert( const XclImpChRoot
& rRoot
,
1124 ScfPropertySet
& rPropSet
, sal_uInt16 nFormatIdx
, sal_Int16 nLineWeight
) const
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
);
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() :
1163 void XclImpChPieFormat::ReadChPieFormat( XclImpStream
& rStrm
)
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() :
1181 void XclImpChSeriesFormat::ReadChSeriesFormat( XclImpStream
& rStrm
)
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
),
1210 void XclImpChAttachedLabel::ReadChAttachedLabel( XclImpStream
& rStrm
)
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
) );
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
1244 void XclImpChDataFormat::ReadSubRecord( XclImpStream
& rStrm
)
1246 switch( rStrm
.GetRecId() )
1248 case EXC_ID_CHMARKERFORMAT
:
1249 mxMarkerFmt
.reset( new XclImpChMarkerFormat
);
1250 mxMarkerFmt
->ReadChMarkerFormat( rStrm
);
1252 case EXC_ID_CHPIEFORMAT
:
1253 mxPieFmt
.reset( new XclImpChPieFormat
);
1254 mxPieFmt
->ReadChPieFormat( rStrm
);
1256 case EXC_ID_CHSERIESFORMAT
:
1257 mxSeriesFmt
.reset( new XclImpChSeriesFormat
);
1258 mxSeriesFmt
->ReadChSeriesFormat( rStrm
);
1260 case EXC_ID_CH3DDATAFORMAT
:
1261 mx3dDataFmt
.reset( new XclImpCh3dDataFormat
);
1262 mx3dDataFmt
->ReadCh3dDataFormat( rStrm
);
1264 case EXC_ID_CHATTACHEDLABEL
:
1265 mxAttLabel
.reset( new XclImpChAttachedLabel( GetChRoot() ) );
1266 mxAttLabel
->ReadChAttachedLabel( rStrm
);
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
1291 mxLineFmt
= pGroupFmt
->mxLineFmt
;
1292 if( !mxAreaFmt
&& !mxEscherFmt
)
1294 mxAreaFmt
= pGroupFmt
->mxAreaFmt
;
1295 mxEscherFmt
= pGroupFmt
->mxEscherFmt
;
1298 mxMarkerFmt
= pGroupFmt
->mxMarkerFmt
;
1300 mxPieFmt
= pGroupFmt
->mxPieFmt
;
1302 mxSeriesFmt
= pGroupFmt
->mxSeriesFmt
;
1304 mx3dDataFmt
= pGroupFmt
->mx3dDataFmt
;
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. */
1312 mxLineFmt
.reset( new XclImpChLineFormat
);
1313 if( !mxAreaFmt
&& !mxEscherFmt
)
1314 mxAreaFmt
.reset( new XclImpChAreaFormat
);
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
1329 if( IsAutoLine() && pSeriesFmt
->IsAutoLine() )
1331 if( IsAutoArea() && pSeriesFmt
->IsAutoArea() )
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() )
1344 // remove formats not used for the current chart type
1345 RemoveUnusedFormats( rTypeInfo
);
1346 // update data label
1347 UpdateDataLabel( pSeriesFmt
);
1350 void XclImpChDataFormat::UpdateTrendLineFormat()
1353 mxLineFmt
.reset( new XclImpChLineFormat
);
1355 mxEscherFmt
.reset();
1356 mxMarkerFmt
.reset();
1358 mxSeriesFmt
.reset();
1359 mx3dDataFmt
.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 );
1376 if( mxMarkerFmt
.is() )
1377 mxMarkerFmt
->Convert( GetChRoot(), rPropSet
, maData
.mnFormatIdx
, GetLineWeight() );
1379 mxPieFmt
->Convert( rPropSet
);
1380 if( mx3dDataFmt
.is() )
1381 mx3dDataFmt
->Convert( rPropSet
);
1383 mxLabel
->ConvertDataLabel( rPropSet
, rTypeInfo
);
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
)
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
;
1427 xDefText
= pParentFmt
->GetDataLabel();
1429 xDefText
= GetChartData().GetDefaultText( EXC_CHTEXTTYPE_DATALABEL
);
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
1447 >> maData
.mfIntercept
1448 >> maData
.mnShowEquation
1449 >> maData
.mnShowRSquared
1450 >> maData
.mfForecastFor
1451 >> maData
.mfForecastBack
;
1454 Reference
< XRegressionCurve
> XclImpChSerTrendLine::CreateRegressionCurve() const
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
;
1465 case EXC_CHSERTREND_EXPONENTIAL
:
1466 aService
= SERVICE_CHART2_EXPREGCURVE
;
1468 case EXC_CHSERTREND_LOGARITHMIC
:
1469 aService
= SERVICE_CHART2_LOGREGCURVE
;
1471 case EXC_CHSERTREND_POWER
:
1472 aService
= SERVICE_CHART2_POTREGCURVE
;
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 );
1500 // #i20819# polynomial trend lines
1501 // #i66819# moving average trend lines
1502 // #i5085# manual trend line size
1503 // #i34093# manual crossing point
1508 // ----------------------------------------------------------------------------
1510 XclImpChSerErrorBar::XclImpChSerErrorBar( const XclImpChRoot
& rRoot
) :
1511 XclImpChRoot( rRoot
)
1515 void XclImpChSerErrorBar::ReadChSerErrorBar( XclImpStream
& rStrm
)
1517 rStrm
>> maData
.mnBarType
>> maData
.mnSourceType
>> maData
.mnLineEnd
;
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
);
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
);
1560 case EXC_CHSERERR_STDDEV
:
1561 aBarProp
.SetProperty( EXC_CHPROP_ERRORBARSTYLE
, cssc::ErrorBarStyle::STANDARD_DEVIATION
);
1562 aBarProp
.SetProperty( EXC_CHPROP_WEIGHT
, pPrimaryBar
->maData
.mfValue
);
1564 case EXC_CHSERERR_STDERR
:
1565 aBarProp
.SetProperty( EXC_CHPROP_ERRORBARSTYLE
, cssc::ErrorBarStyle::STANDARD_ERROR
);
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
1579 Reference
< XLabeledDataSequence
> xValueSeq
= pPosBar
->CreateValueSequence();
1580 if( xValueSeq
.is() )
1581 aLabeledSeqVec
.push_back( xValueSeq
);
1583 // add negative values
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() )
1594 xDataSink
->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec
) );
1602 // error bar formatting
1603 if( pPrimaryBar
->mxDataFmt
.is() && xErrorBar
.is() )
1604 pPrimaryBar
->mxDataFmt
->ConvertLine( aBarProp
, EXC_CHOBJTYPE_ERRORBAR
);
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
);
1634 case EXC_ID_CHDATAFORMAT
:
1635 ReadChDataFormat( rStrm
);
1637 case EXC_ID_CHSERGROUP
:
1638 rStrm
>> mnGroupIdx
;
1640 case EXC_ID_CHSERPARENT
:
1641 ReadChSerParent( rStrm
);
1643 case EXC_ID_CHSERTRENDLINE
:
1644 ReadChSerTrendLine( rStrm
);
1646 case EXC_ID_CHSERERRORBAR
:
1647 ReadChSerErrorBar( rStrm
);
1652 void XclImpChSeries::SetDataFormat( XclImpChDataFormatRef xDataFmt
)
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
)
1673 XclImpChTextRef
* pxLabel
= GetDataLabelRef( xLabel
->GetPointPos().mnPointIdx
);
1674 if( pxLabel
&& !*pxLabel
)
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
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
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
) )
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() );
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
) ) );
1759 DBG_ERRORFILE( "lclGetPointPropSet - no data point property set" );
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
;
1793 Reference
< XLabeledDataSequence
> xYValueSeq
=
1794 CreateValueSequence( EXC_CHPROP_ROLE_YVALUES
);
1795 if( xYValueSeq
.is() )
1796 aLabeledSeqVec
.push_back( xYValueSeq
);
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
);
1824 ConvertTrendLines( xDataSeries
);
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
);
1839 aSeriesProp
.SetBoolProperty( EXC_CHPROP_VARYCOLORSBY
, rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
);
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
);
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 )
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
);
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
];
1928 XclImpChTextRef
* XclImpChSeries::GetDataLabelRef( sal_uInt16 nPointIdx
)
1930 if( (nPointIdx
== EXC_CHDATAFORMAT_ALLPOINTS
) || (nPointIdx
< EXC_CHDATAFORMAT_MAXPOINTCOUNT
) )
1931 return &maLabels
[ nPointIdx
];
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
);
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;
1978 rStrm
>> maData
.mnOverlap
>> maData
.mnGap
>> maData
.mnFlags
;
1983 case EXC_ID_CHRADARLINE
:
1984 case EXC_ID_CHRADARAREA
:
1985 rStrm
>> maData
.mnFlags
;
1989 rStrm
>> maData
.mnRotation
>> maData
.mnPieHole
;
1990 if( GetBiff() == EXC_BIFF8
)
1991 rStrm
>> maData
.mnFlags
;
1996 case EXC_ID_CHPIEEXT
:
1997 maData
.mnRotation
= 0;
1998 maData
.mnPieHole
= 0;
2002 case EXC_ID_CHSCATTER
:
2003 if( GetBiff() == EXC_BIFF8
)
2004 rStrm
>> maData
.mnBubbleSize
>> maData
.mnBubbleType
>> maData
.mnFlags
;
2009 case EXC_ID_CHSURFACE
:
2010 rStrm
>> maData
.mnFlags
;
2021 void XclImpChType::Finalize( bool bStockChart
)
2026 maTypeInfo
= GetChartTypeInfo( bStockChart
?
2027 EXC_CHTYPEID_STOCK
: EXC_CHTYPEID_LINE
);
2030 maTypeInfo
= GetChartTypeInfo( ::get_flagvalue(
2031 maData
.mnFlags
, EXC_CHBAR_HORIZONTAL
,
2032 EXC_CHTYPEID_HORBAR
, EXC_CHTYPEID_BAR
) );
2035 maTypeInfo
= GetChartTypeInfo( (maData
.mnPieHole
> 0) ?
2036 EXC_CHTYPEID_DONUT
: EXC_CHTYPEID_PIE
);
2038 case EXC_ID_CHSCATTER
:
2039 maTypeInfo
= GetChartTypeInfo( ::get_flagvalue(
2040 maData
.mnFlags
, EXC_CHSCATTER_BUBBLES
,
2041 EXC_CHTYPEID_BUBBLES
, EXC_CHTYPEID_SCATTER
) );
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();
2059 bool XclImpChType::IsStacked() const
2061 bool bStacked
= false;
2062 if( maTypeInfo
.mbSupportsStacking
) switch( maTypeInfo
.meTypeCateg
)
2064 case EXC_CHTYPECATEG_LINE
:
2066 ::get_flag( maData
.mnFlags
, EXC_CHLINE_STACKED
) &&
2067 !::get_flag( maData
.mnFlags
, EXC_CHLINE_PERCENT
);
2069 case EXC_CHTYPECATEG_BAR
:
2071 ::get_flag( maData
.mnFlags
, EXC_CHBAR_STACKED
) &&
2072 !::get_flag( maData
.mnFlags
, EXC_CHBAR_PERCENT
);
2079 bool XclImpChType::IsPercent() const
2081 bool bPercent
= false;
2082 if( maTypeInfo
.mbSupportsStacking
) switch( maTypeInfo
.meTypeCateg
)
2084 case EXC_CHTYPECATEG_LINE
:
2086 ::get_flag( maData
.mnFlags
, EXC_CHLINE_STACKED
) &&
2087 ::get_flag( maData
.mnFlags
, EXC_CHLINE_PERCENT
);
2089 case EXC_CHTYPECATEG_BAR
:
2091 ::get_flag( maData
.mnFlags
, EXC_CHBAR_STACKED
) &&
2092 ::get_flag( maData
.mnFlags
, EXC_CHBAR_PERCENT
);
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
2108 OUString aCoordSysService
;
2109 if( maTypeInfo
.mbPolarCoordSystem
)
2112 aCoordSysService
= SERVICE_CHART2_POLARCOORDSYS3D
;
2114 aCoordSysService
= SERVICE_CHART2_POLARCOORDSYS2D
;
2119 aCoordSysService
= SERVICE_CHART2_CARTESIANCOORDSYS3D
;
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_BAR
:
2147 ScfPropertySet
aTypeProp( xChartType
);
2148 Sequence
< sal_Int32
> aInt32Seq( 2 );
2149 aInt32Seq
[ 0 ] = aInt32Seq
[ 1 ] = -maData
.mnOverlap
;
2150 aTypeProp
.SetProperty( EXC_CHPROP_OVERLAPSEQ
, aInt32Seq
);
2151 aInt32Seq
[ 0 ] = aInt32Seq
[ 1 ] = maData
.mnGap
;
2152 aTypeProp
.SetProperty( EXC_CHPROP_GAPWIDTHSEQ
, aInt32Seq
);
2155 case EXC_CHTYPECATEG_PIE
:
2157 ScfPropertySet
aTypeProp( xChartType
);
2158 aTypeProp
.SetBoolProperty( EXC_CHPROP_USERINGS
, maTypeInfo
.meTypeId
== EXC_CHTYPEID_DONUT
);
2159 /* #i85166# starting angle of first pie slice. 3D pie charts use Y
2160 rotation setting in view3D element. Of-pie charts do not
2161 support pie rotation. */
2162 if( !b3dChart
&& (maTypeInfo
.meTypeId
!= EXC_CHTYPEID_PIEEXT
) )
2164 ScfPropertySet
aDiaProp( xDiagram
);
2165 XclImpChRoot::ConvertPieRotation( aDiaProp
, maData
.mnRotation
);
2175 // ----------------------------------------------------------------------------
2177 void XclImpChChart3d::ReadChChart3d( XclImpStream
& rStrm
)
2179 rStrm
>> maData
.mnRotation
2180 >> maData
.mnElevation
2182 >> maData
.mnRelHeight
2183 >> maData
.mnRelDepth
2184 >> maData
.mnDepthGap
2188 void XclImpChChart3d::Convert( ScfPropertySet
& rPropSet
, bool b3dWallChart
) const
2190 namespace cssd
= ::com::sun::star::drawing
;
2191 DBG_ASSERT( ::get_flag( maData
.mnFlags
, EXC_CHCHART3D_HASWALLS
) == b3dWallChart
, "XclImpChChart3d::Convert - wrong wall flag" );
2193 sal_Int32 nRotationY
= 0;
2194 sal_Int32 nRotationX
= 0;
2195 sal_Int32 nPerspective
= 15;
2196 bool bRightAngled
= false;
2197 cssd::ProjectionMode eProjMode
= cssd::ProjectionMode_PERSPECTIVE
;
2198 Color aAmbientColor
, aLightColor
;
2202 // Y rotation (Excel [0..359], Chart2 [-179,180])
2203 nRotationY
= maData
.mnRotation
% 360;
2204 if( nRotationY
> 180 ) nRotationY
-= 360;
2205 // X rotation a.k.a. elevation (Excel [-90..90], Chart2 [-179,180])
2206 nRotationX
= limit_cast
< sal_Int32
, sal_Int32
>( maData
.mnElevation
, -90, 90 );
2207 // perspective (Excel and Chart2 [0,100])
2208 nPerspective
= limit_cast
< sal_Int32
, sal_Int32
>( maData
.mnEyeDist
, 0, 100 );
2209 // right-angled axes
2210 bRightAngled
= !::get_flag( maData
.mnFlags
, EXC_CHCHART3D_REAL3D
);
2211 // projection mode (parallel axes, if right-angled, #i90360# or if perspective is at 0%)
2212 bool bParallel
= bRightAngled
|| (nPerspective
== 0);
2213 eProjMode
= bParallel
? cssd::ProjectionMode_PARALLEL
: cssd::ProjectionMode_PERSPECTIVE
;
2214 // ambient color (Gray 20%)
2215 aAmbientColor
.SetColor( RGB_COLORDATA( 204, 204, 204 ) );
2216 // light color (Gray 60%)
2217 aLightColor
.SetColor( RGB_COLORDATA( 102, 102, 102 ) );
2221 // Y rotation not used in pie charts, but 'first pie slice angle'
2223 XclImpChRoot::ConvertPieRotation( rPropSet
, maData
.mnRotation
);
2224 // X rotation a.k.a. elevation (map Excel [10..80] to Chart2 [-80,-10])
2225 nRotationX
= limit_cast
< sal_Int32
, sal_Int32
>( maData
.mnElevation
, 10, 80 ) - 90;
2226 // perspective (Excel and Chart2 [0,100])
2227 nPerspective
= limit_cast
< sal_Int32
, sal_Int32
>( maData
.mnEyeDist
, 0, 100 );
2228 // no right-angled axes in pie charts, but parallel projection
2229 bRightAngled
= false;
2230 eProjMode
= cssd::ProjectionMode_PARALLEL
;
2231 // ambient color (Gray 30%)
2232 aAmbientColor
.SetColor( RGB_COLORDATA( 179, 179, 179 ) );
2233 // light color (Gray 70%)
2234 aLightColor
.SetColor( RGB_COLORDATA( 76, 76, 76 ) );
2238 rPropSet
.SetProperty( EXC_CHPROP_ROTATIONVERTICAL
, nRotationY
);
2239 rPropSet
.SetProperty( EXC_CHPROP_ROTATIONHORIZONTAL
, nRotationX
);
2240 rPropSet
.SetProperty( EXC_CHPROP_PERSPECTIVE
, nPerspective
);
2241 rPropSet
.SetBoolProperty( EXC_CHPROP_RIGHTANGLEDAXES
, bRightAngled
);
2242 rPropSet
.SetProperty( EXC_CHPROP_D3DSCENEPERSPECTIVE
, eProjMode
);
2245 rPropSet
.SetProperty( EXC_CHPROP_D3DSCENESHADEMODE
, cssd::ShadeMode_FLAT
);
2246 rPropSet
.SetColorProperty( EXC_CHPROP_D3DSCENEAMBIENTCOLOR
, aAmbientColor
);
2247 rPropSet
.SetBoolProperty( EXC_CHPROP_D3DSCENELIGHTON1
, false );
2248 rPropSet
.SetBoolProperty( EXC_CHPROP_D3DSCENELIGHTON2
, true );
2249 rPropSet
.SetColorProperty( EXC_CHPROP_D3DSCENELIGHTCOLOR2
, aLightColor
);
2250 rPropSet
.SetProperty( EXC_CHPROP_D3DSCENELIGHTDIR2
, cssd::Direction3D( 0.2, 0.4, 1.0 ) );
2253 // ----------------------------------------------------------------------------
2255 XclImpChLegend::XclImpChLegend( const XclImpChRoot
& rRoot
) :
2256 XclImpChRoot( rRoot
)
2260 void XclImpChLegend::ReadHeaderRecord( XclImpStream
& rStrm
)
2262 rStrm
>> maData
.maRect
>> maData
.mnDockMode
>> maData
.mnSpacing
>> maData
.mnFlags
;
2264 // trace unsupported features
2265 if( GetTracer().IsEnabled() )
2267 if( maData
.mnDockMode
== EXC_CHLEGEND_NOTDOCKED
)
2268 GetTracer().TraceChartLegendPosition();
2269 if( ::get_flag( maData
.mnFlags
, EXC_CHLEGEND_DATATABLE
) )
2270 GetTracer().TraceChartDataTable();
2274 void XclImpChLegend::ReadSubRecord( XclImpStream
& rStrm
)
2276 switch( rStrm
.GetRecId() )
2279 mxText
.reset( new XclImpChText( GetChRoot() ) );
2280 mxText
->ReadRecordGroup( rStrm
);
2282 case EXC_ID_CHFRAME
:
2283 mxFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_LEGEND
) );
2284 mxFrame
->ReadRecordGroup( rStrm
);
2289 void XclImpChLegend::Finalize()
2291 // legend default formatting differs in OOChart and Excel, missing frame means automatic
2293 mxFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_LEGEND
) );
2294 // Update text formatting. If mxText is empty, the passed default text is used.
2295 lclUpdateText( mxText
, GetChartData().GetDefaultText( EXC_CHTEXTTYPE_LEGEND
) );
2298 Reference
< XLegend
> XclImpChLegend::CreateLegend() const
2300 Reference
< XLegend
> xLegend( ScfApiHelper::CreateInstance( SERVICE_CHART2_LEGEND
), UNO_QUERY
);
2303 ScfPropertySet
aLegendProp( xLegend
);
2307 mxFrame
->Convert( aLegendProp
);
2310 mxText
->ConvertFont( aLegendProp
);
2311 // special legend properties
2312 GetChartPropSetHelper().WriteLegendProperties( aLegendProp
, maData
);
2317 // ----------------------------------------------------------------------------
2319 XclImpChDropBar::XclImpChDropBar( sal_uInt16 nDropBar
) :
2320 mnDropBar( nDropBar
),
2325 void XclImpChDropBar::ReadHeaderRecord( XclImpStream
& rStrm
)
2330 void XclImpChDropBar::Convert( const XclImpChRoot
& rRoot
, ScfPropertySet
& rPropSet
) const
2332 XclChObjectType eObjType
= EXC_CHOBJTYPE_BACKGROUND
;
2335 case EXC_CHDROPBAR_UP
: eObjType
= EXC_CHOBJTYPE_WHITEDROPBAR
; break;
2336 case EXC_CHDROPBAR_DOWN
: eObjType
= EXC_CHOBJTYPE_BLACKDROPBAR
; break;
2338 ConvertFrameBase( rRoot
, rPropSet
, eObjType
);
2341 // ----------------------------------------------------------------------------
2343 XclImpChTypeGroup::XclImpChTypeGroup( const XclImpChRoot
& rRoot
) :
2344 XclImpChRoot( rRoot
),
2346 maTypeInfo( maType
.GetTypeInfo() )
2348 // Initialize unused format indexes set. At this time, all formats are unused.
2349 for( sal_uInt16 nFormatIdx
= 0; nFormatIdx
<= EXC_CHSERIES_MAXSERIES
; ++nFormatIdx
)
2350 maUnusedFormats
.insert( maUnusedFormats
.end(), nFormatIdx
);
2353 void XclImpChTypeGroup::ReadHeaderRecord( XclImpStream
& rStrm
)
2355 rStrm
>> maData
.maRect
>> maData
.mnFlags
>> maData
.mnGroupIdx
;
2358 void XclImpChTypeGroup::ReadSubRecord( XclImpStream
& rStrm
)
2360 switch( rStrm
.GetRecId() )
2362 case EXC_ID_CHCHART3D
:
2363 mxChart3d
.reset( new XclImpChChart3d
);
2364 mxChart3d
->ReadChChart3d( rStrm
);
2366 case EXC_ID_CHLEGEND
:
2367 mxLegend
.reset( new XclImpChLegend( GetChRoot() ) );
2368 mxLegend
->ReadRecordGroup( rStrm
);
2370 case EXC_ID_CHDEFAULTTEXT
:
2371 GetChartData().ReadChDefaultText( rStrm
);
2373 case EXC_ID_CHDROPBAR
:
2374 ReadChDropBar( rStrm
);
2376 case EXC_ID_CHCHARTLINE
:
2377 ReadChChartLine( rStrm
);
2379 case EXC_ID_CHDATAFORMAT
:
2380 ReadChDataFormat( rStrm
);
2383 maType
.ReadChType( rStrm
);
2387 void XclImpChTypeGroup::Finalize()
2389 // check and set valid chart type
2391 (maType
.GetRecId() == EXC_ID_CHLINE
) && // must be a line chart
2392 !mxChart3d
&& // must be a 2d chart
2393 HasHiLoLine() && // must contain hi-lo lines
2394 (maSeries
.size() == static_cast<XclImpChSeriesVec::size_type
>(HasDropBars() ? 4 : 3)); // correct series count
2395 maType
.Finalize( bStockChart
);
2397 // extended type info
2398 maTypeInfo
.Set( maType
.GetTypeInfo(), mxChart3d
.is(), false );
2400 // reverse series order for some unstacked 2D chart types
2401 if( maTypeInfo
.mbReverseSeries
&& !Is3dChart() && !maType
.IsStacked() && !maType
.IsPercent() )
2402 ::std::reverse( maSeries
.begin(), maSeries
.end() );
2404 // update chart type group format, may depend on chart type finalized above
2405 if( mxGroupFmt
.is() )
2406 mxGroupFmt
->UpdateGroupFormat( maTypeInfo
);
2409 void XclImpChTypeGroup::AddSeries( XclImpChSeriesRef xSeries
)
2412 maSeries
.push_back( xSeries
);
2413 // store first inserted series separately, series order may be reversed later
2414 if( !mxFirstSeries
)
2415 mxFirstSeries
= xSeries
;
2418 void XclImpChTypeGroup::SetUsedFormatIndex( sal_uInt16 nFormatIdx
)
2420 maUnusedFormats
.erase( nFormatIdx
);
2423 sal_uInt16
XclImpChTypeGroup::PopUnusedFormatIndex()
2425 DBG_ASSERT( !maUnusedFormats
.empty(), "XclImpChTypeGroup::PopUnusedFormatIndex - no more format indexes available" );
2426 sal_uInt16 nFormatIdx
= maUnusedFormats
.empty() ? 0 : *maUnusedFormats
.begin();
2427 SetUsedFormatIndex( nFormatIdx
);
2431 bool XclImpChTypeGroup::HasVarPointFormat() const
2433 return ::get_flag( maData
.mnFlags
, EXC_CHTYPEGROUP_VARIEDCOLORS
) &&
2434 ((maTypeInfo
.meVarPointMode
== EXC_CHVARPOINT_MULTI
) || // multiple series allowed
2435 ((maTypeInfo
.meVarPointMode
== EXC_CHVARPOINT_SINGLE
) && // or exactly 1 series?
2436 (maSeries
.size() == 1)));
2439 bool XclImpChTypeGroup::HasConnectorLines() const
2441 // existence of connector lines (only in stacked bar charts)
2442 bool bAnyStacked
= maType
.IsStacked() || maType
.IsPercent();
2443 XclImpChLineFormatRef xConnLine
= maChartLines
.get( EXC_CHCHARTLINE_CONNECT
);
2444 return bAnyStacked
&& (maTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_BAR
) && xConnLine
.is() && xConnLine
->HasLine();
2447 const String
& XclImpChTypeGroup::GetSingleSeriesTitle() const
2449 // no automatic title for series with trendlines or error bars
2450 // pie charts always show an automatic title, even if more series exist
2451 return (mxFirstSeries
.is() && !mxFirstSeries
->HasChildSeries() && (maTypeInfo
.mbSingleSeriesVis
|| (maSeries
.size() == 1))) ?
2452 mxFirstSeries
->GetTitle() : String::EmptyString();
2455 void XclImpChTypeGroup::ConvertChart3d( ScfPropertySet
& rPropSet
) const
2457 if( mxChart3d
.is() )
2458 mxChart3d
->Convert( rPropSet
, Is3dWallChart() );
2461 Reference
< XCoordinateSystem
> XclImpChTypeGroup::CreateCoordSystem() const
2463 return maType
.CreateCoordSystem( Is3dChart() );
2466 Reference
< XChartType
> XclImpChTypeGroup::CreateChartType( Reference
< XDiagram
> xDiagram
, sal_Int32 nApiAxesSetIdx
) const
2468 DBG_ASSERT( IsValidGroup(), "XclImpChTypeGroup::CreateChartType - type group without series" );
2470 // create the chart type object
2471 Reference
< XChartType
> xChartType
= maType
.CreateChartType( xDiagram
, Is3dChart() );
2473 // bar chart connector lines
2474 if( HasConnectorLines() )
2476 ScfPropertySet
aDiaProp( xDiagram
);
2477 aDiaProp
.SetBoolProperty( EXC_CHPROP_CONNECTBARS
, true );
2480 /* Stock chart needs special processing. Create one 'big' series with
2481 data sequences of different roles. */
2482 if( maTypeInfo
.meTypeId
== EXC_CHTYPEID_STOCK
)
2483 CreateStockSeries( xChartType
, nApiAxesSetIdx
);
2485 CreateDataSeries( xChartType
, nApiAxesSetIdx
);
2490 Reference
< XLabeledDataSequence
> XclImpChTypeGroup::CreateCategSequence() const
2492 Reference
< XLabeledDataSequence
> xLabeledSeq
;
2493 // create category sequence from first visible series
2494 if( mxFirstSeries
.is() )
2495 xLabeledSeq
= mxFirstSeries
->CreateCategSequence( EXC_CHPROP_ROLE_CATEG
);
2499 void XclImpChTypeGroup::ReadChDropBar( XclImpStream
& rStrm
)
2501 sal_uInt16 nDropBar
= EXC_CHDROPBAR_NONE
;
2502 if( !maDropBars
.has( EXC_CHDROPBAR_UP
) )
2503 nDropBar
= EXC_CHDROPBAR_UP
;
2504 else if( !maDropBars
.has( EXC_CHDROPBAR_DOWN
) )
2505 nDropBar
= EXC_CHDROPBAR_DOWN
;
2507 if( nDropBar
!= EXC_CHDROPBAR_NONE
)
2509 XclImpChDropBarRef
xDropBar( new XclImpChDropBar( nDropBar
) );
2510 xDropBar
->ReadRecordGroup( rStrm
);
2511 maDropBars
[ nDropBar
] = xDropBar
;
2515 void XclImpChTypeGroup::ReadChChartLine( XclImpStream
& rStrm
)
2517 sal_uInt16 nLineId
= rStrm
.ReaduInt16();
2518 if( (rStrm
.GetNextRecId() == EXC_ID_CHLINEFORMAT
) && rStrm
.StartNextRecord() )
2520 XclImpChLineFormatRef
xLineFmt( new XclImpChLineFormat
);
2521 xLineFmt
->ReadChLineFormat( rStrm
);
2522 maChartLines
[ nLineId
] = xLineFmt
;
2526 void XclImpChTypeGroup::ReadChDataFormat( XclImpStream
& rStrm
)
2528 // global series and data point format
2529 XclImpChDataFormatRef
xDataFmt( new XclImpChDataFormat( GetChRoot() ) );
2530 xDataFmt
->ReadRecordGroup( rStrm
);
2531 const XclChDataPointPos
& rPos
= xDataFmt
->GetPointPos();
2532 if( (rPos
.mnSeriesIdx
== 0) && (rPos
.mnPointIdx
== 0) &&
2533 (xDataFmt
->GetFormatIdx() == EXC_CHDATAFORMAT_DEFAULT
) )
2534 mxGroupFmt
= xDataFmt
;
2538 void XclImpChTypeGroup::InsertDataSeries( Reference
< XChartType
> xChartType
,
2539 Reference
< XDataSeries
> xSeries
, sal_Int32 nApiAxesSetIdx
) const
2541 Reference
< XDataSeriesContainer
> xSeriesCont( xChartType
, UNO_QUERY
);
2542 if( xSeriesCont
.is() && xSeries
.is() )
2544 // series stacking mode
2545 namespace cssc
= ::com::sun::star::chart2
;
2546 cssc::StackingDirection eStacking
= cssc::StackingDirection_NO_STACKING
;
2547 // stacked overrides deep-3d
2548 if( maType
.IsStacked() || maType
.IsPercent() )
2549 eStacking
= cssc::StackingDirection_Y_STACKING
;
2550 else if( Is3dDeepChart() )
2551 eStacking
= cssc::StackingDirection_Z_STACKING
;
2553 // additional series properties
2554 ScfPropertySet
aSeriesProp( xSeries
);
2555 aSeriesProp
.SetProperty( EXC_CHPROP_STACKINGDIR
, eStacking
);
2556 aSeriesProp
.SetProperty( EXC_CHPROP_ATTAXISINDEX
, nApiAxesSetIdx
);
2558 // insert series into container
2561 xSeriesCont
->addDataSeries( xSeries
);
2565 DBG_ERRORFILE( "XclImpChTypeGroup::InsertDataSeries - cannot add data series" );
2570 void XclImpChTypeGroup::CreateDataSeries( Reference
< XChartType
> xChartType
, sal_Int32 nApiAxesSetIdx
) const
2572 bool bSpline
= false;
2573 for( XclImpChSeriesVec::const_iterator aIt
= maSeries
.begin(), aEnd
= maSeries
.end(); aIt
!= aEnd
; ++aIt
)
2575 Reference
< XDataSeries
> xDataSeries
= (*aIt
)->CreateDataSeries();
2576 InsertDataSeries( xChartType
, xDataSeries
, nApiAxesSetIdx
);
2577 bSpline
|= (*aIt
)->HasSpline();
2579 // spline - TODO: set at single series (#i66858#)
2580 if( bSpline
&& !maTypeInfo
.IsSeriesFrameFormat() && (maTypeInfo
.meTypeCateg
!= EXC_CHTYPECATEG_RADAR
) )
2582 ScfPropertySet
aTypeProp( xChartType
);
2583 aTypeProp
.SetProperty( EXC_CHPROP_CURVESTYLE
, ::com::sun::star::chart2::CurveStyle_CUBIC_SPLINES
);
2587 void XclImpChTypeGroup::CreateStockSeries( Reference
< XChartType
> xChartType
, sal_Int32 nApiAxesSetIdx
) const
2589 // create the data series object
2590 Reference
< XDataSeries
> xDataSeries( ScfApiHelper::CreateInstance( SERVICE_CHART2_DATASERIES
), UNO_QUERY
);
2591 Reference
< XDataSink
> xDataSink( xDataSeries
, UNO_QUERY
);
2592 if( xDataSink
.is() )
2594 // create a list of data sequences from all series
2595 ::std::vector
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
;
2596 DBG_ASSERT( maSeries
.size() >= 3, "XclImpChTypeGroup::CreateChartType - missing stock series" );
2597 int nRoleIdx
= (maSeries
.size() == 3) ? 1 : 0;
2598 for( XclImpChSeriesVec::const_iterator aIt
= maSeries
.begin(), aEnd
= maSeries
.end();
2599 (nRoleIdx
< 4) && (aIt
!= aEnd
); ++nRoleIdx
, ++aIt
)
2601 // create a data sequence with a specific role
2605 case 0: aRole
= EXC_CHPROP_ROLE_OPENVALUES
; break;
2606 case 1: aRole
= EXC_CHPROP_ROLE_HIGHVALUES
; break;
2607 case 2: aRole
= EXC_CHPROP_ROLE_LOWVALUES
; break;
2608 case 3: aRole
= EXC_CHPROP_ROLE_CLOSEVALUES
; break;
2610 Reference
< XLabeledDataSequence
> xDataSeq
= (*aIt
)->CreateValueSequence( aRole
);
2612 aLabeledSeqVec
.push_back( xDataSeq
);
2615 // attach labeled data sequences to series and insert series into chart type
2616 xDataSink
->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec
) );
2618 // formatting of special stock chart elements
2619 ScfPropertySet
aTypeProp( xChartType
);
2620 aTypeProp
.SetBoolProperty( EXC_CHPROP_JAPANESE
, HasDropBars() );
2621 aTypeProp
.SetBoolProperty( EXC_CHPROP_SHOWFIRST
, HasDropBars() );
2622 aTypeProp
.SetBoolProperty( EXC_CHPROP_SHOWHIGHLOW
, true );
2623 // hi-lo line format
2624 XclImpChLineFormatRef xHiLoLine
= maChartLines
.get( EXC_CHCHARTLINE_HILO
);
2625 if( xHiLoLine
.is() )
2627 ScfPropertySet
aSeriesProp( xDataSeries
);
2628 xHiLoLine
->Convert( GetChRoot(), aSeriesProp
, EXC_CHOBJTYPE_HILOLINE
);
2630 // white dropbar format
2631 XclImpChDropBarRef xUpBar
= maDropBars
.get( EXC_CHDROPBAR_UP
);
2632 Reference
< XPropertySet
> xWhitePropSet
;
2633 if( xUpBar
.is() && aTypeProp
.GetProperty( xWhitePropSet
, EXC_CHPROP_WHITEDAY
) )
2635 ScfPropertySet
aBarProp( xWhitePropSet
);
2636 xUpBar
->Convert( GetChRoot(), aBarProp
);
2638 // black dropbar format
2639 XclImpChDropBarRef xDownBar
= maDropBars
.get( EXC_CHDROPBAR_DOWN
);
2640 Reference
< XPropertySet
> xBlackPropSet
;
2641 if( xDownBar
.is() && aTypeProp
.GetProperty( xBlackPropSet
, EXC_CHPROP_BLACKDAY
) )
2643 ScfPropertySet
aBarProp( xBlackPropSet
);
2644 xDownBar
->Convert( GetChRoot(), aBarProp
);
2647 // insert the series into the chart type object
2648 InsertDataSeries( xChartType
, xDataSeries
, nApiAxesSetIdx
);
2652 // Axes =======================================================================
2654 XclImpChLabelRange::XclImpChLabelRange( const XclImpChRoot
& rRoot
) :
2655 XclImpChRoot( rRoot
)
2659 void XclImpChLabelRange::ReadChLabelRange( XclImpStream
& rStrm
)
2661 rStrm
>> maData
.mnCross
>> maData
.mnLabelFreq
>> maData
.mnTickFreq
>> maData
.mnFlags
;
2664 void XclImpChLabelRange::Convert( ScfPropertySet
& rPropSet
, ScaleData
& rScaleData
, bool bMirrorOrient
) const
2666 // do not overlap text unless all labels are visible
2667 rPropSet
.SetBoolProperty( EXC_CHPROP_TEXTOVERLAP
, maData
.mnLabelFreq
== 1 );
2668 // do not break text into several lines unless all labels are visible
2669 rPropSet
.SetBoolProperty( EXC_CHPROP_TEXTBREAK
, maData
.mnLabelFreq
== 1 );
2670 // do not stagger labels in two lines
2671 namespace cssc
= ::com::sun::star::chart
;
2672 rPropSet
.SetProperty( EXC_CHPROP_ARRANGEORDER
, cssc::ChartAxisArrangeOrderType_SIDE_BY_SIDE
);
2675 namespace cssc2
= ::com::sun::star::chart2
;
2676 bool bReverse
= ::get_flag( maData
.mnFlags
, EXC_CHLABELRANGE_REVERSE
) != bMirrorOrient
;
2677 rScaleData
.Orientation
= bReverse
? cssc2::AxisOrientation_REVERSE
: cssc2::AxisOrientation_MATHEMATICAL
;
2679 //! TODO #i58731# show n-th category
2682 void XclImpChLabelRange::ConvertAxisPosition( ScfPropertySet
& rPropSet
, bool b3dChart
) const
2684 /* Crossing mode (max-cross flag overrides other crossing settings). Excel
2685 does not move the Y axis in 3D charts, regardless of actual settings.
2686 But: the Y axis has to be moved to "end", if the X axis is mirrored,
2687 to keep it at the left end of the chart. */
2688 bool bMaxCross
= ::get_flag( maData
.mnFlags
, b3dChart
? EXC_CHLABELRANGE_REVERSE
: EXC_CHLABELRANGE_MAXCROSS
);
2689 namespace cssc
= ::com::sun::star::chart
;
2690 cssc::ChartAxisPosition eAxisPos
= bMaxCross
? cssc::ChartAxisPosition_END
: cssc::ChartAxisPosition_VALUE
;
2691 rPropSet
.SetProperty( EXC_CHPROP_CROSSOVERPOSITION
, eAxisPos
);
2693 // crossing position
2694 double fCrossingPos
= b3dChart
? 1.0 : maData
.mnCross
;
2695 rPropSet
.SetProperty( EXC_CHPROP_CROSSOVERVALUE
, fCrossingPos
);
2698 // ----------------------------------------------------------------------------
2700 XclImpChValueRange::XclImpChValueRange( const XclImpChRoot
& rRoot
) :
2701 XclImpChRoot( rRoot
)
2705 void XclImpChValueRange::ReadChValueRange( XclImpStream
& rStrm
)
2707 rStrm
>> maData
.mfMin
2709 >> maData
.mfMajorStep
2710 >> maData
.mfMinorStep
2715 void XclImpChValueRange::Convert( ScaleData
& rScaleData
, bool bMirrorOrient
) const
2717 // scaling algorithm
2718 bool bLogScale
= ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_LOGSCALE
);
2719 OUString aScalingService
= bLogScale
? SERVICE_CHART2_LOGSCALING
: SERVICE_CHART2_LINEARSCALING
;
2720 rScaleData
.Scaling
.set( ScfApiHelper::CreateInstance( aScalingService
), UNO_QUERY
);
2723 lclSetExpValueOrClearAny( rScaleData
.Minimum
, maData
.mfMin
, bLogScale
, ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMIN
) );
2724 lclSetExpValueOrClearAny( rScaleData
.Maximum
, maData
.mfMax
, bLogScale
, ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMAX
) );
2727 bool bAutoMajor
= ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMAJOR
);
2728 bool bAutoMinor
= ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMINOR
);
2730 IncrementData
& rIncrementData
= rScaleData
.IncrementData
;
2731 lclSetValueOrClearAny( rIncrementData
.Distance
, maData
.mfMajorStep
, bAutoMajor
);
2733 Sequence
< SubIncrement
>& rSubIncrementSeq
= rIncrementData
.SubIncrements
;
2734 rSubIncrementSeq
.realloc( 1 );
2735 Any
& rIntervalCount
= rSubIncrementSeq
[ 0 ].IntervalCount
;
2738 rIntervalCount
<<= sal_Int32( 10 );
2742 sal_Int32 nCount
= 0;
2743 if( !bAutoMajor
&& !bAutoMinor
&& (0.0 < maData
.mfMinorStep
) && (maData
.mfMinorStep
<= maData
.mfMajorStep
) )
2745 double fCount
= maData
.mfMajorStep
/ maData
.mfMinorStep
+ 0.5;
2746 if( fCount
< 1001.0 )
2747 nCount
= static_cast< sal_Int32
>( fCount
);
2749 lclSetValueOrClearAny( rIntervalCount
, nCount
, nCount
== 0 );
2753 namespace cssc2
= ::com::sun::star::chart2
;
2754 bool bReverse
= ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_REVERSE
) != bMirrorOrient
;
2755 rScaleData
.Orientation
= bReverse
? cssc2::AxisOrientation_REVERSE
: cssc2::AxisOrientation_MATHEMATICAL
;
2758 void XclImpChValueRange::ConvertAxisPosition( ScfPropertySet
& rPropSet
) const
2760 bool bMaxCross
= ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_MAXCROSS
);
2761 bool bAutoCross
= ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
);
2762 bool bLogScale
= ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_LOGSCALE
);
2764 // crossing mode (max-cross flag overrides other crossing settings)
2765 namespace cssc
= ::com::sun::star::chart
;
2766 cssc::ChartAxisPosition eAxisPos
= bMaxCross
? cssc::ChartAxisPosition_END
: cssc::ChartAxisPosition_VALUE
;
2767 rPropSet
.SetProperty( EXC_CHPROP_CROSSOVERPOSITION
, eAxisPos
);
2769 // crossing position
2770 double fCrossingPos
= bAutoCross
? 0.0 : maData
.mfCross
;
2771 if( bLogScale
) fCrossingPos
= pow( 10.0, fCrossingPos
);
2772 rPropSet
.SetProperty( EXC_CHPROP_CROSSOVERVALUE
, fCrossingPos
);
2775 // ----------------------------------------------------------------------------
2779 sal_Int32
lclGetApiTickmarks( sal_uInt8 nXclTickPos
)
2781 using namespace ::com::sun::star::chart2::TickmarkStyle
;
2782 sal_Int32 nApiTickmarks
= NONE
;
2783 ::set_flag( nApiTickmarks
, INNER
, ::get_flag( nXclTickPos
, EXC_CHTICK_INSIDE
) );
2784 ::set_flag( nApiTickmarks
, OUTER
, ::get_flag( nXclTickPos
, EXC_CHTICK_OUTSIDE
) );
2785 return nApiTickmarks
;
2788 ::com::sun::star::chart::ChartAxisLabelPosition
lclGetApiLabelPosition( sal_Int8 nXclLabelPos
)
2790 using namespace ::com::sun::star::chart
;
2791 switch( nXclLabelPos
)
2793 case EXC_CHTICK_LOW
: return ChartAxisLabelPosition_OUTSIDE_START
;
2794 case EXC_CHTICK_HIGH
: return ChartAxisLabelPosition_OUTSIDE_END
;
2795 case EXC_CHTICK_NEXT
: return ChartAxisLabelPosition_NEAR_AXIS
;
2797 return ChartAxisLabelPosition_NEAR_AXIS
;
2802 XclImpChTick::XclImpChTick( const XclImpChRoot
& rRoot
) :
2803 XclImpChRoot( rRoot
)
2807 void XclImpChTick::ReadChTick( XclImpStream
& rStrm
)
2809 rStrm
>> maData
.mnMajor
2811 >> maData
.mnLabelPos
2812 >> maData
.mnBackMode
2814 >> maData
.maTextColor
2817 if( GetBiff() == EXC_BIFF8
)
2819 // #116397# BIFF8: index into palette used instead of RGB data
2820 maData
.maTextColor
= GetPalette().GetColor( rStrm
.ReaduInt16() );
2822 rStrm
>> maData
.mnRotation
;
2826 // BIFF2-BIFF7: get rotation from text orientation
2827 sal_uInt8 nOrient
= ::extract_value
< sal_uInt8
>( maData
.mnFlags
, 2, 3 );
2828 maData
.mnRotation
= XclTools::GetXclRotFromOrient( nOrient
);
2832 Color
XclImpChTick::GetFontColor() const
2834 return ::get_flag( maData
.mnFlags
, EXC_CHTICK_AUTOCOLOR
) ? GetFontAutoColor() : maData
.maTextColor
;
2837 sal_uInt16
XclImpChTick::GetRotation() const
2839 return ::get_flag( maData
.mnFlags
, EXC_CHTICK_AUTOROT
) ? EXC_CHART_AUTOROTATION
: maData
.mnRotation
;
2842 void XclImpChTick::Convert( ScfPropertySet
& rPropSet
) const
2844 rPropSet
.SetProperty( EXC_CHPROP_MAJORTICKS
, lclGetApiTickmarks( maData
.mnMajor
) );
2845 rPropSet
.SetProperty( EXC_CHPROP_MINORTICKS
, lclGetApiTickmarks( maData
.mnMinor
) );
2846 rPropSet
.SetProperty( EXC_CHPROP_LABELPOSITION
, lclGetApiLabelPosition( maData
.mnLabelPos
) );
2847 rPropSet
.SetProperty( EXC_CHPROP_MARKPOSITION
, ::com::sun::star::chart::ChartAxisMarkPosition_AT_AXIS
);
2850 // ----------------------------------------------------------------------------
2852 XclImpChAxis::XclImpChAxis( const XclImpChRoot
& rRoot
, sal_uInt16 nAxisType
) :
2853 XclImpChRoot( rRoot
),
2854 mnNumFmtIdx( EXC_FORMAT_NOTFOUND
)
2856 maData
.mnType
= nAxisType
;
2859 void XclImpChAxis::ReadHeaderRecord( XclImpStream
& rStrm
)
2861 rStrm
>> maData
.mnType
>> maData
.maRect
;
2864 void XclImpChAxis::ReadSubRecord( XclImpStream
& rStrm
)
2866 switch( rStrm
.GetRecId() )
2868 case EXC_ID_CHLABELRANGE
:
2869 mxLabelRange
.reset( new XclImpChLabelRange( GetChRoot() ) );
2870 mxLabelRange
->ReadChLabelRange( rStrm
);
2872 case EXC_ID_CHVALUERANGE
:
2873 mxValueRange
.reset( new XclImpChValueRange( GetChRoot() ) );
2874 mxValueRange
->ReadChValueRange( rStrm
);
2876 case EXC_ID_CHFORMAT
:
2877 rStrm
>> mnNumFmtIdx
;
2880 mxTick
.reset( new XclImpChTick( GetChRoot() ) );
2881 mxTick
->ReadChTick( rStrm
);
2884 mxFont
.reset( new XclImpChFont
);
2885 mxFont
->ReadChFont( rStrm
);
2887 case EXC_ID_CHAXISLINE
:
2888 ReadChAxisLine( rStrm
);
2893 void XclImpChAxis::Finalize()
2895 // add default scaling, needed e.g. to adjust rotation direction of pie and radar charts
2897 mxLabelRange
.reset( new XclImpChLabelRange( GetChRoot() ) );
2899 mxValueRange
.reset( new XclImpChValueRange( GetChRoot() ) );
2900 // remove invisible grid lines completely
2901 if( mxMajorGrid
.is() && !mxMajorGrid
->HasLine() )
2902 mxMajorGrid
.reset();
2903 if( mxMinorGrid
.is() && !mxMinorGrid
->HasLine() )
2904 mxMinorGrid
.reset();
2905 // default tick settings different in OOChart and Excel
2907 mxTick
.reset( new XclImpChTick( GetChRoot() ) );
2908 // #i4140# different default axis line color
2911 XclChLineFormat aLineFmt
;
2912 // set "show axis" flag, default if line format record is missing
2913 ::set_flag( aLineFmt
.mnFlags
, EXC_CHLINEFORMAT_SHOWAXIS
);
2914 mxAxisLine
.reset( new XclImpChLineFormat( aLineFmt
) );
2916 // add wall/floor frame for 3d charts
2921 sal_uInt16
XclImpChAxis::GetFontIndex() const
2923 return mxFont
.is() ? mxFont
->GetFontIndex() : EXC_FONT_NOTFOUND
;
2926 Color
XclImpChAxis::GetFontColor() const
2928 return mxTick
.is() ? mxTick
->GetFontColor() : GetFontAutoColor();
2931 sal_uInt16
XclImpChAxis::GetRotation() const
2933 return mxTick
.is() ? mxTick
->GetRotation() : EXC_CHART_AUTOROTATION
;
2936 Reference
< XAxis
> XclImpChAxis::CreateAxis( const XclImpChTypeGroup
& rTypeGroup
, const XclImpChAxis
* pCrossingAxis
) const
2938 namespace cssc2
= ::com::sun::star::chart2
;
2940 // create the axis object (always)
2941 Reference
< XAxis
> xAxis( ScfApiHelper::CreateInstance( SERVICE_CHART2_AXIS
), UNO_QUERY
);
2944 ScfPropertySet
aAxisProp( xAxis
);
2945 // #i58688# axis enabled
2946 aAxisProp
.SetBoolProperty( EXC_CHPROP_SHOW
, IsActivated() );
2948 // axis line properties
2949 if( mxAxisLine
.is() )
2950 mxAxisLine
->Convert( GetChRoot(), aAxisProp
, EXC_CHOBJTYPE_AXISLINE
);
2951 // axis ticks properties
2953 mxTick
->Convert( aAxisProp
);
2955 // axis caption text --------------------------------------------------
2957 // radar charts disable their category labels via chart type, not via axis
2958 bool bHasLabels
= HasLabels() &&
2959 ((GetAxisType() != EXC_CHAXIS_X
) || rTypeGroup
.HasCategoryLabels());
2960 aAxisProp
.SetBoolProperty( EXC_CHPROP_DISPLAYLABELS
, bHasLabels
);
2963 // font settings from CHFONT record or from default text
2965 ConvertFontBase( GetChRoot(), aAxisProp
);
2966 else if( const XclImpChText
* pDefText
= GetChartData().GetDefaultText( EXC_CHTEXTTYPE_AXISLABEL
).get() )
2967 pDefText
->ConvertFont( aAxisProp
);
2968 // label text rotation
2969 ConvertRotationBase( GetChRoot(), aAxisProp
, true );
2971 sal_uInt32 nScNumFmt
= GetNumFmtBuffer().GetScFormat( mnNumFmtIdx
);
2972 if( nScNumFmt
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
2973 aAxisProp
.SetProperty( EXC_CHPROP_NUMBERFORMAT
, static_cast< sal_Int32
>( nScNumFmt
) );
2976 // axis scaling and increment -----------------------------------------
2978 const XclChExtTypeInfo
& rTypeInfo
= rTypeGroup
.GetTypeInfo();
2979 ScaleData aScaleData
= xAxis
->getScaleData();
2981 switch( GetAxisType() )
2984 if( rTypeInfo
.mbCategoryAxis
)
2986 aScaleData
.AxisType
= cssc2::AxisType::CATEGORY
;
2987 aScaleData
.Categories
= rTypeGroup
.CreateCategSequence();
2990 aScaleData
.AxisType
= cssc2::AxisType::REALNUMBER
;
2993 aScaleData
.AxisType
= rTypeGroup
.IsPercent() ?
2994 cssc2::AxisType::PERCENT
: cssc2::AxisType::REALNUMBER
;
2997 aScaleData
.AxisType
= cssc2::AxisType::SERIES
;
3000 // axis scaling settings, dependent on axis type
3001 switch( aScaleData
.AxisType
)
3003 case cssc2::AxisType::CATEGORY
:
3004 case cssc2::AxisType::SERIES
:
3005 // #i71684# radar charts have reversed rotation direction
3006 mxLabelRange
->Convert( aAxisProp
, aScaleData
, rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_RADAR
);
3008 case cssc2::AxisType::REALNUMBER
:
3009 case cssc2::AxisType::PERCENT
:
3010 // #i85167# pie/donut charts have reversed rotation direction (at Y axis!)
3011 mxValueRange
->Convert( aScaleData
, rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
);
3014 DBG_ERRORFILE( "XclImpChAxis::CreateAxis - unknown axis type" );
3017 /* Do not set a value to the Origin member anymore (will be done via
3018 new axis properties 'CrossoverPosition' and 'CrossoverValue'). */
3019 aScaleData
.Origin
.clear();
3022 xAxis
->setScaleData( aScaleData
);
3024 // grid ---------------------------------------------------------------
3027 ScfPropertySet
aGridProp( xAxis
->getGridProperties() );
3028 aGridProp
.SetBoolProperty( EXC_CHPROP_SHOW
, HasMajorGrid() );
3029 if( mxMajorGrid
.is() )
3030 mxMajorGrid
->Convert( GetChRoot(), aGridProp
, EXC_CHOBJTYPE_GRIDLINE
);
3032 Sequence
< Reference
< XPropertySet
> > aSubGridPropSeq
= xAxis
->getSubGridProperties();
3033 if( aSubGridPropSeq
.hasElements() )
3035 ScfPropertySet
aSubGridProp( aSubGridPropSeq
[ 0 ] );
3036 aSubGridProp
.SetBoolProperty( EXC_CHPROP_SHOW
, HasMinorGrid() );
3037 if( mxMinorGrid
.is() )
3038 mxMinorGrid
->Convert( GetChRoot(), aSubGridProp
, EXC_CHOBJTYPE_GRIDLINE
);
3041 // position of crossing axis ------------------------------------------
3044 pCrossingAxis
->ConvertAxisPosition( aAxisProp
, rTypeGroup
);
3049 void XclImpChAxis::ConvertWall( ScfPropertySet
& rPropSet
) const
3051 if( mxWallFrame
.is() )
3052 mxWallFrame
->Convert( rPropSet
);
3055 void XclImpChAxis::ConvertAxisPosition( ScfPropertySet
& rPropSet
, const XclImpChTypeGroup
& rTypeGroup
) const
3057 if( ((GetAxisType() == EXC_CHAXIS_X
) && rTypeGroup
.GetTypeInfo().mbCategoryAxis
) || (GetAxisType() == EXC_CHAXIS_Z
) )
3058 mxLabelRange
->ConvertAxisPosition( rPropSet
, rTypeGroup
.Is3dChart() );
3060 mxValueRange
->ConvertAxisPosition( rPropSet
);
3063 void XclImpChAxis::ReadChAxisLine( XclImpStream
& rStrm
)
3065 XclImpChLineFormatRef
* pxLineFmt
= 0;
3066 bool bWallFrame
= false;
3067 switch( rStrm
.ReaduInt16() )
3069 case EXC_CHAXISLINE_AXISLINE
: pxLineFmt
= &mxAxisLine
; break;
3070 case EXC_CHAXISLINE_MAJORGRID
: pxLineFmt
= &mxMajorGrid
; break;
3071 case EXC_CHAXISLINE_MINORGRID
: pxLineFmt
= &mxMinorGrid
; break;
3072 case EXC_CHAXISLINE_WALLS
: bWallFrame
= true; break;
3077 bool bLoop
= pxLineFmt
|| bWallFrame
;
3080 sal_uInt16 nRecId
= rStrm
.GetNextRecId();
3081 bLoop
= ((nRecId
== EXC_ID_CHLINEFORMAT
) ||
3082 (nRecId
== EXC_ID_CHAREAFORMAT
) ||
3083 (nRecId
== EXC_ID_CHESCHERFORMAT
))
3084 && rStrm
.StartNextRecord();
3087 if( pxLineFmt
&& (nRecId
== EXC_ID_CHLINEFORMAT
) )
3089 pxLineFmt
->reset( new XclImpChLineFormat
);
3090 (*pxLineFmt
)->ReadChLineFormat( rStrm
);
3092 else if( bWallFrame
&& mxWallFrame
.is() )
3094 mxWallFrame
->ReadSubRecord( rStrm
);
3100 void XclImpChAxis::CreateWallFrame()
3102 switch( GetAxisType() )
3105 mxWallFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_WALL3D
) );
3108 mxWallFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_FLOOR3D
) );
3111 mxWallFrame
.reset();
3115 // ----------------------------------------------------------------------------
3117 XclImpChAxesSet::XclImpChAxesSet( const XclImpChRoot
& rRoot
, sal_uInt16 nAxesSetId
) :
3118 XclImpChRoot( rRoot
)
3120 maData
.mnAxesSetId
= nAxesSetId
;
3123 void XclImpChAxesSet::ReadHeaderRecord( XclImpStream
& rStrm
)
3125 rStrm
>> maData
.mnAxesSetId
>> maData
.maRect
;
3128 void XclImpChAxesSet::ReadSubRecord( XclImpStream
& rStrm
)
3130 switch( rStrm
.GetRecId() )
3132 case EXC_ID_CHFRAMEPOS
:
3133 mxPos
.reset( new XclImpChFramePos
);
3134 mxPos
->ReadChFramePos( rStrm
);
3137 ReadChAxis( rStrm
);
3140 ReadChText( rStrm
);
3142 case EXC_ID_CHPLOTFRAME
:
3143 ReadChPlotFrame( rStrm
);
3145 case EXC_ID_CHTYPEGROUP
:
3146 ReadChTypeGroup( rStrm
);
3151 void XclImpChAxesSet::Finalize()
3153 if( IsValidAxesSet() )
3155 // finalize chart type groups, erase empty groups without series
3156 XclImpChTypeGroupMap aValidGroups
;
3157 for( XclImpChTypeGroupMap::const_iterator aIt
= maTypeGroups
.begin(), aEnd
= maTypeGroups
.end(); aIt
!= aEnd
; ++aIt
)
3159 XclImpChTypeGroupRef xTypeGroup
= aIt
->second
;
3160 xTypeGroup
->Finalize();
3161 if( xTypeGroup
->IsValidGroup() )
3162 aValidGroups
[ aIt
->first
] = xTypeGroup
;
3164 maTypeGroups
.swap( aValidGroups
);
3167 // invalid chart type groups are deleted now, check again with IsValidAxesSet()
3168 if( IsValidAxesSet() )
3170 // always create missing axis objects
3172 mxXAxis
.reset( new XclImpChAxis( GetChRoot(), EXC_CHAXIS_X
) );
3174 mxYAxis
.reset( new XclImpChAxis( GetChRoot(), EXC_CHAXIS_Y
) );
3175 if( !mxZAxis
&& GetFirstTypeGroup()->Is3dDeepChart() )
3176 mxZAxis
.reset( new XclImpChAxis( GetChRoot(), EXC_CHAXIS_Z
) );
3179 if( mxXAxis
.is() ) mxXAxis
->Finalize();
3180 if( mxYAxis
.is() ) mxYAxis
->Finalize();
3181 if( mxZAxis
.is() ) mxZAxis
->Finalize();
3183 // finalize axis titles
3184 XclImpChTextRef xDefText
= GetChartData().GetDefaultText( EXC_CHTEXTTYPE_AXISTITLE
);
3185 lclFinalizeTitle( mxXAxisTitle
, xDefText
);
3186 lclFinalizeTitle( mxYAxisTitle
, xDefText
);
3187 lclFinalizeTitle( mxZAxisTitle
, xDefText
);
3189 // #i47745# missing plot frame -> invisible border and area
3191 mxPlotFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_PLOTFRAME
) );
3195 XclImpChTypeGroupRef
XclImpChAxesSet::GetFirstTypeGroup() const
3197 XclImpChTypeGroupRef xTypeGroup
;
3198 if( !maTypeGroups
.empty() )
3199 xTypeGroup
= maTypeGroups
.begin()->second
;
3203 XclImpChLegendRef
XclImpChAxesSet::GetLegend() const
3205 XclImpChLegendRef xLegend
;
3206 for( XclImpChTypeGroupMap::const_iterator aIt
= maTypeGroups
.begin(), aEnd
= maTypeGroups
.end(); !xLegend
&& (aIt
!= aEnd
); ++aIt
)
3207 xLegend
= aIt
->second
->GetLegend();
3211 const String
& XclImpChAxesSet::GetSingleSeriesTitle() const
3213 return (maTypeGroups
.size() == 1) ? maTypeGroups
.begin()->second
->GetSingleSeriesTitle() : String::EmptyString();
3216 void XclImpChAxesSet::Convert( Reference
< XDiagram
> xDiagram
) const
3218 if( IsValidAxesSet() && xDiagram
.is() )
3220 // diagram background formatting
3221 if( GetAxesSetId() == EXC_CHAXESSET_PRIMARY
)
3222 ConvertBackground( xDiagram
);
3224 // create the coordinate system, this inserts all chart types and series
3225 Reference
< XCoordinateSystem
> xCoordSystem
= CreateCoordSystem( xDiagram
);
3226 if( xCoordSystem
.is() )
3228 // insert coordinate system, if not already done
3231 Reference
< XCoordinateSystemContainer
> xCoordSystemCont( xDiagram
, UNO_QUERY_THROW
);
3232 Sequence
< Reference
< XCoordinateSystem
> > aCoordSystems
= xCoordSystemCont
->getCoordinateSystems();
3233 if( aCoordSystems
.getLength() == 0 )
3234 xCoordSystemCont
->addCoordinateSystem( xCoordSystem
);
3238 DBG_ERRORFILE( "XclImpChAxesSet::Convert - cannot insert coordinate system" );
3241 // create the axes with grids and axis titles and insert them into the diagram
3242 ConvertAxis( mxXAxis
, mxXAxisTitle
, xCoordSystem
, mxYAxis
.get() );
3243 ConvertAxis( mxYAxis
, mxYAxisTitle
, xCoordSystem
, mxXAxis
.get() );
3244 ConvertAxis( mxZAxis
, mxZAxisTitle
, xCoordSystem
, 0 );
3249 void XclImpChAxesSet::ReadChAxis( XclImpStream
& rStrm
)
3251 XclImpChAxisRef
xAxis( new XclImpChAxis( GetChRoot() ) );
3252 xAxis
->ReadRecordGroup( rStrm
);
3254 switch( xAxis
->GetAxisType() )
3256 case EXC_CHAXIS_X
: mxXAxis
= xAxis
; break;
3257 case EXC_CHAXIS_Y
: mxYAxis
= xAxis
; break;
3258 case EXC_CHAXIS_Z
: mxZAxis
= xAxis
; break;
3262 void XclImpChAxesSet::ReadChText( XclImpStream
& rStrm
)
3264 XclImpChTextRef
xText( new XclImpChText( GetChRoot() ) );
3265 xText
->ReadRecordGroup( rStrm
);
3267 switch( xText
->GetLinkTarget() )
3269 case EXC_CHOBJLINK_XAXIS
: mxXAxisTitle
= xText
; break;
3270 case EXC_CHOBJLINK_YAXIS
: mxYAxisTitle
= xText
; break;
3271 case EXC_CHOBJLINK_ZAXIS
: mxZAxisTitle
= xText
; break;
3275 void XclImpChAxesSet::ReadChPlotFrame( XclImpStream
& rStrm
)
3277 if( (rStrm
.GetNextRecId() == EXC_ID_CHFRAME
) && rStrm
.StartNextRecord() )
3279 mxPlotFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_PLOTFRAME
) );
3280 mxPlotFrame
->ReadRecordGroup( rStrm
);
3284 void XclImpChAxesSet::ReadChTypeGroup( XclImpStream
& rStrm
)
3286 XclImpChTypeGroupRef
xTypeGroup( new XclImpChTypeGroup( GetChRoot() ) );
3287 xTypeGroup
->ReadRecordGroup( rStrm
);
3288 maTypeGroups
[ xTypeGroup
->GetGroupIdx() ] = xTypeGroup
;
3291 Reference
< XCoordinateSystem
> XclImpChAxesSet::CreateCoordSystem( Reference
< XDiagram
> xDiagram
) const
3293 Reference
< XCoordinateSystem
> xCoordSystem
;
3295 /* Try to get existing ccordinate system. For now, all series from primary
3296 and secondary axes sets are inserted into one coordinate system. Later,
3297 this should be changed to use one coordinate system for each axes set. */
3298 Reference
< XCoordinateSystemContainer
> xCoordSystemCont( xDiagram
, UNO_QUERY
);
3299 if( xCoordSystemCont
.is() )
3301 Sequence
< Reference
< XCoordinateSystem
> > aCoordSystems
= xCoordSystemCont
->getCoordinateSystems();
3302 DBG_ASSERT( aCoordSystems
.getLength() <= 1, "XclImpChAxesSet::CreateCoordSystem - too many existing coordinate systems" );
3303 if( aCoordSystems
.getLength() > 0 )
3304 xCoordSystem
= aCoordSystems
[ 0 ];
3307 // create the coordinate system according to the first chart type
3308 if( !xCoordSystem
.is() )
3310 XclImpChTypeGroupRef xTypeGroup
= GetFirstTypeGroup();
3311 if( xTypeGroup
.is() )
3313 xCoordSystem
= xTypeGroup
->CreateCoordSystem();
3314 // convert 3d chart settings
3315 ScfPropertySet
aDiaProp( xDiagram
);
3316 xTypeGroup
->ConvertChart3d( aDiaProp
);
3320 /* Create XChartType objects for all chart type groups. Each group will
3321 add its series to the data provider attached to the chart document. */
3322 Reference
< XChartTypeContainer
> xChartTypeCont( xCoordSystem
, UNO_QUERY
);
3323 if( xChartTypeCont
.is() )
3325 sal_Int32 nApiAxesSetIdx
= GetApiAxesSetIndex();
3326 for( XclImpChTypeGroupMap::const_iterator aIt
= maTypeGroups
.begin(), aEnd
= maTypeGroups
.end(); aIt
!= aEnd
; ++aIt
)
3330 Reference
< XChartType
> xChartType
= aIt
->second
->CreateChartType( xDiagram
, nApiAxesSetIdx
);
3331 if( xChartType
.is() )
3332 xChartTypeCont
->addChartType( xChartType
);
3336 DBG_ERRORFILE( "XclImpChAxesSet::CreateCoordSystem - cannot add chart type" );
3341 return xCoordSystem
;
3344 void XclImpChAxesSet::ConvertAxis(
3345 XclImpChAxisRef xChAxis
, XclImpChTextRef xChAxisTitle
,
3346 Reference
< XCoordinateSystem
> xCoordSystem
, const XclImpChAxis
* pCrossingAxis
) const
3350 // create and attach the axis object
3351 Reference
< XAxis
> xAxis
= CreateAxis( *xChAxis
, pCrossingAxis
);
3354 // create and attach the axis title
3355 if( xChAxisTitle
.is() )
3357 Reference
< XTitled
> xTitled( xAxis
, UNO_QUERY
);
3359 xTitled
->setTitleObject( xChAxisTitle
->CreateTitle() );
3362 // insert axis into coordinate system
3365 sal_Int32 nApiAxisDim
= xChAxis
->GetApiAxisDimension();
3366 sal_Int32 nApiAxesSetIdx
= GetApiAxesSetIndex();
3367 xCoordSystem
->setAxisByDimension( nApiAxisDim
, xAxis
, nApiAxesSetIdx
);
3371 DBG_ERRORFILE( "XclImpChAxesSet::ConvertAxis - cannot set axis" );
3377 Reference
< XAxis
> XclImpChAxesSet::CreateAxis( const XclImpChAxis
& rChAxis
, const XclImpChAxis
* pCrossingAxis
) const
3379 Reference
< XAxis
> xAxis
;
3380 if( const XclImpChTypeGroup
* pTypeGroup
= GetFirstTypeGroup().get() )
3381 xAxis
= rChAxis
.CreateAxis( *pTypeGroup
, pCrossingAxis
);
3385 void XclImpChAxesSet::ConvertBackground( Reference
< XDiagram
> xDiagram
) const
3387 XclImpChTypeGroupRef xTypeGroup
= GetFirstTypeGroup();
3388 if( xTypeGroup
.is() && xTypeGroup
->Is3dWallChart() )
3390 // wall/floor formatting (3D charts)
3393 ScfPropertySet
aWallProp( xDiagram
->getWall() );
3394 mxXAxis
->ConvertWall( aWallProp
);
3398 ScfPropertySet
aFloorProp( xDiagram
->getFloor() );
3399 mxYAxis
->ConvertWall( aFloorProp
);
3402 else if( mxPlotFrame
.is() )
3404 // diagram background formatting
3405 ScfPropertySet
aWallProp( xDiagram
->getWall() );
3406 mxPlotFrame
->Convert( aWallProp
);
3410 // The chart object ===========================================================
3412 XclImpChChart::XclImpChChart( const XclImpRoot
& rRoot
) :
3413 XclImpChRoot( rRoot
, this )
3415 mxPrimAxesSet
.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_PRIMARY
) );
3416 mxSecnAxesSet
.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_SECONDARY
) );
3419 XclImpChChart::~XclImpChChart()
3423 void XclImpChChart::ReadHeaderRecord( XclImpStream
& rStrm
)
3425 // coordinates are stored as 16.16 fixed point
3429 void XclImpChChart::ReadSubRecord( XclImpStream
& rStrm
)
3431 switch( rStrm
.GetRecId() )
3433 case EXC_ID_CHFRAME
:
3434 mxFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND
) );
3435 mxFrame
->ReadRecordGroup( rStrm
);
3437 case EXC_ID_CHSERIES
:
3438 ReadChSeries( rStrm
);
3440 case EXC_ID_CHPROPERTIES
:
3441 ReadChProperties( rStrm
);
3443 case EXC_ID_CHDEFAULTTEXT
:
3444 ReadChDefaultText( rStrm
);
3446 case EXC_ID_CHAXESSET
:
3447 ReadChAxesSet( rStrm
);
3450 ReadChText( rStrm
);
3453 Finalize(); // finalize the entire chart object
3458 void XclImpChChart::ReadChDefaultText( XclImpStream
& rStrm
)
3460 sal_uInt16 nTextId
= rStrm
.ReaduInt16();
3461 if( (rStrm
.GetNextRecId() == EXC_ID_CHTEXT
) && rStrm
.StartNextRecord() )
3463 XclImpChTextRef
xText( new XclImpChText( GetChRoot() ) );
3464 xText
->ReadRecordGroup( rStrm
);
3465 maDefTexts
[ nTextId
] = xText
;
3469 void XclImpChChart::ReadChDataFormat( XclImpStream
& rStrm
)
3471 XclImpChDataFormatRef
xDataFmt( new XclImpChDataFormat( GetChRoot() ) );
3472 xDataFmt
->ReadRecordGroup( rStrm
);
3473 if( xDataFmt
->GetPointPos().mnSeriesIdx
<= EXC_CHSERIES_MAXSERIES
)
3475 XclImpChDataFormatRef
& rxMapFmt
= maDataFmts
[ xDataFmt
->GetPointPos() ];
3476 /* Do not overwrite existing data format group, Excel always uses the
3477 first data format group occuring in any CHSERIES group. */
3479 rxMapFmt
= xDataFmt
;
3483 void XclImpChChart::UpdateObjFrame( const XclObjLineData
& rLineData
, const XclObjFillData
& rFillData
)
3486 mxFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND
) );
3487 mxFrame
->UpdateObjFrame( rLineData
, rFillData
);
3490 XclImpChTypeGroupRef
XclImpChChart::GetTypeGroup( sal_uInt16 nGroupIdx
) const
3492 XclImpChTypeGroupRef xTypeGroup
= mxPrimAxesSet
->GetTypeGroup( nGroupIdx
);
3493 if( !xTypeGroup
) xTypeGroup
= mxSecnAxesSet
->GetTypeGroup( nGroupIdx
);
3494 if( !xTypeGroup
) xTypeGroup
= mxPrimAxesSet
->GetFirstTypeGroup();
3498 XclImpChTextRef
XclImpChChart::GetDefaultText( XclChTextType eTextType
) const
3500 sal_uInt16 nDefTextId
= EXC_CHDEFTEXT_GLOBAL
;
3501 bool bBiff8
= GetBiff() == EXC_BIFF8
;
3504 case EXC_CHTEXTTYPE_TITLE
: nDefTextId
= EXC_CHDEFTEXT_GLOBAL
; break;
3505 case EXC_CHTEXTTYPE_LEGEND
: nDefTextId
= EXC_CHDEFTEXT_GLOBAL
; break;
3506 case EXC_CHTEXTTYPE_AXISTITLE
: nDefTextId
= bBiff8
? EXC_CHDEFTEXT_AXESSET
: EXC_CHDEFTEXT_GLOBAL
; break;
3507 case EXC_CHTEXTTYPE_AXISLABEL
: nDefTextId
= bBiff8
? EXC_CHDEFTEXT_AXESSET
: EXC_CHDEFTEXT_GLOBAL
; break;
3508 case EXC_CHTEXTTYPE_DATALABEL
: nDefTextId
= bBiff8
? EXC_CHDEFTEXT_AXESSET
: EXC_CHDEFTEXT_GLOBAL
; break;
3510 return maDefTexts
.get( nDefTextId
);
3513 void XclImpChChart::Convert( Reference
< XChartDocument
> xChartDoc
, ScfProgressBar
& rProgress
, const OUString
& rObjName
) const
3515 // initialize conversion (locks the model to suppress any internal updates)
3516 InitConversion( xChartDoc
);
3518 // chart frame and title
3521 ScfPropertySet
aFrameProp( xChartDoc
->getPageBackground() );
3522 mxFrame
->Convert( aFrameProp
);
3526 Reference
< XTitled
> xTitled( xChartDoc
, UNO_QUERY
);
3527 Reference
< XTitle
> xTitle
= mxTitle
->CreateTitle();
3528 if( xTitled
.is() && xTitle
.is() )
3529 xTitled
->setTitleObject( xTitle
);
3532 /* Create the diagram object and attach it to the chart document. Currently,
3533 one diagram is used to carry all coordinate systems and data series. */
3534 Reference
< XDiagram
> xDiagram
= CreateDiagram();
3535 xChartDoc
->setFirstDiagram( xDiagram
);
3537 // coordinate systems and chart types, convert axis settings
3538 mxPrimAxesSet
->Convert( xDiagram
);
3539 mxSecnAxesSet
->Convert( xDiagram
);
3542 if( xDiagram
.is() && mxLegend
.is() )
3543 xDiagram
->setLegend( mxLegend
->CreateLegend() );
3545 // set the IncludeHiddenCells property via the old API as only this ensures that the data provider and al created sequences get this flag correctly
3546 Reference
< com::sun::star::chart::XChartDocument
> xStandardApiChartDoc( xChartDoc
, UNO_QUERY
);
3547 if( xStandardApiChartDoc
.is() )
3549 ScfPropertySet
aDiagramProp( xStandardApiChartDoc
->getDiagram() );
3550 bool bShowVisCells
= (maProps
.mnFlags
& EXC_CHPROPS_SHOWVISIBLEONLY
);
3551 aDiagramProp
.SetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS
, !bShowVisCells
);
3555 FinishConversion( rProgress
);
3557 ScDocument
* pDoc
= &GetRoot().GetDoc();
3558 ScChartListenerCollection
* pChartCollection
= pDoc
->GetChartListenerCollection();
3559 if (pChartCollection
)
3561 // Now, start listening to this chart.
3562 ::std::auto_ptr
< vector
<ScSharedTokenRef
> > pRefTokens(new vector
<ScSharedTokenRef
>);
3563 for (XclImpChSeriesVec::const_iterator itr
= maSeries
.begin(), itrEnd
= maSeries
.end(); itr
!= itrEnd
; ++itr
)
3565 const XclImpChSeriesRef
& rSeries
= *itr
;
3566 rSeries
->FillAllSourceLinks(*pRefTokens
);
3568 if (!pRefTokens
->empty())
3570 ::std::auto_ptr
<ScChartListener
> pListener(
3571 new ScChartListener(rObjName
, pDoc
, pRefTokens
.release()));
3572 pListener
->SetDirty(true);
3573 pListener
->StartListeningTo();
3574 pChartCollection
->Insert(pListener
.release());
3580 void XclImpChChart::ReadChSeries( XclImpStream
& rStrm
)
3582 sal_uInt16 nNewSeriesIdx
= static_cast< sal_uInt16
>( maSeries
.size() );
3583 XclImpChSeriesRef
xSeries( new XclImpChSeries( GetChRoot(), nNewSeriesIdx
) );
3584 xSeries
->ReadRecordGroup( rStrm
);
3585 maSeries
.push_back( xSeries
);
3588 void XclImpChChart::ReadChProperties( XclImpStream
& rStrm
)
3590 rStrm
>> maProps
.mnFlags
>> maProps
.mnEmptyMode
;
3593 void XclImpChChart::ReadChAxesSet( XclImpStream
& rStrm
)
3595 XclImpChAxesSetRef
xAxesSet( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_NONE
) );
3596 xAxesSet
->ReadRecordGroup( rStrm
);
3597 switch( xAxesSet
->GetAxesSetId() )
3599 case EXC_CHAXESSET_PRIMARY
: mxPrimAxesSet
= xAxesSet
; break;
3600 case EXC_CHAXESSET_SECONDARY
: mxSecnAxesSet
= xAxesSet
; break;
3604 void XclImpChChart::ReadChText( XclImpStream
& rStrm
)
3606 XclImpChTextRef
xText( new XclImpChText( GetChRoot() ) );
3607 xText
->ReadRecordGroup( rStrm
);
3608 switch( xText
->GetLinkTarget() )
3610 case EXC_CHOBJLINK_TITLE
:
3613 case EXC_CHOBJLINK_DATA
:
3615 sal_uInt16 nSeriesIdx
= xText
->GetPointPos().mnSeriesIdx
;
3616 if( nSeriesIdx
< maSeries
.size() )
3617 maSeries
[ nSeriesIdx
]->SetDataLabel( xText
);
3623 void XclImpChChart::Finalize()
3625 // finalize series (must be done first)
3627 // #i49218# legend may be attached to primary or secondary axes set
3628 mxLegend
= mxPrimAxesSet
->GetLegend();
3630 mxLegend
= mxSecnAxesSet
->GetLegend();
3632 mxLegend
->Finalize();
3633 // axes sets, updates chart type group default formats -> must be called before FinalizeDataFormats()
3634 mxPrimAxesSet
->Finalize();
3635 mxSecnAxesSet
->Finalize();
3636 // formatting of all series
3637 FinalizeDataFormats();
3638 // #i47745# missing frame -> invisible border and area
3640 mxFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND
) );
3645 void XclImpChChart::FinalizeSeries()
3647 for( XclImpChSeriesVec::iterator aSIt
= maSeries
.begin(), aSEnd
= maSeries
.end(); aSIt
!= aSEnd
; ++aSIt
)
3649 XclImpChSeriesRef xSeries
= *aSIt
;
3650 if( xSeries
->HasParentSeries() )
3652 /* Process child series (trend lines and error bars). Data of
3653 child series will be set at the connected parent series. */
3654 if( xSeries
->GetParentIdx() < maSeries
.size() )
3655 maSeries
[ xSeries
->GetParentIdx() ]->AddChildSeries( *xSeries
);
3659 // insert the series into the related chart type group
3660 if( XclImpChTypeGroup
* pTypeGroup
= GetTypeGroup( xSeries
->GetGroupIdx() ).get() )
3661 pTypeGroup
->AddSeries( xSeries
);
3666 void XclImpChChart::FinalizeDataFormats()
3668 /* #i51639# (part 1): CHDATAFORMAT groups are part of CHSERIES groups.
3669 Each CHDATAFORMAT group specifies the series and data point it is
3670 assigned to. This makes it possible to have a data format that is
3671 related to another series, e.g. a CHDATAFORMAT group for series 2 is
3672 part of a CHSERIES group that describes series 1. Therefore the chart
3673 itself has collected all CHDATAFORMAT groups to be able to store data
3674 format groups for series that have not been imported at that time. This
3675 loop finally assigns these groups to the related series. */
3676 for( XclImpChDataFormatMap::const_iterator aMIt
= maDataFmts
.begin(), aMEnd
= maDataFmts
.end(); aMIt
!= aMEnd
; ++aMIt
)
3678 sal_uInt16 nSeriesIdx
= aMIt
->first
.mnSeriesIdx
;
3679 if( nSeriesIdx
< maSeries
.size() )
3680 maSeries
[ nSeriesIdx
]->SetDataFormat( aMIt
->second
);
3683 /* #i51639# (part 2): Finalize data formats of all series. This adds for
3684 example missing CHDATAFORMAT groups for entire series that are needed
3685 for automatic colors of lines and areas. */
3686 for( XclImpChSeriesVec::iterator aVIt
= maSeries
.begin(), aVEnd
= maSeries
.end(); aVIt
!= aVEnd
; ++aVIt
)
3687 (*aVIt
)->FinalizeDataFormats();
3690 void XclImpChChart::FinalizeTitle()
3692 if( (!mxTitle
|| (!mxTitle
->IsDeleted() && !mxTitle
->HasString())) && !mxSecnAxesSet
->IsValidAxesSet() )
3694 /* Chart title is auto-generated from series title, if there is only
3695 one series with title in the chart. */
3696 const String
& rSerTitle
= mxPrimAxesSet
->GetSingleSeriesTitle();
3697 if( rSerTitle
.Len() > 0 )
3700 mxTitle
.reset( new XclImpChText( GetChRoot() ) );
3701 mxTitle
->SetString( rSerTitle
);
3705 // will reset mxTitle, if it does not contain a string
3706 lclFinalizeTitle( mxTitle
, GetDefaultText( EXC_CHTEXTTYPE_TITLE
) );
3709 Reference
< XDiagram
> XclImpChChart::CreateDiagram() const
3711 // create a diagram object
3712 Reference
< XDiagram
> xDiagram( ScfApiHelper::CreateInstance( SERVICE_CHART2_DIAGRAM
), UNO_QUERY
);
3714 // convert global chart settings
3715 ScfPropertySet
aDiaProp( xDiagram
);
3717 // treatment of missing values
3718 using namespace ::com::sun::star::chart::MissingValueTreatment
;
3719 sal_Int32 nMissingValues
= LEAVE_GAP
;
3720 switch( maProps
.mnEmptyMode
)
3722 case EXC_CHPROPS_EMPTY_SKIP
: nMissingValues
= LEAVE_GAP
; break;
3723 case EXC_CHPROPS_EMPTY_ZERO
: nMissingValues
= USE_ZERO
; break;
3724 case EXC_CHPROPS_EMPTY_INTERPOLATE
: nMissingValues
= CONTINUE
; break;
3726 aDiaProp
.SetProperty( EXC_CHPROP_MISSINGVALUETREATMENT
, nMissingValues
);
3731 // ----------------------------------------------------------------------------
3733 XclImpChart::XclImpChart( const XclImpRoot
& rRoot
, bool bOwnTab
) :
3734 XclImpRoot( rRoot
),
3735 mbOwnTab( bOwnTab
),
3736 mbIsPivotChart( false )
3740 void XclImpChart::ReadChartSubStream( XclImpStream
& rStrm
)
3742 XclImpPageSettings
& rPageSett
= GetPageSettings();
3743 XclImpTabViewSettings
& rTabViewSett
= GetTabViewSettings();
3746 while( bLoop
&& rStrm
.StartNextRecord() )
3748 // page settings - only for charts in entire sheet
3749 if( mbOwnTab
) switch( rStrm
.GetRecId() )
3751 case EXC_ID_HORPAGEBREAKS
:
3752 case EXC_ID_VERPAGEBREAKS
: rPageSett
.ReadPageBreaks( rStrm
); break;
3754 case EXC_ID_FOOTER
: rPageSett
.ReadHeaderFooter( rStrm
); break;
3755 case EXC_ID_LEFTMARGIN
:
3756 case EXC_ID_RIGHTMARGIN
:
3757 case EXC_ID_TOPMARGIN
:
3758 case EXC_ID_BOTTOMMARGIN
: rPageSett
.ReadMargin( rStrm
); break;
3759 case EXC_ID_PRINTHEADERS
: rPageSett
.ReadPrintHeaders( rStrm
); break;
3760 case EXC_ID_PRINTGRIDLINES
: rPageSett
.ReadPrintGridLines( rStrm
); break;
3761 case EXC_ID_HCENTER
:
3762 case EXC_ID_VCENTER
: rPageSett
.ReadCenter( rStrm
); break;
3763 case EXC_ID_SETUP
: rPageSett
.ReadSetup( rStrm
); break;
3764 case EXC_ID8_IMGDATA
: rPageSett
.ReadImgData( rStrm
); break;
3766 case EXC_ID_WINDOW2
: rTabViewSett
.ReadWindow2( rStrm
, true );break;
3767 case EXC_ID_SCL
: rTabViewSett
.ReadScl( rStrm
); break;
3768 case EXC_ID_SHEETEXT
: //0x0862
3770 XclImpPalette
& rPal
= GetPalette();
3771 rTabViewSett
.ReadTabBgColor( rStrm
, rPal
);
3776 switch( rStrm
.GetRecId() )
3778 case EXC_ID_EOF
: bLoop
= false; break;
3780 // #i31882# ignore embedded chart objects
3784 case EXC_ID5_BOF
: XclTools::SkipSubStream( rStrm
); break;
3786 case EXC_ID_CHCHART
: ReadChChart( rStrm
); break;
3787 case EXC_ID_OBJ
: GetTracer().TraceChartEmbeddedObj(); break;
3789 case EXC_ID8_CHPIVOTREF
:
3790 GetTracer().TracePivotChartExists();
3791 mbIsPivotChart
= true;
3797 void XclImpChart::UpdateObjFrame( const XclObjLineData
& rLineData
, const XclObjFillData
& rFillData
)
3800 mxChartData
.reset( new XclImpChChart( GetRoot() ) );
3801 mxChartData
->UpdateObjFrame( rLineData
, rFillData
);
3804 sal_Size
XclImpChart::GetProgressSize() const
3806 return mxChartData
.is() ? mxChartData
->GetProgressSize() : 0;
3809 void XclImpChart::Convert( Reference
< XModel
> xModel
, ScfProgressBar
& rProgress
, const OUString
& rObjName
) const
3811 Reference
< XChartDocument
> xChartDoc( xModel
, UNO_QUERY
);
3812 if( mxChartData
.is() && xChartDoc
.is() )
3813 mxChartData
->Convert( xChartDoc
, rProgress
, rObjName
);
3816 void XclImpChart::ReadChChart( XclImpStream
& rStrm
)
3818 mxChartData
.reset( new XclImpChChart( GetRoot() ) );
3819 mxChartData
->ReadRecordGroup( rStrm
);
3822 // ============================================================================