1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "xichart.hxx"
25 #include <com/sun/star/frame/XModel.hpp>
26 #include <com/sun/star/drawing/Direction3D.hpp>
27 #include <com/sun/star/drawing/ProjectionMode.hpp>
28 #include <com/sun/star/drawing/ShadeMode.hpp>
29 #include <com/sun/star/drawing/XShape.hpp>
30 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
31 #include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp>
32 #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
33 #include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
34 #include <com/sun/star/chart/ChartAxisPosition.hpp>
35 #include <com/sun/star/chart/ChartLegendExpansion.hpp>
36 #include <com/sun/star/chart/TimeInterval.hpp>
37 #include <com/sun/star/chart/TimeUnit.hpp>
38 #include <com/sun/star/chart/XChartDocument.hpp>
39 #include <com/sun/star/chart/XDiagramPositioning.hpp>
40 #include <com/sun/star/chart/DataLabelPlacement.hpp>
41 #include <com/sun/star/chart/ErrorBarStyle.hpp>
42 #include <com/sun/star/chart/MissingValueTreatment.hpp>
43 #include <com/sun/star/chart2/CartesianCoordinateSystem2d.hpp>
44 #include <com/sun/star/chart2/CartesianCoordinateSystem3d.hpp>
45 #include <com/sun/star/chart2/FormattedString.hpp>
46 #include <com/sun/star/chart2/LogarithmicScaling.hpp>
47 #include <com/sun/star/chart2/LinearScaling.hpp>
48 #include <com/sun/star/chart2/PolarCoordinateSystem2d.hpp>
49 #include <com/sun/star/chart2/PolarCoordinateSystem3d.hpp>
50 #include <com/sun/star/chart2/XChartDocument.hpp>
51 #include <com/sun/star/chart2/XDiagram.hpp>
52 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
53 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
54 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
55 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
56 #include <com/sun/star/chart2/XTitled.hpp>
57 #include <com/sun/star/chart2/AxisType.hpp>
58 #include <com/sun/star/chart2/CurveStyle.hpp>
59 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
60 #include <com/sun/star/chart2/DataPointLabel.hpp>
61 #include <com/sun/star/chart2/LegendPosition.hpp>
62 #include <com/sun/star/chart2/StackingDirection.hpp>
63 #include <com/sun/star/chart2/TickmarkStyle.hpp>
64 #include <com/sun/star/chart2/RelativePosition.hpp>
65 #include <com/sun/star/chart2/RelativeSize.hpp>
66 #include <com/sun/star/chart2/data/XDataProvider.hpp>
67 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
68 #include <com/sun/star/chart2/data/XDataSink.hpp>
69 #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
71 #include <sfx2/objsh.hxx>
72 #include <svx/svdpage.hxx>
73 #include <svx/unoapi.hxx>
75 #include "document.hxx"
76 #include "drwlayer.hxx"
77 #include "rangeutl.hxx"
78 #include "tokenarray.hxx"
80 #include "compiler.hxx"
81 #include "reftokenhelper.hxx"
82 #include "chartlis.hxx"
83 #include "fprogressbar.hxx"
84 #include "xltracer.hxx"
85 #include "xistream.hxx"
86 #include "xiformula.hxx"
87 #include "xistyle.hxx"
91 using ::com::sun::star::uno::Any
;
92 using ::com::sun::star::uno::Reference
;
93 using ::com::sun::star::uno::Sequence
;
94 using ::com::sun::star::uno::UNO_QUERY
;
95 using ::com::sun::star::uno::UNO_QUERY_THROW
;
96 using ::com::sun::star::uno::UNO_SET_THROW
;
97 using ::com::sun::star::uno::Exception
;
98 using ::com::sun::star::beans::XPropertySet
;
99 using ::com::sun::star::lang::XMultiServiceFactory
;
100 using ::com::sun::star::frame::XModel
;
101 using ::com::sun::star::util::XNumberFormatsSupplier
;
102 using ::com::sun::star::drawing::XDrawPage
;
103 using ::com::sun::star::drawing::XDrawPageSupplier
;
104 using ::com::sun::star::drawing::XShape
;
106 using ::com::sun::star::chart2::IncrementData
;
107 using ::com::sun::star::chart2::RelativePosition
;
108 using ::com::sun::star::chart2::RelativeSize
;
109 using ::com::sun::star::chart2::ScaleData
;
110 using ::com::sun::star::chart2::SubIncrement
;
111 using ::com::sun::star::chart2::XAxis
;
112 using ::com::sun::star::chart2::XChartDocument
;
113 using ::com::sun::star::chart2::XChartType
;
114 using ::com::sun::star::chart2::XChartTypeContainer
;
115 using ::com::sun::star::chart2::XCoordinateSystem
;
116 using ::com::sun::star::chart2::XCoordinateSystemContainer
;
117 using ::com::sun::star::chart2::XDataSeries
;
118 using ::com::sun::star::chart2::XDataSeriesContainer
;
119 using ::com::sun::star::chart2::XDiagram
;
120 using ::com::sun::star::chart2::XFormattedString
;
121 using ::com::sun::star::chart2::XLegend
;
122 using ::com::sun::star::chart2::XRegressionCurve
;
123 using ::com::sun::star::chart2::XRegressionCurveContainer
;
124 using ::com::sun::star::chart2::XScaling
;
125 using ::com::sun::star::chart2::XTitle
;
126 using ::com::sun::star::chart2::XTitled
;
128 using ::com::sun::star::chart2::data::XDataProvider
;
129 using ::com::sun::star::chart2::data::XDataReceiver
;
130 using ::com::sun::star::chart2::data::XDataSequence
;
131 using ::com::sun::star::chart2::data::XDataSink
;
132 using ::com::sun::star::chart2::data::XLabeledDataSequence
;
133 using ::com::sun::star::chart2::data::LabeledDataSequence
;
135 using ::formula::FormulaToken
;
136 using ::formula::StackVar
;
137 using ::boost::shared_ptr
;
139 using ::std::auto_ptr
;
141 namespace cssc
= ::com::sun::star::chart
;
142 namespace cssc2
= ::com::sun::star::chart2
;
144 // Helpers ====================================================================
148 XclImpStream
& operator>>( XclImpStream
& rStrm
, XclChRectangle
& rRect
)
150 return rStrm
>> rRect
.mnX
>> rRect
.mnY
>> rRect
.mnWidth
>> rRect
.mnHeight
;
153 inline void lclSetValueOrClearAny( Any
& rAny
, double fValue
, bool bClear
)
161 void lclSetExpValueOrClearAny( Any
& rAny
, double fValue
, bool bLogScale
, bool bClear
)
163 if( !bClear
&& bLogScale
)
164 fValue
= pow( 10.0, fValue
);
165 lclSetValueOrClearAny( rAny
, fValue
, bClear
);
168 double lclGetSerialDay( const XclImpRoot
& rRoot
, sal_uInt16 nValue
, sal_uInt16 nTimeUnit
)
172 case EXC_CHDATERANGE_DAYS
:
174 case EXC_CHDATERANGE_MONTHS
:
175 return rRoot
.GetDoubleFromDateTime( Date( 1, static_cast< sal_uInt16
>( 1 + nValue
% 12 ), static_cast< sal_uInt16
>( rRoot
.GetBaseYear() + nValue
/ 12 ) ) );
176 case EXC_CHDATERANGE_YEARS
:
177 return rRoot
.GetDoubleFromDateTime( Date( 1, 1, static_cast< sal_uInt16
>( rRoot
.GetBaseYear() + nValue
) ) );
179 OSL_ENSURE( false, "lclGetSerialDay - unexpected time unit" );
184 void lclConvertTimeValue( const XclImpRoot
& rRoot
, Any
& rAny
, sal_uInt16 nValue
, bool bAuto
, sal_uInt16 nTimeUnit
)
189 rAny
<<= lclGetSerialDay( rRoot
, nValue
, nTimeUnit
);
192 sal_Int32
lclGetApiTimeUnit( sal_uInt16 nTimeUnit
)
196 case EXC_CHDATERANGE_DAYS
: return cssc::TimeUnit::DAY
;
197 case EXC_CHDATERANGE_MONTHS
: return cssc::TimeUnit::MONTH
;
198 case EXC_CHDATERANGE_YEARS
: return cssc::TimeUnit::YEAR
;
199 default: OSL_ENSURE( false, "lclGetApiTimeUnit - unexpected time unit" );
201 return cssc::TimeUnit::DAY
;
204 void lclConvertTimeInterval( Any
& rInterval
, sal_uInt16 nValue
, bool bAuto
, sal_uInt16 nTimeUnit
)
206 if( bAuto
|| (nValue
== 0) )
209 rInterval
<<= cssc::TimeInterval( nValue
, lclGetApiTimeUnit( nTimeUnit
) );
214 // Common =====================================================================
216 /** Stores global data needed in various classes of the Chart import filter. */
217 struct XclImpChRootData
: public XclChRootData
219 XclImpChChart
& mrChartData
; /// The chart data object.
221 inline explicit XclImpChRootData( XclImpChChart
& rChartData
) : mrChartData( rChartData
) {}
224 // ----------------------------------------------------------------------------
226 XclImpChRoot::XclImpChRoot( const XclImpRoot
& rRoot
, XclImpChChart
& rChartData
) :
228 mxChData( new XclImpChRootData( rChartData
) )
232 XclImpChRoot::~XclImpChRoot()
236 XclImpChChart
& XclImpChRoot::GetChartData() const
238 return mxChData
->mrChartData
;
241 const XclChTypeInfo
& XclImpChRoot::GetChartTypeInfo( XclChTypeId eType
) const
243 return mxChData
->mxTypeInfoProv
->GetTypeInfo( eType
);
246 const XclChTypeInfo
& XclImpChRoot::GetChartTypeInfo( sal_uInt16 nRecId
) const
248 return mxChData
->mxTypeInfoProv
->GetTypeInfoFromRecId( nRecId
);
251 const XclChFormatInfo
& XclImpChRoot::GetFormatInfo( XclChObjectType eObjType
) const
253 return mxChData
->mxFmtInfoProv
->GetFormatInfo( eObjType
);
256 Color
XclImpChRoot::GetFontAutoColor() const
258 return GetPalette().GetColor( EXC_COLOR_CHWINDOWTEXT
);
261 Color
XclImpChRoot::GetSeriesLineAutoColor( sal_uInt16 nFormatIdx
) const
263 return GetPalette().GetColor( XclChartHelper::GetSeriesLineAutoColorIdx( nFormatIdx
) );
266 Color
XclImpChRoot::GetSeriesFillAutoColor( sal_uInt16 nFormatIdx
) const
268 const XclImpPalette
& rPal
= GetPalette();
269 Color aColor
= rPal
.GetColor( XclChartHelper::GetSeriesFillAutoColorIdx( nFormatIdx
) );
270 sal_uInt8 nTrans
= XclChartHelper::GetSeriesFillAutoTransp( nFormatIdx
);
271 return ScfTools::GetMixedColor( aColor
, rPal
.GetColor( EXC_COLOR_CHWINDOWBACK
), nTrans
);
274 void XclImpChRoot::InitConversion( const Reference
<XChartDocument
>& xChartDoc
, const Rectangle
& rChartRect
) const
276 // create formatting object tables
277 mxChData
->InitConversion( GetRoot(), xChartDoc
, rChartRect
);
279 // lock the model to suppress any internal updates
280 Reference
< XModel
> xModel( xChartDoc
, UNO_QUERY
);
282 xModel
->lockControllers();
284 SfxObjectShell
* pDocShell
= GetDocShell();
285 Reference
< XDataReceiver
> xDataRec( xChartDoc
, UNO_QUERY
);
286 if( pDocShell
&& xDataRec
.is() )
288 // create and register a data provider
289 Reference
< XDataProvider
> xDataProv(
290 ScfApiHelper::CreateInstance( pDocShell
, SERVICE_CHART2_DATAPROVIDER
), UNO_QUERY
);
292 xDataRec
->attachDataProvider( xDataProv
);
293 // attach the number formatter
294 Reference
< XNumberFormatsSupplier
> xNumFmtSupp( pDocShell
->GetModel(), UNO_QUERY
);
295 if( xNumFmtSupp
.is() )
296 xDataRec
->attachNumberFormatsSupplier( xNumFmtSupp
);
300 void XclImpChRoot::FinishConversion( XclImpDffConverter
& rDffConv
) const
302 rDffConv
.Progress( EXC_CHART_PROGRESS_SIZE
);
304 Reference
< XModel
> xModel( mxChData
->mxChartDoc
, UNO_QUERY
);
306 xModel
->unlockControllers();
307 rDffConv
.Progress( EXC_CHART_PROGRESS_SIZE
);
309 mxChData
->FinishConversion();
312 Reference
< XDataProvider
> XclImpChRoot::GetDataProvider() const
314 return mxChData
->mxChartDoc
->getDataProvider();
317 Reference
< XShape
> XclImpChRoot::GetTitleShape( const XclChTextKey
& rTitleKey
) const
319 return mxChData
->GetTitleShape( rTitleKey
);
322 sal_Int32
XclImpChRoot::CalcHmmFromChartX( sal_Int32 nPosX
) const
324 return static_cast< sal_Int32
>( mxChData
->mfUnitSizeX
* nPosX
+ mxChData
->mnBorderGapX
+ 0.5 );
327 sal_Int32
XclImpChRoot::CalcHmmFromChartY( sal_Int32 nPosY
) const
329 return static_cast< sal_Int32
>( mxChData
->mfUnitSizeY
* nPosY
+ mxChData
->mnBorderGapY
+ 0.5 );
332 ::com::sun::star::awt::Rectangle
XclImpChRoot::CalcHmmFromChartRect( const XclChRectangle
& rRect
) const
334 return ::com::sun::star::awt::Rectangle(
335 CalcHmmFromChartX( rRect
.mnX
),
336 CalcHmmFromChartY( rRect
.mnY
),
337 CalcHmmFromChartX( rRect
.mnWidth
),
338 CalcHmmFromChartY( rRect
.mnHeight
) );
341 double XclImpChRoot::CalcRelativeFromHmmX( sal_Int32 nPosX
) const
343 return static_cast< double >( nPosX
) / mxChData
->maChartRect
.GetWidth();
346 double XclImpChRoot::CalcRelativeFromHmmY( sal_Int32 nPosY
) const
348 return static_cast< double >( nPosY
) / mxChData
->maChartRect
.GetHeight();
351 double XclImpChRoot::CalcRelativeFromChartX( sal_Int32 nPosX
) const
353 return CalcRelativeFromHmmX( CalcHmmFromChartX( nPosX
) );
356 double XclImpChRoot::CalcRelativeFromChartY( sal_Int32 nPosY
) const
358 return CalcRelativeFromHmmY( CalcHmmFromChartY( nPosY
) );
361 void XclImpChRoot::ConvertLineFormat( ScfPropertySet
& rPropSet
,
362 const XclChLineFormat
& rLineFmt
, XclChPropertyMode ePropMode
) const
364 GetChartPropSetHelper().WriteLineProperties(
365 rPropSet
, *mxChData
->mxLineDashTable
, rLineFmt
, ePropMode
);
368 void XclImpChRoot::ConvertAreaFormat( ScfPropertySet
& rPropSet
,
369 const XclChAreaFormat
& rAreaFmt
, XclChPropertyMode ePropMode
) const
371 GetChartPropSetHelper().WriteAreaProperties( rPropSet
, rAreaFmt
, ePropMode
);
374 void XclImpChRoot::ConvertEscherFormat( ScfPropertySet
& rPropSet
,
375 const XclChEscherFormat
& rEscherFmt
, const XclChPicFormat
* pPicFmt
,
376 sal_uInt32 nDffFillType
, XclChPropertyMode ePropMode
) const
378 GetChartPropSetHelper().WriteEscherProperties( rPropSet
,
379 *mxChData
->mxGradientTable
, *mxChData
->mxHatchTable
, *mxChData
->mxBitmapTable
,
380 rEscherFmt
, pPicFmt
, nDffFillType
, ePropMode
);
383 void XclImpChRoot::ConvertFont( ScfPropertySet
& rPropSet
,
384 sal_uInt16 nFontIdx
, const Color
* pFontColor
) const
386 GetFontBuffer().WriteFontProperties( rPropSet
, EXC_FONTPROPSET_CHART
, nFontIdx
, pFontColor
);
389 void XclImpChRoot::ConvertPieRotation( ScfPropertySet
& rPropSet
, sal_uInt16 nAngle
)
391 sal_Int32 nApiRot
= (450 - (nAngle
% 360)) % 360;
392 rPropSet
.SetProperty( EXC_CHPROP_STARTINGANGLE
, nApiRot
);
395 // ----------------------------------------------------------------------------
397 XclImpChGroupBase::~XclImpChGroupBase()
401 void XclImpChGroupBase::ReadRecordGroup( XclImpStream
& rStrm
)
403 // read contents of the header record
404 ReadHeaderRecord( rStrm
);
406 // only read sub records, if the next record is a CHBEGIN
407 if( rStrm
.GetNextRecId() == EXC_ID_CHBEGIN
)
409 // read the CHBEGIN record, may be used for special initial processing
410 rStrm
.StartNextRecord();
411 ReadSubRecord( rStrm
);
413 // read the nested records
415 while( bLoop
&& rStrm
.StartNextRecord() )
417 sal_uInt16 nRecId
= rStrm
.GetRecId();
418 bLoop
= nRecId
!= EXC_ID_CHEND
;
419 // skip unsupported nested blocks
420 if( nRecId
== EXC_ID_CHBEGIN
)
423 ReadSubRecord( rStrm
);
426 /* Returns with current CHEND record or unchanged stream, if no record
427 group present. In every case another call to StartNextRecord() will go
428 to next record of interest. */
431 void XclImpChGroupBase::SkipBlock( XclImpStream
& rStrm
)
433 OSL_ENSURE( rStrm
.GetRecId() == EXC_ID_CHBEGIN
, "XclImpChGroupBase::SkipBlock - no CHBEGIN record" );
434 // do nothing if current record is not CHBEGIN
435 bool bLoop
= rStrm
.GetRecId() == EXC_ID_CHBEGIN
;
436 while( bLoop
&& rStrm
.StartNextRecord() )
438 sal_uInt16 nRecId
= rStrm
.GetRecId();
439 bLoop
= nRecId
!= EXC_ID_CHEND
;
440 // skip nested record groups
441 if( nRecId
== EXC_ID_CHBEGIN
)
446 // Frame formatting ===========================================================
448 void XclImpChFramePos::ReadChFramePos( XclImpStream
& rStrm
)
450 rStrm
>> maData
.mnTLMode
>> maData
.mnBRMode
;
451 /* According to the spec, the upper 16 bits of all members in the
452 rectangle are unused and may contain garbage. */
453 maData
.maRect
.mnX
= rStrm
.ReadInt16(); rStrm
.Ignore( 2 );
454 maData
.maRect
.mnY
= rStrm
.ReadInt16(); rStrm
.Ignore( 2 );
455 maData
.maRect
.mnWidth
= rStrm
.ReadInt16(); rStrm
.Ignore( 2 );
456 maData
.maRect
.mnHeight
= rStrm
.ReadInt16(); rStrm
.Ignore( 2 );
459 // ----------------------------------------------------------------------------
461 void XclImpChLineFormat::ReadChLineFormat( XclImpStream
& rStrm
)
463 rStrm
>> maData
.maColor
>> maData
.mnPattern
>> maData
.mnWeight
>> maData
.mnFlags
;
465 const XclImpRoot
& rRoot
= rStrm
.GetRoot();
466 if( rRoot
.GetBiff() == EXC_BIFF8
)
467 // BIFF8: index into palette used instead of RGB data
468 maData
.maColor
= rRoot
.GetPalette().GetColor( rStrm
.ReaduInt16() );
471 void XclImpChLineFormat::Convert( const XclImpChRoot
& rRoot
,
472 ScfPropertySet
& rPropSet
, XclChObjectType eObjType
, sal_uInt16 nFormatIdx
) const
474 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
477 XclChLineFormat aLineFmt
;
478 aLineFmt
.maColor
= (eObjType
== EXC_CHOBJTYPE_LINEARSERIES
) ?
479 rRoot
.GetSeriesLineAutoColor( nFormatIdx
) :
480 rRoot
.GetPalette().GetColor( rFmtInfo
.mnAutoLineColorIdx
);
481 aLineFmt
.mnPattern
= EXC_CHLINEFORMAT_SOLID
;
482 aLineFmt
.mnWeight
= rFmtInfo
.mnAutoLineWeight
;
483 rRoot
.ConvertLineFormat( rPropSet
, aLineFmt
, rFmtInfo
.mePropMode
);
487 rRoot
.ConvertLineFormat( rPropSet
, maData
, rFmtInfo
.mePropMode
);
491 // ----------------------------------------------------------------------------
493 void XclImpChAreaFormat::ReadChAreaFormat( XclImpStream
& rStrm
)
495 rStrm
>> maData
.maPattColor
>> maData
.maBackColor
>> maData
.mnPattern
>> maData
.mnFlags
;
497 const XclImpRoot
& rRoot
= rStrm
.GetRoot();
498 if( rRoot
.GetBiff() == EXC_BIFF8
)
500 // BIFF8: index into palette used instead of RGB data
501 const XclImpPalette
& rPal
= rRoot
.GetPalette();
502 maData
.maPattColor
= rPal
.GetColor( rStrm
.ReaduInt16() );
503 maData
.maBackColor
= rPal
.GetColor( rStrm
.ReaduInt16());
507 void XclImpChAreaFormat::Convert( const XclImpChRoot
& rRoot
,
508 ScfPropertySet
& rPropSet
, XclChObjectType eObjType
, sal_uInt16 nFormatIdx
) const
510 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
513 XclChAreaFormat aAreaFmt
;
514 aAreaFmt
.maPattColor
= (eObjType
== EXC_CHOBJTYPE_FILLEDSERIES
) ?
515 rRoot
.GetSeriesFillAutoColor( nFormatIdx
) :
516 rRoot
.GetPalette().GetColor( rFmtInfo
.mnAutoPattColorIdx
);
517 aAreaFmt
.mnPattern
= EXC_PATT_SOLID
;
518 rRoot
.ConvertAreaFormat( rPropSet
, aAreaFmt
, rFmtInfo
.mePropMode
);
522 rRoot
.ConvertAreaFormat( rPropSet
, maData
, rFmtInfo
.mePropMode
);
526 // ----------------------------------------------------------------------------
528 XclImpChEscherFormat::XclImpChEscherFormat( const XclImpRoot
& rRoot
) :
529 mnDffFillType( mso_fillSolid
)
531 maData
.mxItemSet
.reset(
532 new SfxItemSet( rRoot
.GetDoc().GetDrawLayer()->GetItemPool() ) );
535 void XclImpChEscherFormat::ReadHeaderRecord( XclImpStream
& rStrm
)
537 // read from stream - CHESCHERFORMAT uses own ID for record continuation
538 XclImpDffPropSet
aPropSet( rStrm
.GetRoot() );
539 rStrm
.ResetRecord( true, rStrm
.GetRecId() );
542 aPropSet
.FillToItemSet( *maData
.mxItemSet
);
543 // get fill type from DFF property set
544 mnDffFillType
= aPropSet
.GetPropertyValue( DFF_Prop_fillType
, mso_fillSolid
);
547 void XclImpChEscherFormat::ReadSubRecord( XclImpStream
& rStrm
)
549 switch( rStrm
.GetRecId() )
551 case EXC_ID_CHPICFORMAT
:
552 rStrm
>> maPicFmt
.mnBmpMode
;
554 rStrm
>> maPicFmt
.mnFlags
>> maPicFmt
.mfScale
;
559 void XclImpChEscherFormat::Convert( const XclImpChRoot
& rRoot
,
560 ScfPropertySet
& rPropSet
, XclChObjectType eObjType
, bool bUsePicFmt
) const
562 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
563 rRoot
.ConvertEscherFormat( rPropSet
, maData
, bUsePicFmt
? &maPicFmt
: 0, mnDffFillType
, rFmtInfo
.mePropMode
);
566 // ----------------------------------------------------------------------------
568 XclImpChFrameBase::XclImpChFrameBase( const XclChFormatInfo
& rFmtInfo
)
570 if( rFmtInfo
.mbCreateDefFrame
) switch( rFmtInfo
.meDefFrameType
)
572 case EXC_CHFRAMETYPE_AUTO
:
573 mxLineFmt
.reset( new XclImpChLineFormat
);
574 if( rFmtInfo
.mbIsFrame
)
575 mxAreaFmt
.reset( new XclImpChAreaFormat
);
577 case EXC_CHFRAMETYPE_INVISIBLE
:
579 XclChLineFormat aLineFmt
;
580 ::set_flag( aLineFmt
.mnFlags
, EXC_CHLINEFORMAT_AUTO
, false );
581 aLineFmt
.mnPattern
= EXC_CHLINEFORMAT_NONE
;
582 mxLineFmt
.reset( new XclImpChLineFormat( aLineFmt
) );
583 if( rFmtInfo
.mbIsFrame
)
585 XclChAreaFormat aAreaFmt
;
586 ::set_flag( aAreaFmt
.mnFlags
, EXC_CHAREAFORMAT_AUTO
, false );
587 aAreaFmt
.mnPattern
= EXC_PATT_NONE
;
588 mxAreaFmt
.reset( new XclImpChAreaFormat( aAreaFmt
) );
593 OSL_FAIL( "XclImpChFrameBase::XclImpChFrameBase - unknown frame type" );
597 void XclImpChFrameBase::ReadSubRecord( XclImpStream
& rStrm
)
599 switch( rStrm
.GetRecId() )
601 case EXC_ID_CHLINEFORMAT
:
602 mxLineFmt
.reset( new XclImpChLineFormat
);
603 mxLineFmt
->ReadChLineFormat( rStrm
);
605 case EXC_ID_CHAREAFORMAT
:
606 mxAreaFmt
.reset( new XclImpChAreaFormat
);
607 mxAreaFmt
->ReadChAreaFormat( rStrm
);
609 case EXC_ID_CHESCHERFORMAT
:
610 mxEscherFmt
.reset( new XclImpChEscherFormat( rStrm
.GetRoot() ) );
611 mxEscherFmt
->ReadRecordGroup( rStrm
);
616 void XclImpChFrameBase::ConvertLineBase( const XclImpChRoot
& rRoot
,
617 ScfPropertySet
& rPropSet
, XclChObjectType eObjType
, sal_uInt16 nFormatIdx
) const
620 mxLineFmt
->Convert( rRoot
, rPropSet
, eObjType
, nFormatIdx
);
623 void XclImpChFrameBase::ConvertAreaBase( const XclImpChRoot
& rRoot
,
624 ScfPropertySet
& rPropSet
, XclChObjectType eObjType
, sal_uInt16 nFormatIdx
, bool bUsePicFmt
) const
626 if( rRoot
.GetFormatInfo( eObjType
).mbIsFrame
)
628 // CHESCHERFORMAT overrides CHAREAFORMAT (even if it is auto)
630 mxEscherFmt
->Convert( rRoot
, rPropSet
, eObjType
, bUsePicFmt
);
632 mxAreaFmt
->Convert( rRoot
, rPropSet
, eObjType
, nFormatIdx
);
636 void XclImpChFrameBase::ConvertFrameBase( const XclImpChRoot
& rRoot
,
637 ScfPropertySet
& rPropSet
, XclChObjectType eObjType
, sal_uInt16 nFormatIdx
, bool bUsePicFmt
) const
639 ConvertLineBase( rRoot
, rPropSet
, eObjType
, nFormatIdx
);
640 ConvertAreaBase( rRoot
, rPropSet
, eObjType
, nFormatIdx
, bUsePicFmt
);
643 // ----------------------------------------------------------------------------
645 XclImpChFrame::XclImpChFrame( const XclImpChRoot
& rRoot
, XclChObjectType eObjType
) :
646 XclImpChFrameBase( rRoot
.GetFormatInfo( eObjType
) ),
647 XclImpChRoot( rRoot
),
648 meObjType( eObjType
)
652 void XclImpChFrame::ReadHeaderRecord( XclImpStream
& rStrm
)
654 rStrm
>> maData
.mnFormat
>> maData
.mnFlags
;
657 void XclImpChFrame::UpdateObjFrame( const XclObjLineData
& rLineData
, const XclObjFillData
& rFillData
)
659 const XclImpPalette
& rPal
= GetPalette();
661 if( rLineData
.IsVisible() && (!mxLineFmt
|| !mxLineFmt
->HasLine()) )
664 XclChLineFormat aLineFmt
;
665 aLineFmt
.maColor
= rPal
.GetColor( rLineData
.mnColorIdx
);
666 switch( rLineData
.mnStyle
)
668 case EXC_OBJ_LINE_SOLID
: aLineFmt
.mnPattern
= EXC_CHLINEFORMAT_SOLID
; break;
669 case EXC_OBJ_LINE_DASH
: aLineFmt
.mnPattern
= EXC_CHLINEFORMAT_DASH
; break;
670 case EXC_OBJ_LINE_DOT
: aLineFmt
.mnPattern
= EXC_CHLINEFORMAT_DOT
; break;
671 case EXC_OBJ_LINE_DASHDOT
: aLineFmt
.mnPattern
= EXC_CHLINEFORMAT_DASHDOT
; break;
672 case EXC_OBJ_LINE_DASHDOTDOT
: aLineFmt
.mnPattern
= EXC_CHLINEFORMAT_DASHDOTDOT
; break;
673 case EXC_OBJ_LINE_MEDTRANS
: aLineFmt
.mnPattern
= EXC_CHLINEFORMAT_MEDTRANS
; break;
674 case EXC_OBJ_LINE_DARKTRANS
: aLineFmt
.mnPattern
= EXC_CHLINEFORMAT_DARKTRANS
; break;
675 case EXC_OBJ_LINE_LIGHTTRANS
: aLineFmt
.mnPattern
= EXC_CHLINEFORMAT_LIGHTTRANS
; break;
676 case EXC_OBJ_LINE_NONE
: aLineFmt
.mnPattern
= EXC_CHLINEFORMAT_NONE
; break;
677 default: aLineFmt
.mnPattern
= EXC_CHLINEFORMAT_SOLID
;
679 switch( rLineData
.mnWidth
)
681 case EXC_OBJ_LINE_HAIR
: aLineFmt
.mnWeight
= EXC_CHLINEFORMAT_HAIR
; break;
682 case EXC_OBJ_LINE_THIN
: aLineFmt
.mnWeight
= EXC_CHLINEFORMAT_SINGLE
; break;
683 case EXC_OBJ_LINE_MEDIUM
: aLineFmt
.mnWeight
= EXC_CHLINEFORMAT_DOUBLE
; break;
684 case EXC_OBJ_LINE_THICK
: aLineFmt
.mnWeight
= EXC_CHLINEFORMAT_TRIPLE
; break;
685 default: aLineFmt
.mnWeight
= EXC_CHLINEFORMAT_HAIR
;
687 ::set_flag( aLineFmt
.mnFlags
, EXC_CHLINEFORMAT_AUTO
, rLineData
.IsAuto() );
688 mxLineFmt
.reset( new XclImpChLineFormat( aLineFmt
) );
691 if( rFillData
.IsFilled() && (!mxAreaFmt
|| !mxAreaFmt
->HasArea()) && !mxEscherFmt
)
694 XclChAreaFormat aAreaFmt
;
695 aAreaFmt
.maPattColor
= rPal
.GetColor( rFillData
.mnPattColorIdx
);
696 aAreaFmt
.maBackColor
= rPal
.GetColor( rFillData
.mnBackColorIdx
);
697 aAreaFmt
.mnPattern
= rFillData
.mnPattern
;
698 ::set_flag( aAreaFmt
.mnFlags
, EXC_CHAREAFORMAT_AUTO
, rFillData
.IsAuto() );
699 mxAreaFmt
.reset( new XclImpChAreaFormat( aAreaFmt
) );
703 void XclImpChFrame::Convert( ScfPropertySet
& rPropSet
, bool bUsePicFmt
) const
705 ConvertFrameBase( GetChRoot(), rPropSet
, meObjType
, EXC_CHDATAFORMAT_UNKNOWN
, bUsePicFmt
);
708 // Source links ===============================================================
712 /** Creates a labeled data sequence object, adds link for series title if present. */
713 Reference
< XLabeledDataSequence
> lclCreateLabeledDataSequence(
714 const XclImpChSourceLinkRef
& xValueLink
, const OUString
& rValueRole
,
715 const XclImpChSourceLink
* pTitleLink
= 0 )
717 // create data sequence for values and title
718 Reference
< XDataSequence
> xValueSeq
;
720 xValueSeq
= xValueLink
->CreateDataSequence( rValueRole
);
721 Reference
< XDataSequence
> xTitleSeq
;
723 xTitleSeq
= pTitleLink
->CreateDataSequence( EXC_CHPROP_ROLE_LABEL
);
725 // create the labeled data sequence, if values or title are present
726 Reference
< XLabeledDataSequence
> xLabeledSeq
;
727 if( xValueSeq
.is() || xTitleSeq
.is() )
728 xLabeledSeq
.set( LabeledDataSequence::create(comphelper::getProcessComponentContext()), UNO_QUERY
);
729 if( xLabeledSeq
.is() )
732 xLabeledSeq
->setValues( xValueSeq
);
734 xLabeledSeq
->setLabel( xTitleSeq
);
741 // ----------------------------------------------------------------------------
743 XclImpChSourceLink::XclImpChSourceLink( const XclImpChRoot
& rRoot
) :
744 XclImpChRoot( rRoot
)
748 XclImpChSourceLink::~XclImpChSourceLink()
752 void XclImpChSourceLink::ReadChSourceLink( XclImpStream
& rStrm
)
754 rStrm
>> maData
.mnDestType
757 >> maData
.mnNumFmtIdx
;
759 mxTokenArray
.reset();
760 if( GetLinkType() == EXC_CHSRCLINK_WORKSHEET
)
763 XclTokenArray aXclTokArr
;
766 // convert BIFF formula tokens to Calc token array
767 if( const ScTokenArray
* pTokens
= GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CHART
, aXclTokArr
) )
768 mxTokenArray
.reset( pTokens
->Clone() );
771 // try to read a following CHSTRING record
772 if( (rStrm
.GetNextRecId() == EXC_ID_CHSTRING
) && rStrm
.StartNextRecord() )
774 mxString
.reset( new XclImpString
);
776 mxString
->Read( rStrm
, EXC_STR_8BITLENGTH
| EXC_STR_SEPARATEFORMATS
);
780 void XclImpChSourceLink::SetString( const String
& rString
)
783 mxString
.reset( new XclImpString
);
784 mxString
->SetText( rString
);
787 void XclImpChSourceLink::SetTextFormats( const XclFormatRunVec
& rFormats
)
790 mxString
->SetFormats( rFormats
);
793 sal_uInt16
XclImpChSourceLink::GetCellCount() const
795 sal_uInt32 nCellCount
= 0;
798 mxTokenArray
->Reset();
799 for( const FormulaToken
* pToken
= mxTokenArray
->First(); pToken
; pToken
= mxTokenArray
->Next() )
801 switch( pToken
->GetType() )
803 case ::formula::svSingleRef
:
804 case ::formula::svExternalSingleRef
:
808 case ::formula::svDoubleRef
:
809 case ::formula::svExternalDoubleRef
:
812 const ScComplexRefData
& rComplexRef
= static_cast< const ScToken
* >( pToken
)->GetDoubleRef();
813 const ScSingleRefData
& rRef1
= rComplexRef
.Ref1
;
814 const ScSingleRefData
& rRef2
= rComplexRef
.Ref2
;
815 sal_uInt32 nTabs
= static_cast< sal_uInt32
>( rRef2
.nTab
- rRef1
.nTab
+ 1 );
816 sal_uInt32 nCols
= static_cast< sal_uInt32
>( rRef2
.nCol
- rRef1
.nCol
+ 1 );
817 sal_uInt32 nRows
= static_cast< sal_uInt32
>( rRef2
.nRow
- rRef1
.nRow
+ 1 );
818 nCellCount
+= nCols
* nRows
* nTabs
;
825 return limit_cast
< sal_uInt16
>( nCellCount
);
828 void XclImpChSourceLink::ConvertNumFmt( ScfPropertySet
& rPropSet
, bool bPercent
) const
830 bool bLinkToSource
= ::get_flag( maData
.mnFlags
, EXC_CHSRCLINK_NUMFMT
);
831 sal_uInt32 nScNumFmt
= bLinkToSource
? GetNumFmtBuffer().GetScFormat( maData
.mnNumFmtIdx
) : NUMBERFORMAT_ENTRY_NOT_FOUND
;
832 OUString aPropName
= bPercent
? OUString( EXC_CHPROP_PERCENTAGENUMFMT
) : OUString( EXC_CHPROP_NUMBERFORMAT
);
833 if( nScNumFmt
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
834 rPropSet
.SetProperty( aPropName
, static_cast< sal_Int32
>( nScNumFmt
) );
836 // restore 'link to source' at data point (series may contain manual number format)
837 rPropSet
.SetAnyProperty( aPropName
, Any() );
840 Reference
< XDataSequence
> XclImpChSourceLink::CreateDataSequence( const OUString
& rRole
) const
842 Reference
< XDataSequence
> xDataSeq
;
843 Reference
< XDataProvider
> xDataProv
= GetDataProvider();
844 if( xDataProv
.is() && mxTokenArray
)
846 ScCompiler
aComp( GetDocPtr(), ScAddress(), *mxTokenArray
);
847 aComp
.SetGrammar(GetDoc().GetGrammar());
848 OUStringBuffer aRangeRep
;
849 aComp
.CreateStringFromTokenArray( aRangeRep
);
852 xDataSeq
= xDataProv
->createDataSequenceByRangeRepresentation( aRangeRep
.makeStringAndClear() );
854 ScfPropertySet
aSeqProp( xDataSeq
);
855 aSeqProp
.SetProperty( EXC_CHPROP_ROLE
, rRole
);
859 // OSL_FAIL( "XclImpChSourceLink::CreateDataSequence - cannot create data sequence" );
862 else if( rRole
== EXC_CHPROP_ROLE_LABEL
&& mxString
&& mxString
->GetText().Len() )
866 OUString aString
= OUString::createFromAscii("\"");
867 xDataSeq
= xDataProv
->createDataSequenceByRangeRepresentation( aString
+ mxString
->GetText() + aString
);
869 ScfPropertySet
aSeqProp( xDataSeq
);
870 aSeqProp
.SetProperty( EXC_CHPROP_ROLE
, rRole
);
872 catch( Exception
& ) { }
877 Sequence
< Reference
< XFormattedString
> > XclImpChSourceLink::CreateStringSequence(
878 const XclImpChRoot
& rRoot
, sal_uInt16 nLeadFontIdx
, const Color
& rLeadFontColor
) const
880 ::std::vector
< Reference
< XFormattedString
> > aStringVec
;
883 for( XclImpStringIterator
aIt( *mxString
); aIt
.Is(); ++aIt
)
885 Reference
< css::chart2::XFormattedString2
> xFmtStr
= css::chart2::FormattedString::create( comphelper::getProcessComponentContext() );
887 xFmtStr
->setString( aIt
.GetPortionText() );
889 // set font formatting and font color
890 ScfPropertySet
aStringProp( xFmtStr
);
891 sal_uInt16 nFontIdx
= aIt
.GetPortionFont();
892 if( (nFontIdx
== EXC_FONT_NOTFOUND
) && (aIt
.GetPortionIndex() == 0) )
893 // leading unformatted portion - use passed font settings
894 rRoot
.ConvertFont( aStringProp
, nLeadFontIdx
, &rLeadFontColor
);
896 rRoot
.ConvertFont( aStringProp
, nFontIdx
);
898 // add string to vector of strings
899 aStringVec
.push_back( xFmtStr
);
902 return ScfApiHelper::VectorToSequence( aStringVec
);
905 void XclImpChSourceLink::FillSourceLink( ::std::vector
< ScTokenRef
>& rTokens
) const
911 mxTokenArray
->Reset();
912 for (FormulaToken
* p
= mxTokenArray
->First(); p
; p
= mxTokenArray
->Next())
914 ScTokenRef
pToken(static_cast<ScToken
*>(p
->Clone()));
915 if (ScRefTokenHelper::isRef(pToken
))
916 // This is a reference token. Store it.
917 ScRefTokenHelper::join(rTokens
, pToken
);
921 // Text =======================================================================
923 XclImpChFontBase::~XclImpChFontBase()
927 void XclImpChFontBase::ConvertFontBase( const XclImpChRoot
& rRoot
, ScfPropertySet
& rPropSet
) const
929 Color aFontColor
= GetFontColor();
930 rRoot
.ConvertFont( rPropSet
, GetFontIndex(), &aFontColor
);
933 void XclImpChFontBase::ConvertRotationBase( const XclImpChRoot
& rRoot
, ScfPropertySet
& rPropSet
, bool bSupportsStacked
) const
935 rRoot
.GetChartPropSetHelper().WriteRotationProperties( rPropSet
, GetRotation(), bSupportsStacked
);
938 // ----------------------------------------------------------------------------
940 XclImpChFont::XclImpChFont() :
941 mnFontIdx( EXC_FONT_NOTFOUND
)
945 void XclImpChFont::ReadChFont( XclImpStream
& rStrm
)
950 // ----------------------------------------------------------------------------
952 XclImpChText::XclImpChText( const XclImpChRoot
& rRoot
) :
953 XclImpChRoot( rRoot
)
957 void XclImpChText::ReadHeaderRecord( XclImpStream
& rStrm
)
959 rStrm
>> maData
.mnHAlign
962 >> maData
.maTextColor
966 if( GetBiff() == EXC_BIFF8
)
968 // BIFF8: index into palette used instead of RGB data
969 maData
.maTextColor
= GetPalette().GetColor( rStrm
.ReaduInt16() );
970 // placement and rotation
971 rStrm
>> maData
.mnFlags2
>> maData
.mnRotation
;
975 // BIFF2-BIFF7: get rotation from text orientation
976 sal_uInt8 nOrient
= ::extract_value
< sal_uInt8
>( maData
.mnFlags
, 8, 3 );
977 maData
.mnRotation
= XclTools::GetXclRotFromOrient( nOrient
);
981 void XclImpChText::ReadSubRecord( XclImpStream
& rStrm
)
983 switch( rStrm
.GetRecId() )
985 case EXC_ID_CHFRAMEPOS
:
986 mxFramePos
.reset( new XclImpChFramePos
);
987 mxFramePos
->ReadChFramePos( rStrm
);
990 mxFont
.reset( new XclImpChFont
);
991 mxFont
->ReadChFont( rStrm
);
993 case EXC_ID_CHFORMATRUNS
:
994 if( GetBiff() == EXC_BIFF8
)
995 XclImpString::ReadFormats( rStrm
, maFormats
);
997 case EXC_ID_CHSOURCELINK
:
998 mxSrcLink
.reset( new XclImpChSourceLink( GetChRoot() ) );
999 mxSrcLink
->ReadChSourceLink( rStrm
);
1001 case EXC_ID_CHFRAME
:
1002 mxFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_TEXT
) );
1003 mxFrame
->ReadRecordGroup( rStrm
);
1005 case EXC_ID_CHOBJECTLINK
:
1006 rStrm
>> maObjLink
.mnTarget
>> maObjLink
.maPointPos
.mnSeriesIdx
>> maObjLink
.maPointPos
.mnPointIdx
;
1008 case EXC_ID_CHFRLABELPROPS
:
1009 ReadChFrLabelProps( rStrm
);
1012 if( mxSrcLink
&& !maFormats
.empty() )
1013 mxSrcLink
->SetTextFormats( maFormats
);
1018 sal_uInt16
XclImpChText::GetFontIndex() const
1020 return mxFont
? mxFont
->GetFontIndex() : EXC_FONT_NOTFOUND
;
1023 Color
XclImpChText::GetFontColor() const
1025 return ::get_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOCOLOR
) ? GetFontAutoColor() : maData
.maTextColor
;
1028 sal_uInt16
XclImpChText::GetRotation() const
1030 return maData
.mnRotation
;
1033 void XclImpChText::SetString( const String
& rString
)
1036 mxSrcLink
.reset( new XclImpChSourceLink( GetChRoot() ) );
1037 mxSrcLink
->SetString( rString
);
1040 void XclImpChText::UpdateText( const XclImpChText
* pParentText
)
1044 // update missing members
1046 mxFrame
= pParentText
->mxFrame
;
1049 mxFont
= pParentText
->mxFont
;
1050 // text color is taken from CHTEXT record, not from font in CHFONT
1051 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOCOLOR
, ::get_flag( pParentText
->maData
.mnFlags
, EXC_CHTEXT_AUTOCOLOR
) );
1052 maData
.maTextColor
= pParentText
->maData
.maTextColor
;
1057 void XclImpChText::UpdateDataLabel( bool bCateg
, bool bValue
, bool bPercent
)
1059 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
, bCateg
);
1060 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWVALUE
, bValue
);
1061 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWPERCENT
, bPercent
);
1062 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEGPERC
, bCateg
&& bPercent
);
1063 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_DELETED
, !bCateg
&& !bValue
&& !bPercent
);
1066 void XclImpChText::ConvertFont( ScfPropertySet
& rPropSet
) const
1068 ConvertFontBase( GetChRoot(), rPropSet
);
1071 void XclImpChText::ConvertRotation( ScfPropertySet
& rPropSet
, bool bSupportsStacked
) const
1073 ConvertRotationBase( GetChRoot(), rPropSet
, bSupportsStacked
);
1076 void XclImpChText::ConvertFrame( ScfPropertySet
& rPropSet
) const
1079 mxFrame
->Convert( rPropSet
);
1082 void XclImpChText::ConvertNumFmt( ScfPropertySet
& rPropSet
, bool bPercent
) const
1085 mxSrcLink
->ConvertNumFmt( rPropSet
, bPercent
);
1088 void XclImpChText::ConvertDataLabel( ScfPropertySet
& rPropSet
, const XclChTypeInfo
& rTypeInfo
) const
1090 // existing CHFRLABELPROPS record wins over flags from CHTEXT
1091 sal_uInt16 nShowFlags
= mxLabelProps
? mxLabelProps
->mnFlags
: maData
.mnFlags
;
1092 sal_uInt16 SHOWANYCATEG
= mxLabelProps
? EXC_CHFRLABELPROPS_SHOWCATEG
: (EXC_CHTEXT_SHOWCATEGPERC
| EXC_CHTEXT_SHOWCATEG
);
1093 sal_uInt16 SHOWANYVALUE
= mxLabelProps
? EXC_CHFRLABELPROPS_SHOWVALUE
: EXC_CHTEXT_SHOWVALUE
;
1094 sal_uInt16 SHOWANYPERCENT
= mxLabelProps
? EXC_CHFRLABELPROPS_SHOWPERCENT
: (EXC_CHTEXT_SHOWPERCENT
| EXC_CHTEXT_SHOWCATEGPERC
);
1095 sal_uInt16 SHOWANYBUBBLE
= mxLabelProps
? EXC_CHFRLABELPROPS_SHOWBUBBLE
: EXC_CHTEXT_SHOWBUBBLE
;
1097 // get raw flags for label values
1098 bool bShowNone
= IsDeleted();
1099 bool bShowCateg
= !bShowNone
&& ::get_flag( nShowFlags
, SHOWANYCATEG
);
1100 bool bShowPercent
= !bShowNone
&& ::get_flag( nShowFlags
, SHOWANYPERCENT
);
1101 bool bShowValue
= !bShowNone
&& ::get_flag( nShowFlags
, SHOWANYVALUE
);
1102 bool bShowBubble
= !bShowNone
&& ::get_flag( nShowFlags
, SHOWANYBUBBLE
);
1104 // adjust to Chart2 behaviour
1105 if( rTypeInfo
.meTypeId
== EXC_CHTYPEID_BUBBLES
)
1106 bShowValue
= bShowBubble
; // Chart2 bubble charts show bubble size if 'ShowValue' is set
1109 bool bShowAny
= bShowValue
|| bShowPercent
|| bShowCateg
;
1110 bool bShowSymbol
= bShowAny
&& ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWSYMBOL
);
1112 // create API struct for label values, set API label separator
1113 cssc2::DataPointLabel
aPointLabel( bShowValue
, bShowPercent
, bShowCateg
, bShowSymbol
);
1114 rPropSet
.SetProperty( EXC_CHPROP_LABEL
, aPointLabel
);
1115 String aSep
= mxLabelProps
? mxLabelProps
->maSeparator
: OUString('\n');
1116 if( aSep
.Len() == 0 )
1118 rPropSet
.SetStringProperty( EXC_CHPROP_LABELSEPARATOR
, aSep
);
1120 // text properties of attached label
1123 ConvertFont( rPropSet
);
1124 ConvertRotation( rPropSet
, false );
1126 using namespace cssc::DataLabelPlacement
;
1127 sal_Int32 nPlacement
= rTypeInfo
.mnDefaultLabelPos
;
1128 switch( ::extract_value
< sal_uInt16
>( maData
.mnFlags2
, 0, 4 ) )
1130 case EXC_CHTEXT_POS_DEFAULT
: nPlacement
= rTypeInfo
.mnDefaultLabelPos
; break;
1131 case EXC_CHTEXT_POS_OUTSIDE
: nPlacement
= OUTSIDE
; break;
1132 case EXC_CHTEXT_POS_INSIDE
: nPlacement
= INSIDE
; break;
1133 case EXC_CHTEXT_POS_CENTER
: nPlacement
= CENTER
; break;
1134 case EXC_CHTEXT_POS_AXIS
: nPlacement
= NEAR_ORIGIN
; break;
1135 case EXC_CHTEXT_POS_ABOVE
: nPlacement
= TOP
; break;
1136 case EXC_CHTEXT_POS_BELOW
: nPlacement
= BOTTOM
; break;
1137 case EXC_CHTEXT_POS_LEFT
: nPlacement
= LEFT
; break;
1138 case EXC_CHTEXT_POS_RIGHT
: nPlacement
= RIGHT
; break;
1139 case EXC_CHTEXT_POS_AUTO
: nPlacement
= AVOID_OVERLAP
; break;
1141 rPropSet
.SetProperty( EXC_CHPROP_LABELPLACEMENT
, nPlacement
);
1142 // label number format (percentage format wins over value format)
1143 if( bShowPercent
|| bShowValue
)
1144 ConvertNumFmt( rPropSet
, bShowPercent
);
1148 Reference
< XTitle
> XclImpChText::CreateTitle() const
1150 Reference
< XTitle
> xTitle
;
1151 if( mxSrcLink
&& mxSrcLink
->HasString() )
1153 // create the formatted strings
1154 Sequence
< Reference
< XFormattedString
> > aStringSeq(
1155 mxSrcLink
->CreateStringSequence( GetChRoot(), GetFontIndex(), GetFontColor() ) );
1156 if( aStringSeq
.hasElements() )
1158 // create the title object
1159 xTitle
.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_TITLE
), UNO_QUERY
);
1162 // set the formatted strings
1163 xTitle
->setText( aStringSeq
);
1164 // more title formatting properties
1165 ScfPropertySet
aTitleProp( xTitle
);
1166 ConvertFrame( aTitleProp
);
1167 ConvertRotation( aTitleProp
, true );
1174 void XclImpChText::ConvertTitlePosition( const XclChTextKey
& rTitleKey
) const
1176 if( !mxFramePos
) return;
1178 const XclChFramePos
& rPosData
= mxFramePos
->GetFramePosData();
1179 OSL_ENSURE( (rPosData
.mnTLMode
== EXC_CHFRAMEPOS_PARENT
) && (rPosData
.mnBRMode
== EXC_CHFRAMEPOS_PARENT
),
1180 "XclImpChText::ConvertTitlePosition - unexpected frame position mode" );
1182 /* Check if title is moved manually. To get the actual position of the
1183 title, we do some kind of hack and use the values from the CHTEXT
1184 record, effectively ignoring the contents of the CHFRAMEPOS record
1185 which contains the position relative to the default title position
1186 (according to the spec, the CHFRAMEPOS supersedes the CHTEXT record).
1187 Especially when it comes to axis titles, things would become very
1188 complicated here, because the relative title position is stored in a
1189 measurement unit that is dependent on the size of the inner plot area,
1190 the interpretation of the X and Y coordinate is dependent on the
1191 direction of the axis, and in 3D charts, and the title default
1192 positions are dependent on the 3D view settings (rotation, elevation,
1193 and perspective). Thus, it is easier to assume that the creator has
1194 written out the correct absolute position and size of the title in the
1195 CHTEXT record. This is assured by checking that the shape size stored
1196 in the CHTEXT record is non-zero. */
1197 if( (rPosData
.mnTLMode
== EXC_CHFRAMEPOS_PARENT
) &&
1198 ((rPosData
.maRect
.mnX
!= 0) || (rPosData
.maRect
.mnY
!= 0)) &&
1199 (maData
.maRect
.mnWidth
> 0) && (maData
.maRect
.mnHeight
> 0) ) try
1201 Reference
< XShape
> xTitleShape( GetTitleShape( rTitleKey
), UNO_SET_THROW
);
1202 // the call to XShape.getSize() may recalc the chart view
1203 ::com::sun::star::awt::Size aTitleSize
= xTitleShape
->getSize();
1204 // rotated titles need special handling...
1205 sal_Int32 nScRot
= XclTools::GetScRotation( GetRotation(), 0 );
1206 double fRad
= nScRot
* F_PI18000
;
1207 double fSin
= fabs( sin( fRad
) );
1208 double fCos
= fabs( cos( fRad
) );
1209 ::com::sun::star::awt::Size
aBoundSize(
1210 static_cast< sal_Int32
>( fCos
* aTitleSize
.Width
+ fSin
* aTitleSize
.Height
+ 0.5 ),
1211 static_cast< sal_Int32
>( fSin
* aTitleSize
.Width
+ fCos
* aTitleSize
.Height
+ 0.5 ) );
1212 // calculate the title position from the values in the CHTEXT record
1213 ::com::sun::star::awt::Point
aTitlePos(
1214 CalcHmmFromChartX( maData
.maRect
.mnX
),
1215 CalcHmmFromChartY( maData
.maRect
.mnY
) );
1216 // add part of height to X direction, if title is rotated down (clockwise)
1217 if( nScRot
> 18000 )
1218 aTitlePos
.X
+= static_cast< sal_Int32
>( fSin
* aTitleSize
.Height
+ 0.5 );
1219 // add part of width to Y direction, if title is rotated up (counterclockwise)
1220 else if( nScRot
> 0 )
1221 aTitlePos
.Y
+= static_cast< sal_Int32
>( fSin
* aTitleSize
.Width
+ 0.5 );
1222 // set the resulting position at the title shape
1223 xTitleShape
->setPosition( aTitlePos
);
1230 void XclImpChText::ReadChFrLabelProps( XclImpStream
& rStrm
)
1232 if( GetBiff() == EXC_BIFF8
)
1234 mxLabelProps
.reset( new XclChFrLabelProps
);
1237 rStrm
>> mxLabelProps
->mnFlags
>> nSepLen
;
1239 mxLabelProps
->maSeparator
= rStrm
.ReadUniString( nSepLen
);
1245 void lclUpdateText( XclImpChTextRef
& rxText
, const XclImpChText
* xDefText
)
1248 rxText
->UpdateText( xDefText
);
1251 XclImpChTextRef
xNew(new XclImpChText(*xDefText
));
1256 void lclFinalizeTitle( XclImpChTextRef
& rxTitle
, const XclImpChText
* pDefText
, const String
& rAutoTitle
)
1258 /* Do not update a title, if it is not visible (if rxTitle is null).
1259 Existing reference indicates enabled title. */
1262 if( !rxTitle
->HasString() )
1263 rxTitle
->SetString( rAutoTitle
);
1264 if( rxTitle
->HasString() )
1265 rxTitle
->UpdateText(pDefText
);
1273 // Data series ================================================================
1275 void XclImpChMarkerFormat::ReadChMarkerFormat( XclImpStream
& rStrm
)
1277 rStrm
>> maData
.maLineColor
>> maData
.maFillColor
>> maData
.mnMarkerType
>> maData
.mnFlags
;
1279 const XclImpRoot
& rRoot
= rStrm
.GetRoot();
1280 if( rRoot
.GetBiff() == EXC_BIFF8
)
1282 // BIFF8: index into palette used instead of RGB data
1283 const XclImpPalette
& rPal
= rRoot
.GetPalette();
1284 maData
.maLineColor
= rPal
.GetColor( rStrm
.ReaduInt16() );
1285 maData
.maFillColor
= rPal
.GetColor( rStrm
.ReaduInt16() );
1287 rStrm
>> maData
.mnMarkerSize
;
1291 void XclImpChMarkerFormat::Convert( const XclImpChRoot
& rRoot
,
1292 ScfPropertySet
& rPropSet
, sal_uInt16 nFormatIdx
, sal_Int16 nLineWeight
) const
1296 XclChMarkerFormat aMarkerFmt
;
1297 // line and fill color of the symbol are equal to series line color
1298 //! TODO: Excel sets no fill color for specific symbols (e.g. cross)
1299 aMarkerFmt
.maLineColor
= aMarkerFmt
.maFillColor
= rRoot
.GetSeriesLineAutoColor( nFormatIdx
);
1300 switch( nLineWeight
)
1302 case EXC_CHLINEFORMAT_HAIR
: aMarkerFmt
.mnMarkerSize
= EXC_CHMARKERFORMAT_HAIRSIZE
; break;
1303 case EXC_CHLINEFORMAT_SINGLE
: aMarkerFmt
.mnMarkerSize
= EXC_CHMARKERFORMAT_SINGLESIZE
; break;
1304 case EXC_CHLINEFORMAT_DOUBLE
: aMarkerFmt
.mnMarkerSize
= EXC_CHMARKERFORMAT_DOUBLESIZE
; break;
1305 case EXC_CHLINEFORMAT_TRIPLE
: aMarkerFmt
.mnMarkerSize
= EXC_CHMARKERFORMAT_TRIPLESIZE
; break;
1306 default: aMarkerFmt
.mnMarkerSize
= EXC_CHMARKERFORMAT_SINGLESIZE
;
1308 aMarkerFmt
.mnMarkerType
= XclChartHelper::GetAutoMarkerType( nFormatIdx
);
1309 rRoot
.GetChartPropSetHelper().WriteMarkerProperties( rPropSet
, aMarkerFmt
);
1313 rRoot
.GetChartPropSetHelper().WriteMarkerProperties( rPropSet
, maData
);
1317 void XclImpChMarkerFormat::ConvertColor( const XclImpChRoot
& rRoot
,
1318 ScfPropertySet
& rPropSet
, sal_uInt16 nFormatIdx
) const
1320 Color aLineColor
= IsAuto() ? rRoot
.GetSeriesLineAutoColor( nFormatIdx
) : maData
.maFillColor
;
1321 rPropSet
.SetColorProperty( EXC_CHPROP_COLOR
, aLineColor
);
1324 // ----------------------------------------------------------------------------
1326 XclImpChPieFormat::XclImpChPieFormat() :
1331 void XclImpChPieFormat::ReadChPieFormat( XclImpStream
& rStrm
)
1336 void XclImpChPieFormat::Convert( ScfPropertySet
& rPropSet
) const
1338 double fApiDist
= ::std::min
< double >( mnPieDist
/ 100.0, 1.0 );
1339 rPropSet
.SetProperty( EXC_CHPROP_OFFSET
, fApiDist
);
1342 // ----------------------------------------------------------------------------
1344 XclImpChSeriesFormat::XclImpChSeriesFormat() :
1349 void XclImpChSeriesFormat::ReadChSeriesFormat( XclImpStream
& rStrm
)
1354 // ----------------------------------------------------------------------------
1356 void XclImpCh3dDataFormat::ReadCh3dDataFormat( XclImpStream
& rStrm
)
1358 rStrm
>> maData
.mnBase
>> maData
.mnTop
;
1361 void XclImpCh3dDataFormat::Convert( ScfPropertySet
& rPropSet
) const
1363 using namespace ::com::sun::star::chart2::DataPointGeometry3D
;
1364 sal_Int32 nApiType
= (maData
.mnBase
== EXC_CH3DDATAFORMAT_RECT
) ?
1365 ((maData
.mnTop
== EXC_CH3DDATAFORMAT_STRAIGHT
) ? CUBOID
: PYRAMID
) :
1366 ((maData
.mnTop
== EXC_CH3DDATAFORMAT_STRAIGHT
) ? CYLINDER
: CONE
);
1367 rPropSet
.SetProperty( EXC_CHPROP_GEOMETRY3D
, nApiType
);
1370 // ----------------------------------------------------------------------------
1372 XclImpChAttachedLabel::XclImpChAttachedLabel( const XclImpChRoot
& rRoot
) :
1373 XclImpChRoot( rRoot
),
1378 void XclImpChAttachedLabel::ReadChAttachedLabel( XclImpStream
& rStrm
)
1383 XclImpChTextRef
XclImpChAttachedLabel::CreateDataLabel( const XclImpChText
* pParent
) const
1385 const sal_uInt16 EXC_CHATTLABEL_SHOWANYVALUE
= EXC_CHATTLABEL_SHOWVALUE
;
1386 const sal_uInt16 EXC_CHATTLABEL_SHOWANYPERCENT
= EXC_CHATTLABEL_SHOWPERCENT
| EXC_CHATTLABEL_SHOWCATEGPERC
;
1387 const sal_uInt16 EXC_CHATTLABEL_SHOWANYCATEG
= EXC_CHATTLABEL_SHOWCATEG
| EXC_CHATTLABEL_SHOWCATEGPERC
;
1389 XclImpChTextRef
xLabel( pParent
? new XclImpChText( *pParent
) : new XclImpChText( GetChRoot() ) );
1390 xLabel
->UpdateDataLabel(
1391 ::get_flag( mnFlags
, EXC_CHATTLABEL_SHOWANYCATEG
),
1392 ::get_flag( mnFlags
, EXC_CHATTLABEL_SHOWANYVALUE
),
1393 ::get_flag( mnFlags
, EXC_CHATTLABEL_SHOWANYPERCENT
) );
1397 // ----------------------------------------------------------------------------
1399 XclImpChDataFormat::XclImpChDataFormat( const XclImpChRoot
& rRoot
) :
1400 XclImpChRoot( rRoot
)
1404 void XclImpChDataFormat::ReadHeaderRecord( XclImpStream
& rStrm
)
1406 rStrm
>> maData
.maPointPos
.mnPointIdx
1407 >> maData
.maPointPos
.mnSeriesIdx
1408 >> maData
.mnFormatIdx
1412 void XclImpChDataFormat::ReadSubRecord( XclImpStream
& rStrm
)
1414 switch( rStrm
.GetRecId() )
1416 case EXC_ID_CHMARKERFORMAT
:
1417 mxMarkerFmt
.reset( new XclImpChMarkerFormat
);
1418 mxMarkerFmt
->ReadChMarkerFormat( rStrm
);
1420 case EXC_ID_CHPIEFORMAT
:
1421 mxPieFmt
.reset( new XclImpChPieFormat
);
1422 mxPieFmt
->ReadChPieFormat( rStrm
);
1424 case EXC_ID_CHSERIESFORMAT
:
1425 mxSeriesFmt
.reset( new XclImpChSeriesFormat
);
1426 mxSeriesFmt
->ReadChSeriesFormat( rStrm
);
1428 case EXC_ID_CH3DDATAFORMAT
:
1429 mx3dDataFmt
.reset( new XclImpCh3dDataFormat
);
1430 mx3dDataFmt
->ReadCh3dDataFormat( rStrm
);
1432 case EXC_ID_CHATTACHEDLABEL
:
1433 mxAttLabel
.reset( new XclImpChAttachedLabel( GetChRoot() ) );
1434 mxAttLabel
->ReadChAttachedLabel( rStrm
);
1437 XclImpChFrameBase::ReadSubRecord( rStrm
);
1441 void XclImpChDataFormat::SetPointPos( const XclChDataPointPos
& rPointPos
, sal_uInt16 nFormatIdx
)
1443 maData
.maPointPos
= rPointPos
;
1444 maData
.mnFormatIdx
= nFormatIdx
;
1447 void XclImpChDataFormat::UpdateGroupFormat( const XclChExtTypeInfo
& rTypeInfo
)
1449 // remove formats not used for the current chart type
1450 RemoveUnusedFormats( rTypeInfo
);
1453 void XclImpChDataFormat::UpdateSeriesFormat( const XclChExtTypeInfo
& rTypeInfo
, const XclImpChDataFormat
* pGroupFmt
)
1455 // update missing formats from passed chart type group format
1459 mxLineFmt
= pGroupFmt
->mxLineFmt
;
1460 if( !mxAreaFmt
&& !mxEscherFmt
)
1462 mxAreaFmt
= pGroupFmt
->mxAreaFmt
;
1463 mxEscherFmt
= pGroupFmt
->mxEscherFmt
;
1466 mxMarkerFmt
= pGroupFmt
->mxMarkerFmt
;
1468 mxPieFmt
= pGroupFmt
->mxPieFmt
;
1470 mxSeriesFmt
= pGroupFmt
->mxSeriesFmt
;
1472 mx3dDataFmt
= pGroupFmt
->mx3dDataFmt
;
1474 mxAttLabel
= pGroupFmt
->mxAttLabel
;
1477 /* Create missing but required formats. Existing line, area, and marker
1478 format objects are needed to create automatic series formatting. */
1480 mxLineFmt
.reset( new XclImpChLineFormat
);
1481 if( !mxAreaFmt
&& !mxEscherFmt
)
1482 mxAreaFmt
.reset( new XclImpChAreaFormat
);
1484 mxMarkerFmt
.reset( new XclImpChMarkerFormat
);
1486 // remove formats not used for the current chart type
1487 RemoveUnusedFormats( rTypeInfo
);
1488 // update data label
1489 UpdateDataLabel( pGroupFmt
);
1492 void XclImpChDataFormat::UpdatePointFormat( const XclChExtTypeInfo
& rTypeInfo
, const XclImpChDataFormat
* pSeriesFmt
)
1494 // remove formats if they are automatic in this and in the passed series format
1497 if( IsAutoLine() && pSeriesFmt
->IsAutoLine() )
1499 if( IsAutoArea() && pSeriesFmt
->IsAutoArea() )
1501 if( IsAutoMarker() && pSeriesFmt
->IsAutoMarker() )
1502 mxMarkerFmt
.reset();
1503 mxSeriesFmt
.reset();
1506 // Excel ignores 3D bar format for single data points
1507 mx3dDataFmt
.reset();
1508 // remove point line formats for linear chart types, TODO: implement in OOChart
1509 if( !rTypeInfo
.IsSeriesFrameFormat() )
1512 // remove formats not used for the current chart type
1513 RemoveUnusedFormats( rTypeInfo
);
1514 // update data label
1515 UpdateDataLabel( pSeriesFmt
);
1518 void XclImpChDataFormat::UpdateTrendLineFormat()
1521 mxLineFmt
.reset( new XclImpChLineFormat
);
1523 mxEscherFmt
.reset();
1524 mxMarkerFmt
.reset();
1526 mxSeriesFmt
.reset();
1527 mx3dDataFmt
.reset();
1529 // update data label
1530 UpdateDataLabel( 0 );
1533 void XclImpChDataFormat::Convert( ScfPropertySet
& rPropSet
, const XclChExtTypeInfo
& rTypeInfo
) const
1535 /* Line and area format.
1536 #i71810# If the data points are filled with bitmaps, textures, or
1537 patterns, then only bar charts will use the CHPICFORMAT record to
1538 determine stacking/streching mode. All other chart types ignore this
1539 record and always use the property 'fill-type' from the DFF property
1540 set (streched for bitmaps, and stacked for textures and patterns). */
1541 bool bUsePicFmt
= rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_BAR
;
1542 ConvertFrameBase( GetChRoot(), rPropSet
, rTypeInfo
.GetSeriesObjectType(), maData
.mnFormatIdx
, bUsePicFmt
);
1544 #if EXC_CHART2_3DBAR_HAIRLINES_ONLY
1545 // #i83151# only hair lines in 3D charts with filled data points
1546 if( rTypeInfo
.mb3dChart
&& rTypeInfo
.IsSeriesFrameFormat() && mxLineFmt
&& mxLineFmt
->HasLine() )
1547 rPropSet
.SetProperty
< sal_Int32
>( "BorderWidth", 0 );
1552 mxMarkerFmt
->Convert( GetChRoot(), rPropSet
, maData
.mnFormatIdx
, GetLineWeight() );
1554 mxPieFmt
->Convert( rPropSet
);
1556 mx3dDataFmt
->Convert( rPropSet
);
1558 mxLabel
->ConvertDataLabel( rPropSet
, rTypeInfo
);
1561 rPropSet
.SetProperty
< sal_Int16
>( EXC_CHPROP_PERCENTDIAGONAL
, 0 );
1563 /* Special case: set marker color as line color, if series line is not
1564 visible. This makes the color visible in the marker area.
1565 TODO: remove this if OOChart supports own colors in markers. */
1566 if( !rTypeInfo
.IsSeriesFrameFormat() && !HasLine() && mxMarkerFmt
)
1567 mxMarkerFmt
->ConvertColor( GetChRoot(), rPropSet
, maData
.mnFormatIdx
);
1570 void XclImpChDataFormat::ConvertLine( ScfPropertySet
& rPropSet
, XclChObjectType eObjType
) const
1572 ConvertLineBase( GetChRoot(), rPropSet
, eObjType
);
1575 void XclImpChDataFormat::ConvertArea( ScfPropertySet
& rPropSet
, sal_uInt16 nFormatIdx
, bool bUsePicFmt
) const
1577 ConvertAreaBase( GetChRoot(), rPropSet
, EXC_CHOBJTYPE_FILLEDSERIES
, nFormatIdx
, bUsePicFmt
);
1580 void XclImpChDataFormat::RemoveUnusedFormats( const XclChExtTypeInfo
& rTypeInfo
)
1582 // data point marker only in linear 2D charts
1583 if( rTypeInfo
.IsSeriesFrameFormat() )
1584 mxMarkerFmt
.reset();
1585 // pie format only in pie/donut charts
1586 if( rTypeInfo
.meTypeCateg
!= EXC_CHTYPECATEG_PIE
)
1588 // 3D format only in 3D bar charts
1589 if( !rTypeInfo
.mb3dChart
|| (rTypeInfo
.meTypeCateg
!= EXC_CHTYPECATEG_BAR
) )
1590 mx3dDataFmt
.reset();
1593 void XclImpChDataFormat::UpdateDataLabel( const XclImpChDataFormat
* pParentFmt
)
1595 /* CHTEXT groups linked to data labels override existing CHATTACHEDLABEL
1596 records. Only if there is a CHATTACHEDLABEL record without a CHTEXT
1597 group, the contents of the CHATTACHEDLABEL record are used. In this
1598 case a new CHTEXT group is created and filled with the settings from
1599 the CHATTACHEDLABEL record. */
1600 const XclImpChText
* pDefText
= NULL
;
1602 pDefText
= pParentFmt
->GetDataLabel();
1604 pDefText
= GetChartData().GetDefaultText( EXC_CHTEXTTYPE_DATALABEL
);
1606 mxLabel
->UpdateText(pDefText
);
1607 else if (mxAttLabel
)
1608 mxLabel
= mxAttLabel
->CreateDataLabel( pDefText
);
1611 // ----------------------------------------------------------------------------
1613 XclImpChSerTrendLine::XclImpChSerTrendLine( const XclImpChRoot
& rRoot
) :
1614 XclImpChRoot( rRoot
)
1618 void XclImpChSerTrendLine::ReadChSerTrendLine( XclImpStream
& rStrm
)
1620 rStrm
>> maData
.mnLineType
1622 >> maData
.mfIntercept
1623 >> maData
.mnShowEquation
1624 >> maData
.mnShowRSquared
1625 >> maData
.mfForecastFor
1626 >> maData
.mfForecastBack
;
1629 Reference
< XRegressionCurve
> XclImpChSerTrendLine::CreateRegressionCurve() const
1633 switch( maData
.mnLineType
)
1635 case EXC_CHSERTREND_POLYNOMIAL
:
1636 // TODO: only linear trend lines are supported by OOChart (#i20819#)
1637 if( maData
.mnOrder
== 1 )
1638 aService
= SERVICE_CHART2_LINEARREGCURVE
;
1640 case EXC_CHSERTREND_EXPONENTIAL
:
1641 aService
= SERVICE_CHART2_EXPREGCURVE
;
1643 case EXC_CHSERTREND_LOGARITHMIC
:
1644 aService
= SERVICE_CHART2_LOGREGCURVE
;
1646 case EXC_CHSERTREND_POWER
:
1647 aService
= SERVICE_CHART2_POTREGCURVE
;
1650 Reference
< XRegressionCurve
> xRegCurve
;
1651 if( !aService
.isEmpty() )
1652 xRegCurve
.set( ScfApiHelper::CreateInstance( aService
), UNO_QUERY
);
1654 // trend line formatting
1655 if( xRegCurve
.is() && mxDataFmt
)
1657 ScfPropertySet
aPropSet( xRegCurve
);
1658 mxDataFmt
->ConvertLine( aPropSet
, EXC_CHOBJTYPE_TRENDLINE
);
1660 // #i83100# show equation and correlation coefficient
1661 ScfPropertySet
aLabelProp( xRegCurve
->getEquationProperties() );
1662 aLabelProp
.SetBoolProperty( EXC_CHPROP_SHOWEQUATION
, maData
.mnShowEquation
!= 0 );
1663 aLabelProp
.SetBoolProperty( EXC_CHPROP_SHOWCORRELATION
, maData
.mnShowRSquared
!= 0 );
1665 // #i83100# formatting of the equation text box
1666 if (const XclImpChText
* pLabel
= mxDataFmt
->GetDataLabel())
1668 pLabel
->ConvertFont( aLabelProp
);
1669 pLabel
->ConvertFrame( aLabelProp
);
1670 pLabel
->ConvertNumFmt( aLabelProp
, false );
1675 // #i20819# polynomial trend lines
1676 // #i66819# moving average trend lines
1677 // #i5085# manual trend line size
1678 // #i34093# manual crossing point
1683 // ----------------------------------------------------------------------------
1685 XclImpChSerErrorBar::XclImpChSerErrorBar( const XclImpChRoot
& rRoot
) :
1686 XclImpChRoot( rRoot
)
1690 void XclImpChSerErrorBar::ReadChSerErrorBar( XclImpStream
& rStrm
)
1692 rStrm
>> maData
.mnBarType
>> maData
.mnSourceType
>> maData
.mnLineEnd
;
1694 rStrm
>> maData
.mfValue
>> maData
.mnValueCount
;
1697 void XclImpChSerErrorBar::SetSeriesData( XclImpChSourceLinkRef xValueLink
, XclImpChDataFormatRef xDataFmt
)
1699 mxValueLink
= xValueLink
;
1700 mxDataFmt
= xDataFmt
;
1703 Reference
< XLabeledDataSequence
> XclImpChSerErrorBar::CreateValueSequence() const
1705 return lclCreateLabeledDataSequence( mxValueLink
, XclChartHelper::GetErrorBarValuesRole( maData
.mnBarType
) );
1708 Reference
< XPropertySet
> XclImpChSerErrorBar::CreateErrorBar( const XclImpChSerErrorBar
* pPosBar
, const XclImpChSerErrorBar
* pNegBar
)
1710 Reference
< XPropertySet
> xErrorBar
;
1712 if( const XclImpChSerErrorBar
* pPrimaryBar
= pPosBar
? pPosBar
: pNegBar
)
1714 xErrorBar
.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_ERRORBAR
), UNO_QUERY
);
1715 ScfPropertySet
aBarProp( xErrorBar
);
1717 // plus/minus bars visible?
1718 aBarProp
.SetBoolProperty( EXC_CHPROP_SHOWPOSITIVEERROR
, pPosBar
!= 0 );
1719 aBarProp
.SetBoolProperty( EXC_CHPROP_SHOWNEGATIVEERROR
, pNegBar
!= 0 );
1721 // type of displayed error
1722 switch( pPrimaryBar
->maData
.mnSourceType
)
1724 case EXC_CHSERERR_PERCENT
:
1725 aBarProp
.SetProperty( EXC_CHPROP_ERRORBARSTYLE
, cssc::ErrorBarStyle::RELATIVE
);
1726 aBarProp
.SetProperty( EXC_CHPROP_POSITIVEERROR
, pPrimaryBar
->maData
.mfValue
);
1727 aBarProp
.SetProperty( EXC_CHPROP_NEGATIVEERROR
, pPrimaryBar
->maData
.mfValue
);
1729 case EXC_CHSERERR_FIXED
:
1730 aBarProp
.SetProperty( EXC_CHPROP_ERRORBARSTYLE
, cssc::ErrorBarStyle::ABSOLUTE
);
1731 aBarProp
.SetProperty( EXC_CHPROP_POSITIVEERROR
, pPrimaryBar
->maData
.mfValue
);
1732 aBarProp
.SetProperty( EXC_CHPROP_NEGATIVEERROR
, pPrimaryBar
->maData
.mfValue
);
1734 case EXC_CHSERERR_STDDEV
:
1735 aBarProp
.SetProperty( EXC_CHPROP_ERRORBARSTYLE
, cssc::ErrorBarStyle::STANDARD_DEVIATION
);
1736 aBarProp
.SetProperty( EXC_CHPROP_WEIGHT
, pPrimaryBar
->maData
.mfValue
);
1738 case EXC_CHSERERR_STDERR
:
1739 aBarProp
.SetProperty( EXC_CHPROP_ERRORBARSTYLE
, cssc::ErrorBarStyle::STANDARD_ERROR
);
1741 case EXC_CHSERERR_CUSTOM
:
1743 aBarProp
.SetProperty( EXC_CHPROP_ERRORBARSTYLE
, cssc::ErrorBarStyle::FROM_DATA
);
1744 // attach data sequences to erorr bar
1745 Reference
< XDataSink
> xDataSink( xErrorBar
, UNO_QUERY
);
1746 if( xDataSink
.is() )
1748 // create vector of all value sequences
1749 ::std::vector
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
;
1750 // add positive values
1753 Reference
< XLabeledDataSequence
> xValueSeq
= pPosBar
->CreateValueSequence();
1754 if( xValueSeq
.is() )
1755 aLabeledSeqVec
.push_back( xValueSeq
);
1757 // add negative values
1760 Reference
< XLabeledDataSequence
> xValueSeq
= pNegBar
->CreateValueSequence();
1761 if( xValueSeq
.is() )
1762 aLabeledSeqVec
.push_back( xValueSeq
);
1764 // attach labeled data sequences to series
1765 if( aLabeledSeqVec
.empty() )
1768 xDataSink
->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec
) );
1776 // error bar formatting
1777 if( pPrimaryBar
->mxDataFmt
&& xErrorBar
.is() )
1778 pPrimaryBar
->mxDataFmt
->ConvertLine( aBarProp
, EXC_CHOBJTYPE_ERRORBAR
);
1784 // ----------------------------------------------------------------------------
1786 XclImpChSeries::XclImpChSeries( const XclImpChRoot
& rRoot
, sal_uInt16 nSeriesIdx
) :
1787 XclImpChRoot( rRoot
),
1788 mnGroupIdx( EXC_CHSERGROUP_NONE
),
1789 mnSeriesIdx( nSeriesIdx
),
1790 mnParentIdx( EXC_CHSERIES_INVALID
)
1794 void XclImpChSeries::ReadHeaderRecord( XclImpStream
& rStrm
)
1796 rStrm
>> maData
.mnCategType
>> maData
.mnValueType
>> maData
.mnCategCount
>> maData
.mnValueCount
;
1797 if( GetBiff() == EXC_BIFF8
)
1798 rStrm
>> maData
.mnBubbleType
>> maData
.mnBubbleCount
;
1801 void XclImpChSeries::ReadSubRecord( XclImpStream
& rStrm
)
1803 switch( rStrm
.GetRecId() )
1805 case EXC_ID_CHSOURCELINK
:
1806 ReadChSourceLink( rStrm
);
1808 case EXC_ID_CHDATAFORMAT
:
1809 ReadChDataFormat( rStrm
);
1811 case EXC_ID_CHSERGROUP
:
1812 rStrm
>> mnGroupIdx
;
1814 case EXC_ID_CHSERPARENT
:
1815 ReadChSerParent( rStrm
);
1817 case EXC_ID_CHSERTRENDLINE
:
1818 ReadChSerTrendLine( rStrm
);
1820 case EXC_ID_CHSERERRORBAR
:
1821 ReadChSerErrorBar( rStrm
);
1826 void XclImpChSeries::SetDataFormat( const XclImpChDataFormatRef
& xDataFmt
)
1831 sal_uInt16 nPointIdx
= xDataFmt
->GetPointPos().mnPointIdx
;
1832 if (nPointIdx
== EXC_CHDATAFORMAT_ALLPOINTS
)
1835 // Don't overwrite the existing format.
1838 mxSeriesFmt
= xDataFmt
;
1839 if (HasParentSeries())
1842 XclImpChTypeGroupRef pTypeGroup
= GetChartData().GetTypeGroup(mnGroupIdx
);
1844 pTypeGroup
->SetUsedFormatIndex(xDataFmt
->GetFormatIdx());
1849 if (nPointIdx
>= EXC_CHDATAFORMAT_MAXPOINTCOUNT
)
1850 // Above the max point count. Bail out.
1853 XclImpChDataFormatMap::iterator itr
= maPointFmts
.lower_bound(nPointIdx
);
1854 if (itr
== maPointFmts
.end() || maPointFmts
.key_comp()(nPointIdx
, itr
->first
))
1856 // No object exists at this point index position. Insert it.
1857 itr
= maPointFmts
.insert(itr
, XclImpChDataFormatMap::value_type(nPointIdx
, xDataFmt
));
1861 void XclImpChSeries::SetDataLabel( const XclImpChTextRef
& xLabel
)
1866 sal_uInt16 nPointIdx
= xLabel
->GetPointPos().mnPointIdx
;
1867 if ((nPointIdx
!= EXC_CHDATAFORMAT_ALLPOINTS
) && (nPointIdx
>= EXC_CHDATAFORMAT_MAXPOINTCOUNT
))
1868 // Above the maximum allowed data points. Bail out.
1871 XclImpChTextMap::iterator itr
= maLabels
.lower_bound(nPointIdx
);
1872 if (itr
== maLabels
.end() || maLabels
.key_comp()(nPointIdx
, itr
->first
))
1874 // No object exists at this point index position. Insert it.
1875 itr
= maLabels
.insert(itr
, XclImpChTextMap::value_type(nPointIdx
, xLabel
));
1879 void XclImpChSeries::AddChildSeries( const XclImpChSeries
& rSeries
)
1881 OSL_ENSURE( !HasParentSeries(), "XclImpChSeries::AddChildSeries - not allowed for child series" );
1883 /* In Excel, trend lines and error bars are stored as own series. In Calc,
1884 these are properties of the parent series. This function adds the
1885 settings of the passed series to this series. */
1886 maTrendLines
.insert( maTrendLines
.end(), rSeries
.maTrendLines
.begin(), rSeries
.maTrendLines
.end() );
1887 maErrorBars
.insert( rSeries
.maErrorBars
.begin(), rSeries
.maErrorBars
.end() );
1890 void XclImpChSeries::FinalizeDataFormats()
1892 if( HasParentSeries() )
1894 // *** series is a child series, e.g. trend line or error bar ***
1896 // create missing series format
1898 mxSeriesFmt
= CreateDataFormat( EXC_CHDATAFORMAT_ALLPOINTS
, 0 );
1902 // #i83100# set text label format, e.g. for trend line equations
1903 XclImpChTextRef xLabel
;
1904 XclImpChTextMap::iterator itr
= maLabels
.find(EXC_CHDATAFORMAT_ALLPOINTS
);
1905 if (itr
!= maLabels
.end())
1906 xLabel
= itr
->second
;
1907 mxSeriesFmt
->SetDataLabel(xLabel
);
1908 // create missing automatic formats
1909 mxSeriesFmt
->UpdateTrendLineFormat();
1912 // copy series formatting to child objects
1913 for( XclImpChSerTrendLineList::iterator aLIt
= maTrendLines
.begin(), aLEnd
= maTrendLines
.end(); aLIt
!= aLEnd
; ++aLIt
)
1914 (*aLIt
)->SetDataFormat( mxSeriesFmt
);
1915 for( XclImpChSerErrorBarMap::iterator aMIt
= maErrorBars
.begin(), aMEnd
= maErrorBars
.end(); aMIt
!= aMEnd
; ++aMIt
)
1916 aMIt
->second
->SetSeriesData( mxValueLink
, mxSeriesFmt
);
1918 else if( XclImpChTypeGroup
* pTypeGroup
= GetChartData().GetTypeGroup( mnGroupIdx
).get() )
1920 // *** series is a regular data series ***
1922 // create missing series format
1925 // #i51639# use a new unused format index to create series default format
1926 sal_uInt16 nFormatIdx
= pTypeGroup
->PopUnusedFormatIndex();
1927 mxSeriesFmt
= CreateDataFormat( EXC_CHDATAFORMAT_ALLPOINTS
, nFormatIdx
);
1930 // set text labels to data formats
1931 for( XclImpChTextMap::iterator aTIt
= maLabels
.begin(), aTEnd
= maLabels
.end(); aTIt
!= aTEnd
; ++aTIt
)
1933 sal_uInt16 nPointIdx
= aTIt
->first
;
1934 if (nPointIdx
== EXC_CHDATAFORMAT_ALLPOINTS
)
1937 mxSeriesFmt
= CreateDataFormat(nPointIdx
, EXC_CHDATAFORMAT_DEFAULT
);
1938 mxSeriesFmt
->SetDataLabel(aTIt
->second
);
1940 else if (nPointIdx
< EXC_CHDATAFORMAT_MAXPOINTCOUNT
)
1942 XclImpChDataFormatRef p
;
1943 XclImpChDataFormatMap::iterator itr
= maPointFmts
.lower_bound(nPointIdx
);
1944 if (itr
== maPointFmts
.end() || maPointFmts
.key_comp()(nPointIdx
, itr
->first
))
1946 // No object exists at this point index position. Insert
1948 p
= CreateDataFormat(nPointIdx
, EXC_CHDATAFORMAT_DEFAULT
);
1949 itr
= maPointFmts
.insert(
1950 itr
, XclImpChDataFormatMap::value_type(nPointIdx
, p
));
1954 p
->SetDataLabel(aTIt
->second
);
1958 // update series format (copy missing formatting from group default format)
1960 mxSeriesFmt
->UpdateSeriesFormat( pTypeGroup
->GetTypeInfo(), pTypeGroup
->GetGroupFormat().get() );
1962 // update data point formats (removes unchanged automatic formatting)
1963 for( XclImpChDataFormatMap::iterator aFIt
= maPointFmts
.begin(), aFEnd
= maPointFmts
.end(); aFIt
!= aFEnd
; ++aFIt
)
1964 aFIt
->second
->UpdatePointFormat( pTypeGroup
->GetTypeInfo(), mxSeriesFmt
.get() );
1970 /** Returns the property set of the specified data point. */
1971 ScfPropertySet
lclGetPointPropSet( Reference
< XDataSeries
> xDataSeries
, sal_uInt16 nPointIdx
)
1973 ScfPropertySet aPropSet
;
1976 aPropSet
.Set( xDataSeries
->getDataPointByIndex( static_cast< sal_Int32
>( nPointIdx
) ) );
1980 OSL_FAIL( "lclGetPointPropSet - no data point property set" );
1987 Reference
< XLabeledDataSequence
> XclImpChSeries::CreateValueSequence( const OUString
& rValueRole
) const
1989 return lclCreateLabeledDataSequence( mxValueLink
, rValueRole
, mxTitleLink
.get() );
1992 Reference
< XLabeledDataSequence
> XclImpChSeries::CreateCategSequence( const OUString
& rCategRole
) const
1994 return lclCreateLabeledDataSequence( mxCategLink
, rCategRole
);
1997 Reference
< XDataSeries
> XclImpChSeries::CreateDataSeries() const
1999 Reference
< XDataSeries
> xDataSeries
;
2000 if( const XclImpChTypeGroup
* pTypeGroup
= GetChartData().GetTypeGroup( mnGroupIdx
).get() )
2002 const XclChExtTypeInfo
& rTypeInfo
= pTypeGroup
->GetTypeInfo();
2004 // create the data series object
2005 xDataSeries
.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_DATASERIES
), UNO_QUERY
);
2007 // attach data and title sequences to series
2008 Reference
< XDataSink
> xDataSink( xDataSeries
, UNO_QUERY
);
2009 if( xDataSink
.is() )
2011 // create vector of all value sequences
2012 ::std::vector
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
;
2014 Reference
< XLabeledDataSequence
> xYValueSeq
=
2015 CreateValueSequence( EXC_CHPROP_ROLE_YVALUES
);
2016 if( xYValueSeq
.is() )
2017 aLabeledSeqVec
.push_back( xYValueSeq
);
2019 if( !rTypeInfo
.mbCategoryAxis
)
2021 Reference
< XLabeledDataSequence
> xXValueSeq
=
2022 CreateCategSequence( EXC_CHPROP_ROLE_XVALUES
);
2023 if( xXValueSeq
.is() )
2024 aLabeledSeqVec
.push_back( xXValueSeq
);
2025 // add size values of bubble charts
2026 if( rTypeInfo
.meTypeId
== EXC_CHTYPEID_BUBBLES
)
2028 Reference
< XLabeledDataSequence
> xSizeValueSeq
=
2029 lclCreateLabeledDataSequence( mxBubbleLink
, EXC_CHPROP_ROLE_SIZEVALUES
, mxTitleLink
.get() );
2030 if( xSizeValueSeq
.is() )
2031 aLabeledSeqVec
.push_back( xSizeValueSeq
);
2034 // attach labeled data sequences to series
2035 if( !aLabeledSeqVec
.empty() )
2036 xDataSink
->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec
) );
2039 // series formatting
2040 ScfPropertySet
aSeriesProp( xDataSeries
);
2042 mxSeriesFmt
->Convert( aSeriesProp
, rTypeInfo
);
2045 ConvertTrendLines( xDataSeries
);
2048 Reference
< XPropertySet
> xErrorBarX
= CreateErrorBar( EXC_CHSERERR_XPLUS
, EXC_CHSERERR_XMINUS
);
2049 if( xErrorBarX
.is() )
2050 aSeriesProp
.SetProperty( EXC_CHPROP_ERRORBARX
, xErrorBarX
);
2051 Reference
< XPropertySet
> xErrorBarY
= CreateErrorBar( EXC_CHSERERR_YPLUS
, EXC_CHSERERR_YMINUS
);
2052 if( xErrorBarY
.is() )
2053 aSeriesProp
.SetProperty( EXC_CHPROP_ERRORBARY
, xErrorBarY
);
2055 // own area formatting for every data point (TODO: varying line color not supported)
2056 bool bVarPointFmt
= pTypeGroup
->HasVarPointFormat() && rTypeInfo
.IsSeriesFrameFormat();
2057 #if EXC_CHART2_VARYCOLORSBY_PROP
2058 aSeriesProp
.SetBoolProperty( EXC_CHPROP_VARYCOLORSBY
, bVarPointFmt
);
2060 aSeriesProp
.SetBoolProperty( EXC_CHPROP_VARYCOLORSBY
, rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
);
2062 // #i91271# always set area formatting for every point in pie/doughnut charts
2063 if (mxSeriesFmt
&& mxValueLink
&& ((bVarPointFmt
&& mxSeriesFmt
->IsAutoArea()) || (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
)))
2065 for( sal_uInt16 nPointIdx
= 0, nPointCount
= mxValueLink
->GetCellCount(); nPointIdx
< nPointCount
; ++nPointIdx
)
2067 ScfPropertySet aPointProp
= lclGetPointPropSet( xDataSeries
, nPointIdx
);
2068 mxSeriesFmt
->ConvertArea( aPointProp
, bVarPointFmt
? nPointIdx
: mnSeriesIdx
, false );
2072 // data point formatting
2073 for( XclImpChDataFormatMap::const_iterator aIt
= maPointFmts
.begin(), aEnd
= maPointFmts
.end(); aIt
!= aEnd
; ++aIt
)
2075 ScfPropertySet aPointProp
= lclGetPointPropSet( xDataSeries
, aIt
->first
);
2076 aIt
->second
->Convert( aPointProp
, rTypeInfo
);
2082 void XclImpChSeries::FillAllSourceLinks( ::std::vector
< ScTokenRef
>& rTokens
) const
2085 mxValueLink
->FillSourceLink( rTokens
);
2087 mxCategLink
->FillSourceLink( rTokens
);
2089 mxTitleLink
->FillSourceLink( rTokens
);
2091 mxBubbleLink
->FillSourceLink( rTokens
);
2094 void XclImpChSeries::ReadChSourceLink( XclImpStream
& rStrm
)
2096 XclImpChSourceLinkRef
xSrcLink( new XclImpChSourceLink( GetChRoot() ) );
2097 xSrcLink
->ReadChSourceLink( rStrm
);
2098 switch( xSrcLink
->GetDestType() )
2100 case EXC_CHSRCLINK_TITLE
: mxTitleLink
= xSrcLink
; break;
2101 case EXC_CHSRCLINK_VALUES
: mxValueLink
= xSrcLink
; break;
2102 case EXC_CHSRCLINK_CATEGORY
: mxCategLink
= xSrcLink
; break;
2103 case EXC_CHSRCLINK_BUBBLES
: mxBubbleLink
= xSrcLink
; break;
2107 void XclImpChSeries::ReadChDataFormat( XclImpStream
& rStrm
)
2109 // #i51639# chart stores all data formats and assigns them later to the series
2110 GetChartData().ReadChDataFormat( rStrm
);
2113 void XclImpChSeries::ReadChSerParent( XclImpStream
& rStrm
)
2115 rStrm
>> mnParentIdx
;
2116 // index to parent series is 1-based, convert it to 0-based
2117 if( mnParentIdx
> 0 )
2120 mnParentIdx
= EXC_CHSERIES_INVALID
;
2123 void XclImpChSeries::ReadChSerTrendLine( XclImpStream
& rStrm
)
2125 XclImpChSerTrendLineRef
xTrendLine( new XclImpChSerTrendLine( GetChRoot() ) );
2126 xTrendLine
->ReadChSerTrendLine( rStrm
);
2127 maTrendLines
.push_back( xTrendLine
);
2130 void XclImpChSeries::ReadChSerErrorBar( XclImpStream
& rStrm
)
2132 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2133 auto_ptr
<XclImpChSerErrorBar
> pErrorBar(new XclImpChSerErrorBar(GetChRoot()));
2134 SAL_WNODEPRECATED_DECLARATIONS_POP
2135 pErrorBar
->ReadChSerErrorBar(rStrm
);
2136 sal_uInt8 nBarType
= pErrorBar
->GetBarType();
2137 maErrorBars
.insert(nBarType
, pErrorBar
);
2140 XclImpChDataFormatRef
XclImpChSeries::CreateDataFormat( sal_uInt16 nPointIdx
, sal_uInt16 nFormatIdx
)
2142 XclImpChDataFormatRef
xDataFmt( new XclImpChDataFormat( GetChRoot() ) );
2143 xDataFmt
->SetPointPos( XclChDataPointPos( mnSeriesIdx
, nPointIdx
), nFormatIdx
);
2147 void XclImpChSeries::ConvertTrendLines( Reference
< XDataSeries
> xDataSeries
) const
2149 Reference
< XRegressionCurveContainer
> xRegCurveCont( xDataSeries
, UNO_QUERY
);
2150 if( xRegCurveCont
.is() )
2152 for( XclImpChSerTrendLineList::const_iterator aIt
= maTrendLines
.begin(), aEnd
= maTrendLines
.end(); aIt
!= aEnd
; ++aIt
)
2156 Reference
< XRegressionCurve
> xRegCurve
= (*aIt
)->CreateRegressionCurve();
2157 if( xRegCurve
.is() )
2158 xRegCurveCont
->addRegressionCurve( xRegCurve
);
2162 OSL_FAIL( "XclImpChSeries::ConvertTrendLines - cannot add regression curve" );
2168 Reference
< XPropertySet
> XclImpChSeries::CreateErrorBar( sal_uInt8 nPosBarId
, sal_uInt8 nNegBarId
) const
2170 XclImpChSerErrorBarMap::const_iterator itrPosBar
= maErrorBars
.find(nPosBarId
);
2171 XclImpChSerErrorBarMap::const_iterator itrNegBar
= maErrorBars
.find(nNegBarId
);
2172 XclImpChSerErrorBarMap::const_iterator itrEnd
= maErrorBars
.end();
2173 if (itrPosBar
== itrEnd
|| itrNegBar
== itrEnd
)
2174 return Reference
<XPropertySet
>();
2176 return XclImpChSerErrorBar::CreateErrorBar(itrPosBar
->second
, itrNegBar
->second
);
2179 // Chart type groups ==========================================================
2181 XclImpChType::XclImpChType( const XclImpChRoot
& rRoot
) :
2182 XclImpChRoot( rRoot
),
2183 mnRecId( EXC_ID_CHUNKNOWN
),
2184 maTypeInfo( rRoot
.GetChartTypeInfo( EXC_CHTYPEID_UNKNOWN
) )
2188 void XclImpChType::ReadChType( XclImpStream
& rStrm
)
2190 sal_uInt16 nRecId
= rStrm
.GetRecId();
2191 bool bKnownType
= true;
2196 rStrm
>> maData
.mnOverlap
>> maData
.mnGap
>> maData
.mnFlags
;
2201 case EXC_ID_CHRADARLINE
:
2202 case EXC_ID_CHRADARAREA
:
2203 rStrm
>> maData
.mnFlags
;
2207 rStrm
>> maData
.mnRotation
>> maData
.mnPieHole
;
2208 if( GetBiff() == EXC_BIFF8
)
2209 rStrm
>> maData
.mnFlags
;
2214 case EXC_ID_CHPIEEXT
:
2215 maData
.mnRotation
= 0;
2216 maData
.mnPieHole
= 0;
2220 case EXC_ID_CHSCATTER
:
2221 if( GetBiff() == EXC_BIFF8
)
2222 rStrm
>> maData
.mnBubbleSize
>> maData
.mnBubbleType
>> maData
.mnFlags
;
2227 case EXC_ID_CHSURFACE
:
2228 rStrm
>> maData
.mnFlags
;
2239 void XclImpChType::Finalize( bool bStockChart
)
2244 maTypeInfo
= GetChartTypeInfo( bStockChart
?
2245 EXC_CHTYPEID_STOCK
: EXC_CHTYPEID_LINE
);
2248 maTypeInfo
= GetChartTypeInfo( ::get_flagvalue(
2249 maData
.mnFlags
, EXC_CHBAR_HORIZONTAL
,
2250 EXC_CHTYPEID_HORBAR
, EXC_CHTYPEID_BAR
) );
2253 maTypeInfo
= GetChartTypeInfo( (maData
.mnPieHole
> 0) ?
2254 EXC_CHTYPEID_DONUT
: EXC_CHTYPEID_PIE
);
2256 case EXC_ID_CHSCATTER
:
2257 maTypeInfo
= GetChartTypeInfo( ::get_flagvalue(
2258 maData
.mnFlags
, EXC_CHSCATTER_BUBBLES
,
2259 EXC_CHTYPEID_BUBBLES
, EXC_CHTYPEID_SCATTER
) );
2262 maTypeInfo
= GetChartTypeInfo( mnRecId
);
2265 switch( maTypeInfo
.meTypeId
)
2267 case EXC_CHTYPEID_PIEEXT
:
2268 case EXC_CHTYPEID_BUBBLES
:
2269 case EXC_CHTYPEID_SURFACE
:
2270 case EXC_CHTYPEID_UNKNOWN
:
2271 GetTracer().TraceChartUnKnownType();
2277 bool XclImpChType::IsStacked() const
2279 bool bStacked
= false;
2280 if( maTypeInfo
.mbSupportsStacking
) switch( maTypeInfo
.meTypeCateg
)
2282 case EXC_CHTYPECATEG_LINE
:
2284 ::get_flag( maData
.mnFlags
, EXC_CHLINE_STACKED
) &&
2285 !::get_flag( maData
.mnFlags
, EXC_CHLINE_PERCENT
);
2287 case EXC_CHTYPECATEG_BAR
:
2289 ::get_flag( maData
.mnFlags
, EXC_CHBAR_STACKED
) &&
2290 !::get_flag( maData
.mnFlags
, EXC_CHBAR_PERCENT
);
2297 bool XclImpChType::IsPercent() const
2299 bool bPercent
= false;
2300 if( maTypeInfo
.mbSupportsStacking
) switch( maTypeInfo
.meTypeCateg
)
2302 case EXC_CHTYPECATEG_LINE
:
2304 ::get_flag( maData
.mnFlags
, EXC_CHLINE_STACKED
) &&
2305 ::get_flag( maData
.mnFlags
, EXC_CHLINE_PERCENT
);
2307 case EXC_CHTYPECATEG_BAR
:
2309 ::get_flag( maData
.mnFlags
, EXC_CHBAR_STACKED
) &&
2310 ::get_flag( maData
.mnFlags
, EXC_CHBAR_PERCENT
);
2317 bool XclImpChType::HasCategoryLabels() const
2319 // radar charts disable category labels in chart type, not in CHTICK of X axis
2320 return (maTypeInfo
.meTypeCateg
!= EXC_CHTYPECATEG_RADAR
) || ::get_flag( maData
.mnFlags
, EXC_CHRADAR_AXISLABELS
);
2323 Reference
< XCoordinateSystem
> XclImpChType::CreateCoordSystem( bool b3dChart
) const
2325 // create the coordinate system object
2326 Reference
< css::uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
2327 Reference
< XCoordinateSystem
> xCoordSystem
;
2328 if( maTypeInfo
.mbPolarCoordSystem
)
2331 xCoordSystem
= css::chart2::PolarCoordinateSystem3d::create(xContext
);
2333 xCoordSystem
= css::chart2::PolarCoordinateSystem2d::create(xContext
);
2338 xCoordSystem
= css::chart2::CartesianCoordinateSystem3d::create(xContext
);
2340 xCoordSystem
= css::chart2::CartesianCoordinateSystem2d::create(xContext
);
2343 // swap X and Y axis
2344 if( maTypeInfo
.mbSwappedAxesSet
)
2346 ScfPropertySet
aCoordSysProp( xCoordSystem
);
2347 aCoordSysProp
.SetBoolProperty( EXC_CHPROP_SWAPXANDYAXIS
, true );
2350 return xCoordSystem
;
2353 Reference
< XChartType
> XclImpChType::CreateChartType( Reference
< XDiagram
> xDiagram
, bool b3dChart
) const
2355 OUString aService
= OUString::createFromAscii( maTypeInfo
.mpcServiceName
);
2356 Reference
< XChartType
> xChartType( ScfApiHelper::CreateInstance( aService
), UNO_QUERY
);
2358 // additional properties
2359 switch( maTypeInfo
.meTypeCateg
)
2361 case EXC_CHTYPECATEG_BAR
:
2363 ScfPropertySet
aTypeProp( xChartType
);
2364 Sequence
< sal_Int32
> aInt32Seq( 2 );
2365 aInt32Seq
[ 0 ] = aInt32Seq
[ 1 ] = -maData
.mnOverlap
;
2366 aTypeProp
.SetProperty( EXC_CHPROP_OVERLAPSEQ
, aInt32Seq
);
2367 aInt32Seq
[ 0 ] = aInt32Seq
[ 1 ] = maData
.mnGap
;
2368 aTypeProp
.SetProperty( EXC_CHPROP_GAPWIDTHSEQ
, aInt32Seq
);
2371 case EXC_CHTYPECATEG_PIE
:
2373 ScfPropertySet
aTypeProp( xChartType
);
2374 aTypeProp
.SetBoolProperty( EXC_CHPROP_USERINGS
, maTypeInfo
.meTypeId
== EXC_CHTYPEID_DONUT
);
2375 /* #i85166# starting angle of first pie slice. 3D pie charts use Y
2376 rotation setting in view3D element. Of-pie charts do not
2377 support pie rotation. */
2378 if( !b3dChart
&& (maTypeInfo
.meTypeId
!= EXC_CHTYPEID_PIEEXT
) )
2380 ScfPropertySet
aDiaProp( xDiagram
);
2381 XclImpChRoot::ConvertPieRotation( aDiaProp
, maData
.mnRotation
);
2391 // ----------------------------------------------------------------------------
2393 void XclImpChChart3d::ReadChChart3d( XclImpStream
& rStrm
)
2395 rStrm
>> maData
.mnRotation
2396 >> maData
.mnElevation
2398 >> maData
.mnRelHeight
2399 >> maData
.mnRelDepth
2400 >> maData
.mnDepthGap
2404 void XclImpChChart3d::Convert( ScfPropertySet
& rPropSet
, bool b3dWallChart
) const
2406 namespace cssd
= ::com::sun::star::drawing
;
2408 // #i104057# do not assert this, written by broken external generators
2409 // OSL_ENSURE( ::get_flag( maData.mnFlags, EXC_CHCHART3D_HASWALLS ) == b3dWallChart, "XclImpChChart3d::Convert - wrong wall flag" );
2411 sal_Int32 nRotationY
= 0;
2412 sal_Int32 nRotationX
= 0;
2413 sal_Int32 nPerspective
= 15;
2414 bool bRightAngled
= false;
2415 cssd::ProjectionMode eProjMode
= cssd::ProjectionMode_PERSPECTIVE
;
2416 Color aAmbientColor
, aLightColor
;
2420 // Y rotation (Excel [0..359], Chart2 [-179,180])
2421 nRotationY
= maData
.mnRotation
% 360;
2422 if( nRotationY
> 180 ) nRotationY
-= 360;
2423 // X rotation a.k.a. elevation (Excel [-90..90], Chart2 [-179,180])
2424 nRotationX
= limit_cast
< sal_Int32
, sal_Int32
>( maData
.mnElevation
, -90, 90 );
2425 // perspective (Excel and Chart2 [0,100])
2426 nPerspective
= limit_cast
< sal_Int32
, sal_Int32
>( maData
.mnEyeDist
, 0, 100 );
2427 // right-angled axes
2428 bRightAngled
= !::get_flag( maData
.mnFlags
, EXC_CHCHART3D_REAL3D
);
2429 // projection mode (parallel axes, if right-angled, #i90360# or if perspective is at 0%)
2430 bool bParallel
= bRightAngled
|| (nPerspective
== 0);
2431 eProjMode
= bParallel
? cssd::ProjectionMode_PARALLEL
: cssd::ProjectionMode_PERSPECTIVE
;
2432 // ambient color (Gray 20%)
2433 aAmbientColor
.SetColor( RGB_COLORDATA( 204, 204, 204 ) );
2434 // light color (Gray 60%)
2435 aLightColor
.SetColor( RGB_COLORDATA( 102, 102, 102 ) );
2439 // Y rotation not used in pie charts, but 'first pie slice angle'
2441 XclImpChRoot::ConvertPieRotation( rPropSet
, maData
.mnRotation
);
2442 // X rotation a.k.a. elevation (map Excel [10..80] to Chart2 [-80,-10])
2443 nRotationX
= limit_cast
< sal_Int32
, sal_Int32
>( maData
.mnElevation
, 10, 80 ) - 90;
2444 // perspective (Excel and Chart2 [0,100])
2445 nPerspective
= limit_cast
< sal_Int32
, sal_Int32
>( maData
.mnEyeDist
, 0, 100 );
2446 // no right-angled axes in pie charts, but parallel projection
2447 bRightAngled
= false;
2448 eProjMode
= cssd::ProjectionMode_PARALLEL
;
2449 // ambient color (Gray 30%)
2450 aAmbientColor
.SetColor( RGB_COLORDATA( 179, 179, 179 ) );
2451 // light color (Gray 70%)
2452 aLightColor
.SetColor( RGB_COLORDATA( 76, 76, 76 ) );
2456 rPropSet
.SetProperty( EXC_CHPROP_3DRELATIVEHEIGHT
, (sal_Int32
)(maData
.mnRelHeight
/ 2)); // seems to be 200%, cange to 100%
2457 rPropSet
.SetProperty( EXC_CHPROP_ROTATIONVERTICAL
, nRotationY
);
2458 rPropSet
.SetProperty( EXC_CHPROP_ROTATIONHORIZONTAL
, nRotationX
);
2459 rPropSet
.SetProperty( EXC_CHPROP_PERSPECTIVE
, nPerspective
);
2460 rPropSet
.SetBoolProperty( EXC_CHPROP_RIGHTANGLEDAXES
, bRightAngled
);
2461 rPropSet
.SetProperty( EXC_CHPROP_D3DSCENEPERSPECTIVE
, eProjMode
);
2464 rPropSet
.SetProperty( EXC_CHPROP_D3DSCENESHADEMODE
, cssd::ShadeMode_FLAT
);
2465 rPropSet
.SetColorProperty( EXC_CHPROP_D3DSCENEAMBIENTCOLOR
, aAmbientColor
);
2466 rPropSet
.SetBoolProperty( EXC_CHPROP_D3DSCENELIGHTON1
, false );
2467 rPropSet
.SetBoolProperty( EXC_CHPROP_D3DSCENELIGHTON2
, true );
2468 rPropSet
.SetColorProperty( EXC_CHPROP_D3DSCENELIGHTCOLOR2
, aLightColor
);
2469 rPropSet
.SetProperty( EXC_CHPROP_D3DSCENELIGHTDIR2
, cssd::Direction3D( 0.2, 0.4, 1.0 ) );
2472 // ----------------------------------------------------------------------------
2474 XclImpChLegend::XclImpChLegend( const XclImpChRoot
& rRoot
) :
2475 XclImpChRoot( rRoot
)
2479 void XclImpChLegend::ReadHeaderRecord( XclImpStream
& rStrm
)
2481 rStrm
>> maData
.maRect
>> maData
.mnDockMode
>> maData
.mnSpacing
>> maData
.mnFlags
;
2483 // trace unsupported features
2484 if( GetTracer().IsEnabled() )
2486 if( maData
.mnDockMode
== EXC_CHLEGEND_NOTDOCKED
)
2487 GetTracer().TraceChartLegendPosition();
2488 if( ::get_flag( maData
.mnFlags
, EXC_CHLEGEND_DATATABLE
) )
2489 GetTracer().TraceChartDataTable();
2493 void XclImpChLegend::ReadSubRecord( XclImpStream
& rStrm
)
2495 switch( rStrm
.GetRecId() )
2497 case EXC_ID_CHFRAMEPOS
:
2498 mxFramePos
.reset( new XclImpChFramePos
);
2499 mxFramePos
->ReadChFramePos( rStrm
);
2502 mxText
.reset( new XclImpChText( GetChRoot() ) );
2503 mxText
->ReadRecordGroup( rStrm
);
2505 case EXC_ID_CHFRAME
:
2506 mxFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_LEGEND
) );
2507 mxFrame
->ReadRecordGroup( rStrm
);
2512 void XclImpChLegend::Finalize()
2514 // legend default formatting differs in OOChart and Excel, missing frame means automatic
2516 mxFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_LEGEND
) );
2517 // Update text formatting. If mxText is empty, the passed default text is used.
2518 lclUpdateText( mxText
, GetChartData().GetDefaultText( EXC_CHTEXTTYPE_LEGEND
) );
2521 Reference
< XLegend
> XclImpChLegend::CreateLegend() const
2523 Reference
< XLegend
> xLegend( ScfApiHelper::CreateInstance( SERVICE_CHART2_LEGEND
), UNO_QUERY
);
2526 ScfPropertySet
aLegendProp( xLegend
);
2527 aLegendProp
.SetBoolProperty( EXC_CHPROP_SHOW
, true );
2531 mxFrame
->Convert( aLegendProp
);
2534 mxText
->ConvertFont( aLegendProp
);
2536 /* Legend position and size. Default positions are used only if the
2537 plot area is positioned automatically (Excel sets the plot area to
2538 manual mode, if the legend is moved or resized). With manual plot
2539 areas, Excel ignores the value in maData.mnDockMode completely. */
2540 cssc2::LegendPosition eApiPos
= cssc2::LegendPosition_CUSTOM
;
2541 cssc::ChartLegendExpansion eApiExpand
= cssc::ChartLegendExpansion_CUSTOM
;
2542 if( !GetChartData().IsManualPlotArea() ) switch( maData
.mnDockMode
)
2544 case EXC_CHLEGEND_LEFT
:
2545 eApiPos
= cssc2::LegendPosition_LINE_START
;
2546 eApiExpand
= cssc::ChartLegendExpansion_HIGH
;
2548 case EXC_CHLEGEND_RIGHT
:
2549 // top-right not supported
2550 case EXC_CHLEGEND_CORNER
:
2551 eApiPos
= cssc2::LegendPosition_LINE_END
;
2552 eApiExpand
= cssc::ChartLegendExpansion_HIGH
;
2554 case EXC_CHLEGEND_TOP
:
2555 eApiPos
= cssc2::LegendPosition_PAGE_START
;
2556 eApiExpand
= cssc::ChartLegendExpansion_WIDE
;
2558 case EXC_CHLEGEND_BOTTOM
:
2559 eApiPos
= cssc2::LegendPosition_PAGE_END
;
2560 eApiExpand
= cssc::ChartLegendExpansion_WIDE
;
2564 // no automatic position/size: try to find the correct position and size
2565 if( eApiPos
== cssc2::LegendPosition_CUSTOM
)
2567 const XclChFramePos
* pFramePos
= mxFramePos
? &mxFramePos
->GetFramePosData() : 0;
2569 /* Legend position. Only the settings from the CHFRAMEPOS record
2570 are used by Excel, the position in the CHLEGEND record will be
2574 RelativePosition
aRelPos(
2575 CalcRelativeFromChartX( pFramePos
->maRect
.mnX
),
2576 CalcRelativeFromChartY( pFramePos
->maRect
.mnY
),
2577 ::com::sun::star::drawing::Alignment_TOP_LEFT
);
2578 aLegendProp
.SetProperty( EXC_CHPROP_RELATIVEPOSITION
, aRelPos
);
2582 // no manual position/size found, just go for the default
2583 eApiPos
= cssc2::LegendPosition_LINE_END
;
2586 /* Legend size. The member mnBRMode specifies whether size is
2587 automatic or changes manually. Manual size is given in points,
2588 not in chart units. */
2589 if( pFramePos
&& (pFramePos
->mnBRMode
== EXC_CHFRAMEPOS_ABSSIZE_POINTS
) &&
2590 (pFramePos
->maRect
.mnWidth
> 0) && (pFramePos
->maRect
.mnHeight
> 0) )
2592 eApiExpand
= cssc::ChartLegendExpansion_CUSTOM
;
2593 sal_Int32 nWidthHmm
= static_cast< sal_Int32
>( pFramePos
->maRect
.mnWidth
/ EXC_POINTS_PER_HMM
);
2594 sal_Int32 nHeightHmm
= static_cast< sal_Int32
>( pFramePos
->maRect
.mnHeight
/ EXC_POINTS_PER_HMM
);
2595 RelativeSize
aRelSize( CalcRelativeFromHmmX( nWidthHmm
), CalcRelativeFromHmmY( nHeightHmm
) );
2596 aLegendProp
.SetProperty( EXC_CHPROP_RELATIVESIZE
, aRelSize
);
2600 // automatic size: determine entry direction from flags
2601 eApiExpand
= ::get_flagvalue( maData
.mnFlags
, EXC_CHLEGEND_STACKED
,
2602 cssc::ChartLegendExpansion_HIGH
, cssc::ChartLegendExpansion_WIDE
);
2605 aLegendProp
.SetProperty( EXC_CHPROP_ANCHORPOSITION
, eApiPos
);
2606 aLegendProp
.SetProperty( EXC_CHPROP_EXPANSION
, eApiExpand
);
2611 // ----------------------------------------------------------------------------
2613 XclImpChDropBar::XclImpChDropBar( sal_uInt16 nDropBar
) :
2614 mnDropBar( nDropBar
),
2619 void XclImpChDropBar::ReadHeaderRecord( XclImpStream
& rStrm
)
2624 void XclImpChDropBar::Convert( const XclImpChRoot
& rRoot
, ScfPropertySet
& rPropSet
) const
2626 XclChObjectType eObjType
= EXC_CHOBJTYPE_BACKGROUND
;
2629 case EXC_CHDROPBAR_UP
: eObjType
= EXC_CHOBJTYPE_WHITEDROPBAR
; break;
2630 case EXC_CHDROPBAR_DOWN
: eObjType
= EXC_CHOBJTYPE_BLACKDROPBAR
; break;
2632 ConvertFrameBase( rRoot
, rPropSet
, eObjType
);
2635 // ----------------------------------------------------------------------------
2637 XclImpChTypeGroup::XclImpChTypeGroup( const XclImpChRoot
& rRoot
) :
2638 XclImpChRoot( rRoot
),
2640 maTypeInfo( maType
.GetTypeInfo() )
2642 // Initialize unused format indexes set. At this time, all formats are unused.
2643 for( sal_uInt16 nFormatIdx
= 0; nFormatIdx
<= EXC_CHSERIES_MAXSERIES
; ++nFormatIdx
)
2644 maUnusedFormats
.insert( maUnusedFormats
.end(), nFormatIdx
);
2647 void XclImpChTypeGroup::ReadHeaderRecord( XclImpStream
& rStrm
)
2650 rStrm
>> maData
.mnFlags
>> maData
.mnGroupIdx
;
2653 void XclImpChTypeGroup::ReadSubRecord( XclImpStream
& rStrm
)
2655 switch( rStrm
.GetRecId() )
2657 case EXC_ID_CHCHART3D
:
2658 mxChart3d
.reset( new XclImpChChart3d
);
2659 mxChart3d
->ReadChChart3d( rStrm
);
2661 case EXC_ID_CHLEGEND
:
2662 mxLegend
.reset( new XclImpChLegend( GetChRoot() ) );
2663 mxLegend
->ReadRecordGroup( rStrm
);
2665 case EXC_ID_CHDEFAULTTEXT
:
2666 GetChartData().ReadChDefaultText( rStrm
);
2668 case EXC_ID_CHDROPBAR
:
2669 ReadChDropBar( rStrm
);
2671 case EXC_ID_CHCHARTLINE
:
2672 ReadChChartLine( rStrm
);
2674 case EXC_ID_CHDATAFORMAT
:
2675 ReadChDataFormat( rStrm
);
2678 maType
.ReadChType( rStrm
);
2682 void XclImpChTypeGroup::Finalize()
2684 // check and set valid chart type
2686 (maType
.GetRecId() == EXC_ID_CHLINE
) && // must be a line chart
2687 !mxChart3d
&& // must be a 2d chart
2688 HasHiLoLine() && // must contain hi-lo lines
2689 (maSeries
.size() == static_cast<XclImpChSeriesVec::size_type
>(HasDropBars() ? 4 : 3)); // correct series count
2690 maType
.Finalize( bStockChart
);
2692 // extended type info
2693 maTypeInfo
.Set( maType
.GetTypeInfo(), static_cast< bool >(mxChart3d
), false );
2695 // reverse series order for some unstacked 2D chart types
2696 if( maTypeInfo
.mbReverseSeries
&& !Is3dChart() && !maType
.IsStacked() && !maType
.IsPercent() )
2697 ::std::reverse( maSeries
.begin(), maSeries
.end() );
2699 // update chart type group format, may depend on chart type finalized above
2701 mxGroupFmt
->UpdateGroupFormat( maTypeInfo
);
2704 void XclImpChTypeGroup::AddSeries( XclImpChSeriesRef xSeries
)
2707 maSeries
.push_back( xSeries
);
2708 // store first inserted series separately, series order may be reversed later
2709 if( !mxFirstSeries
)
2710 mxFirstSeries
= xSeries
;
2713 void XclImpChTypeGroup::SetUsedFormatIndex( sal_uInt16 nFormatIdx
)
2715 maUnusedFormats
.erase( nFormatIdx
);
2718 sal_uInt16
XclImpChTypeGroup::PopUnusedFormatIndex()
2720 OSL_ENSURE( !maUnusedFormats
.empty(), "XclImpChTypeGroup::PopUnusedFormatIndex - no more format indexes available" );
2721 sal_uInt16 nFormatIdx
= maUnusedFormats
.empty() ? 0 : *maUnusedFormats
.begin();
2722 SetUsedFormatIndex( nFormatIdx
);
2726 bool XclImpChTypeGroup::HasVarPointFormat() const
2728 return ::get_flag( maData
.mnFlags
, EXC_CHTYPEGROUP_VARIEDCOLORS
) &&
2729 ((maTypeInfo
.meVarPointMode
== EXC_CHVARPOINT_MULTI
) || // multiple series allowed
2730 ((maTypeInfo
.meVarPointMode
== EXC_CHVARPOINT_SINGLE
) && // or exactly 1 series?
2731 (maSeries
.size() == 1)));
2734 bool XclImpChTypeGroup::HasConnectorLines() const
2736 // existence of connector lines (only in stacked bar charts)
2737 if ( !(maType
.IsStacked() || maType
.IsPercent()) || (maTypeInfo
.meTypeCateg
!= EXC_CHTYPECATEG_BAR
) )
2739 XclImpChLineFormatMap::const_iterator xConLine
= maChartLines
.find( EXC_CHCHARTLINE_CONNECT
);
2740 return ( xConLine
!= maChartLines
.end() && xConLine
->second
->HasLine() );
2743 const String
& XclImpChTypeGroup::GetSingleSeriesTitle() const
2745 // no automatic title for series with trendlines or error bars
2746 // pie charts always show an automatic title, even if more series exist
2747 return (mxFirstSeries
&& !mxFirstSeries
->HasChildSeries() && (maTypeInfo
.mbSingleSeriesVis
|| (maSeries
.size() == 1))) ?
2748 mxFirstSeries
->GetTitle() : String::EmptyString();
2751 void XclImpChTypeGroup::ConvertChart3d( ScfPropertySet
& rPropSet
) const
2754 mxChart3d
->Convert( rPropSet
, Is3dWallChart() );
2757 Reference
< XCoordinateSystem
> XclImpChTypeGroup::CreateCoordSystem() const
2759 return maType
.CreateCoordSystem( Is3dChart() );
2762 Reference
< XChartType
> XclImpChTypeGroup::CreateChartType( Reference
< XDiagram
> xDiagram
, sal_Int32 nApiAxesSetIdx
) const
2764 OSL_ENSURE( IsValidGroup(), "XclImpChTypeGroup::CreateChartType - type group without series" );
2766 // create the chart type object
2767 Reference
< XChartType
> xChartType
= maType
.CreateChartType( xDiagram
, Is3dChart() );
2769 // bar chart connector lines
2770 if( HasConnectorLines() )
2772 ScfPropertySet
aDiaProp( xDiagram
);
2773 aDiaProp
.SetBoolProperty( EXC_CHPROP_CONNECTBARS
, true );
2776 /* Stock chart needs special processing. Create one 'big' series with
2777 data sequences of different roles. */
2778 if( maTypeInfo
.meTypeId
== EXC_CHTYPEID_STOCK
)
2779 CreateStockSeries( xChartType
, nApiAxesSetIdx
);
2781 CreateDataSeries( xChartType
, nApiAxesSetIdx
);
2786 Reference
< XLabeledDataSequence
> XclImpChTypeGroup::CreateCategSequence() const
2788 Reference
< XLabeledDataSequence
> xLabeledSeq
;
2789 // create category sequence from first visible series
2791 xLabeledSeq
= mxFirstSeries
->CreateCategSequence( EXC_CHPROP_ROLE_CATEG
);
2795 void XclImpChTypeGroup::ReadChDropBar( XclImpStream
& rStrm
)
2797 if (maDropBars
.find(EXC_CHDROPBAR_UP
) == maDropBars
.end())
2799 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2800 auto_ptr
<XclImpChDropBar
> p(new XclImpChDropBar(EXC_CHDROPBAR_UP
));
2801 SAL_WNODEPRECATED_DECLARATIONS_POP
2802 p
->ReadRecordGroup(rStrm
);
2803 maDropBars
.insert(EXC_CHDROPBAR_UP
, p
);
2805 else if(maDropBars
.find(EXC_CHDROPBAR_DOWN
) == maDropBars
.end())
2807 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2808 auto_ptr
<XclImpChDropBar
> p(new XclImpChDropBar(EXC_CHDROPBAR_DOWN
));
2809 SAL_WNODEPRECATED_DECLARATIONS_POP
2810 p
->ReadRecordGroup(rStrm
);
2811 maDropBars
.insert(EXC_CHDROPBAR_DOWN
, p
);
2815 void XclImpChTypeGroup::ReadChChartLine( XclImpStream
& rStrm
)
2817 sal_uInt16 nLineId
= rStrm
.ReaduInt16();
2818 if( (rStrm
.GetNextRecId() == EXC_ID_CHLINEFORMAT
) && rStrm
.StartNextRecord() )
2820 XclImpChLineFormat xLineFmt
;
2821 xLineFmt
.ReadChLineFormat( rStrm
);
2822 maChartLines
[ nLineId
] = xLineFmt
;
2826 void XclImpChTypeGroup::ReadChDataFormat( XclImpStream
& rStrm
)
2828 // global series and data point format
2829 XclImpChDataFormatRef
xDataFmt( new XclImpChDataFormat( GetChRoot() ) );
2830 xDataFmt
->ReadRecordGroup( rStrm
);
2831 const XclChDataPointPos
& rPos
= xDataFmt
->GetPointPos();
2832 if( (rPos
.mnSeriesIdx
== 0) && (rPos
.mnPointIdx
== 0) &&
2833 (xDataFmt
->GetFormatIdx() == EXC_CHDATAFORMAT_DEFAULT
) )
2834 mxGroupFmt
= xDataFmt
;
2838 void XclImpChTypeGroup::InsertDataSeries( Reference
< XChartType
> xChartType
,
2839 Reference
< XDataSeries
> xSeries
, sal_Int32 nApiAxesSetIdx
) const
2841 Reference
< XDataSeriesContainer
> xSeriesCont( xChartType
, UNO_QUERY
);
2842 if( xSeriesCont
.is() && xSeries
.is() )
2844 // series stacking mode
2845 cssc2::StackingDirection eStacking
= cssc2::StackingDirection_NO_STACKING
;
2846 // stacked overrides deep-3d
2847 if( maType
.IsStacked() || maType
.IsPercent() )
2848 eStacking
= cssc2::StackingDirection_Y_STACKING
;
2849 else if( Is3dDeepChart() )
2850 eStacking
= cssc2::StackingDirection_Z_STACKING
;
2852 // additional series properties
2853 ScfPropertySet
aSeriesProp( xSeries
);
2854 aSeriesProp
.SetProperty( EXC_CHPROP_STACKINGDIR
, eStacking
);
2855 aSeriesProp
.SetProperty( EXC_CHPROP_ATTAXISINDEX
, nApiAxesSetIdx
);
2857 // insert series into container
2860 xSeriesCont
->addDataSeries( xSeries
);
2864 OSL_FAIL( "XclImpChTypeGroup::InsertDataSeries - cannot add data series" );
2869 void XclImpChTypeGroup::CreateDataSeries( Reference
< XChartType
> xChartType
, sal_Int32 nApiAxesSetIdx
) const
2871 bool bSpline
= false;
2872 for( XclImpChSeriesVec::const_iterator aIt
= maSeries
.begin(), aEnd
= maSeries
.end(); aIt
!= aEnd
; ++aIt
)
2874 Reference
< XDataSeries
> xDataSeries
= (*aIt
)->CreateDataSeries();
2875 InsertDataSeries( xChartType
, xDataSeries
, nApiAxesSetIdx
);
2876 bSpline
|= (*aIt
)->HasSpline();
2878 // spline - TODO: set at single series (#i66858#)
2879 if( bSpline
&& !maTypeInfo
.IsSeriesFrameFormat() && (maTypeInfo
.meTypeCateg
!= EXC_CHTYPECATEG_RADAR
) )
2881 ScfPropertySet
aTypeProp( xChartType
);
2882 aTypeProp
.SetProperty( EXC_CHPROP_CURVESTYLE
, ::com::sun::star::chart2::CurveStyle_CUBIC_SPLINES
);
2886 void XclImpChTypeGroup::CreateStockSeries( Reference
< XChartType
> xChartType
, sal_Int32 nApiAxesSetIdx
) const
2888 // create the data series object
2889 Reference
< XDataSeries
> xDataSeries( ScfApiHelper::CreateInstance( SERVICE_CHART2_DATASERIES
), UNO_QUERY
);
2890 Reference
< XDataSink
> xDataSink( xDataSeries
, UNO_QUERY
);
2891 if( xDataSink
.is() )
2893 // create a list of data sequences from all series
2894 ::std::vector
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
;
2895 OSL_ENSURE( maSeries
.size() >= 3, "XclImpChTypeGroup::CreateChartType - missing stock series" );
2896 int nRoleIdx
= (maSeries
.size() == 3) ? 1 : 0;
2897 for( XclImpChSeriesVec::const_iterator aIt
= maSeries
.begin(), aEnd
= maSeries
.end();
2898 (nRoleIdx
< 4) && (aIt
!= aEnd
); ++nRoleIdx
, ++aIt
)
2900 // create a data sequence with a specific role
2904 case 0: aRole
= EXC_CHPROP_ROLE_OPENVALUES
; break;
2905 case 1: aRole
= EXC_CHPROP_ROLE_HIGHVALUES
; break;
2906 case 2: aRole
= EXC_CHPROP_ROLE_LOWVALUES
; break;
2907 case 3: aRole
= EXC_CHPROP_ROLE_CLOSEVALUES
; break;
2909 Reference
< XLabeledDataSequence
> xDataSeq
= (*aIt
)->CreateValueSequence( aRole
);
2911 aLabeledSeqVec
.push_back( xDataSeq
);
2914 // attach labeled data sequences to series and insert series into chart type
2915 xDataSink
->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec
) );
2917 // formatting of special stock chart elements
2918 ScfPropertySet
aTypeProp( xChartType
);
2919 aTypeProp
.SetBoolProperty( EXC_CHPROP_JAPANESE
, HasDropBars() );
2920 aTypeProp
.SetBoolProperty( EXC_CHPROP_SHOWFIRST
, HasDropBars() );
2921 aTypeProp
.SetBoolProperty( EXC_CHPROP_SHOWHIGHLOW
, true );
2922 // hi-lo line format
2923 XclImpChLineFormatMap::const_iterator xHiLoLine
= maChartLines
.find( EXC_CHCHARTLINE_HILO
);
2924 if ( xHiLoLine
!= maChartLines
.end() )
2926 ScfPropertySet
aSeriesProp( xDataSeries
);
2927 xHiLoLine
->second
->Convert( GetChRoot(), aSeriesProp
, EXC_CHOBJTYPE_HILOLINE
);
2929 // white dropbar format
2930 XclImpChDropBarMap::const_iterator itr
= maDropBars
.find(EXC_CHDROPBAR_UP
);
2931 Reference
<XPropertySet
> xWhitePropSet
;
2932 if (itr
!= maDropBars
.end() && aTypeProp
.GetProperty(xWhitePropSet
, EXC_CHPROP_WHITEDAY
))
2934 ScfPropertySet
aBarProp( xWhitePropSet
);
2935 itr
->second
->Convert(GetChRoot(), aBarProp
);
2937 // black dropbar format
2938 itr
= maDropBars
.find(EXC_CHDROPBAR_DOWN
);
2939 Reference
<XPropertySet
> xBlackPropSet
;
2940 if (itr
!= maDropBars
.end() && aTypeProp
.GetProperty(xBlackPropSet
, EXC_CHPROP_BLACKDAY
))
2942 ScfPropertySet
aBarProp( xBlackPropSet
);
2943 itr
->second
->Convert(GetChRoot(), aBarProp
);
2946 // insert the series into the chart type object
2947 InsertDataSeries( xChartType
, xDataSeries
, nApiAxesSetIdx
);
2951 // Axes =======================================================================
2953 XclImpChLabelRange::XclImpChLabelRange( const XclImpChRoot
& rRoot
) :
2954 XclImpChRoot( rRoot
)
2958 void XclImpChLabelRange::ReadChLabelRange( XclImpStream
& rStrm
)
2960 rStrm
>> maLabelData
.mnCross
>> maLabelData
.mnLabelFreq
>> maLabelData
.mnTickFreq
>> maLabelData
.mnFlags
;
2963 void XclImpChLabelRange::ReadChDateRange( XclImpStream
& rStrm
)
2965 rStrm
>> maDateData
.mnMinDate
2966 >> maDateData
.mnMaxDate
2967 >> maDateData
.mnMajorStep
2968 >> maDateData
.mnMajorUnit
2969 >> maDateData
.mnMinorStep
2970 >> maDateData
.mnMinorUnit
2971 >> maDateData
.mnBaseUnit
2972 >> maDateData
.mnCross
2973 >> maDateData
.mnFlags
;
2976 void XclImpChLabelRange::Convert( ScfPropertySet
& rPropSet
, ScaleData
& rScaleData
, bool bMirrorOrient
) const
2978 // automatic axis type detection
2979 rScaleData
.AutoDateAxis
= ::get_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTODATE
);
2981 // the flag EXC_CHDATERANGE_DATEAXIS specifies whether this is a date axis
2982 if( ::get_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_DATEAXIS
) )
2984 /* Chart2 requires axis type CATEGORY for automatic category/date axis
2985 (even if it is a date axis currently). */
2986 rScaleData
.AxisType
= rScaleData
.AutoDateAxis
? cssc2::AxisType::CATEGORY
: cssc2::AxisType::DATE
;
2987 rScaleData
.Scaling
= css::chart2::LinearScaling::create( comphelper::getProcessComponentContext() );
2988 /* Min/max values depend on base time unit, they specify the number of
2989 days, months, or years starting from null date. */
2990 lclConvertTimeValue( GetRoot(), rScaleData
.Minimum
, maDateData
.mnMinDate
, ::get_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOMIN
), maDateData
.mnBaseUnit
);
2991 lclConvertTimeValue( GetRoot(), rScaleData
.Maximum
, maDateData
.mnMaxDate
, ::get_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOMAX
), maDateData
.mnBaseUnit
);
2993 cssc::TimeIncrement
& rTimeIncrement
= rScaleData
.TimeIncrement
;
2994 lclConvertTimeInterval( rTimeIncrement
.MajorTimeInterval
, maDateData
.mnMajorStep
, ::get_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOMAJOR
), maDateData
.mnMajorUnit
);
2995 lclConvertTimeInterval( rTimeIncrement
.MinorTimeInterval
, maDateData
.mnMinorStep
, ::get_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOMINOR
), maDateData
.mnMinorUnit
);
2997 if( ::get_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOBASE
) )
2998 rTimeIncrement
.TimeResolution
.clear();
3000 rTimeIncrement
.TimeResolution
<<= lclGetApiTimeUnit( maDateData
.mnBaseUnit
);
3004 // do not overlap text unless all labels are visible
3005 rPropSet
.SetBoolProperty( EXC_CHPROP_TEXTOVERLAP
, maLabelData
.mnLabelFreq
== 1 );
3006 // do not break text into several lines unless all labels are visible
3007 rPropSet
.SetBoolProperty( EXC_CHPROP_TEXTBREAK
, maLabelData
.mnLabelFreq
== 1 );
3008 // do not stagger labels in two lines
3009 rPropSet
.SetProperty( EXC_CHPROP_ARRANGEORDER
, cssc::ChartAxisArrangeOrderType_SIDE_BY_SIDE
);
3013 bool bReverse
= ::get_flag( maLabelData
.mnFlags
, EXC_CHLABELRANGE_REVERSE
) != bMirrorOrient
;
3014 rScaleData
.Orientation
= bReverse
? cssc2::AxisOrientation_REVERSE
: cssc2::AxisOrientation_MATHEMATICAL
;
3016 //! TODO #i58731# show n-th category
3019 void XclImpChLabelRange::ConvertAxisPosition( ScfPropertySet
& rPropSet
, bool b3dChart
) const
3021 /* Crossing mode (max-cross flag overrides other crossing settings). Excel
3022 does not move the Y axis in 3D charts, regardless of actual settings.
3023 But: the Y axis has to be moved to "end", if the X axis is mirrored,
3024 to keep it at the left end of the chart. */
3025 bool bMaxCross
= ::get_flag( maLabelData
.mnFlags
, b3dChart
? EXC_CHLABELRANGE_REVERSE
: EXC_CHLABELRANGE_MAXCROSS
);
3026 cssc::ChartAxisPosition eAxisPos
= bMaxCross
? cssc::ChartAxisPosition_END
: cssc::ChartAxisPosition_VALUE
;
3027 rPropSet
.SetProperty( EXC_CHPROP_CROSSOVERPOSITION
, eAxisPos
);
3029 // crossing position (depending on axis type text/date)
3030 if( ::get_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_DATEAXIS
) )
3032 bool bAutoCross
= ::get_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOCROSS
);
3033 /* Crossing position value depends on base time unit, it specifies the
3034 number of days, months, or years from null date. Note that Excel
3035 2007/2010 write broken BIFF8 files, they always stores the number
3036 of days cregardless of the base time unit (and they are reading it
3037 the same way, thus wrongly displaying files written by Excel
3038 97-2003). This filter sticks to the correct behaviour of Excel
3040 double fCrossingPos
= bAutoCross
? 1.0 : lclGetSerialDay( GetRoot(), maDateData
.mnCross
, maDateData
.mnBaseUnit
);
3041 rPropSet
.SetProperty( EXC_CHPROP_CROSSOVERVALUE
, fCrossingPos
);
3045 double fCrossingPos
= b3dChart
? 1.0 : maLabelData
.mnCross
;
3046 rPropSet
.SetProperty( EXC_CHPROP_CROSSOVERVALUE
, fCrossingPos
);
3050 // ----------------------------------------------------------------------------
3052 XclImpChValueRange::XclImpChValueRange( const XclImpChRoot
& rRoot
) :
3053 XclImpChRoot( rRoot
)
3057 void XclImpChValueRange::ReadChValueRange( XclImpStream
& rStrm
)
3059 rStrm
>> maData
.mfMin
3061 >> maData
.mfMajorStep
3062 >> maData
.mfMinorStep
3067 void XclImpChValueRange::Convert( ScaleData
& rScaleData
, bool bMirrorOrient
) const
3069 // scaling algorithm
3070 bool bLogScale
= ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_LOGSCALE
);
3072 rScaleData
.Scaling
= css::chart2::LogarithmicScaling::create( comphelper::getProcessComponentContext() );
3074 rScaleData
.Scaling
= css::chart2::LinearScaling::create( comphelper::getProcessComponentContext() );
3077 lclSetExpValueOrClearAny( rScaleData
.Minimum
, maData
.mfMin
, bLogScale
, ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMIN
) );
3078 lclSetExpValueOrClearAny( rScaleData
.Maximum
, maData
.mfMax
, bLogScale
, ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMAX
) );
3081 bool bAutoMajor
= ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMAJOR
);
3082 bool bAutoMinor
= ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMINOR
);
3084 IncrementData
& rIncrementData
= rScaleData
.IncrementData
;
3085 lclSetValueOrClearAny( rIncrementData
.Distance
, maData
.mfMajorStep
, bAutoMajor
);
3087 Sequence
< SubIncrement
>& rSubIncrementSeq
= rIncrementData
.SubIncrements
;
3088 rSubIncrementSeq
.realloc( 1 );
3089 Any
& rIntervalCount
= rSubIncrementSeq
[ 0 ].IntervalCount
;
3090 rIntervalCount
.clear();
3094 rIntervalCount
<<= sal_Int32( 9 );
3098 if( !bAutoMajor
&& !bAutoMinor
&& (0.0 < maData
.mfMinorStep
) && (maData
.mfMinorStep
<= maData
.mfMajorStep
) )
3100 double fCount
= maData
.mfMajorStep
/ maData
.mfMinorStep
+ 0.5;
3101 if( (1.0 <= fCount
) && (fCount
< 1001.0) )
3102 rIntervalCount
<<= static_cast< sal_Int32
>( fCount
);
3107 bool bReverse
= ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_REVERSE
) != bMirrorOrient
;
3108 rScaleData
.Orientation
= bReverse
? cssc2::AxisOrientation_REVERSE
: cssc2::AxisOrientation_MATHEMATICAL
;
3111 void XclImpChValueRange::ConvertAxisPosition( ScfPropertySet
& rPropSet
) const
3113 bool bMaxCross
= ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_MAXCROSS
);
3114 bool bAutoCross
= ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
);
3115 bool bLogScale
= ::get_flag( maData
.mnFlags
, EXC_CHVALUERANGE_LOGSCALE
);
3117 // crossing mode (max-cross flag overrides other crossing settings)
3118 cssc::ChartAxisPosition eAxisPos
= bMaxCross
? cssc::ChartAxisPosition_END
: cssc::ChartAxisPosition_VALUE
;
3119 rPropSet
.SetProperty( EXC_CHPROP_CROSSOVERPOSITION
, eAxisPos
);
3121 // crossing position
3122 double fCrossingPos
= bAutoCross
? 0.0 : maData
.mfCross
;
3123 if( bLogScale
) fCrossingPos
= pow( 10.0, fCrossingPos
);
3124 rPropSet
.SetProperty( EXC_CHPROP_CROSSOVERVALUE
, fCrossingPos
);
3127 // ----------------------------------------------------------------------------
3131 sal_Int32
lclGetApiTickmarks( sal_uInt8 nXclTickPos
)
3133 using namespace ::com::sun::star::chart2::TickmarkStyle
;
3134 sal_Int32 nApiTickmarks
= NONE
;
3135 ::set_flag( nApiTickmarks
, INNER
, ::get_flag( nXclTickPos
, EXC_CHTICK_INSIDE
) );
3136 ::set_flag( nApiTickmarks
, OUTER
, ::get_flag( nXclTickPos
, EXC_CHTICK_OUTSIDE
) );
3137 return nApiTickmarks
;
3140 cssc::ChartAxisLabelPosition
lclGetApiLabelPosition( sal_Int8 nXclLabelPos
)
3142 using namespace ::com::sun::star::chart
;
3143 switch( nXclLabelPos
)
3145 case EXC_CHTICK_LOW
: return ChartAxisLabelPosition_OUTSIDE_START
;
3146 case EXC_CHTICK_HIGH
: return ChartAxisLabelPosition_OUTSIDE_END
;
3147 case EXC_CHTICK_NEXT
: return ChartAxisLabelPosition_NEAR_AXIS
;
3149 return ChartAxisLabelPosition_NEAR_AXIS
;
3154 XclImpChTick::XclImpChTick( const XclImpChRoot
& rRoot
) :
3155 XclImpChRoot( rRoot
)
3159 void XclImpChTick::ReadChTick( XclImpStream
& rStrm
)
3161 rStrm
>> maData
.mnMajor
3163 >> maData
.mnLabelPos
3164 >> maData
.mnBackMode
;
3166 rStrm
>> maData
.maTextColor
3169 if( GetBiff() == EXC_BIFF8
)
3171 // BIFF8: index into palette used instead of RGB data
3172 maData
.maTextColor
= GetPalette().GetColor( rStrm
.ReaduInt16() );
3174 rStrm
>> maData
.mnRotation
;
3178 // BIFF2-BIFF7: get rotation from text orientation
3179 sal_uInt8 nOrient
= ::extract_value
< sal_uInt8
>( maData
.mnFlags
, 2, 3 );
3180 maData
.mnRotation
= XclTools::GetXclRotFromOrient( nOrient
);
3184 Color
XclImpChTick::GetFontColor() const
3186 return ::get_flag( maData
.mnFlags
, EXC_CHTICK_AUTOCOLOR
) ? GetFontAutoColor() : maData
.maTextColor
;
3189 sal_uInt16
XclImpChTick::GetRotation() const
3191 /* n#720443: Ignore auto-rotation if there is a suggested rotation.
3192 * Better fix would be to improve our axis auto rotation algorithm.
3194 if( maData
.mnRotation
!= EXC_ROT_NONE
)
3195 return maData
.mnRotation
;
3196 return ::get_flag( maData
.mnFlags
, EXC_CHTICK_AUTOROT
) ? EXC_CHART_AUTOROTATION
: maData
.mnRotation
;
3199 void XclImpChTick::Convert( ScfPropertySet
& rPropSet
) const
3201 rPropSet
.SetProperty( EXC_CHPROP_MAJORTICKS
, lclGetApiTickmarks( maData
.mnMajor
) );
3202 rPropSet
.SetProperty( EXC_CHPROP_MINORTICKS
, lclGetApiTickmarks( maData
.mnMinor
) );
3203 rPropSet
.SetProperty( EXC_CHPROP_LABELPOSITION
, lclGetApiLabelPosition( maData
.mnLabelPos
) );
3204 rPropSet
.SetProperty( EXC_CHPROP_MARKPOSITION
, cssc::ChartAxisMarkPosition_AT_AXIS
);
3207 // ----------------------------------------------------------------------------
3209 XclImpChAxis::XclImpChAxis( const XclImpChRoot
& rRoot
, sal_uInt16 nAxisType
) :
3210 XclImpChRoot( rRoot
),
3211 mnNumFmtIdx( EXC_FORMAT_NOTFOUND
)
3213 maData
.mnType
= nAxisType
;
3216 void XclImpChAxis::ReadHeaderRecord( XclImpStream
& rStrm
)
3218 rStrm
>> maData
.mnType
;
3221 void XclImpChAxis::ReadSubRecord( XclImpStream
& rStrm
)
3223 switch( rStrm
.GetRecId() )
3225 case EXC_ID_CHLABELRANGE
:
3226 mxLabelRange
.reset( new XclImpChLabelRange( GetChRoot() ) );
3227 mxLabelRange
->ReadChLabelRange( rStrm
);
3229 case EXC_ID_CHDATERANGE
:
3231 mxLabelRange
.reset( new XclImpChLabelRange( GetChRoot() ) );
3232 mxLabelRange
->ReadChDateRange( rStrm
);
3234 case EXC_ID_CHVALUERANGE
:
3235 mxValueRange
.reset( new XclImpChValueRange( GetChRoot() ) );
3236 mxValueRange
->ReadChValueRange( rStrm
);
3238 case EXC_ID_CHFORMAT
:
3239 rStrm
>> mnNumFmtIdx
;
3242 mxTick
.reset( new XclImpChTick( GetChRoot() ) );
3243 mxTick
->ReadChTick( rStrm
);
3246 mxFont
.reset( new XclImpChFont
);
3247 mxFont
->ReadChFont( rStrm
);
3249 case EXC_ID_CHAXISLINE
:
3250 ReadChAxisLine( rStrm
);
3255 void XclImpChAxis::Finalize()
3257 // add default scaling, needed e.g. to adjust rotation direction of pie and radar charts
3259 mxLabelRange
.reset( new XclImpChLabelRange( GetChRoot() ) );
3261 mxValueRange
.reset( new XclImpChValueRange( GetChRoot() ) );
3262 // remove invisible grid lines completely
3263 if( mxMajorGrid
&& !mxMajorGrid
->HasLine() )
3264 mxMajorGrid
.reset();
3265 if( mxMinorGrid
&& !mxMinorGrid
->HasLine() )
3266 mxMinorGrid
.reset();
3267 // default tick settings different in OOChart and Excel
3269 mxTick
.reset( new XclImpChTick( GetChRoot() ) );
3270 // #i4140# different default axis line color
3273 XclChLineFormat aLineFmt
;
3274 // set "show axis" flag, default if line format record is missing
3275 ::set_flag( aLineFmt
.mnFlags
, EXC_CHLINEFORMAT_SHOWAXIS
);
3276 mxAxisLine
.reset( new XclImpChLineFormat( aLineFmt
) );
3278 // add wall/floor frame for 3d charts
3283 sal_uInt16
XclImpChAxis::GetFontIndex() const
3285 return mxFont
? mxFont
->GetFontIndex() : EXC_FONT_NOTFOUND
;
3288 Color
XclImpChAxis::GetFontColor() const
3290 return mxTick
? mxTick
->GetFontColor() : GetFontAutoColor();
3293 sal_uInt16
XclImpChAxis::GetRotation() const
3295 return mxTick
? mxTick
->GetRotation() : EXC_CHART_AUTOROTATION
;
3298 Reference
< XAxis
> XclImpChAxis::CreateAxis( const XclImpChTypeGroup
& rTypeGroup
, const XclImpChAxis
* pCrossingAxis
) const
3300 // create the axis object (always)
3301 Reference
< XAxis
> xAxis( ScfApiHelper::CreateInstance( SERVICE_CHART2_AXIS
), UNO_QUERY
);
3304 ScfPropertySet
aAxisProp( xAxis
);
3305 // #i58688# axis enabled
3306 aAxisProp
.SetBoolProperty( EXC_CHPROP_SHOW
, IsActivated() );
3308 // axis line properties
3310 mxAxisLine
->Convert( GetChRoot(), aAxisProp
, EXC_CHOBJTYPE_AXISLINE
);
3311 // axis ticks properties
3313 mxTick
->Convert( aAxisProp
);
3315 // axis caption text --------------------------------------------------
3317 // radar charts disable their category labels via chart type, not via axis
3318 bool bHasLabels
= HasLabels() &&
3319 ((GetAxisType() != EXC_CHAXIS_X
) || rTypeGroup
.HasCategoryLabels());
3320 aAxisProp
.SetBoolProperty( EXC_CHPROP_DISPLAYLABELS
, bHasLabels
);
3323 // font settings from CHFONT record or from default text
3325 ConvertFontBase( GetChRoot(), aAxisProp
);
3326 else if( const XclImpChText
* pDefText
= GetChartData().GetDefaultText( EXC_CHTEXTTYPE_AXISLABEL
) )
3327 pDefText
->ConvertFont( aAxisProp
);
3328 // label text rotation
3329 ConvertRotationBase( GetChRoot(), aAxisProp
, true );
3331 sal_uInt32 nScNumFmt
= GetNumFmtBuffer().GetScFormat( mnNumFmtIdx
);
3332 if( nScNumFmt
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
3333 aAxisProp
.SetProperty( EXC_CHPROP_NUMBERFORMAT
, static_cast< sal_Int32
>( nScNumFmt
) );
3336 // axis scaling and increment -----------------------------------------
3338 const XclChExtTypeInfo
& rTypeInfo
= rTypeGroup
.GetTypeInfo();
3339 ScaleData aScaleData
= xAxis
->getScaleData();
3341 switch( GetAxisType() )
3344 if( rTypeInfo
.mbCategoryAxis
)
3346 aScaleData
.AxisType
= cssc2::AxisType::CATEGORY
;
3347 aScaleData
.Categories
= rTypeGroup
.CreateCategSequence();
3350 aScaleData
.AxisType
= cssc2::AxisType::REALNUMBER
;
3353 aScaleData
.AxisType
= rTypeGroup
.IsPercent() ?
3354 cssc2::AxisType::PERCENT
: cssc2::AxisType::REALNUMBER
;
3357 aScaleData
.AxisType
= cssc2::AxisType::SERIES
;
3360 // axis scaling settings, dependent on axis type
3361 switch( aScaleData
.AxisType
)
3363 case cssc2::AxisType::CATEGORY
:
3364 case cssc2::AxisType::SERIES
:
3365 OSL_ENSURE( mxLabelRange
, "Missing Label Range" );
3366 // #i71684# radar charts have reversed rotation direction
3368 mxLabelRange
->Convert( aAxisProp
, aScaleData
, rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_RADAR
);
3370 case cssc2::AxisType::REALNUMBER
:
3371 case cssc2::AxisType::PERCENT
:
3372 // #i85167# pie/donut charts have reversed rotation direction (at Y axis!)
3373 mxValueRange
->Convert( aScaleData
, rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
);
3376 OSL_FAIL( "XclImpChAxis::CreateAxis - unknown axis type" );
3379 /* Do not set a value to the Origin member anymore (will be done via
3380 new axis properties 'CrossoverPosition' and 'CrossoverValue'). */
3381 aScaleData
.Origin
.clear();
3384 xAxis
->setScaleData( aScaleData
);
3386 // grid ---------------------------------------------------------------
3389 ScfPropertySet
aGridProp( xAxis
->getGridProperties() );
3390 aGridProp
.SetBoolProperty( EXC_CHPROP_SHOW
, HasMajorGrid() );
3392 mxMajorGrid
->Convert( GetChRoot(), aGridProp
, EXC_CHOBJTYPE_GRIDLINE
);
3394 Sequence
< Reference
< XPropertySet
> > aSubGridPropSeq
= xAxis
->getSubGridProperties();
3395 if( aSubGridPropSeq
.hasElements() )
3397 ScfPropertySet
aSubGridProp( aSubGridPropSeq
[ 0 ] );
3398 aSubGridProp
.SetBoolProperty( EXC_CHPROP_SHOW
, HasMinorGrid() );
3400 mxMinorGrid
->Convert( GetChRoot(), aSubGridProp
, EXC_CHOBJTYPE_GRIDLINE
);
3403 // position of crossing axis ------------------------------------------
3406 pCrossingAxis
->ConvertAxisPosition( aAxisProp
, rTypeGroup
);
3411 void XclImpChAxis::ConvertWall( ScfPropertySet
& rPropSet
) const
3413 // #i71810# walls and floor in 3D charts use the CHPICFORMAT record for bitmap mode
3415 mxWallFrame
->Convert( rPropSet
, true );
3418 void XclImpChAxis::ConvertAxisPosition( ScfPropertySet
& rPropSet
, const XclImpChTypeGroup
& rTypeGroup
) const
3420 if( ((GetAxisType() == EXC_CHAXIS_X
) && rTypeGroup
.GetTypeInfo().mbCategoryAxis
) || (GetAxisType() == EXC_CHAXIS_Z
) )
3422 OSL_ENSURE( mxLabelRange
, "Missing Label Range" );
3424 mxLabelRange
->ConvertAxisPosition( rPropSet
, rTypeGroup
.Is3dChart() );
3427 mxValueRange
->ConvertAxisPosition( rPropSet
);
3430 void XclImpChAxis::ReadChAxisLine( XclImpStream
& rStrm
)
3432 XclImpChLineFormatRef
* pxLineFmt
= 0;
3433 bool bWallFrame
= false;
3434 switch( rStrm
.ReaduInt16() )
3436 case EXC_CHAXISLINE_AXISLINE
: pxLineFmt
= &mxAxisLine
; break;
3437 case EXC_CHAXISLINE_MAJORGRID
: pxLineFmt
= &mxMajorGrid
; break;
3438 case EXC_CHAXISLINE_MINORGRID
: pxLineFmt
= &mxMinorGrid
; break;
3439 case EXC_CHAXISLINE_WALLS
: bWallFrame
= true; break;
3444 bool bLoop
= pxLineFmt
|| bWallFrame
;
3447 sal_uInt16 nRecId
= rStrm
.GetNextRecId();
3448 bLoop
= ((nRecId
== EXC_ID_CHLINEFORMAT
) ||
3449 (nRecId
== EXC_ID_CHAREAFORMAT
) ||
3450 (nRecId
== EXC_ID_CHESCHERFORMAT
))
3451 && rStrm
.StartNextRecord();
3454 if( pxLineFmt
&& (nRecId
== EXC_ID_CHLINEFORMAT
) )
3456 pxLineFmt
->reset( new XclImpChLineFormat
);
3457 (*pxLineFmt
)->ReadChLineFormat( rStrm
);
3459 else if( bWallFrame
&& mxWallFrame
)
3461 mxWallFrame
->ReadSubRecord( rStrm
);
3467 void XclImpChAxis::CreateWallFrame()
3469 switch( GetAxisType() )
3472 mxWallFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_WALL3D
) );
3475 mxWallFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_FLOOR3D
) );
3478 mxWallFrame
.reset();
3482 // ----------------------------------------------------------------------------
3484 XclImpChAxesSet::XclImpChAxesSet( const XclImpChRoot
& rRoot
, sal_uInt16 nAxesSetId
) :
3485 XclImpChRoot( rRoot
)
3487 maData
.mnAxesSetId
= nAxesSetId
;
3490 void XclImpChAxesSet::ReadHeaderRecord( XclImpStream
& rStrm
)
3492 rStrm
>> maData
.mnAxesSetId
>> maData
.maRect
;
3495 void XclImpChAxesSet::ReadSubRecord( XclImpStream
& rStrm
)
3497 switch( rStrm
.GetRecId() )
3499 case EXC_ID_CHFRAMEPOS
:
3500 mxFramePos
.reset( new XclImpChFramePos
);
3501 mxFramePos
->ReadChFramePos( rStrm
);
3504 ReadChAxis( rStrm
);
3507 ReadChText( rStrm
);
3509 case EXC_ID_CHPLOTFRAME
:
3510 ReadChPlotFrame( rStrm
);
3512 case EXC_ID_CHTYPEGROUP
:
3513 ReadChTypeGroup( rStrm
);
3518 void XclImpChAxesSet::Finalize()
3520 if( IsValidAxesSet() )
3522 // finalize chart type groups, erase empty groups without series
3523 XclImpChTypeGroupMap aValidGroups
;
3524 for( XclImpChTypeGroupMap::const_iterator aIt
= maTypeGroups
.begin(), aEnd
= maTypeGroups
.end(); aIt
!= aEnd
; ++aIt
)
3526 XclImpChTypeGroupRef xTypeGroup
= aIt
->second
;
3527 xTypeGroup
->Finalize();
3528 if( xTypeGroup
->IsValidGroup() )
3529 aValidGroups
.insert(
3530 XclImpChTypeGroupMap::value_type(aIt
->first
, xTypeGroup
));
3532 maTypeGroups
.swap( aValidGroups
);
3535 // invalid chart type groups are deleted now, check again with IsValidAxesSet()
3536 if( IsValidAxesSet() )
3538 // always create missing axis objects
3540 mxXAxis
.reset( new XclImpChAxis( GetChRoot(), EXC_CHAXIS_X
) );
3542 mxYAxis
.reset( new XclImpChAxis( GetChRoot(), EXC_CHAXIS_Y
) );
3543 if( !mxZAxis
&& GetFirstTypeGroup()->Is3dDeepChart() )
3544 mxZAxis
.reset( new XclImpChAxis( GetChRoot(), EXC_CHAXIS_Z
) );
3547 if( mxXAxis
) mxXAxis
->Finalize();
3548 if( mxYAxis
) mxYAxis
->Finalize();
3549 if( mxZAxis
) mxZAxis
->Finalize();
3551 // finalize axis titles
3552 const XclImpChText
* pDefText
= GetChartData().GetDefaultText( EXC_CHTEXTTYPE_AXISTITLE
);
3553 String
aAutoTitle("Axis Title");
3554 lclFinalizeTitle( mxXAxisTitle
, pDefText
, aAutoTitle
);
3555 lclFinalizeTitle( mxYAxisTitle
, pDefText
, aAutoTitle
);
3556 lclFinalizeTitle( mxZAxisTitle
, pDefText
, aAutoTitle
);
3558 // #i47745# missing plot frame -> invisible border and area
3560 mxPlotFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_PLOTFRAME
) );
3564 XclImpChTypeGroupRef
XclImpChAxesSet::GetTypeGroup( sal_uInt16 nGroupIdx
) const
3566 XclImpChTypeGroupMap::const_iterator itr
= maTypeGroups
.find(nGroupIdx
);
3567 return itr
== maTypeGroups
.end() ? XclImpChTypeGroupRef() : itr
->second
;
3570 XclImpChTypeGroupRef
XclImpChAxesSet::GetFirstTypeGroup() const
3572 XclImpChTypeGroupRef xTypeGroup
;
3573 if( !maTypeGroups
.empty() )
3574 xTypeGroup
= maTypeGroups
.begin()->second
;
3578 XclImpChLegendRef
XclImpChAxesSet::GetLegend() const
3580 XclImpChLegendRef xLegend
;
3581 for( XclImpChTypeGroupMap::const_iterator aIt
= maTypeGroups
.begin(), aEnd
= maTypeGroups
.end(); !xLegend
&& (aIt
!= aEnd
); ++aIt
)
3582 xLegend
= aIt
->second
->GetLegend();
3586 const String
& XclImpChAxesSet::GetSingleSeriesTitle() const
3588 return (maTypeGroups
.size() == 1) ? maTypeGroups
.begin()->second
->GetSingleSeriesTitle() : String::EmptyString();
3591 void XclImpChAxesSet::Convert( Reference
< XDiagram
> xDiagram
) const
3593 if( IsValidAxesSet() && xDiagram
.is() )
3595 // diagram background formatting
3596 if( GetAxesSetId() == EXC_CHAXESSET_PRIMARY
)
3597 ConvertBackground( xDiagram
);
3599 // create the coordinate system, this inserts all chart types and series
3600 Reference
< XCoordinateSystem
> xCoordSystem
= CreateCoordSystem( xDiagram
);
3601 if( xCoordSystem
.is() )
3603 // insert coordinate system, if not already done
3606 Reference
< XCoordinateSystemContainer
> xCoordSystemCont( xDiagram
, UNO_QUERY_THROW
);
3607 Sequence
< Reference
< XCoordinateSystem
> > aCoordSystems
= xCoordSystemCont
->getCoordinateSystems();
3608 if( aCoordSystems
.getLength() == 0 )
3609 xCoordSystemCont
->addCoordinateSystem( xCoordSystem
);
3613 OSL_FAIL( "XclImpChAxesSet::Convert - cannot insert coordinate system" );
3616 // create the axes with grids and axis titles and insert them into the diagram
3617 ConvertAxis( mxXAxis
, mxXAxisTitle
, xCoordSystem
, mxYAxis
.get() );
3618 ConvertAxis( mxYAxis
, mxYAxisTitle
, xCoordSystem
, mxXAxis
.get() );
3619 ConvertAxis( mxZAxis
, mxZAxisTitle
, xCoordSystem
, 0 );
3624 void XclImpChAxesSet::ConvertTitlePositions() const
3627 mxXAxisTitle
->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE
, maData
.mnAxesSetId
, EXC_CHAXIS_X
) );
3629 mxYAxisTitle
->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE
, maData
.mnAxesSetId
, EXC_CHAXIS_Y
) );
3631 mxZAxisTitle
->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE
, maData
.mnAxesSetId
, EXC_CHAXIS_Z
) );
3634 void XclImpChAxesSet::ReadChAxis( XclImpStream
& rStrm
)
3636 XclImpChAxisRef
xAxis( new XclImpChAxis( GetChRoot() ) );
3637 xAxis
->ReadRecordGroup( rStrm
);
3639 switch( xAxis
->GetAxisType() )
3641 case EXC_CHAXIS_X
: mxXAxis
= xAxis
; break;
3642 case EXC_CHAXIS_Y
: mxYAxis
= xAxis
; break;
3643 case EXC_CHAXIS_Z
: mxZAxis
= xAxis
; break;
3647 void XclImpChAxesSet::ReadChText( XclImpStream
& rStrm
)
3649 XclImpChTextRef
xText( new XclImpChText( GetChRoot() ) );
3650 xText
->ReadRecordGroup( rStrm
);
3652 switch( xText
->GetLinkTarget() )
3654 case EXC_CHOBJLINK_XAXIS
: mxXAxisTitle
= xText
; break;
3655 case EXC_CHOBJLINK_YAXIS
: mxYAxisTitle
= xText
; break;
3656 case EXC_CHOBJLINK_ZAXIS
: mxZAxisTitle
= xText
; break;
3660 void XclImpChAxesSet::ReadChPlotFrame( XclImpStream
& rStrm
)
3662 if( (rStrm
.GetNextRecId() == EXC_ID_CHFRAME
) && rStrm
.StartNextRecord() )
3664 mxPlotFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_PLOTFRAME
) );
3665 mxPlotFrame
->ReadRecordGroup( rStrm
);
3669 void XclImpChAxesSet::ReadChTypeGroup( XclImpStream
& rStrm
)
3671 XclImpChTypeGroupRef
xTypeGroup( new XclImpChTypeGroup( GetChRoot() ) );
3672 xTypeGroup
->ReadRecordGroup( rStrm
);
3673 sal_uInt16 nGroupIdx
= xTypeGroup
->GetGroupIdx();
3674 XclImpChTypeGroupMap::iterator itr
= maTypeGroups
.lower_bound(nGroupIdx
);
3675 if (itr
!= maTypeGroups
.end() && !maTypeGroups
.key_comp()(nGroupIdx
, itr
->first
))
3676 // Overwrite the existing element.
3677 itr
->second
= xTypeGroup
;
3679 maTypeGroups
.insert(
3680 itr
, XclImpChTypeGroupMap::value_type(nGroupIdx
, xTypeGroup
));
3683 Reference
< XCoordinateSystem
> XclImpChAxesSet::CreateCoordSystem( Reference
< XDiagram
> xDiagram
) const
3685 Reference
< XCoordinateSystem
> xCoordSystem
;
3687 /* Try to get existing ccordinate system. For now, all series from primary
3688 and secondary axes sets are inserted into one coordinate system. Later,
3689 this should be changed to use one coordinate system for each axes set. */
3690 Reference
< XCoordinateSystemContainer
> xCoordSystemCont( xDiagram
, UNO_QUERY
);
3691 if( xCoordSystemCont
.is() )
3693 Sequence
< Reference
< XCoordinateSystem
> > aCoordSystems
= xCoordSystemCont
->getCoordinateSystems();
3694 OSL_ENSURE( aCoordSystems
.getLength() <= 1, "XclImpChAxesSet::CreateCoordSystem - too many existing coordinate systems" );
3695 if( aCoordSystems
.getLength() > 0 )
3696 xCoordSystem
= aCoordSystems
[ 0 ];
3699 // create the coordinate system according to the first chart type
3700 if( !xCoordSystem
.is() )
3702 XclImpChTypeGroupRef xTypeGroup
= GetFirstTypeGroup();
3705 xCoordSystem
= xTypeGroup
->CreateCoordSystem();
3706 // convert 3d chart settings
3707 ScfPropertySet
aDiaProp( xDiagram
);
3708 xTypeGroup
->ConvertChart3d( aDiaProp
);
3712 /* Create XChartType objects for all chart type groups. Each group will
3713 add its series to the data provider attached to the chart document. */
3714 Reference
< XChartTypeContainer
> xChartTypeCont( xCoordSystem
, UNO_QUERY
);
3715 if( xChartTypeCont
.is() )
3717 sal_Int32 nApiAxesSetIdx
= GetApiAxesSetIndex();
3718 for( XclImpChTypeGroupMap::const_iterator aIt
= maTypeGroups
.begin(), aEnd
= maTypeGroups
.end(); aIt
!= aEnd
; ++aIt
)
3722 Reference
< XChartType
> xChartType
= aIt
->second
->CreateChartType( xDiagram
, nApiAxesSetIdx
);
3723 if( xChartType
.is() )
3724 xChartTypeCont
->addChartType( xChartType
);
3728 OSL_FAIL( "XclImpChAxesSet::CreateCoordSystem - cannot add chart type" );
3733 return xCoordSystem
;
3736 void XclImpChAxesSet::ConvertAxis(
3737 XclImpChAxisRef xChAxis
, XclImpChTextRef xChAxisTitle
,
3738 Reference
< XCoordinateSystem
> xCoordSystem
, const XclImpChAxis
* pCrossingAxis
) const
3742 // create and attach the axis object
3743 Reference
< XAxis
> xAxis
= CreateAxis( *xChAxis
, pCrossingAxis
);
3746 // create and attach the axis title
3747 if( xChAxisTitle
) try
3749 Reference
< XTitled
> xTitled( xAxis
, UNO_QUERY_THROW
);
3750 Reference
< XTitle
> xTitle( xChAxisTitle
->CreateTitle(), UNO_SET_THROW
);
3751 xTitled
->setTitleObject( xTitle
);
3755 OSL_FAIL( "XclImpChAxesSet::ConvertAxis - cannot set axis title" );
3758 // insert axis into coordinate system
3761 sal_Int32 nApiAxisDim
= xChAxis
->GetApiAxisDimension();
3762 sal_Int32 nApiAxesSetIdx
= GetApiAxesSetIndex();
3763 xCoordSystem
->setAxisByDimension( nApiAxisDim
, xAxis
, nApiAxesSetIdx
);
3767 OSL_FAIL( "XclImpChAxesSet::ConvertAxis - cannot set axis" );
3773 Reference
< XAxis
> XclImpChAxesSet::CreateAxis( const XclImpChAxis
& rChAxis
, const XclImpChAxis
* pCrossingAxis
) const
3775 Reference
< XAxis
> xAxis
;
3776 if( const XclImpChTypeGroup
* pTypeGroup
= GetFirstTypeGroup().get() )
3777 xAxis
= rChAxis
.CreateAxis( *pTypeGroup
, pCrossingAxis
);
3781 void XclImpChAxesSet::ConvertBackground( Reference
< XDiagram
> xDiagram
) const
3783 XclImpChTypeGroupRef xTypeGroup
= GetFirstTypeGroup();
3784 if( xTypeGroup
&& xTypeGroup
->Is3dWallChart() )
3786 // wall/floor formatting (3D charts)
3789 ScfPropertySet
aWallProp( xDiagram
->getWall() );
3790 mxXAxis
->ConvertWall( aWallProp
);
3794 ScfPropertySet
aFloorProp( xDiagram
->getFloor() );
3795 mxYAxis
->ConvertWall( aFloorProp
);
3798 else if( mxPlotFrame
)
3800 // diagram background formatting
3801 ScfPropertySet
aWallProp( xDiagram
->getWall() );
3802 mxPlotFrame
->Convert( aWallProp
);
3806 // The chart object ===========================================================
3808 XclImpChChart::XclImpChChart( const XclImpRoot
& rRoot
) :
3809 XclImpChRoot( rRoot
, *this )
3811 mxPrimAxesSet
.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_PRIMARY
) );
3812 mxSecnAxesSet
.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_SECONDARY
) );
3815 XclImpChChart::~XclImpChChart()
3819 void XclImpChChart::ReadHeaderRecord( XclImpStream
& rStrm
)
3821 // coordinates are stored as 16.16 fixed point
3825 void XclImpChChart::ReadSubRecord( XclImpStream
& rStrm
)
3827 switch( rStrm
.GetRecId() )
3829 case EXC_ID_CHFRAME
:
3830 mxFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND
) );
3831 mxFrame
->ReadRecordGroup( rStrm
);
3833 case EXC_ID_CHSERIES
:
3834 ReadChSeries( rStrm
);
3836 case EXC_ID_CHPROPERTIES
:
3837 ReadChProperties( rStrm
);
3839 case EXC_ID_CHDEFAULTTEXT
:
3840 ReadChDefaultText( rStrm
);
3842 case EXC_ID_CHAXESSET
:
3843 ReadChAxesSet( rStrm
);
3846 ReadChText( rStrm
);
3849 Finalize(); // finalize the entire chart object
3854 void XclImpChChart::ReadChDefaultText( XclImpStream
& rStrm
)
3856 sal_uInt16 nTextId
= rStrm
.ReaduInt16();
3857 if( (rStrm
.GetNextRecId() == EXC_ID_CHTEXT
) && rStrm
.StartNextRecord() )
3859 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3860 auto_ptr
<XclImpChText
> pText(new XclImpChText(GetChRoot()));
3861 SAL_WNODEPRECATED_DECLARATIONS_POP
3862 pText
->ReadRecordGroup(rStrm
);
3863 maDefTexts
.insert(nTextId
, pText
);
3867 void XclImpChChart::ReadChDataFormat( XclImpStream
& rStrm
)
3869 XclImpChDataFormatRef
xDataFmt( new XclImpChDataFormat( GetChRoot() ) );
3870 xDataFmt
->ReadRecordGroup( rStrm
);
3871 if( xDataFmt
->GetPointPos().mnSeriesIdx
<= EXC_CHSERIES_MAXSERIES
)
3873 const XclChDataPointPos
& rPos
= xDataFmt
->GetPointPos();
3874 XclImpChDataFormatMap::iterator itr
= maDataFmts
.lower_bound(rPos
);
3875 if (itr
== maDataFmts
.end() || maDataFmts
.key_comp()(rPos
, itr
->first
))
3876 // No element exists for this data point. Insert it.
3878 itr
, XclImpChDataFormatMap::value_type(rPos
, xDataFmt
));
3880 /* Do not overwrite existing data format group, Excel always uses the
3881 first data format group occuring in any CHSERIES group. */
3885 void XclImpChChart::UpdateObjFrame( const XclObjLineData
& rLineData
, const XclObjFillData
& rFillData
)
3888 mxFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND
) );
3889 mxFrame
->UpdateObjFrame( rLineData
, rFillData
);
3892 XclImpChTypeGroupRef
XclImpChChart::GetTypeGroup( sal_uInt16 nGroupIdx
) const
3894 XclImpChTypeGroupRef xTypeGroup
= mxPrimAxesSet
->GetTypeGroup( nGroupIdx
);
3895 if( !xTypeGroup
) xTypeGroup
= mxSecnAxesSet
->GetTypeGroup( nGroupIdx
);
3896 if( !xTypeGroup
) xTypeGroup
= mxPrimAxesSet
->GetFirstTypeGroup();
3900 const XclImpChText
* XclImpChChart::GetDefaultText( XclChTextType eTextType
) const
3902 sal_uInt16 nDefTextId
= EXC_CHDEFTEXT_GLOBAL
;
3903 bool bBiff8
= GetBiff() == EXC_BIFF8
;
3906 case EXC_CHTEXTTYPE_TITLE
: nDefTextId
= EXC_CHDEFTEXT_GLOBAL
; break;
3907 case EXC_CHTEXTTYPE_LEGEND
: nDefTextId
= EXC_CHDEFTEXT_GLOBAL
; break;
3908 case EXC_CHTEXTTYPE_AXISTITLE
: nDefTextId
= bBiff8
? EXC_CHDEFTEXT_AXESSET
: EXC_CHDEFTEXT_GLOBAL
; break;
3909 case EXC_CHTEXTTYPE_AXISLABEL
: nDefTextId
= bBiff8
? EXC_CHDEFTEXT_AXESSET
: EXC_CHDEFTEXT_GLOBAL
; break;
3910 case EXC_CHTEXTTYPE_DATALABEL
: nDefTextId
= bBiff8
? EXC_CHDEFTEXT_AXESSET
: EXC_CHDEFTEXT_GLOBAL
; break;
3913 XclImpChTextMap::const_iterator itr
= maDefTexts
.find(nDefTextId
);
3914 return itr
== maDefTexts
.end() ? NULL
: itr
->second
;
3917 bool XclImpChChart::IsManualPlotArea() const
3919 // there is no real automatic mode in BIFF5 charts
3920 return (GetBiff() <= EXC_BIFF5
) || ::get_flag( maProps
.mnFlags
, EXC_CHPROPS_USEMANPLOTAREA
);
3923 void XclImpChChart::Convert( const Reference
<XChartDocument
>& xChartDoc
,
3924 XclImpDffConverter
& rDffConv
, const OUString
& rObjName
, const Rectangle
& rChartRect
) const
3926 // initialize conversion (locks the model to suppress any internal updates)
3927 InitConversion( xChartDoc
, rChartRect
);
3929 // chart frame formatting
3932 ScfPropertySet
aFrameProp( xChartDoc
->getPageBackground() );
3933 mxFrame
->Convert( aFrameProp
);
3939 Reference
< XTitled
> xTitled( xChartDoc
, UNO_QUERY_THROW
);
3940 Reference
< XTitle
> xTitle( mxTitle
->CreateTitle(), UNO_SET_THROW
);
3941 xTitled
->setTitleObject( xTitle
);
3947 /* Create the diagram object and attach it to the chart document. Currently,
3948 one diagram is used to carry all coordinate systems and data series. */
3949 Reference
< XDiagram
> xDiagram
= CreateDiagram();
3950 xChartDoc
->setFirstDiagram( xDiagram
);
3952 // coordinate systems and chart types, convert axis settings
3953 mxPrimAxesSet
->Convert( xDiagram
);
3954 mxSecnAxesSet
->Convert( xDiagram
);
3957 if( xDiagram
.is() && mxLegend
)
3958 xDiagram
->setLegend( mxLegend
->CreateLegend() );
3960 /* Following all conversions needing the old Chart1 API that involves full
3961 initialization of the chart view. */
3962 Reference
< cssc::XChartDocument
> xChart1Doc( xChartDoc
, UNO_QUERY
);
3963 if( xChart1Doc
.is() )
3965 Reference
< cssc::XDiagram
> xDiagram1
= xChart1Doc
->getDiagram();
3967 /* Set the 'IncludeHiddenCells' property via the old API as only this
3968 ensures that the data provider and all created sequences get this
3970 ScfPropertySet
aDiaProp( xDiagram1
);
3971 bool bShowVisCells
= ::get_flag( maProps
.mnFlags
, EXC_CHPROPS_SHOWVISIBLEONLY
);
3972 aDiaProp
.SetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS
, !bShowVisCells
);
3974 // plot area position and size (there is no real automatic mode in BIFF5 charts)
3975 XclImpChFramePosRef xPlotAreaPos
= mxPrimAxesSet
->GetPlotAreaFramePos();
3976 if( IsManualPlotArea() && xPlotAreaPos
) try
3978 const XclChFramePos
& rFramePos
= xPlotAreaPos
->GetFramePosData();
3979 if( (rFramePos
.mnTLMode
== EXC_CHFRAMEPOS_PARENT
) && (rFramePos
.mnBRMode
== EXC_CHFRAMEPOS_PARENT
) )
3981 Reference
< cssc::XDiagramPositioning
> xPositioning( xDiagram1
, UNO_QUERY_THROW
);
3982 ::com::sun::star::awt::Rectangle aDiagramRect
= CalcHmmFromChartRect( rFramePos
.maRect
);
3983 // for pie charts, always set inner plot area size to exclude the data labels as Excel does
3984 const XclImpChTypeGroup
* pFirstTypeGroup
= mxPrimAxesSet
->GetFirstTypeGroup().get();
3985 if( pFirstTypeGroup
&& (pFirstTypeGroup
->GetTypeInfo().meTypeCateg
== EXC_CHTYPECATEG_PIE
) )
3986 xPositioning
->setDiagramPositionExcludingAxes( aDiagramRect
);
3987 else if( pFirstTypeGroup
&& pFirstTypeGroup
->Is3dChart() )
3988 xPositioning
->setDiagramPositionIncludingAxesAndAxisTitles( aDiagramRect
);
3990 xPositioning
->setDiagramPositionIncludingAxes( aDiagramRect
);
3997 // positions of all title objects
3999 mxTitle
->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_TITLE
) );
4000 mxPrimAxesSet
->ConvertTitlePositions();
4001 mxSecnAxesSet
->ConvertTitlePositions();
4005 FinishConversion( rDffConv
);
4007 // start listening to this chart
4008 ScDocument
& rDoc
= GetRoot().GetDoc();
4009 if( ScChartListenerCollection
* pChartCollection
= rDoc
.GetChartListenerCollection() )
4011 SAL_WNODEPRECATED_DECLARATIONS_PUSH
4012 ::std::auto_ptr
< ::std::vector
< ScTokenRef
> > xRefTokens( new ::std::vector
< ScTokenRef
> );
4013 SAL_WNODEPRECATED_DECLARATIONS_POP
4014 for( XclImpChSeriesVec::const_iterator aIt
= maSeries
.begin(), aEnd
= maSeries
.end(); aIt
!= aEnd
; ++aIt
)
4015 (*aIt
)->FillAllSourceLinks( *xRefTokens
);
4016 if( !xRefTokens
->empty() )
4018 SAL_WNODEPRECATED_DECLARATIONS_PUSH
4019 ::std::auto_ptr
< ScChartListener
> xListener( new ScChartListener( rObjName
, &rDoc
, xRefTokens
.release() ) );
4020 SAL_WNODEPRECATED_DECLARATIONS_POP
4021 xListener
->SetUsed( true );
4022 xListener
->StartListeningTo();
4023 pChartCollection
->insert( xListener
.release() );
4028 void XclImpChChart::ReadChSeries( XclImpStream
& rStrm
)
4030 sal_uInt16 nNewSeriesIdx
= static_cast< sal_uInt16
>( maSeries
.size() );
4031 XclImpChSeriesRef
xSeries( new XclImpChSeries( GetChRoot(), nNewSeriesIdx
) );
4032 xSeries
->ReadRecordGroup( rStrm
);
4033 maSeries
.push_back( xSeries
);
4036 void XclImpChChart::ReadChProperties( XclImpStream
& rStrm
)
4038 rStrm
>> maProps
.mnFlags
>> maProps
.mnEmptyMode
;
4041 void XclImpChChart::ReadChAxesSet( XclImpStream
& rStrm
)
4043 XclImpChAxesSetRef
xAxesSet( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_NONE
) );
4044 xAxesSet
->ReadRecordGroup( rStrm
);
4045 switch( xAxesSet
->GetAxesSetId() )
4047 case EXC_CHAXESSET_PRIMARY
: mxPrimAxesSet
= xAxesSet
; break;
4048 case EXC_CHAXESSET_SECONDARY
: mxSecnAxesSet
= xAxesSet
; break;
4052 void XclImpChChart::ReadChText( XclImpStream
& rStrm
)
4054 XclImpChTextRef
xText( new XclImpChText( GetChRoot() ) );
4055 xText
->ReadRecordGroup( rStrm
);
4056 switch( xText
->GetLinkTarget() )
4058 case EXC_CHOBJLINK_TITLE
:
4061 case EXC_CHOBJLINK_DATA
:
4063 sal_uInt16 nSeriesIdx
= xText
->GetPointPos().mnSeriesIdx
;
4064 if( nSeriesIdx
< maSeries
.size() )
4065 maSeries
[ nSeriesIdx
]->SetDataLabel( xText
);
4071 void XclImpChChart::Finalize()
4073 // finalize series (must be done first)
4075 // #i49218# legend may be attached to primary or secondary axes set
4076 mxLegend
= mxPrimAxesSet
->GetLegend();
4078 mxLegend
= mxSecnAxesSet
->GetLegend();
4080 mxLegend
->Finalize();
4081 // axes sets, updates chart type group default formats -> must be called before FinalizeDataFormats()
4082 mxPrimAxesSet
->Finalize();
4083 mxSecnAxesSet
->Finalize();
4084 // formatting of all series
4085 FinalizeDataFormats();
4086 // #i47745# missing frame -> invisible border and area
4088 mxFrame
.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND
) );
4093 void XclImpChChart::FinalizeSeries()
4095 for( XclImpChSeriesVec::iterator aSIt
= maSeries
.begin(), aSEnd
= maSeries
.end(); aSIt
!= aSEnd
; ++aSIt
)
4097 XclImpChSeriesRef xSeries
= *aSIt
;
4098 if( xSeries
->HasParentSeries() )
4100 /* Process child series (trend lines and error bars). Data of
4101 child series will be set at the connected parent series. */
4102 if( xSeries
->GetParentIdx() < maSeries
.size() )
4103 maSeries
[ xSeries
->GetParentIdx() ]->AddChildSeries( *xSeries
);
4107 // insert the series into the related chart type group
4108 if( XclImpChTypeGroup
* pTypeGroup
= GetTypeGroup( xSeries
->GetGroupIdx() ).get() )
4109 pTypeGroup
->AddSeries( xSeries
);
4114 void XclImpChChart::FinalizeDataFormats()
4116 /* #i51639# (part 1): CHDATAFORMAT groups are part of CHSERIES groups.
4117 Each CHDATAFORMAT group specifies the series and data point it is
4118 assigned to. This makes it possible to have a data format that is
4119 related to another series, e.g. a CHDATAFORMAT group for series 2 is
4120 part of a CHSERIES group that describes series 1. Therefore the chart
4121 itself has collected all CHDATAFORMAT groups to be able to store data
4122 format groups for series that have not been imported at that time. This
4123 loop finally assigns these groups to the related series. */
4124 for( XclImpChDataFormatMap::const_iterator aMIt
= maDataFmts
.begin(), aMEnd
= maDataFmts
.end(); aMIt
!= aMEnd
; ++aMIt
)
4126 sal_uInt16 nSeriesIdx
= aMIt
->first
.mnSeriesIdx
;
4127 if( nSeriesIdx
< maSeries
.size() )
4128 maSeries
[ nSeriesIdx
]->SetDataFormat( aMIt
->second
);
4131 /* #i51639# (part 2): Finalize data formats of all series. This adds for
4132 example missing CHDATAFORMAT groups for entire series that are needed
4133 for automatic colors of lines and areas. */
4134 for( XclImpChSeriesVec::iterator aVIt
= maSeries
.begin(), aVEnd
= maSeries
.end(); aVIt
!= aVEnd
; ++aVIt
)
4135 (*aVIt
)->FinalizeDataFormats();
4138 void XclImpChChart::FinalizeTitle()
4140 // special handling for auto-generated title
4142 if( !mxTitle
|| (!mxTitle
->IsDeleted() && !mxTitle
->HasString()) )
4144 // automatic title from first series name (if there are no series on secondary axes set)
4145 if( !mxSecnAxesSet
->IsValidAxesSet() )
4146 aAutoTitle
= mxPrimAxesSet
->GetSingleSeriesTitle();
4147 if( mxTitle
|| (aAutoTitle
.Len() > 0) )
4150 mxTitle
.reset( new XclImpChText( GetChRoot() ) );
4151 if( aAutoTitle
.Len() == 0 )
4152 aAutoTitle
= "Chart Title";
4156 // will reset mxTitle, if it does not contain a string and no auto title exists
4157 lclFinalizeTitle( mxTitle
, GetDefaultText( EXC_CHTEXTTYPE_TITLE
), aAutoTitle
);
4160 Reference
< XDiagram
> XclImpChChart::CreateDiagram() const
4162 // create a diagram object
4163 Reference
< XDiagram
> xDiagram( ScfApiHelper::CreateInstance( SERVICE_CHART2_DIAGRAM
), UNO_QUERY
);
4165 // convert global chart settings
4166 ScfPropertySet
aDiaProp( xDiagram
);
4168 // treatment of missing values
4169 using namespace cssc::MissingValueTreatment
;
4170 sal_Int32 nMissingValues
= LEAVE_GAP
;
4171 switch( maProps
.mnEmptyMode
)
4173 case EXC_CHPROPS_EMPTY_SKIP
: nMissingValues
= LEAVE_GAP
; break;
4174 case EXC_CHPROPS_EMPTY_ZERO
: nMissingValues
= USE_ZERO
; break;
4175 case EXC_CHPROPS_EMPTY_INTERPOLATE
: nMissingValues
= CONTINUE
; break;
4177 aDiaProp
.SetProperty( EXC_CHPROP_MISSINGVALUETREATMENT
, nMissingValues
);
4182 // ----------------------------------------------------------------------------
4184 XclImpChartDrawing::XclImpChartDrawing( const XclImpRoot
& rRoot
, bool bOwnTab
) :
4185 XclImpDrawing( rRoot
, bOwnTab
), // sheet charts may contain OLE objects
4186 mnScTab( rRoot
.GetCurrScTab() ),
4191 void XclImpChartDrawing::ConvertObjects( XclImpDffConverter
& rDffConv
,
4192 const Reference
< XModel
>& rxModel
, const Rectangle
& rChartRect
)
4194 maChartRect
= rChartRect
; // needed in CalcAnchorRect() callback
4196 SdrModel
* pSdrModel
= 0;
4197 SdrPage
* pSdrPage
= 0;
4200 // chart sheet: insert all shapes into the sheet, not into the chart object
4201 pSdrModel
= GetDoc().GetDrawLayer();
4202 pSdrPage
= GetSdrPage( mnScTab
);
4206 // embedded chart object: insert all shapes into the chart
4209 Reference
< XDrawPageSupplier
> xDrawPageSupp( rxModel
, UNO_QUERY_THROW
);
4210 Reference
< XDrawPage
> xDrawPage( xDrawPageSupp
->getDrawPage(), UNO_SET_THROW
);
4211 pSdrPage
= ::GetSdrPageFromXDrawPage( xDrawPage
);
4212 pSdrModel
= pSdrPage
? pSdrPage
->GetModel() : 0;
4219 if( pSdrModel
&& pSdrPage
)
4220 ImplConvertObjects( rDffConv
, *pSdrModel
, *pSdrPage
);
4223 Rectangle
XclImpChartDrawing::CalcAnchorRect( const XclObjAnchor
& rAnchor
, bool bDffAnchor
) const
4225 /* In objects with DFF client anchor, the position of the shape is stored
4226 in the cell address components of the client anchor. In old BIFF3-BIFF5
4227 objects, the position is stored in the offset components of the anchor. */
4229 static_cast< long >( static_cast< double >( bDffAnchor
? rAnchor
.maFirst
.mnCol
: rAnchor
.mnLX
) / EXC_CHART_TOTALUNITS
* maChartRect
.GetWidth() + 0.5 ),
4230 static_cast< long >( static_cast< double >( bDffAnchor
? rAnchor
.maFirst
.mnRow
: rAnchor
.mnTY
) / EXC_CHART_TOTALUNITS
* maChartRect
.GetHeight() + 0.5 ),
4231 static_cast< long >( static_cast< double >( bDffAnchor
? rAnchor
.maLast
.mnCol
: rAnchor
.mnRX
) / EXC_CHART_TOTALUNITS
* maChartRect
.GetWidth() + 0.5 ),
4232 static_cast< long >( static_cast< double >( bDffAnchor
? rAnchor
.maLast
.mnRow
: rAnchor
.mnBY
) / EXC_CHART_TOTALUNITS
* maChartRect
.GetHeight() + 0.5 ) );
4234 // move shapes into chart area for sheet charts
4236 aRect
.Move( maChartRect
.Left(), maChartRect
.Top() );
4240 void XclImpChartDrawing::OnObjectInserted( const XclImpDrawObjBase
& )
4244 // ----------------------------------------------------------------------------
4246 XclImpChart::XclImpChart( const XclImpRoot
& rRoot
, bool bOwnTab
) :
4247 XclImpRoot( rRoot
),
4248 mbOwnTab( bOwnTab
),
4249 mbIsPivotChart( false )
4253 XclImpChart::~XclImpChart()
4257 void XclImpChart::ReadChartSubStream( XclImpStream
& rStrm
)
4259 XclImpPageSettings
& rPageSett
= GetPageSettings();
4260 XclImpTabViewSettings
& rTabViewSett
= GetTabViewSettings();
4263 while( bLoop
&& rStrm
.StartNextRecord() )
4265 // page settings - only for charts in entire sheet
4266 if( mbOwnTab
) switch( rStrm
.GetRecId() )
4268 case EXC_ID_HORPAGEBREAKS
:
4269 case EXC_ID_VERPAGEBREAKS
: rPageSett
.ReadPageBreaks( rStrm
); break;
4271 case EXC_ID_FOOTER
: rPageSett
.ReadHeaderFooter( rStrm
); break;
4272 case EXC_ID_LEFTMARGIN
:
4273 case EXC_ID_RIGHTMARGIN
:
4274 case EXC_ID_TOPMARGIN
:
4275 case EXC_ID_BOTTOMMARGIN
: rPageSett
.ReadMargin( rStrm
); break;
4276 case EXC_ID_PRINTHEADERS
: rPageSett
.ReadPrintHeaders( rStrm
); break;
4277 case EXC_ID_PRINTGRIDLINES
: rPageSett
.ReadPrintGridLines( rStrm
); break;
4278 case EXC_ID_HCENTER
:
4279 case EXC_ID_VCENTER
: rPageSett
.ReadCenter( rStrm
); break;
4280 case EXC_ID_SETUP
: rPageSett
.ReadSetup( rStrm
); break;
4281 case EXC_ID8_IMGDATA
: rPageSett
.ReadImgData( rStrm
); break;
4283 case EXC_ID_WINDOW2
: rTabViewSett
.ReadWindow2( rStrm
, true );break;
4284 case EXC_ID_SCL
: rTabViewSett
.ReadScl( rStrm
); break;
4286 case EXC_ID_SHEETEXT
: //0x0862
4288 // FIXME: do not need to pass palette, XclImpTabVieSettings is derived from root
4289 XclImpPalette
& rPal
= GetPalette();
4290 rTabViewSett
.ReadTabBgColor( rStrm
, rPal
);
4294 case EXC_ID_CODENAME
: ReadCodeName( rStrm
, false ); break;
4298 switch( rStrm
.GetRecId() )
4300 case EXC_ID_EOF
: bLoop
= false; break;
4302 // #i31882# ignore embedded chart objects
4306 case EXC_ID5_BOF
: XclTools::SkipSubStream( rStrm
); break;
4308 case EXC_ID_CHCHART
: ReadChChart( rStrm
); break;
4310 case EXC_ID8_CHPIVOTREF
:
4311 GetTracer().TracePivotChartExists();
4312 mbIsPivotChart
= true;
4315 // BIFF specific records
4316 default: switch( GetBiff() )
4318 case EXC_BIFF5
: switch( rStrm
.GetRecId() )
4320 case EXC_ID_OBJ
: GetChartDrawing().ReadObj( rStrm
); break;
4323 case EXC_BIFF8
: switch( rStrm
.GetRecId() )
4325 case EXC_ID_MSODRAWING
: GetChartDrawing().ReadMsoDrawing( rStrm
); break;
4326 // #i61786# weird documents: OBJ without MSODRAWING -> read in BIFF5 format
4327 case EXC_ID_OBJ
: GetChartDrawing().ReadObj( rStrm
); break;
4336 void XclImpChart::UpdateObjFrame( const XclObjLineData
& rLineData
, const XclObjFillData
& rFillData
)
4339 mxChartData
.reset( new XclImpChChart( GetRoot() ) );
4340 mxChartData
->UpdateObjFrame( rLineData
, rFillData
);
4343 sal_Size
XclImpChart::GetProgressSize() const
4346 (mxChartData
? mxChartData
->GetProgressSize() : 0) +
4347 (mxChartDrawing
? mxChartDrawing
->GetProgressSize() : 0);
4350 void XclImpChart::Convert( Reference
< XModel
> xModel
, XclImpDffConverter
& rDffConv
, const OUString
& rObjName
, const Rectangle
& rChartRect
) const
4352 Reference
< XChartDocument
> xChartDoc( xModel
, UNO_QUERY
);
4353 if( xChartDoc
.is() )
4356 mxChartData
->Convert( xChartDoc
, rDffConv
, rObjName
, rChartRect
);
4357 if( mxChartDrawing
)
4358 mxChartDrawing
->ConvertObjects( rDffConv
, xModel
, rChartRect
);
4362 XclImpChartDrawing
& XclImpChart::GetChartDrawing()
4364 if( !mxChartDrawing
)
4365 mxChartDrawing
.reset( new XclImpChartDrawing( GetRoot(), mbOwnTab
) );
4366 return *mxChartDrawing
;
4369 void XclImpChart::ReadChChart( XclImpStream
& rStrm
)
4371 mxChartData
.reset( new XclImpChChart( GetRoot() ) );
4372 mxChartData
->ReadRecordGroup( rStrm
);
4375 // ============================================================================
4377 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */