1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xechart.cxx,v $
10 * $Revision: 1.10.62.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 #include "xlsx/xladdress.hxx"
35 #include "xlsx/xlconst.hxx"
36 #include "xlsx/xlformula.hxx"
37 #include "xechart.hxx"
39 #include <com/sun/star/i18n/XBreakIterator.hpp>
40 #include <com/sun/star/i18n/ScriptType.hpp>
41 #include <com/sun/star/drawing/FillStyle.hpp>
42 #include <com/sun/star/chart/XChartDocument.hpp>
43 #include <com/sun/star/chart2/XChartDocument.hpp>
44 #include <com/sun/star/chart2/XDiagram.hpp>
45 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
46 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
47 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
48 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
49 #include <com/sun/star/chart2/XTitled.hpp>
50 #include <com/sun/star/chart2/XColorScheme.hpp>
51 #include <com/sun/star/chart2/data/XDataSource.hpp>
52 #include <com/sun/star/chart2/AxisType.hpp>
53 #include <com/sun/star/chart2/CurveStyle.hpp>
54 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
55 #include <com/sun/star/chart2/DataPointLabel.hpp>
56 #include <com/sun/star/chart2/StackingDirection.hpp>
57 #include <com/sun/star/chart2/TickmarkStyle.hpp>
58 #include <com/sun/star/chart/DataLabelPlacement.hpp>
59 #include <com/sun/star/chart/ErrorBarStyle.hpp>
61 #include <vcl/outdev.hxx>
62 #include <svx/escherex.hxx>
64 #include "document.hxx"
65 #include "rangelst.hxx"
66 #include "rangeutl.hxx"
67 #include "xeformula.hxx"
68 #include "xehelper.hxx"
70 #include "xestyle.hxx"
71 #include "compiler.hxx"
72 #include "tokenarray.hxx"
75 using ::rtl::OUString
;
76 using ::com::sun::star::uno::Any
;
77 using ::com::sun::star::uno::Reference
;
78 using ::com::sun::star::uno::Sequence
;
79 using ::com::sun::star::uno::UNO_QUERY
;
80 using ::com::sun::star::uno::Exception
;
81 using ::com::sun::star::beans::XPropertySet
;
82 using ::com::sun::star::i18n::XBreakIterator
;
83 using ::com::sun::star::frame::XModel
;
84 using ::com::sun::star::chart2::XChartDocument
;
85 using ::com::sun::star::chart2::XDiagram
;
86 using ::com::sun::star::chart2::XCoordinateSystemContainer
;
87 using ::com::sun::star::chart2::XCoordinateSystem
;
88 using ::com::sun::star::chart2::XChartTypeContainer
;
89 using ::com::sun::star::chart2::XChartType
;
90 using ::com::sun::star::chart2::XDataSeriesContainer
;
91 using ::com::sun::star::chart2::XDataSeries
;
92 using ::com::sun::star::chart2::XRegressionCurveContainer
;
93 using ::com::sun::star::chart2::XRegressionCurve
;
94 using ::com::sun::star::chart2::XAxis
;
95 using ::com::sun::star::chart2::XScaling
;
96 using ::com::sun::star::chart2::ScaleData
;
97 using ::com::sun::star::chart2::IncrementData
;
98 using ::com::sun::star::chart2::SubIncrement
;
99 using ::com::sun::star::chart2::XLegend
;
100 using ::com::sun::star::chart2::XTitled
;
101 using ::com::sun::star::chart2::XTitle
;
102 using ::com::sun::star::chart2::XFormattedString
;
103 using ::com::sun::star::chart2::XColorScheme
;
105 using ::com::sun::star::chart2::data::XDataSource
;
106 using ::com::sun::star::chart2::data::XLabeledDataSequence
;
107 using ::com::sun::star::chart2::data::XDataSequence
;
109 // Helpers ====================================================================
113 XclExpStream
& operator<<( XclExpStream
& rStrm
, const XclChRectangle
& rRect
)
115 return rStrm
<< rRect
.mnX
<< rRect
.mnY
<< rRect
.mnWidth
<< rRect
.mnHeight
;
118 inline void lclSaveRecord( XclExpStream
& rStrm
, XclExpRecordRef xRec
)
124 /** Saves the passed record (group) together with a leading value record. */
125 template< typename Type
>
126 void lclSaveRecord( XclExpStream
& rStrm
, XclExpRecordRef xRec
, sal_uInt16 nRecId
, Type nValue
)
130 XclExpValueRecord
< Type
>( nRecId
, nValue
).Save( rStrm
);
135 template< typename Type
>
136 inline bool lclIsAutoAnyOrGetValue( Type
& rValue
, const Any
& rAny
, bool bPercent
)
138 if (!rAny
.hasValue())
151 bool lclIsAutoAnyOrGetScaledValue( double& rfValue
, const Any
& rAny
, Reference
< XScaling
> xScaling
, bool bPercent
)
153 bool bIsAuto
= lclIsAutoAnyOrGetValue( rfValue
, rAny
, bPercent
);
154 if( !bIsAuto
&& xScaling
.is() )
155 rfValue
= xScaling
->doScaling( rfValue
);
162 // Common =====================================================================
164 /** Stores global data needed in various classes of the Chart export filter. */
165 class XclExpChRootData
: public XclChRootData
168 explicit XclExpChRootData( XclExpChChart
* pChartData
);
170 /** Returns a reference to the parent chart data object. */
171 inline XclExpChChart
& GetChartData() const { return *mpChartData
; }
174 XclExpChChart
* mpChartData
; /// Pointer to the chart data object.
177 XclExpChRootData::XclExpChRootData( XclExpChChart
* pChartData
) :
178 mpChartData( pChartData
)
182 // ----------------------------------------------------------------------------
184 XclExpChRoot::XclExpChRoot( const XclExpRoot
& rRoot
, XclExpChChart
* pChartData
) :
186 mxChData( new XclExpChRootData( pChartData
) )
190 XclExpChRoot::~XclExpChRoot()
194 XclExpChChart
& XclExpChRoot::GetChartData() const
196 return mxChData
->GetChartData();
199 const XclChTypeInfo
& XclExpChRoot::GetChartTypeInfo( XclChTypeId eType
) const
201 return mxChData
->GetTypeInfoProvider().GetTypeInfo( eType
);
204 const XclChTypeInfo
& XclExpChRoot::GetChartTypeInfo( const OUString
& rServiceName
) const
206 return mxChData
->GetTypeInfoProvider().GetTypeInfoFromService( rServiceName
);
209 const XclChFormatInfo
& XclExpChRoot::GetFormatInfo( XclChObjectType eObjType
) const
211 return mxChData
->GetFormatInfoProvider().GetFormatInfo( eObjType
);
214 void XclExpChRoot::InitConversion( XChartDocRef xChartDoc
) const
216 mxChData
->InitConversion( xChartDoc
);
219 void XclExpChRoot::FinishConversion() const
221 mxChData
->FinishConversion();
224 bool XclExpChRoot::IsSystemColor( const Color
& rColor
, sal_uInt16 nSysColorIdx
) const
226 XclExpPalette
& rPal
= GetPalette();
227 return rPal
.IsSystemColor( nSysColorIdx
) && (rColor
== rPal
.GetDefColor( nSysColorIdx
));
230 void XclExpChRoot::SetSystemColor( Color
& rColor
, sal_uInt32
& rnColorId
, sal_uInt16 nSysColorIdx
) const
232 DBG_ASSERT( GetPalette().IsSystemColor( nSysColorIdx
), "XclExpChRoot::SetSystemColor - invalid color index" );
233 rColor
= GetPalette().GetDefColor( nSysColorIdx
);
234 rnColorId
= XclExpPalette::GetColorIdFromIndex( nSysColorIdx
);
237 void XclExpChRoot::ConvertLineFormat( XclChLineFormat
& rLineFmt
,
238 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
) const
240 GetChartPropSetHelper().ReadLineProperties(
241 rLineFmt
, mxChData
->GetLineDashTable(), rPropSet
, ePropMode
);
244 bool XclExpChRoot::ConvertAreaFormat( XclChAreaFormat
& rAreaFmt
,
245 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
) const
247 return GetChartPropSetHelper().ReadAreaProperties( rAreaFmt
, rPropSet
, ePropMode
);
250 void XclExpChRoot::ConvertEscherFormat(
251 XclChEscherFormat
& rEscherFmt
, XclChPicFormat
& rPicFmt
,
252 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
) const
254 GetChartPropSetHelper().ReadEscherProperties( rEscherFmt
, rPicFmt
,
255 mxChData
->GetGradientTable(), mxChData
->GetHatchTable(), mxChData
->GetBitmapTable(), rPropSet
, ePropMode
);
258 sal_uInt16
XclExpChRoot::ConvertFont( const ScfPropertySet
& rPropSet
, sal_Int16 nScript
) const
260 XclFontData aFontData
;
261 GetFontPropSetHelper().ReadFontProperties( aFontData
, rPropSet
, EXC_FONTPROPSET_CHART
, nScript
);
262 return GetFontBuffer().Insert( aFontData
, EXC_COLOR_CHARTTEXT
);
265 sal_uInt16
XclExpChRoot::ConvertPieRotation( const ScfPropertySet
& rPropSet
)
267 sal_Int32 nApiRot
= 0;
268 rPropSet
.GetProperty( nApiRot
, EXC_CHPROP_STARTINGANGLE
);
269 return static_cast< sal_uInt16
>( (450 - (nApiRot
% 360)) % 360 );
272 // ----------------------------------------------------------------------------
274 XclExpChGroupBase::XclExpChGroupBase( sal_uInt16 nRecId
, sal_Size nRecSize
) :
275 XclExpRecord( nRecId
, nRecSize
)
279 XclExpChGroupBase::~XclExpChGroupBase()
283 void XclExpChGroupBase::Save( XclExpStream
& rStrm
)
286 XclExpRecord::Save( rStrm
);
288 if( HasSubRecords() )
291 XclExpEmptyRecord( EXC_ID_CHBEGIN
).Save( rStrm
);
293 WriteSubRecords( rStrm
);
295 XclExpEmptyRecord( EXC_ID_CHEND
).Save( rStrm
);
299 bool XclExpChGroupBase::HasSubRecords() const
304 // Frame formatting ===========================================================
306 XclExpChLineFormat::XclExpChLineFormat( const XclExpChRoot
& rRoot
) :
307 XclExpRecord( EXC_ID_CHLINEFORMAT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 12 : 10 ),
308 mnColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
312 void XclExpChLineFormat::SetDefault( XclChFrameType eDefFrameType
)
314 switch( eDefFrameType
)
316 case EXC_CHFRAMETYPE_AUTO
:
319 case EXC_CHFRAMETYPE_INVISIBLE
:
321 maData
.mnPattern
= EXC_CHLINEFORMAT_NONE
;
324 DBG_ERRORFILE( "XclExpChLineFormat::SetDefault - unknown frame type" );
328 void XclExpChLineFormat::Convert( const XclExpChRoot
& rRoot
,
329 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
331 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
332 rRoot
.ConvertLineFormat( maData
, rPropSet
, rFmtInfo
.mePropMode
);
335 // detect system color, set color identifier (TODO: detect automatic series line)
336 if( (eObjType
!= EXC_CHOBJTYPE_LINEARSERIES
) && rRoot
.IsSystemColor( maData
.maColor
, rFmtInfo
.mnAutoLineColorIdx
) )
338 // store color index from automatic format data
339 mnColorId
= XclExpPalette::GetColorIdFromIndex( rFmtInfo
.mnAutoLineColorIdx
);
340 // try to set automatic mode
341 bool bAuto
= (maData
.mnPattern
== EXC_CHLINEFORMAT_SOLID
) && (maData
.mnWeight
== rFmtInfo
.mnAutoLineWeight
);
342 ::set_flag( maData
.mnFlags
, EXC_CHLINEFORMAT_AUTO
, bAuto
);
346 // user defined color - register in palette
347 mnColorId
= rRoot
.GetPalette().InsertColor( maData
.maColor
, EXC_COLOR_CHARTLINE
);
352 // no line - set default system color
353 rRoot
.SetSystemColor( maData
.maColor
, mnColorId
, EXC_COLOR_CHWINDOWTEXT
);
357 bool XclExpChLineFormat::IsDefault( XclChFrameType eDefFrameType
) const
360 ((eDefFrameType
== EXC_CHFRAMETYPE_INVISIBLE
) && !HasLine()) ||
361 ((eDefFrameType
== EXC_CHFRAMETYPE_AUTO
) && IsAuto());
364 void XclExpChLineFormat::WriteBody( XclExpStream
& rStrm
)
366 rStrm
<< maData
.maColor
<< maData
.mnPattern
<< maData
.mnWeight
<< maData
.mnFlags
;
367 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
368 rStrm
<< rStrm
.GetRoot().GetPalette().GetColorIndex( mnColorId
);
373 /** Creates a CHLINEFORMAT record from the passed property set. */
374 XclExpChLineFormatRef
lclCreateLineFormat( const XclExpChRoot
& rRoot
,
375 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
377 XclExpChLineFormatRef
xLineFmt( new XclExpChLineFormat( rRoot
) );
378 xLineFmt
->Convert( rRoot
, rPropSet
, eObjType
);
379 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
380 if( rFmtInfo
.mbDeleteDefFrame
&& xLineFmt
->IsDefault( rFmtInfo
.meDefFrameType
) )
387 // ----------------------------------------------------------------------------
389 XclExpChAreaFormat::XclExpChAreaFormat( const XclExpChRoot
& rRoot
) :
390 XclExpRecord( EXC_ID_CHAREAFORMAT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 16 : 12 ),
391 mnPattColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) ),
392 mnBackColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
396 bool XclExpChAreaFormat::Convert( const XclExpChRoot
& rRoot
,
397 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
399 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
400 bool bComplexFill
= rRoot
.ConvertAreaFormat( maData
, rPropSet
, rFmtInfo
.mePropMode
);
403 bool bSolid
= maData
.mnPattern
== EXC_PATT_SOLID
;
404 // detect system color, set color identifier (TODO: detect automatic series area)
405 if( (eObjType
!= EXC_CHOBJTYPE_FILLEDSERIES
) && rRoot
.IsSystemColor( maData
.maPattColor
, rFmtInfo
.mnAutoPattColorIdx
) )
407 // store color index from automatic format data
408 mnPattColorId
= XclExpPalette::GetColorIdFromIndex( rFmtInfo
.mnAutoPattColorIdx
);
409 // set automatic mode
410 ::set_flag( maData
.mnFlags
, EXC_CHAREAFORMAT_AUTO
, bSolid
);
414 // user defined color - register color in palette
415 mnPattColorId
= rRoot
.GetPalette().InsertColor( maData
.maPattColor
, EXC_COLOR_CHARTAREA
);
417 // background color (default system color for solid fills)
419 rRoot
.SetSystemColor( maData
.maBackColor
, mnBackColorId
, EXC_COLOR_CHWINDOWTEXT
);
421 mnBackColorId
= rRoot
.GetPalette().InsertColor( maData
.maBackColor
, EXC_COLOR_CHARTAREA
);
425 // no area - set default system colors
426 rRoot
.SetSystemColor( maData
.maPattColor
, mnPattColorId
, EXC_COLOR_CHWINDOWBACK
);
427 rRoot
.SetSystemColor( maData
.maBackColor
, mnBackColorId
, EXC_COLOR_CHWINDOWTEXT
);
432 void XclExpChAreaFormat::SetDefault( XclChFrameType eDefFrameType
)
434 switch( eDefFrameType
)
436 case EXC_CHFRAMETYPE_AUTO
:
439 case EXC_CHFRAMETYPE_INVISIBLE
:
441 maData
.mnPattern
= EXC_PATT_NONE
;
444 DBG_ERRORFILE( "XclExpChAreaFormat::SetDefault - unknown frame type" );
448 bool XclExpChAreaFormat::IsDefault( XclChFrameType eDefFrameType
) const
451 ((eDefFrameType
== EXC_CHFRAMETYPE_INVISIBLE
) && !HasArea()) ||
452 ((eDefFrameType
== EXC_CHFRAMETYPE_AUTO
) && IsAuto());
455 void XclExpChAreaFormat::WriteBody( XclExpStream
& rStrm
)
457 rStrm
<< maData
.maPattColor
<< maData
.maBackColor
<< maData
.mnPattern
<< maData
.mnFlags
;
458 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
460 const XclExpPalette
& rPal
= rStrm
.GetRoot().GetPalette();
461 rStrm
<< rPal
.GetColorIndex( mnPattColorId
) << rPal
.GetColorIndex( mnBackColorId
);
465 // ----------------------------------------------------------------------------
467 XclExpChEscherFormat::XclExpChEscherFormat( const XclExpChRoot
& rRoot
) :
468 XclExpChGroupBase( EXC_ID_CHESCHERFORMAT
),
469 mnColor1Id( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) ),
470 mnColor2Id( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) )
472 DBG_ASSERT_BIFF( rRoot
.GetBiff() == EXC_BIFF8
);
476 void XclExpChEscherFormat::Convert( const XclExpChRoot
& rRoot
,
477 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
479 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
480 rRoot
.ConvertEscherFormat( maData
, maPicFmt
, rPropSet
, rFmtInfo
.mePropMode
);
481 // register colors in palette
482 mnColor1Id
= RegisterColor( rRoot
, ESCHER_Prop_fillColor
);
483 mnColor2Id
= RegisterColor( rRoot
, ESCHER_Prop_fillBackColor
);
486 bool XclExpChEscherFormat::IsValid() const
488 return maData
.mxEscherSet
.is();
491 void XclExpChEscherFormat::Save( XclExpStream
& rStrm
)
493 if( maData
.mxEscherSet
.is() )
495 // replace RGB colors with palette indexes in the Escher container
496 const XclExpPalette
& rPal
= rStrm
.GetRoot().GetPalette();
497 maData
.mxEscherSet
->AddOpt( ESCHER_Prop_fillColor
, 0x08000000 | rPal
.GetColorIndex( mnColor1Id
) );
498 maData
.mxEscherSet
->AddOpt( ESCHER_Prop_fillBackColor
, 0x08000000 | rPal
.GetColorIndex( mnColor2Id
) );
500 // save the record group
501 XclExpChGroupBase::Save( rStrm
);
505 bool XclExpChEscherFormat::HasSubRecords() const
507 // no subrecords for gradients
508 return maPicFmt
.mnBmpMode
!= EXC_CHPICFORMAT_NONE
;
511 void XclExpChEscherFormat::WriteSubRecords( XclExpStream
& rStrm
)
513 rStrm
.StartRecord( EXC_ID_CHPICFORMAT
, 14 );
514 rStrm
<< maPicFmt
.mnBmpMode
<< maPicFmt
.mnFormat
<< maPicFmt
.mnFlags
<< maPicFmt
.mfScale
;
518 sal_uInt32
XclExpChEscherFormat::RegisterColor( const XclExpChRoot
& rRoot
, sal_uInt16 nPropId
)
520 sal_uInt32 nBGRValue
;
521 if( maData
.mxEscherSet
.is() && maData
.mxEscherSet
->GetOpt( nPropId
, nBGRValue
) )
524 Color
aColor( RGB_COLORDATA(
525 COLORDATA_BLUE( nBGRValue
),
526 COLORDATA_GREEN( nBGRValue
),
527 COLORDATA_RED( nBGRValue
) ) );
528 return rRoot
.GetPalette().InsertColor( aColor
, EXC_COLOR_CHARTAREA
);
530 return XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
);
533 void XclExpChEscherFormat::WriteBody( XclExpStream
& rStrm
)
535 DBG_ASSERT( maData
.mxEscherSet
.is(), "XclExpChEscherFormat::WriteBody - missing property container" );
536 // write Escher property container via temporary memory stream
537 SvMemoryStream aMemStrm
;
538 maData
.mxEscherSet
->Commit( aMemStrm
);
539 aMemStrm
.Seek( STREAM_SEEK_TO_BEGIN
);
540 rStrm
.CopyFromStream( aMemStrm
);
543 // ----------------------------------------------------------------------------
545 XclExpChFrameBase::XclExpChFrameBase()
549 XclExpChFrameBase::~XclExpChFrameBase()
553 void XclExpChFrameBase::ConvertFrameBase( const XclExpChRoot
& rRoot
,
554 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
557 mxLineFmt
.reset( new XclExpChLineFormat( rRoot
) );
558 mxLineFmt
->Convert( rRoot
, rPropSet
, eObjType
);
559 // area format (only for frame objects)
560 if( rRoot
.GetFormatInfo( eObjType
).mbIsFrame
)
562 mxAreaFmt
.reset( new XclExpChAreaFormat( rRoot
) );
563 bool bComplexFill
= mxAreaFmt
->Convert( rRoot
, rPropSet
, eObjType
);
564 if( (rRoot
.GetBiff() == EXC_BIFF8
) && bComplexFill
)
566 mxEscherFmt
.reset( new XclExpChEscherFormat( rRoot
) );
567 mxEscherFmt
->Convert( rRoot
, rPropSet
, eObjType
);
568 if( mxEscherFmt
->IsValid() )
569 mxAreaFmt
->SetAuto( false );
576 void XclExpChFrameBase::SetDefaultFrameBase( const XclExpChRoot
& rRoot
,
577 XclChFrameType eDefFrameType
, bool bIsFrame
)
580 mxLineFmt
.reset( new XclExpChLineFormat( rRoot
) );
581 mxLineFmt
->SetDefault( eDefFrameType
);
582 // area format (only for frame objects)
585 mxAreaFmt
.reset( new XclExpChAreaFormat( rRoot
) );
586 mxAreaFmt
->SetDefault( eDefFrameType
);
591 bool XclExpChFrameBase::IsDefaultFrameBase( XclChFrameType eDefFrameType
) const
594 (!mxLineFmt
|| mxLineFmt
->IsDefault( eDefFrameType
)) &&
595 (!mxAreaFmt
|| mxAreaFmt
->IsDefault( eDefFrameType
));
598 void XclExpChFrameBase::WriteFrameRecords( XclExpStream
& rStrm
)
600 lclSaveRecord( rStrm
, mxLineFmt
);
601 lclSaveRecord( rStrm
, mxAreaFmt
);
602 lclSaveRecord( rStrm
, mxEscherFmt
);
605 // ----------------------------------------------------------------------------
607 XclExpChFrame::XclExpChFrame( const XclExpChRoot
& rRoot
, XclChObjectType eObjType
) :
608 XclExpChGroupBase( EXC_ID_CHFRAME
, 4 ),
609 XclExpChRoot( rRoot
),
610 meObjType( eObjType
)
614 void XclExpChFrame::Convert( const ScfPropertySet
& rPropSet
)
616 ConvertFrameBase( GetChRoot(), rPropSet
, meObjType
);
619 bool XclExpChFrame::IsDefault() const
621 return IsDefaultFrameBase( GetFormatInfo( meObjType
).meDefFrameType
);
624 bool XclExpChFrame::IsDeleteable() const
626 return IsDefault() && GetFormatInfo( meObjType
).mbDeleteDefFrame
;
629 void XclExpChFrame::Save( XclExpStream
& rStrm
)
633 // wall/floor frame without CHFRAME header record
634 case EXC_CHOBJTYPE_WALL3D
:
635 case EXC_CHOBJTYPE_FLOOR3D
:
636 WriteFrameRecords( rStrm
);
639 XclExpChGroupBase::Save( rStrm
);
643 void XclExpChFrame::WriteSubRecords( XclExpStream
& rStrm
)
645 WriteFrameRecords( rStrm
);
648 void XclExpChFrame::WriteBody( XclExpStream
& rStrm
)
650 rStrm
<< maData
.mnFormat
<< maData
.mnFlags
;
655 /** Creates a CHFRAME record from the passed property set. */
656 XclExpChFrameRef
lclCreateFrame( const XclExpChRoot
& rRoot
,
657 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
659 XclExpChFrameRef
xFrame( new XclExpChFrame( rRoot
, eObjType
) );
660 xFrame
->Convert( rPropSet
);
661 if( xFrame
->IsDeleteable() )
666 void lclAddDoubleRefData(ScTokenArray
& rArray
, const ::formula::FormulaToken
& rToken
,
667 SCsTAB nTab1
, SCsTAB nTab2
, SCsCOL nCol1
, SCsCOL nCol2
, SCsROW nRow1
, SCsROW nRow2
)
669 using namespace ::formula
;
671 StackVar eType
= rToken
.GetType();
672 bool bExternal
= (eType
== svExternalDoubleRef
);
673 DBG_ASSERT(eType
== svDoubleRef
|| eType
== svExternalDoubleRef
, "not a double ref token!");
675 ScComplexRefData aData
;
678 aData
.Ref1
.SetFlag3D(true);
679 aData
.Ref1
.SetTabRel(false);
680 aData
.Ref1
.SetColRel(false);
681 aData
.Ref1
.SetRowRel(false);
682 aData
.Ref2
.SetFlag3D(false);
683 aData
.Ref2
.SetTabRel(false);
684 aData
.Ref2
.SetColRel(false);
685 aData
.Ref2
.SetRowRel(false);
687 aData
.Ref1
.nTab
= nTab1
;
688 aData
.Ref1
.nCol
= nCol1
;
689 aData
.Ref1
.nRow
= nRow1
;
690 aData
.Ref2
.nTab
= nTab2
;
691 aData
.Ref2
.nCol
= nCol2
;
692 aData
.Ref2
.nRow
= nRow2
;
695 rArray
.AddExternalDoubleReference(rToken
.GetIndex(), rToken
.GetString(), aData
);
697 rArray
.AddDoubleReference(aData
);
702 // Source links ===============================================================
704 XclExpChSourceLink::XclExpChSourceLink( const XclExpChRoot
& rRoot
, sal_uInt8 nDestType
) :
705 XclExpRecord( EXC_ID_CHSOURCELINK
),
706 XclExpChRoot( rRoot
)
708 maData
.mnDestType
= nDestType
;
709 maData
.mnLinkType
= EXC_CHSRCLINK_DIRECTLY
;
712 sal_uInt16
XclExpChSourceLink::ConvertDataSequence( Reference
< XDataSequence
> xDataSeq
, bool bSplitToColumns
, sal_uInt16 nDefCount
)
714 using namespace ::formula
;
717 maData
.mnLinkType
= EXC_CHSRCLINK_DEFAULT
;
718 sal_uInt16 nValueCount
= nDefCount
;
723 // Compile the range representation string into token array. Note that the
724 // source range text depends on the current grammar.
725 OUString aRangeRepr
= xDataSeq
->getSourceRangeRepresentation();
726 ScRangeList aScRanges
;
727 ScCompiler
aComp(GetDocPtr(), ScAddress());
728 aComp
.SetGrammar(GetDocPtr()->GetGrammar());
729 ScTokenArray
* pArray
= aComp
.CompileString(aRangeRepr
);
736 for (const FormulaToken
* p
= pArray
->First(); p
; p
= pArray
->Next())
738 StackVar eType
= p
->GetType();
739 if (eType
== svSingleRef
|| eType
== svExternalSingleRef
)
741 // For a single ref token, just add it to the new token array as is.
745 aArray
.AddOpCode(ocUnion
);
750 if (eType
!= svDoubleRef
&& eType
!= svExternalDoubleRef
)
753 // split 3-dimensional ranges into single sheets.
754 const ScComplexRefData
& r
= static_cast<const ScToken
*>(p
)->GetDoubleRef();
755 const ScSingleRefData
& s
= r
.Ref1
;
756 const ScSingleRefData
& e
= r
.Ref2
;
757 for (SCsTAB nTab
= s
.nTab
; nTab
<= e
.nTab
; ++nTab
)
759 if (bSplitToColumns
&& (s
.nRow
!= e
.nRow
))
761 // split 2-dimensional ranges into single columns.
762 for (SCsCOL nCol
= s
.nCol
; nCol
<= e
.nCol
; ++nCol
)
767 aArray
.AddOpCode(ocUnion
);
769 lclAddDoubleRefData(aArray
, *p
, nTab
, nTab
, nCol
, nCol
, s
.nRow
, e
.nRow
);
777 aArray
.AddOpCode(ocUnion
);
779 lclAddDoubleRefData(aArray
, *p
, nTab
, nTab
, s
.nCol
, e
.nCol
, s
.nRow
, e
.nRow
);
784 const ScAddress
aBaseCell(0,0,0);
785 mxLinkFmla
= GetFormulaCompiler().CreateFormula(EXC_FMLATYPE_CHART
, aArray
, &aBaseCell
);
786 maData
.mnLinkType
= EXC_CHSRCLINK_WORKSHEET
;
787 nValueCount
= ulimit_cast
< sal_uInt16
>( aScRanges
.GetCellCount(), EXC_CHDATAFORMAT_MAXPOINTCOUNT
);
791 sal_uInt16
XclExpChSourceLink::ConvertStringSequence( const Sequence
< Reference
< XFormattedString
> >& rStringSeq
)
794 sal_uInt16 nFontIdx
= EXC_FONT_APP
;
795 if( rStringSeq
.hasElements() )
797 mxString
= XclExpStringHelper::CreateString( GetRoot(), String::EmptyString(), EXC_STR_FORCEUNICODE
| EXC_STR_8BITLENGTH
| EXC_STR_SEPARATEFORMATS
);
798 Reference
< XBreakIterator
> xBreakIt
= GetDoc().GetBreakIterator();
799 namespace ApiScriptType
= ::com::sun::star::i18n::ScriptType
;
801 // convert all formatted string entries from the sequence
802 const Reference
< XFormattedString
>* pBeg
= rStringSeq
.getConstArray();
803 const Reference
< XFormattedString
>* pEnd
= pBeg
+ rStringSeq
.getLength();
804 for( const Reference
< XFormattedString
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
808 sal_uInt16 nWstrnFontIdx
= EXC_FONT_NOTFOUND
;
809 sal_uInt16 nAsianFontIdx
= EXC_FONT_NOTFOUND
;
810 sal_uInt16 nCmplxFontIdx
= EXC_FONT_NOTFOUND
;
811 OUString aText
= (*pIt
)->getString();
812 ScfPropertySet
aStrProp( *pIt
);
814 // #i63255# get script type for leading weak characters
815 sal_Int16 nLastScript
= XclExpStringHelper::GetLeadingScriptType( GetRoot(), aText
);
817 // process all script portions
818 sal_Int32 nPortionPos
= 0;
819 sal_Int32 nTextLen
= aText
.getLength();
820 while( nPortionPos
< nTextLen
)
822 // get script type and end position of next script portion
823 sal_Int16 nScript
= xBreakIt
->getScriptType( aText
, nPortionPos
);
824 sal_Int32 nPortionEnd
= xBreakIt
->endOfScript( aText
, nPortionPos
, nScript
);
826 // reuse previous script for following weak portions
827 if( nScript
== ApiScriptType::WEAK
)
828 nScript
= nLastScript
;
830 // Excel start position of this portion
831 sal_uInt16 nXclPortionStart
= mxString
->Len();
832 // add portion text to Excel string
833 XclExpStringHelper::AppendString( *mxString
, GetRoot(), aText
.copy( nPortionPos
, nPortionEnd
- nPortionPos
) );
834 if( nXclPortionStart
< mxString
->Len() )
836 // find font index variable dependent on script type
837 sal_uInt16
& rnFontIdx
= (nScript
== ApiScriptType::COMPLEX
) ? nCmplxFontIdx
:
838 ((nScript
== ApiScriptType::ASIAN
) ? nAsianFontIdx
: nWstrnFontIdx
);
840 // insert font into buffer (if not yet done)
841 if( rnFontIdx
== EXC_FONT_NOTFOUND
)
842 rnFontIdx
= ConvertFont( aStrProp
, nScript
);
844 // insert font index into format run vector
845 mxString
->AppendFormat( nXclPortionStart
, rnFontIdx
);
848 // go to next script portion
849 nLastScript
= nScript
;
850 nPortionPos
= nPortionEnd
;
854 if( !mxString
->IsEmpty() )
856 // get leading font index
857 const XclFormatRunVec
& rFormats
= mxString
->GetFormats();
858 DBG_ASSERT( !rFormats
.empty() && (rFormats
.front().mnChar
== 0),
859 "XclExpChSourceLink::ConvertStringSequenc - missing leading format" );
860 // remove leading format run, if entire string is equally formatted
861 if( rFormats
.size() == 1 )
862 nFontIdx
= mxString
->RemoveLeadingFont();
863 else if( !rFormats
.empty() )
864 nFontIdx
= rFormats
.front().mnFontIdx
;
865 // add trailing format run, if string is rich-formatted
866 if( mxString
->IsRich() )
867 mxString
->AppendTrailingFormat( EXC_FONT_APP
);
873 void XclExpChSourceLink::ConvertNumFmt( const ScfPropertySet
& rPropSet
, bool bPercent
)
875 sal_Int32 nApiNumFmt
= 0;
876 if( bPercent
? rPropSet
.GetProperty( nApiNumFmt
, EXC_CHPROP_PERCENTAGENUMFMT
) : rPropSet
.GetProperty( nApiNumFmt
, EXC_CHPROP_NUMBERFORMAT
) )
878 ::set_flag( maData
.mnFlags
, EXC_CHSRCLINK_NUMFMT
);
879 maData
.mnNumFmtIdx
= GetNumFmtBuffer().Insert( static_cast< sal_uInt32
>( nApiNumFmt
) );
883 void XclExpChSourceLink::AppendString( const String
& rStr
)
887 XclExpStringHelper::AppendString( *mxString
, GetRoot(), rStr
);
890 void XclExpChSourceLink::Save( XclExpStream
& rStrm
)
892 // CHFORMATRUNS record
893 if( mxString
.is() && mxString
->IsRich() )
895 sal_Size nRecSize
= (1 + mxString
->GetFormatsCount()) * ((GetBiff() == EXC_BIFF8
) ? 2 : 1);
896 rStrm
.StartRecord( EXC_ID_CHFORMATRUNS
, nRecSize
);
897 mxString
->WriteFormats( rStrm
, true );
900 // CHSOURCELINK record
901 XclExpRecord::Save( rStrm
);
903 if( mxString
.is() && !mxString
->IsEmpty() )
905 rStrm
.StartRecord( EXC_ID_CHSTRING
, 2 + mxString
->GetSize() );
906 rStrm
<< sal_uInt16( 0 ) << *mxString
;
911 void XclExpChSourceLink::WriteBody( XclExpStream
& rStrm
)
913 rStrm
<< maData
.mnDestType
916 << maData
.mnNumFmtIdx
920 // Text =======================================================================
922 XclExpChFont::XclExpChFont( sal_uInt16 nFontIdx
) :
923 XclExpUInt16Record( EXC_ID_CHFONT
, nFontIdx
)
927 // ----------------------------------------------------------------------------
929 XclExpChObjectLink::XclExpChObjectLink( sal_uInt16 nLinkTarget
, const XclChDataPointPos
& rPointPos
) :
930 XclExpRecord( EXC_ID_CHOBJECTLINK
, 6 )
932 maData
.mnTarget
= nLinkTarget
;
933 maData
.maPointPos
= rPointPos
;
936 void XclExpChObjectLink::WriteBody( XclExpStream
& rStrm
)
938 rStrm
<< maData
.mnTarget
<< maData
.maPointPos
.mnSeriesIdx
<< maData
.maPointPos
.mnPointIdx
;
941 // ----------------------------------------------------------------------------
943 XclExpChFontBase::~XclExpChFontBase()
947 void XclExpChFontBase::ConvertFontBase( const XclExpChRoot
& rRoot
, sal_uInt16 nFontIdx
)
949 if( const XclExpFont
* pFont
= rRoot
.GetFontBuffer().GetFont( nFontIdx
) )
951 XclExpChFontRef
xFont( new XclExpChFont( nFontIdx
) );
952 SetFont( xFont
, pFont
->GetFontData().maColor
, pFont
->GetFontColorId() );
956 void XclExpChFontBase::ConvertFontBase( const XclExpChRoot
& rRoot
, const ScfPropertySet
& rPropSet
)
958 ConvertFontBase( rRoot
, rRoot
.ConvertFont( rPropSet
, rRoot
.GetDefApiScript() ) );
961 void XclExpChFontBase::ConvertRotationBase(
962 const XclExpChRoot
& rRoot
, const ScfPropertySet
& rPropSet
)
964 sal_uInt16 nRotation
= rRoot
.GetChartPropSetHelper().ReadRotationProperties( rPropSet
);
965 SetRotation( nRotation
);
968 // ----------------------------------------------------------------------------
970 XclExpChText::XclExpChText( const XclExpChRoot
& rRoot
) :
971 XclExpChGroupBase( EXC_ID_CHTEXT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 32 : 26 ),
972 XclExpChRoot( rRoot
),
973 mnTextColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
977 void XclExpChText::SetFont( XclExpChFontRef xFont
, const Color
& rColor
, sal_uInt32 nColorId
)
980 maData
.maTextColor
= rColor
;
981 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOCOLOR
, rColor
== COL_AUTO
);
982 mnTextColorId
= nColorId
;
985 void XclExpChText::SetRotation( sal_uInt16 nRotation
)
987 maData
.mnRotation
= nRotation
;
988 ::insert_value( maData
.mnFlags
, XclTools::GetXclOrientFromRot( nRotation
), 8, 3 );
991 void XclExpChText::ConvertTitle( Reference
< XTitle
> xTitle
, sal_uInt16 nTarget
, const String
* pSubTitle
)
994 mxObjLink
.reset( new XclExpChObjectLink( nTarget
, XclChDataPointPos( 0, 0 ) ) );
998 // title frame formatting
999 ScfPropertySet
aTitleProp( xTitle
);
1000 mxFrame
= lclCreateFrame( GetChRoot(), aTitleProp
, EXC_CHOBJTYPE_TEXT
);
1003 mxSrcLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1004 sal_uInt16 nFontIdx
= mxSrcLink
->ConvertStringSequence( xTitle
->getText() );
1007 // append subtitle as the 2nd line of the title.
1008 String aSubTitle
= String::CreateFromAscii("\n");
1009 aSubTitle
.Append(*pSubTitle
);
1010 mxSrcLink
->AppendString(aSubTitle
);
1013 ConvertFontBase( GetChRoot(), nFontIdx
);
1016 ConvertRotationBase( GetChRoot(), aTitleProp
);
1020 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_DELETED
);
1024 void XclExpChText::ConvertLegend( const ScfPropertySet
& rPropSet
)
1026 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOTEXT
);
1027 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOGEN
);
1028 ConvertFontBase( GetChRoot(), rPropSet
);
1031 bool XclExpChText::ConvertDataLabel( const ScfPropertySet
& rPropSet
,
1032 const XclChTypeInfo
& rTypeInfo
, const XclChDataPointPos
& rPointPos
)
1034 namespace cssc
= ::com::sun::star::chart2
;
1035 cssc::DataPointLabel aPointLabel
;
1036 if( rPropSet
.GetProperty( aPointLabel
, EXC_CHPROP_LABEL
) )
1038 //! TODO: make value and percent independent
1039 bool bIsPie
= rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
;
1040 bool bShowValue
= aPointLabel
.ShowNumber
;
1041 bool bShowPercent
= bIsPie
&& !bShowValue
&& aPointLabel
.ShowNumberInPercent
;
1042 bool bShowCateg
= !bShowValue
&& aPointLabel
.ShowCategoryName
;
1043 bool bShowAny
= bShowValue
|| bShowPercent
|| bShowCateg
;
1044 bool bShowSymbol
= bShowAny
&& aPointLabel
.ShowLegendSymbol
;
1046 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOTEXT
);
1047 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWVALUE
, bShowValue
);
1048 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWPERCENT
, bShowPercent
);
1049 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
, bShowCateg
);
1050 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEGPERC
, bShowPercent
&& bShowCateg
);
1051 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWSYMBOL
, bShowSymbol
);
1052 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_DELETED
, !bShowAny
);
1057 ConvertFontBase( GetChRoot(), rPropSet
);
1059 sal_Int32 nPlacement
= 0;
1060 if( rPropSet
.GetProperty( nPlacement
, EXC_CHPROP_LABELPLACEMENT
) )
1062 using namespace ::com::sun::star::chart::DataLabelPlacement
;
1063 if( nPlacement
== rTypeInfo
.mnDefaultLabelPos
)
1065 maData
.mnPlacement
= EXC_CHTEXT_POS_DEFAULT
;
1067 else switch( nPlacement
)
1069 case AVOID_OVERLAP
: maData
.mnPlacement
= EXC_CHTEXT_POS_AUTO
; break;
1070 case CENTER
: maData
.mnPlacement
= EXC_CHTEXT_POS_CENTER
; break;
1071 case TOP
: maData
.mnPlacement
= EXC_CHTEXT_POS_ABOVE
; break;
1072 case TOP_LEFT
: maData
.mnPlacement
= EXC_CHTEXT_POS_LEFT
; break;
1073 case LEFT
: maData
.mnPlacement
= EXC_CHTEXT_POS_LEFT
; break;
1074 case BOTTOM_LEFT
: maData
.mnPlacement
= EXC_CHTEXT_POS_LEFT
; break;
1075 case BOTTOM
: maData
.mnPlacement
= EXC_CHTEXT_POS_BELOW
; break;
1076 case BOTTOM_RIGHT
: maData
.mnPlacement
= EXC_CHTEXT_POS_RIGHT
; break;
1077 case RIGHT
: maData
.mnPlacement
= EXC_CHTEXT_POS_RIGHT
; break;
1078 case TOP_RIGHT
: maData
.mnPlacement
= EXC_CHTEXT_POS_RIGHT
; break;
1079 case INSIDE
: maData
.mnPlacement
= EXC_CHTEXT_POS_INSIDE
; break;
1080 case OUTSIDE
: maData
.mnPlacement
= EXC_CHTEXT_POS_OUTSIDE
; break;
1081 case NEAR_ORIGIN
: maData
.mnPlacement
= EXC_CHTEXT_POS_AXIS
; break;
1082 default: DBG_ERRORFILE( "XclExpChText::ConvertDataLabel - unknown label placement type" );
1085 // source link (contains number format)
1086 mxSrcLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1087 if( bShowValue
|| bShowPercent
)
1088 // percentage format wins over value format
1089 mxSrcLink
->ConvertNumFmt( rPropSet
, bShowPercent
);
1091 mxObjLink
.reset( new XclExpChObjectLink( EXC_CHOBJLINK_DATA
, rPointPos
) );
1092 // return true to indicate existing label
1099 void XclExpChText::ConvertTrendLineEquation( const ScfPropertySet
& rPropSet
, const XclChDataPointPos
& rPointPos
)
1102 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOTEXT
);
1103 if( GetBiff() == EXC_BIFF8
)
1104 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
); // must set this to make equation visible in Excel
1106 mxFrame
= lclCreateFrame( GetChRoot(), rPropSet
, EXC_CHOBJTYPE_TEXT
);
1108 maData
.mnHAlign
= EXC_CHTEXT_ALIGN_TOPLEFT
;
1109 maData
.mnVAlign
= EXC_CHTEXT_ALIGN_TOPLEFT
;
1110 ConvertFontBase( GetChRoot(), rPropSet
);
1111 // source link (contains number format)
1112 mxSrcLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1113 mxSrcLink
->ConvertNumFmt( rPropSet
, false );
1115 mxObjLink
.reset( new XclExpChObjectLink( EXC_CHOBJLINK_DATA
, rPointPos
) );
1118 sal_uInt16
XclExpChText::GetAttLabelFlags() const
1120 sal_uInt16 nFlags
= 0;
1121 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWVALUE
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWVALUE
) );
1122 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWPERCENT
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWPERCENT
) );
1123 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWCATEGPERC
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEGPERC
) );
1124 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWCATEG
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
) );
1128 void XclExpChText::WriteSubRecords( XclExpStream
& rStrm
)
1131 lclSaveRecord( rStrm
, mxFont
);
1132 // CHSOURCELINK group
1133 lclSaveRecord( rStrm
, mxSrcLink
);
1135 lclSaveRecord( rStrm
, mxFrame
);
1136 // CHOBJECTLINK record
1137 lclSaveRecord( rStrm
, mxObjLink
);
1140 void XclExpChText::WriteBody( XclExpStream
& rStrm
)
1142 rStrm
<< maData
.mnHAlign
1144 << maData
.mnBackMode
1145 << maData
.maTextColor
1149 if( GetBiff() == EXC_BIFF8
)
1151 rStrm
<< GetPalette().GetColorIndex( mnTextColorId
)
1152 << maData
.mnPlacement
1153 << maData
.mnRotation
;
1157 // ----------------------------------------------------------------------------
1161 /** Creates and returns an Excel text object from the passed title. */
1162 XclExpChTextRef
lclCreateTitle( const XclExpChRoot
& rRoot
, Reference
< XTitled
> xTitled
, sal_uInt16 nTarget
,
1163 const String
* pSubTitle
= NULL
)
1165 Reference
< XTitle
> xTitle
;
1167 xTitle
= xTitled
->getTitleObject();
1169 XclExpChTextRef
xText( new XclExpChText( rRoot
) );
1170 xText
->ConvertTitle( xTitle
, nTarget
, pSubTitle
);
1171 /* Do not delete the CHTEXT group for the main title. A missing CHTEXT
1172 will be interpreted as auto-generated title showing the series title in
1173 charts that contain exactly one data series. */
1174 if( (nTarget
!= EXC_CHOBJLINK_TITLE
) && !xText
->HasString() )
1182 // Data series ================================================================
1184 XclExpChMarkerFormat::XclExpChMarkerFormat( const XclExpChRoot
& rRoot
) :
1185 XclExpRecord( EXC_ID_CHMARKERFORMAT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 20 : 12 ),
1186 mnLineColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) ),
1187 mnFillColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) )
1191 void XclExpChMarkerFormat::Convert( const XclExpChRoot
& rRoot
,
1192 const ScfPropertySet
& rPropSet
, sal_uInt16 nFormatIdx
)
1194 rRoot
.GetChartPropSetHelper().ReadMarkerProperties( maData
, rPropSet
, nFormatIdx
);
1195 /* Set marker line/fill color to series line color.
1196 TODO: remove this if OOChart supports own colors in markers. */
1198 if( rPropSet
.GetColorProperty( aLineColor
, EXC_CHPROP_COLOR
) )
1199 maData
.maLineColor
= maData
.maFillColor
= aLineColor
;
1200 // register colors in palette
1201 RegisterColors( rRoot
);
1204 void XclExpChMarkerFormat::ConvertStockSymbol( const XclExpChRoot
& rRoot
,
1205 const ScfPropertySet
& rPropSet
, bool bCloseSymbol
)
1207 // clear the automatic flag
1208 ::set_flag( maData
.mnFlags
, EXC_CHMARKERFORMAT_AUTO
, false );
1209 // symbol type and color
1212 // set symbol type for the 'close' data series
1213 maData
.mnMarkerType
= EXC_CHMARKERFORMAT_DOWJ
;
1214 maData
.mnMarkerSize
= EXC_CHMARKERFORMAT_DOUBLESIZE
;
1215 // set symbol line/fill color to series line color
1217 if( rPropSet
.GetColorProperty( aLineColor
, EXC_CHPROP_COLOR
) )
1219 maData
.maLineColor
= maData
.maFillColor
= aLineColor
;
1220 RegisterColors( rRoot
);
1225 // set invisible symbol
1226 maData
.mnMarkerType
= EXC_CHMARKERFORMAT_NOSYMBOL
;
1230 void XclExpChMarkerFormat::RegisterColors( const XclExpChRoot
& rRoot
)
1234 if( HasLineColor() )
1235 mnLineColorId
= rRoot
.GetPalette().InsertColor( maData
.maLineColor
, EXC_COLOR_CHARTLINE
);
1236 if( HasFillColor() )
1237 mnFillColorId
= rRoot
.GetPalette().InsertColor( maData
.maFillColor
, EXC_COLOR_CHARTAREA
);
1241 void XclExpChMarkerFormat::WriteBody( XclExpStream
& rStrm
)
1243 rStrm
<< maData
.maLineColor
<< maData
.maFillColor
<< maData
.mnMarkerType
<< maData
.mnFlags
;
1244 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
1246 const XclExpPalette
& rPal
= rStrm
.GetRoot().GetPalette();
1247 rStrm
<< rPal
.GetColorIndex( mnLineColorId
) << rPal
.GetColorIndex( mnFillColorId
) << maData
.mnMarkerSize
;
1251 // ----------------------------------------------------------------------------
1253 XclExpChPieFormat::XclExpChPieFormat() :
1254 XclExpUInt16Record( EXC_ID_CHPIEFORMAT
, 0 )
1258 void XclExpChPieFormat::Convert( const ScfPropertySet
& rPropSet
)
1260 double fApiDist(0.0);
1261 if( rPropSet
.GetProperty( fApiDist
, EXC_CHPROP_OFFSET
) )
1262 SetValue( limit_cast
< sal_uInt16
>( fApiDist
* 100.0, 0, 100 ) );
1265 // ----------------------------------------------------------------------------
1267 XclExpCh3dDataFormat::XclExpCh3dDataFormat() :
1268 XclExpRecord( EXC_ID_CH3DDATAFORMAT
, 2 )
1272 void XclExpCh3dDataFormat::Convert( const ScfPropertySet
& rPropSet
)
1274 sal_Int32
nApiType(0);
1275 if( rPropSet
.GetProperty( nApiType
, EXC_CHPROP_GEOMETRY3D
) )
1277 using namespace ::com::sun::star::chart2::DataPointGeometry3D
;
1281 maData
.mnBase
= EXC_CH3DDATAFORMAT_RECT
;
1282 maData
.mnTop
= EXC_CH3DDATAFORMAT_STRAIGHT
;
1285 maData
.mnBase
= EXC_CH3DDATAFORMAT_RECT
;
1286 maData
.mnTop
= EXC_CH3DDATAFORMAT_SHARP
;
1289 maData
.mnBase
= EXC_CH3DDATAFORMAT_CIRC
;
1290 maData
.mnTop
= EXC_CH3DDATAFORMAT_STRAIGHT
;
1293 maData
.mnBase
= EXC_CH3DDATAFORMAT_CIRC
;
1294 maData
.mnTop
= EXC_CH3DDATAFORMAT_SHARP
;
1297 DBG_ERRORFILE( "XclExpCh3dDataFormat::Convert - unknown 3D bar format" );
1302 void XclExpCh3dDataFormat::WriteBody( XclExpStream
& rStrm
)
1304 rStrm
<< maData
.mnBase
<< maData
.mnTop
;
1307 // ----------------------------------------------------------------------------
1309 XclExpChAttachedLabel::XclExpChAttachedLabel( sal_uInt16 nFlags
) :
1310 XclExpUInt16Record( EXC_ID_CHATTACHEDLABEL
, nFlags
)
1314 // ----------------------------------------------------------------------------
1316 XclExpChDataFormat::XclExpChDataFormat( const XclExpChRoot
& rRoot
,
1317 const XclChDataPointPos
& rPointPos
, sal_uInt16 nFormatIdx
) :
1318 XclExpChGroupBase( EXC_ID_CHDATAFORMAT
, 8 ),
1319 XclExpChRoot( rRoot
)
1321 maData
.maPointPos
= rPointPos
;
1322 maData
.mnFormatIdx
= nFormatIdx
;
1325 void XclExpChDataFormat::ConvertDataSeries( const ScfPropertySet
& rPropSet
, const XclChExtTypeInfo
& rTypeInfo
)
1327 // line and area formatting
1328 ConvertFrameBase( GetChRoot(), rPropSet
, rTypeInfo
.GetSeriesObjectType() );
1330 // data point symbols
1331 bool bIsFrame
= rTypeInfo
.IsSeriesFrameFormat();
1334 mxMarkerFmt
.reset( new XclExpChMarkerFormat( GetChRoot() ) );
1335 mxMarkerFmt
->Convert( GetChRoot(), rPropSet
, maData
.mnFormatIdx
);
1339 if( rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
)
1341 mxPieFmt
.reset( new XclExpChPieFormat
);
1342 mxPieFmt
->Convert( rPropSet
);
1345 // 3D bars (only allowed for entire series in BIFF8)
1346 if( IsSeriesFormat() && (GetBiff() == EXC_BIFF8
) && rTypeInfo
.mb3dChart
&& (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_BAR
) )
1348 mx3dDataFmt
.reset( new XclExpCh3dDataFormat
);
1349 mx3dDataFmt
->Convert( rPropSet
);
1353 if( IsSeriesFormat() && rTypeInfo
.mbSpline
&& !bIsFrame
)
1354 mxSeriesFmt
.reset( new XclExpUInt16Record( EXC_ID_CHSERIESFORMAT
, EXC_CHSERIESFORMAT_SMOOTHED
) );
1356 // data point labels
1357 XclExpChTextRef
xLabel( new XclExpChText( GetChRoot() ) );
1358 if( xLabel
->ConvertDataLabel( rPropSet
, rTypeInfo
, maData
.maPointPos
) )
1360 // CHTEXT groups for data labels are stored in global CHCHART group
1361 GetChartData().SetDataLabel( xLabel
);
1362 mxAttLabel
.reset( new XclExpChAttachedLabel( xLabel
->GetAttLabelFlags() ) );
1366 void XclExpChDataFormat::ConvertStockSeries( const ScfPropertySet
& rPropSet
, bool bCloseSymbol
)
1368 // set line format to invisible
1369 SetDefaultFrameBase( GetChRoot(), EXC_CHFRAMETYPE_INVISIBLE
, false );
1370 // set symbols to invisible or to 'close' series symbol
1371 mxMarkerFmt
.reset( new XclExpChMarkerFormat( GetChRoot() ) );
1372 mxMarkerFmt
->ConvertStockSymbol( GetChRoot(), rPropSet
, bCloseSymbol
);
1375 void XclExpChDataFormat::ConvertLine( const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
1377 ConvertFrameBase( GetChRoot(), rPropSet
, eObjType
);
1380 void XclExpChDataFormat::WriteSubRecords( XclExpStream
& rStrm
)
1382 lclSaveRecord( rStrm
, mx3dDataFmt
);
1383 WriteFrameRecords( rStrm
);
1384 lclSaveRecord( rStrm
, mxPieFmt
);
1385 lclSaveRecord( rStrm
, mxMarkerFmt
);
1386 lclSaveRecord( rStrm
, mxSeriesFmt
);
1387 lclSaveRecord( rStrm
, mxAttLabel
);
1390 void XclExpChDataFormat::WriteBody( XclExpStream
& rStrm
)
1392 rStrm
<< maData
.maPointPos
.mnPointIdx
1393 << maData
.maPointPos
.mnSeriesIdx
1394 << maData
.mnFormatIdx
1398 // ----------------------------------------------------------------------------
1400 XclExpChSerTrendLine::XclExpChSerTrendLine( const XclExpChRoot
& rRoot
) :
1401 XclExpRecord( EXC_ID_CHSERTRENDLINE
, 28 ),
1402 XclExpChRoot( rRoot
)
1406 bool XclExpChSerTrendLine::Convert( Reference
< XRegressionCurve
> xRegCurve
, sal_uInt16 nSeriesIdx
)
1408 if( !xRegCurve
.is() )
1412 ScfPropertySet
aCurveProp( xRegCurve
);
1413 OUString aService
= aCurveProp
.GetServiceName();
1414 if( aService
== SERVICE_CHART2_LINEARREGCURVE
)
1416 maData
.mnLineType
= EXC_CHSERTREND_POLYNOMIAL
;
1419 else if( aService
== SERVICE_CHART2_EXPREGCURVE
)
1420 maData
.mnLineType
= EXC_CHSERTREND_EXPONENTIAL
;
1421 else if( aService
== SERVICE_CHART2_LOGREGCURVE
)
1422 maData
.mnLineType
= EXC_CHSERTREND_LOGARITHMIC
;
1423 else if( aService
== SERVICE_CHART2_POTREGCURVE
)
1424 maData
.mnLineType
= EXC_CHSERTREND_POWER
;
1429 XclChDataPointPos
aPointPos( nSeriesIdx
);
1430 mxDataFmt
.reset( new XclExpChDataFormat( GetChRoot(), aPointPos
, 0 ) );
1431 mxDataFmt
->ConvertLine( aCurveProp
, EXC_CHOBJTYPE_TRENDLINE
);
1433 // #i83100# show equation and correlation coefficient
1434 ScfPropertySet
aEquationProp( xRegCurve
->getEquationProperties() );
1435 maData
.mnShowEquation
= aEquationProp
.GetBoolProperty( EXC_CHPROP_SHOWEQUATION
) ? 1 : 0;
1436 maData
.mnShowRSquared
= aEquationProp
.GetBoolProperty( EXC_CHPROP_SHOWCORRELATION
) ? 1 : 0;
1438 // #i83100# formatting of the equation text box
1439 if( (maData
.mnShowEquation
!= 0) || (maData
.mnShowRSquared
!= 0) )
1441 mxLabel
.reset( new XclExpChText( GetChRoot() ) );
1442 mxLabel
->ConvertTrendLineEquation( aEquationProp
, aPointPos
);
1446 // #i20819# polynomial trend lines
1447 // #i66819# moving average trend lines
1448 // #i5085# manual trend line size
1449 // #i34093# manual crossing point
1453 void XclExpChSerTrendLine::WriteBody( XclExpStream
& rStrm
)
1455 rStrm
<< maData
.mnLineType
1457 << maData
.mfIntercept
1458 << maData
.mnShowEquation
1459 << maData
.mnShowRSquared
1460 << maData
.mfForecastFor
1461 << maData
.mfForecastBack
;
1464 // ----------------------------------------------------------------------------
1466 XclExpChSerErrorBar::XclExpChSerErrorBar( const XclExpChRoot
& rRoot
, sal_uInt8 nBarType
) :
1467 XclExpRecord( EXC_ID_CHSERERRORBAR
, 14 ),
1468 XclExpChRoot( rRoot
)
1470 maData
.mnBarType
= nBarType
;
1473 bool XclExpChSerErrorBar::Convert( XclExpChSourceLink
& rValueLink
, sal_uInt16
& rnValueCount
, const ScfPropertySet
& rPropSet
)
1475 sal_Int32 nBarStyle
= 0;
1476 bool bOk
= rPropSet
.GetProperty( nBarStyle
, EXC_CHPROP_ERRORBARSTYLE
);
1479 namespace cssc
= ::com::sun::star::chart
;
1482 case cssc::ErrorBarStyle::ABSOLUTE
:
1483 maData
.mnSourceType
= EXC_CHSERERR_FIXED
;
1484 rPropSet
.GetProperty( maData
.mfValue
, EXC_CHPROP_POSITIVEERROR
);
1486 case cssc::ErrorBarStyle::RELATIVE
:
1487 maData
.mnSourceType
= EXC_CHSERERR_PERCENT
;
1488 rPropSet
.GetProperty( maData
.mfValue
, EXC_CHPROP_POSITIVEERROR
);
1490 case cssc::ErrorBarStyle::STANDARD_DEVIATION
:
1491 maData
.mnSourceType
= EXC_CHSERERR_STDDEV
;
1492 rPropSet
.GetProperty( maData
.mfValue
, EXC_CHPROP_WEIGHT
);
1494 case cssc::ErrorBarStyle::STANDARD_ERROR
:
1495 maData
.mnSourceType
= EXC_CHSERERR_STDERR
;
1497 case cssc::ErrorBarStyle::FROM_DATA
:
1500 maData
.mnSourceType
= EXC_CHSERERR_CUSTOM
;
1501 Reference
< XDataSource
> xDataSource( rPropSet
.GetApiPropertySet(), UNO_QUERY
);
1502 if( xDataSource
.is() )
1504 // find first sequence with current role
1505 OUString aRole
= XclChartHelper::GetErrorBarValuesRole( maData
.mnBarType
);
1506 Reference
< XDataSequence
> xValueSeq
;
1508 Sequence
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
= xDataSource
->getDataSequences();
1509 const Reference
< XLabeledDataSequence
>* pBeg
= aLabeledSeqVec
.getConstArray();
1510 const Reference
< XLabeledDataSequence
>* pEnd
= pBeg
+ aLabeledSeqVec
.getLength();
1511 for( const Reference
< XLabeledDataSequence
>* pIt
= pBeg
; !xValueSeq
.is() && (pIt
!= pEnd
); ++pIt
)
1513 Reference
< XDataSequence
> xTmpValueSeq
= (*pIt
)->getValues();
1514 ScfPropertySet
aValueProp( xTmpValueSeq
);
1516 if( aValueProp
.GetProperty( aCurrRole
, EXC_CHPROP_ROLE
) && (aCurrRole
== aRole
) )
1517 xValueSeq
= xTmpValueSeq
;
1519 if( xValueSeq
.is() )
1521 // #i86465# pass value count back to series
1522 rnValueCount
= maData
.mnValueCount
= rValueLink
.ConvertDataSequence( xValueSeq
, true );
1523 bOk
= maData
.mnValueCount
> 0;
1535 void XclExpChSerErrorBar::WriteBody( XclExpStream
& rStrm
)
1537 rStrm
<< maData
.mnBarType
1538 << maData
.mnSourceType
1540 << sal_uInt8( 1 ) // must be 1 to make line visible
1542 << maData
.mnValueCount
;
1545 // ----------------------------------------------------------------------------
1549 /** Returns the property set of the specified data point. */
1550 ScfPropertySet
lclGetPointPropSet( Reference
< XDataSeries
> xDataSeries
, sal_Int32 nPointIdx
)
1552 ScfPropertySet aPropSet
;
1555 aPropSet
.Set( xDataSeries
->getDataPointByIndex( nPointIdx
) );
1559 DBG_ERRORFILE( "lclGetPointPropSet - no data point property set" );
1566 XclExpChSeries::XclExpChSeries( const XclExpChRoot
& rRoot
, sal_uInt16 nSeriesIdx
) :
1567 XclExpChGroupBase( EXC_ID_CHSERIES
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 12 : 8 ),
1568 XclExpChRoot( rRoot
),
1569 mnGroupIdx( EXC_CHSERGROUP_NONE
),
1570 mnSeriesIdx( nSeriesIdx
),
1571 mnParentIdx( EXC_CHSERIES_INVALID
)
1573 // CHSOURCELINK records are always required, even if unused
1574 mxTitleLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1575 mxValueLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_VALUES
) );
1576 mxCategLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_CATEGORY
) );
1577 if( GetBiff() == EXC_BIFF8
)
1578 mxBubbleLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_BUBBLES
) );
1581 bool XclExpChSeries::ConvertDataSeries(
1582 Reference
< XDiagram
> xDiagram
, Reference
< XDataSeries
> xDataSeries
,
1583 const XclChExtTypeInfo
& rTypeInfo
, sal_uInt16 nGroupIdx
, sal_uInt16 nFormatIdx
)
1586 Reference
< XDataSource
> xDataSource( xDataSeries
, UNO_QUERY
);
1587 if( xDataSource
.is() )
1589 Reference
< XDataSequence
> xYValueSeq
, xTitleSeq
, xXValueSeq
;
1591 // find first sequence with role 'values-y'
1592 Sequence
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
= xDataSource
->getDataSequences();
1593 const Reference
< XLabeledDataSequence
>* pBeg
= aLabeledSeqVec
.getConstArray();
1594 const Reference
< XLabeledDataSequence
>* pEnd
= pBeg
+ aLabeledSeqVec
.getLength();
1595 for( const Reference
< XLabeledDataSequence
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
1597 Reference
< XDataSequence
> xTmpValueSeq
= (*pIt
)->getValues();
1598 ScfPropertySet
aValueProp( xTmpValueSeq
);
1600 if( aValueProp
.GetProperty( aRole
, EXC_CHPROP_ROLE
) )
1602 if( !xYValueSeq
.is() && (aRole
== EXC_CHPROP_ROLE_YVALUES
) )
1604 xYValueSeq
= xTmpValueSeq
;
1605 xTitleSeq
= (*pIt
)->getLabel(); // ignore role of label sequence
1607 else if( !xXValueSeq
.is() && !rTypeInfo
.mbCategoryAxis
&& (aRole
== EXC_CHPROP_ROLE_XVALUES
) )
1609 xXValueSeq
= xTmpValueSeq
;
1614 bOk
= xYValueSeq
.is();
1617 // chart type group index
1618 mnGroupIdx
= nGroupIdx
;
1620 // convert source links
1621 maData
.mnValueCount
= mxValueLink
->ConvertDataSequence( xYValueSeq
, true );
1622 mxTitleLink
->ConvertDataSequence( xTitleSeq
, true );
1624 // X values of XY charts
1625 maData
.mnCategCount
= mxCategLink
->ConvertDataSequence( xXValueSeq
, false, maData
.mnValueCount
);
1627 // series formatting
1628 XclChDataPointPos
aPointPos( mnSeriesIdx
);
1629 ScfPropertySet
aSeriesProp( xDataSeries
);
1630 mxSeriesFmt
.reset( new XclExpChDataFormat( GetChRoot(), aPointPos
, nFormatIdx
) );
1631 mxSeriesFmt
->ConvertDataSeries( aSeriesProp
, rTypeInfo
);
1634 CreateTrendLines( xDataSeries
);
1637 CreateErrorBars( aSeriesProp
, EXC_CHPROP_ERRORBARX
, EXC_CHSERERR_XPLUS
, EXC_CHSERERR_XMINUS
);
1638 CreateErrorBars( aSeriesProp
, EXC_CHPROP_ERRORBARY
, EXC_CHSERERR_YPLUS
, EXC_CHSERERR_YMINUS
);
1640 if( maData
.mnValueCount
> 0 )
1642 const sal_Int32 nMaxPointCount
= maData
.mnValueCount
;
1644 /* #i91063# Create missing fill properties in pie/doughnut charts.
1645 If freshly created (never saved to ODF), these charts show
1646 varying point colors but do not return these points via API. */
1647 if( xDiagram
.is() && (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
) )
1649 Reference
< XColorScheme
> xColorScheme
= xDiagram
->getDefaultColorScheme();
1650 if( xColorScheme
.is() )
1652 const OUString aFillStyleName
= CREATE_OUSTRING( "FillStyle" );
1653 const OUString aColorName
= CREATE_OUSTRING( "Color" );
1654 namespace csscd
= ::com::sun::star::drawing
;
1655 for( sal_Int32 nPointIdx
= 0; nPointIdx
< nMaxPointCount
; ++nPointIdx
)
1657 aPointPos
.mnPointIdx
= static_cast< sal_uInt16
>( nPointIdx
);
1658 ScfPropertySet aPointProp
= lclGetPointPropSet( xDataSeries
, nPointIdx
);
1659 // test that the point fill style is solid, but no color is set
1660 csscd::FillStyle eFillStyle
= csscd::FillStyle_NONE
;
1661 if( aPointProp
.GetProperty( eFillStyle
, aFillStyleName
) &&
1662 (eFillStyle
== csscd::FillStyle_SOLID
) &&
1663 !aPointProp
.HasProperty( aColorName
) )
1665 aPointProp
.SetProperty( aColorName
, xColorScheme
->getColorByIndex( nPointIdx
) );
1671 // data point formatting
1672 Sequence
< sal_Int32
> aPointIndexes
;
1673 if( aSeriesProp
.GetProperty( aPointIndexes
, EXC_CHPROP_ATTRIBDATAPOINTS
) && aPointIndexes
.hasElements() )
1675 const sal_Int32
* pnBeg
= aPointIndexes
.getConstArray();
1676 const sal_Int32
* pnEnd
= pnBeg
+ aPointIndexes
.getLength();
1677 for( const sal_Int32
* pnIt
= pnBeg
; (pnIt
!= pnEnd
) && (*pnIt
< nMaxPointCount
); ++pnIt
)
1679 aPointPos
.mnPointIdx
= static_cast< sal_uInt16
>( *pnIt
);
1680 ScfPropertySet aPointProp
= lclGetPointPropSet( xDataSeries
, *pnIt
);
1681 XclExpChDataFormatRef
xPointFmt( new XclExpChDataFormat( GetChRoot(), aPointPos
, nFormatIdx
) );
1682 xPointFmt
->ConvertDataSeries( aPointProp
, rTypeInfo
);
1683 maPointFmts
.AppendRecord( xPointFmt
);
1692 bool XclExpChSeries::ConvertStockSeries( XDataSeriesRef xDataSeries
,
1693 const OUString
& rValueRole
, sal_uInt16 nGroupIdx
, sal_uInt16 nFormatIdx
, bool bCloseSymbol
)
1696 Reference
< XDataSource
> xDataSource( xDataSeries
, UNO_QUERY
);
1697 if( xDataSource
.is() )
1699 Reference
< XDataSequence
> xYValueSeq
, xTitleSeq
;
1701 // find first sequence with passed role
1702 Sequence
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
= xDataSource
->getDataSequences();
1703 const Reference
< XLabeledDataSequence
>* pBeg
= aLabeledSeqVec
.getConstArray();
1704 const Reference
< XLabeledDataSequence
>* pEnd
= pBeg
+ aLabeledSeqVec
.getLength();
1705 for( const Reference
< XLabeledDataSequence
>* pIt
= pBeg
; !xYValueSeq
.is() && (pIt
!= pEnd
); ++pIt
)
1707 Reference
< XDataSequence
> xTmpValueSeq
= (*pIt
)->getValues();
1708 ScfPropertySet
aValueProp( xTmpValueSeq
);
1710 if( aValueProp
.GetProperty( aRole
, EXC_CHPROP_ROLE
) && (aRole
== rValueRole
) )
1712 xYValueSeq
= xTmpValueSeq
;
1713 xTitleSeq
= (*pIt
)->getLabel(); // ignore role of label sequence
1717 bOk
= xYValueSeq
.is();
1720 // chart type group index
1721 mnGroupIdx
= nGroupIdx
;
1722 // convert source links
1723 maData
.mnValueCount
= mxValueLink
->ConvertDataSequence( xYValueSeq
, true );
1724 mxTitleLink
->ConvertDataSequence( xTitleSeq
, true );
1725 // series formatting
1726 ScfPropertySet
aSeriesProp( xDataSeries
);
1727 mxSeriesFmt
.reset( new XclExpChDataFormat( GetChRoot(), XclChDataPointPos( mnSeriesIdx
), nFormatIdx
) );
1728 mxSeriesFmt
->ConvertStockSeries( aSeriesProp
, bCloseSymbol
);
1734 bool XclExpChSeries::ConvertTrendLine( const XclExpChSeries
& rParent
, Reference
< XRegressionCurve
> xRegCurve
)
1736 InitFromParent( rParent
);
1737 mxTrendLine
.reset( new XclExpChSerTrendLine( GetChRoot() ) );
1738 bool bOk
= mxTrendLine
->Convert( xRegCurve
, mnSeriesIdx
);
1741 mxSeriesFmt
= mxTrendLine
->GetDataFormat();
1742 GetChartData().SetDataLabel( mxTrendLine
->GetDataLabel() );
1747 bool XclExpChSeries::ConvertErrorBar( const XclExpChSeries
& rParent
, const ScfPropertySet
& rPropSet
, sal_uInt8 nBarId
)
1749 InitFromParent( rParent
);
1750 // error bar settings
1751 mxErrorBar
.reset( new XclExpChSerErrorBar( GetChRoot(), nBarId
) );
1752 bool bOk
= mxErrorBar
->Convert( *mxValueLink
, maData
.mnValueCount
, rPropSet
);
1755 // error bar formatting
1756 mxSeriesFmt
.reset( new XclExpChDataFormat( GetChRoot(), XclChDataPointPos( mnSeriesIdx
), 0 ) );
1757 mxSeriesFmt
->ConvertLine( rPropSet
, EXC_CHOBJTYPE_ERRORBAR
);
1762 void XclExpChSeries::ConvertCategSequence( Reference
< XLabeledDataSequence
> xCategSeq
)
1764 if( xCategSeq
.is() )
1765 maData
.mnCategCount
= mxCategLink
->ConvertDataSequence( xCategSeq
->getValues(), false );
1768 void XclExpChSeries::WriteSubRecords( XclExpStream
& rStrm
)
1770 lclSaveRecord( rStrm
, mxTitleLink
);
1771 lclSaveRecord( rStrm
, mxValueLink
);
1772 lclSaveRecord( rStrm
, mxCategLink
);
1773 lclSaveRecord( rStrm
, mxBubbleLink
);
1774 lclSaveRecord( rStrm
, mxSeriesFmt
);
1775 maPointFmts
.Save( rStrm
);
1776 if( mnGroupIdx
!= EXC_CHSERGROUP_NONE
)
1777 XclExpUInt16Record( EXC_ID_CHSERGROUP
, mnGroupIdx
).Save( rStrm
);
1778 if( mnParentIdx
!= EXC_CHSERIES_INVALID
)
1779 XclExpUInt16Record( EXC_ID_CHSERPARENT
, mnParentIdx
).Save( rStrm
);
1780 lclSaveRecord( rStrm
, mxTrendLine
);
1781 lclSaveRecord( rStrm
, mxErrorBar
);
1784 void XclExpChSeries::InitFromParent( const XclExpChSeries
& rParent
)
1786 // index to parent series is stored 1-based
1787 mnParentIdx
= rParent
.mnSeriesIdx
+ 1;
1788 /* #i86465# MSO2007 SP1 expects correct point counts in child series
1789 (there was no problem in Excel2003 or Excel2007 without SP1...) */
1790 maData
.mnCategCount
= rParent
.maData
.mnCategCount
;
1791 maData
.mnValueCount
= rParent
.maData
.mnValueCount
;
1794 void XclExpChSeries::CreateTrendLines( XDataSeriesRef xDataSeries
)
1796 Reference
< XRegressionCurveContainer
> xRegCurveCont( xDataSeries
, UNO_QUERY
);
1797 if( xRegCurveCont
.is() )
1799 Sequence
< Reference
< XRegressionCurve
> > aRegCurveSeq
= xRegCurveCont
->getRegressionCurves();
1800 const Reference
< XRegressionCurve
>* pBeg
= aRegCurveSeq
.getConstArray();
1801 const Reference
< XRegressionCurve
>* pEnd
= pBeg
+ aRegCurveSeq
.getLength();
1802 for( const Reference
< XRegressionCurve
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
1804 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
1805 if( xSeries
.is() && !xSeries
->ConvertTrendLine( *this, *pIt
) )
1806 GetChartData().RemoveLastSeries();
1811 void XclExpChSeries::CreateErrorBars( const ScfPropertySet
& rPropSet
,
1812 const OUString
& rBarPropName
, sal_uInt8 nPosBarId
, sal_uInt8 nNegBarId
)
1814 Reference
< XPropertySet
> xErrorBar
;
1815 if( rPropSet
.GetProperty( xErrorBar
, rBarPropName
) && xErrorBar
.is() )
1817 ScfPropertySet
aErrorProp( xErrorBar
);
1818 CreateErrorBar( aErrorProp
, EXC_CHPROP_SHOWPOSITIVEERROR
, nPosBarId
);
1819 CreateErrorBar( aErrorProp
, EXC_CHPROP_SHOWNEGATIVEERROR
, nNegBarId
);
1823 void XclExpChSeries::CreateErrorBar( const ScfPropertySet
& rPropSet
,
1824 const OUString
& rShowPropName
, sal_uInt8 nBarId
)
1826 if( rPropSet
.GetBoolProperty( rShowPropName
) )
1828 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
1829 if( xSeries
.is() && !xSeries
->ConvertErrorBar( *this, rPropSet
, nBarId
) )
1830 GetChartData().RemoveLastSeries();
1834 void XclExpChSeries::WriteBody( XclExpStream
& rStrm
)
1836 rStrm
<< maData
.mnCategType
<< maData
.mnValueType
<< maData
.mnCategCount
<< maData
.mnValueCount
;
1837 if( GetBiff() == EXC_BIFF8
)
1838 rStrm
<< maData
.mnBubbleType
<< maData
.mnBubbleCount
;
1841 // Chart type groups ==========================================================
1843 XclExpChType::XclExpChType( const XclExpChRoot
& rRoot
) :
1844 XclExpRecord( EXC_ID_CHUNKNOWN
),
1845 XclExpChRoot( rRoot
),
1846 maTypeInfo( rRoot
.GetChartTypeInfo( EXC_CHTYPEID_UNKNOWN
) )
1850 void XclExpChType::Convert( Reference
< XDiagram
> xDiagram
, Reference
< XChartType
> xChartType
,
1851 sal_Int32 nApiAxesSetIdx
, bool bSwappedAxesSet
, bool bHasXLabels
)
1853 if( xChartType
.is() )
1855 maTypeInfo
= GetChartTypeInfo( xChartType
->getChartType() );
1856 // special handling for some chart types
1857 switch( maTypeInfo
.meTypeCateg
)
1859 case EXC_CHTYPECATEG_BAR
:
1861 maTypeInfo
= GetChartTypeInfo( bSwappedAxesSet
? EXC_CHTYPEID_HORBAR
: EXC_CHTYPEID_BAR
);
1862 ::set_flag( maData
.mnFlags
, EXC_CHBAR_HORIZONTAL
, bSwappedAxesSet
);
1863 ScfPropertySet
aTypeProp( xChartType
);
1864 Sequence
< sal_Int32
> aInt32Seq
;
1865 maData
.mnOverlap
= 0;
1866 if( aTypeProp
.GetProperty( aInt32Seq
, EXC_CHPROP_OVERLAPSEQ
) && (nApiAxesSetIdx
< aInt32Seq
.getLength()) )
1867 maData
.mnOverlap
= limit_cast
< sal_Int16
>( -aInt32Seq
[ nApiAxesSetIdx
], -100, 100 );
1869 if( aTypeProp
.GetProperty( aInt32Seq
, EXC_CHPROP_GAPWIDTHSEQ
) && (nApiAxesSetIdx
< aInt32Seq
.getLength()) )
1870 maData
.mnGap
= limit_cast
< sal_uInt16
>( aInt32Seq
[ nApiAxesSetIdx
], 0, 500 );
1873 case EXC_CHTYPECATEG_RADAR
:
1874 ::set_flag( maData
.mnFlags
, EXC_CHRADAR_AXISLABELS
, bHasXLabels
);
1876 case EXC_CHTYPECATEG_PIE
:
1878 ScfPropertySet
aTypeProp( xChartType
);
1879 bool bDonut
= aTypeProp
.GetBoolProperty( EXC_CHPROP_USERINGS
);
1880 maTypeInfo
= GetChartTypeInfo( bDonut
? EXC_CHTYPEID_DONUT
: EXC_CHTYPEID_PIE
);
1881 maData
.mnPieHole
= bDonut
? 50 : 0;
1882 // #i85166# starting angle of first pie slice
1883 ScfPropertySet
aDiaProp( xDiagram
);
1884 maData
.mnRotation
= XclExpChRoot::ConvertPieRotation( aDiaProp
);
1887 case EXC_CHTYPECATEG_SCATTER
:
1888 if( GetBiff() == EXC_BIFF8
)
1889 ::set_flag( maData
.mnFlags
, EXC_CHSCATTER_BUBBLES
, maTypeInfo
.meTypeId
== EXC_CHTYPEID_BUBBLES
);
1893 SetRecId( maTypeInfo
.mnRecId
);
1897 void XclExpChType::SetStacked( bool bPercent
)
1899 switch( maTypeInfo
.meTypeCateg
)
1901 case EXC_CHTYPECATEG_LINE
:
1902 ::set_flag( maData
.mnFlags
, EXC_CHLINE_STACKED
);
1903 ::set_flag( maData
.mnFlags
, EXC_CHLINE_PERCENT
, bPercent
);
1905 case EXC_CHTYPECATEG_BAR
:
1906 ::set_flag( maData
.mnFlags
, EXC_CHBAR_STACKED
);
1907 ::set_flag( maData
.mnFlags
, EXC_CHBAR_PERCENT
, bPercent
);
1908 maData
.mnOverlap
= -100;
1914 void XclExpChType::WriteBody( XclExpStream
& rStrm
)
1916 switch( GetRecId() )
1919 rStrm
<< maData
.mnOverlap
<< maData
.mnGap
<< maData
.mnFlags
;
1924 case EXC_ID_CHRADARLINE
:
1925 case EXC_ID_CHRADARAREA
:
1926 rStrm
<< maData
.mnFlags
;
1930 rStrm
<< maData
.mnRotation
<< maData
.mnPieHole
;
1931 if( GetBiff() == EXC_BIFF8
)
1932 rStrm
<< maData
.mnFlags
;
1935 case EXC_ID_CHSCATTER
:
1936 if( GetBiff() == EXC_BIFF8
)
1937 rStrm
<< maData
.mnBubbleSize
<< maData
.mnBubbleType
<< maData
.mnFlags
;
1941 DBG_ERRORFILE( "XclExpChType::WriteBody - unknown chart type" );
1945 // ----------------------------------------------------------------------------
1947 XclExpChChart3d::XclExpChChart3d() :
1948 XclExpRecord( EXC_ID_CHCHART3D
, 14 )
1952 void XclExpChChart3d::Convert( const ScfPropertySet
& rPropSet
, bool b3dWallChart
)
1954 sal_Int32 nRotationY
= 0;
1955 rPropSet
.GetProperty( nRotationY
, EXC_CHPROP_ROTATIONVERTICAL
);
1956 sal_Int32 nRotationX
= 0;
1957 rPropSet
.GetProperty( nRotationX
, EXC_CHPROP_ROTATIONHORIZONTAL
);
1958 sal_Int32 nPerspective
= 15;
1959 rPropSet
.GetProperty( nPerspective
, EXC_CHPROP_PERSPECTIVE
);
1963 // Y rotation (Excel [0..359], Chart2 [-179,180])
1964 if( nRotationY
< 0 ) nRotationY
+= 360;
1965 maData
.mnRotation
= static_cast< sal_uInt16
>( nRotationY
);
1966 // X rotation a.k.a. elevation (Excel [-90..90], Chart2 [-179,180])
1967 maData
.mnElevation
= limit_cast
< sal_Int16
>( nRotationX
, -90, 90 );
1968 // perspective (Excel and Chart2 [0,100])
1969 maData
.mnEyeDist
= limit_cast
< sal_uInt16
>( nPerspective
, 0, 100 );
1972 ::set_flag( maData
.mnFlags
, EXC_CHCHART3D_REAL3D
, !rPropSet
.GetBoolProperty( EXC_CHPROP_RIGHTANGLEDAXES
) );
1973 ::set_flag( maData
.mnFlags
, EXC_CHCHART3D_AUTOHEIGHT
);
1974 ::set_flag( maData
.mnFlags
, EXC_CHCHART3D_HASWALLS
);
1978 // Y rotation not used in pie charts, but 'first pie slice angle'
1979 maData
.mnRotation
= XclExpChRoot::ConvertPieRotation( rPropSet
);
1980 // X rotation a.k.a. elevation (map Chart2 [-80,-10] to Excel [10..80])
1981 maData
.mnElevation
= limit_cast
< sal_Int16
>( (nRotationX
+ 270) % 180, 10, 80 );
1982 // perspective (Excel and Chart2 [0,100])
1983 maData
.mnEyeDist
= limit_cast
< sal_uInt16
>( nPerspective
, 0, 100 );
1989 void XclExpChChart3d::WriteBody( XclExpStream
& rStrm
)
1991 rStrm
<< maData
.mnRotation
1992 << maData
.mnElevation
1994 << maData
.mnRelHeight
1995 << maData
.mnRelDepth
1996 << maData
.mnDepthGap
2000 // ----------------------------------------------------------------------------
2002 XclExpChLegend::XclExpChLegend( const XclExpChRoot
& rRoot
) :
2003 XclExpChGroupBase( EXC_ID_CHLEGEND
, 20 ),
2004 XclExpChRoot( rRoot
)
2008 void XclExpChLegend::Convert( const ScfPropertySet
& rPropSet
)
2011 mxFrame
= lclCreateFrame( GetChRoot(), rPropSet
, EXC_CHOBJTYPE_LEGEND
);
2013 mxText
.reset( new XclExpChText( GetChRoot() ) );
2014 mxText
->ConvertLegend( rPropSet
);
2015 // special legend properties
2016 GetChartPropSetHelper().ReadLegendProperties( maData
, rPropSet
);
2019 void XclExpChLegend::WriteSubRecords( XclExpStream
& rStrm
)
2021 lclSaveRecord( rStrm
, mxText
);
2022 lclSaveRecord( rStrm
, mxFrame
);
2025 void XclExpChLegend::WriteBody( XclExpStream
& rStrm
)
2027 rStrm
<< maData
.maRect
<< maData
.mnDockMode
<< maData
.mnSpacing
<< maData
.mnFlags
;
2030 // ----------------------------------------------------------------------------
2032 XclExpChDropBar::XclExpChDropBar( XclChObjectType eObjType
) :
2033 XclExpChGroupBase( EXC_ID_CHDROPBAR
, 2 ),
2034 meObjType( eObjType
),
2039 void XclExpChDropBar::Convert( const XclExpChRoot
& rRoot
, const ScfPropertySet
& rPropSet
)
2042 ConvertFrameBase( rRoot
, rPropSet
, meObjType
);
2044 SetDefaultFrameBase( rRoot
, EXC_CHFRAMETYPE_INVISIBLE
, true );
2047 void XclExpChDropBar::WriteSubRecords( XclExpStream
& rStrm
)
2049 WriteFrameRecords( rStrm
);
2052 void XclExpChDropBar::WriteBody( XclExpStream
& rStrm
)
2057 // ----------------------------------------------------------------------------
2059 XclExpChTypeGroup::XclExpChTypeGroup( const XclExpChRoot
& rRoot
, sal_uInt16 nGroupIdx
) :
2060 XclExpChGroupBase( EXC_ID_CHTYPEGROUP
, 20 ),
2061 XclExpChRoot( rRoot
),
2063 maTypeInfo( maType
.GetTypeInfo() )
2065 maData
.mnGroupIdx
= nGroupIdx
;
2068 void XclExpChTypeGroup::ConvertType(
2069 Reference
< XDiagram
> xDiagram
, Reference
< XChartType
> xChartType
,
2070 sal_Int32 nApiAxesSetIdx
, bool b3dChart
, bool bSwappedAxesSet
, bool bHasXLabels
)
2072 // chart type settings
2073 maType
.Convert( xDiagram
, xChartType
, nApiAxesSetIdx
, bSwappedAxesSet
, bHasXLabels
);
2075 // spline - TODO: get from single series (#i66858#)
2076 ScfPropertySet
aTypeProp( xChartType
);
2077 ::com::sun::star::chart2::CurveStyle eCurveStyle
;
2078 bool bSpline
= aTypeProp
.GetProperty( eCurveStyle
, EXC_CHPROP_CURVESTYLE
) &&
2079 (eCurveStyle
!= ::com::sun::star::chart2::CurveStyle_LINES
);
2081 // extended type info
2082 maTypeInfo
.Set( maType
.GetTypeInfo(), b3dChart
, bSpline
);
2084 // 3d chart settings
2085 if( maTypeInfo
.mb3dChart
) // only true, if Excel chart supports 3d mode
2087 mxChart3d
.reset( new XclExpChChart3d
);
2088 ScfPropertySet
aDiaProp( xDiagram
);
2089 mxChart3d
->Convert( aDiaProp
, Is3dWallChart() );
2093 void XclExpChTypeGroup::ConvertSeries(
2094 Reference
< XDiagram
> xDiagram
, Reference
< XChartType
> xChartType
,
2095 sal_Int32 nGroupAxesSetIdx
, bool bPercent
, bool bConnectBars
)
2097 Reference
< XDataSeriesContainer
> xSeriesCont( xChartType
, UNO_QUERY
);
2098 if( xSeriesCont
.is() )
2100 typedef ::std::vector
< Reference
< XDataSeries
> > XDataSeriesVec
;
2101 XDataSeriesVec aSeriesVec
;
2103 // copy data series attached to the current axes set to the vector
2104 Sequence
< Reference
< XDataSeries
> > aSeriesSeq
= xSeriesCont
->getDataSeries();
2105 const Reference
< XDataSeries
>* pBeg
= aSeriesSeq
.getConstArray();
2106 const Reference
< XDataSeries
>* pEnd
= pBeg
+ aSeriesSeq
.getLength();
2107 for( const Reference
< XDataSeries
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
2109 ScfPropertySet
aSeriesProp( *pIt
);
2110 sal_Int32
nSeriesAxesSetIdx(0);
2111 if( aSeriesProp
.GetProperty( nSeriesAxesSetIdx
, EXC_CHPROP_ATTAXISINDEX
) && (nSeriesAxesSetIdx
== nGroupAxesSetIdx
) )
2112 aSeriesVec
.push_back( *pIt
);
2115 // Are there any series in the current axes set?
2116 if( !aSeriesVec
.empty() )
2118 // stacking direction (stacked/percent/deep 3d) from first series
2119 ScfPropertySet
aSeriesProp( aSeriesVec
.front() );
2120 namespace cssc
= ::com::sun::star::chart2
;
2121 cssc::StackingDirection eStacking
;
2122 if( !aSeriesProp
.GetProperty( eStacking
, EXC_CHPROP_STACKINGDIR
) )
2123 eStacking
= cssc::StackingDirection_NO_STACKING
;
2125 // stacked or percent chart
2126 if( maTypeInfo
.mbSupportsStacking
&& (eStacking
== cssc::StackingDirection_Y_STACKING
) )
2128 // percent overrides simple stacking
2129 maType
.SetStacked( bPercent
);
2131 // connected data points (only in stacked bar charts)
2132 if( bConnectBars
&& (maTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_BAR
) )
2133 maChartLines
[ EXC_CHCHARTLINE_CONNECT
].reset( new XclExpChLineFormat( GetChRoot() ) );
2137 // reverse series order for some unstacked 2D chart types
2138 if( maTypeInfo
.mbReverseSeries
&& !Is3dChart() )
2139 ::std::reverse( aSeriesVec
.begin(), aSeriesVec
.end() );
2142 // deep 3d chart or clustered 3d chart (stacked is not clustered)
2143 if( (eStacking
== cssc::StackingDirection_NO_STACKING
) && Is3dWallChart() )
2144 mxChart3d
->SetClustered();
2146 // varied point colors
2147 ::set_flag( maData
.mnFlags
, EXC_CHTYPEGROUP_VARIEDCOLORS
, aSeriesProp
.GetBoolProperty( EXC_CHPROP_VARYCOLORSBY
) );
2149 // process all series
2150 for( XDataSeriesVec::const_iterator aIt
= aSeriesVec
.begin(), aEnd
= aSeriesVec
.end(); aIt
!= aEnd
; ++aIt
)
2152 // create Excel series object, stock charts need special processing
2153 if( maTypeInfo
.meTypeId
== EXC_CHTYPEID_STOCK
)
2154 CreateAllStockSeries( xChartType
, *aIt
);
2156 CreateDataSeries( xDiagram
, *aIt
);
2162 void XclExpChTypeGroup::ConvertCategSequence( Reference
< XLabeledDataSequence
> xCategSeq
)
2164 for( size_t nIdx
= 0, nSize
= maSeries
.GetSize(); nIdx
< nSize
; ++nIdx
)
2165 maSeries
.GetRecord( nIdx
)->ConvertCategSequence( xCategSeq
);
2168 void XclExpChTypeGroup::ConvertLegend( const ScfPropertySet
& rPropSet
)
2170 if( rPropSet
.GetBoolProperty( EXC_CHPROP_SHOW
) )
2172 mxLegend
.reset( new XclExpChLegend( GetChRoot() ) );
2173 mxLegend
->Convert( rPropSet
);
2177 void XclExpChTypeGroup::WriteSubRecords( XclExpStream
& rStrm
)
2179 maType
.Save( rStrm
);
2180 lclSaveRecord( rStrm
, mxChart3d
);
2181 lclSaveRecord( rStrm
, mxLegend
);
2182 lclSaveRecord( rStrm
, mxUpBar
);
2183 lclSaveRecord( rStrm
, mxDownBar
);
2184 for( XclExpChLineFormatMap::iterator aLIt
= maChartLines
.begin(), aLEnd
= maChartLines
.end(); aLIt
!= aLEnd
; ++aLIt
)
2185 lclSaveRecord( rStrm
, aLIt
->second
, EXC_ID_CHCHARTLINE
, aLIt
->first
);
2188 sal_uInt16
XclExpChTypeGroup::GetFreeFormatIdx() const
2190 return static_cast< sal_uInt16
>( maSeries
.GetSize() );
2193 void XclExpChTypeGroup::CreateDataSeries(
2194 Reference
< XDiagram
> xDiagram
, Reference
< XDataSeries
> xDataSeries
)
2196 // let chart create series object with correct series index
2197 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
2200 if( xSeries
->ConvertDataSeries( xDiagram
, xDataSeries
, maTypeInfo
, GetGroupIdx(), GetFreeFormatIdx() ) )
2201 maSeries
.AppendRecord( xSeries
);
2203 GetChartData().RemoveLastSeries();
2207 void XclExpChTypeGroup::CreateAllStockSeries(
2208 Reference
< XChartType
> xChartType
, Reference
< XDataSeries
> xDataSeries
)
2210 // create existing series objects
2211 bool bHasOpen
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_OPENVALUES
, false );
2212 bool bHasHigh
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_HIGHVALUES
, false );
2213 bool bHasLow
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_LOWVALUES
, false );
2214 bool bHasClose
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_CLOSEVALUES
, !bHasOpen
);
2216 // formatting of special stock chart elements
2217 ScfPropertySet
aTypeProp( xChartType
);
2219 if( bHasHigh
&& bHasLow
&& aTypeProp
.GetBoolProperty( EXC_CHPROP_SHOWHIGHLOW
) )
2221 ScfPropertySet
aSeriesProp( xDataSeries
);
2222 XclExpChLineFormatRef
xLineFmt( new XclExpChLineFormat( GetChRoot() ) );
2223 xLineFmt
->Convert( GetChRoot(), aSeriesProp
, EXC_CHOBJTYPE_HILOLINE
);
2224 maChartLines
[ EXC_CHCHARTLINE_HILO
] = xLineFmt
;
2227 if( bHasOpen
&& bHasClose
)
2229 // dropbar type is dependent on position in the file - always create both
2230 Reference
< XPropertySet
> xWhitePropSet
, xBlackPropSet
;
2231 // white dropbar format
2232 aTypeProp
.GetProperty( xWhitePropSet
, EXC_CHPROP_WHITEDAY
);
2233 ScfPropertySet
aWhiteProp( xWhitePropSet
);
2234 mxUpBar
.reset( new XclExpChDropBar( EXC_CHOBJTYPE_WHITEDROPBAR
) );
2235 mxUpBar
->Convert( GetChRoot(), aWhiteProp
);
2236 // black dropbar format
2237 aTypeProp
.GetProperty( xBlackPropSet
, EXC_CHPROP_BLACKDAY
);
2238 ScfPropertySet
aBlackProp( xBlackPropSet
);
2239 mxDownBar
.reset( new XclExpChDropBar( EXC_CHOBJTYPE_BLACKDROPBAR
) );
2240 mxDownBar
->Convert( GetChRoot(), aBlackProp
);
2244 bool XclExpChTypeGroup::CreateStockSeries( Reference
< XDataSeries
> xDataSeries
,
2245 const OUString
& rValueRole
, bool bCloseSymbol
)
2248 // let chart create series object with correct series index
2249 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
2252 bOk
= xSeries
->ConvertStockSeries( xDataSeries
,
2253 rValueRole
, GetGroupIdx(), GetFreeFormatIdx(), bCloseSymbol
);
2255 maSeries
.AppendRecord( xSeries
);
2257 GetChartData().RemoveLastSeries();
2262 void XclExpChTypeGroup::WriteBody( XclExpStream
& rStrm
)
2264 rStrm
<< maData
.maRect
<< maData
.mnFlags
<< maData
.mnGroupIdx
;
2267 // Axes =======================================================================
2269 XclExpChLabelRange::XclExpChLabelRange( const XclExpChRoot
& rRoot
) :
2270 XclExpRecord( EXC_ID_CHLABELRANGE
, 8 ),
2271 XclExpChRoot( rRoot
)
2275 void XclExpChLabelRange::Convert( const ScaleData
& rScaleData
, bool bMirrorOrient
)
2278 double fOrigin
= 0.0;
2279 if( !lclIsAutoAnyOrGetValue( fOrigin
, rScaleData
.Origin
, false ) )
2280 maData
.mnCross
= limit_cast
< sal_uInt16
>( fOrigin
, 1, 32767 );
2283 if( (rScaleData
.Orientation
== ::com::sun::star::chart2::AxisOrientation_REVERSE
) != bMirrorOrient
)
2285 ::set_flag( maData
.mnFlags
, EXC_CHLABELRANGE_REVERSE
);
2290 void XclExpChLabelRange::WriteBody( XclExpStream
& rStrm
)
2292 rStrm
<< maData
.mnCross
<< maData
.mnLabelFreq
<< maData
.mnTickFreq
<< maData
.mnFlags
;
2295 // ----------------------------------------------------------------------------
2297 XclExpChValueRange::XclExpChValueRange( const XclExpChRoot
& rRoot
) :
2298 XclExpRecord( EXC_ID_CHVALUERANGE
, 42 ),
2299 XclExpChRoot( rRoot
)
2303 void XclExpChValueRange::Convert( const ScaleData
& rScaleData
, bool bPercent
)
2305 // scaling algorithm
2306 bool bLogScale
= ScfApiHelper::GetServiceName( rScaleData
.Scaling
) == SERVICE_CHART2_LOGSCALING
;
2307 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_LOGSCALE
, bLogScale
);
2308 Reference
< XScaling
> xLogScaling
;
2310 xLogScaling
= rScaleData
.Scaling
;
2313 bool bAutoMin
= lclIsAutoAnyOrGetScaledValue( maData
.mfMin
, rScaleData
.Minimum
, xLogScaling
, bPercent
);
2314 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMIN
, bAutoMin
);
2315 bool bAutoMax
= lclIsAutoAnyOrGetScaledValue( maData
.mfMax
, rScaleData
.Maximum
, xLogScaling
, bPercent
);
2316 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMAX
, bAutoMax
);
2319 bool bAutoCross
= lclIsAutoAnyOrGetScaledValue( maData
.mfCross
, rScaleData
.Origin
, xLogScaling
, bPercent
);
2320 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
, bAutoCross
);
2323 const IncrementData
& rIncrementData
= rScaleData
.IncrementData
;
2324 bool bAutoMajor
= lclIsAutoAnyOrGetValue( maData
.mfMajorStep
, rIncrementData
.Distance
, bPercent
) || (maData
.mfMajorStep
<= 0.0);
2325 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMAJOR
, bAutoMajor
);
2327 const Sequence
< SubIncrement
>& rSubIncrementSeq
= rIncrementData
.SubIncrements
;
2328 sal_Int32 nCount
= 0;
2329 bool bAutoMinor
= bAutoMajor
|| (rSubIncrementSeq
.getLength() < 1) ||
2330 lclIsAutoAnyOrGetValue( nCount
, rSubIncrementSeq
[ 0 ].IntervalCount
, false ) || (nCount
< 1);
2332 maData
.mfMinorStep
= maData
.mfMajorStep
/ nCount
;
2333 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMINOR
, bAutoMinor
);
2336 namespace cssc
= ::com::sun::star::chart2
;
2337 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_REVERSE
, rScaleData
.Orientation
== cssc::AxisOrientation_REVERSE
);
2340 void XclExpChValueRange::WriteBody( XclExpStream
& rStrm
)
2342 rStrm
<< maData
.mfMin
2344 << maData
.mfMajorStep
2345 << maData
.mfMinorStep
2350 // ----------------------------------------------------------------------------
2354 sal_uInt8
lclGetXclTickPos( sal_Int32 nApiTickmarks
)
2356 using namespace ::com::sun::star::chart2::TickmarkStyle
;
2357 sal_uInt8 nXclTickPos
= 0;
2358 ::set_flag( nXclTickPos
, EXC_CHTICK_INSIDE
, ::get_flag( nApiTickmarks
, INNER
) );
2359 ::set_flag( nXclTickPos
, EXC_CHTICK_OUTSIDE
, ::get_flag( nApiTickmarks
, OUTER
) );
2365 XclExpChTick::XclExpChTick( const XclExpChRoot
& rRoot
) :
2366 XclExpRecord( EXC_ID_CHTICK
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 30 : 26 ),
2367 XclExpChRoot( rRoot
),
2368 mnTextColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
2372 void XclExpChTick::Convert( const ScfPropertySet
& rPropSet
)
2375 sal_Int32
nApiTickmarks(0);
2376 if( rPropSet
.GetProperty( nApiTickmarks
, EXC_CHPROP_MAJORTICKS
) )
2377 maData
.mnMajor
= lclGetXclTickPos( nApiTickmarks
);
2378 if( rPropSet
.GetProperty( nApiTickmarks
, EXC_CHPROP_MINORTICKS
) )
2379 maData
.mnMinor
= lclGetXclTickPos( nApiTickmarks
);
2382 void XclExpChTick::SetFontColor( const Color
& rColor
, sal_uInt32 nColorId
)
2384 maData
.maTextColor
= rColor
;
2385 ::set_flag( maData
.mnFlags
, EXC_CHTICK_AUTOCOLOR
, rColor
== COL_AUTO
);
2386 mnTextColorId
= nColorId
;
2389 void XclExpChTick::SetRotation( sal_uInt16 nRotation
)
2391 maData
.mnRotation
= nRotation
;
2392 ::set_flag( maData
.mnFlags
, EXC_CHTICK_AUTOROT
, false );
2393 ::insert_value( maData
.mnFlags
, XclTools::GetXclOrientFromRot( nRotation
), 2, 3 );
2396 void XclExpChTick::WriteBody( XclExpStream
& rStrm
)
2398 rStrm
<< maData
.mnMajor
2400 << maData
.mnLabelPos
2401 << maData
.mnBackMode
2403 << maData
.maTextColor
2405 if( GetBiff() == EXC_BIFF8
)
2406 rStrm
<< GetPalette().GetColorIndex( mnTextColorId
) << maData
.mnRotation
;
2409 // ----------------------------------------------------------------------------
2413 /** Returns an API axis object from the passed coordinate system. */
2414 Reference
< XAxis
> lclGetApiAxis( Reference
< XCoordinateSystem
> xCoordSystem
,
2415 sal_Int32 nApiAxisDim
, sal_Int32 nApiAxesSetIdx
)
2417 Reference
< XAxis
> xAxis
;
2420 if( xCoordSystem
.is() )
2421 xAxis
= xCoordSystem
->getAxisByDimension( nApiAxisDim
, nApiAxesSetIdx
);
2431 XclExpChAxis::XclExpChAxis( const XclExpChRoot
& rRoot
, sal_uInt16 nAxisType
) :
2432 XclExpChGroupBase( EXC_ID_CHAXIS
, 18 ),
2433 XclExpChRoot( rRoot
),
2434 mnNumFmtIdx( EXC_FORMAT_NOTFOUND
)
2436 maData
.mnType
= nAxisType
;
2439 void XclExpChAxis::SetFont( XclExpChFontRef xFont
, const Color
& rColor
, sal_uInt32 nColorId
)
2443 mxTick
->SetFontColor( rColor
, nColorId
);
2446 void XclExpChAxis::SetRotation( sal_uInt16 nRotation
)
2449 mxTick
->SetRotation( nRotation
);
2452 void XclExpChAxis::Convert( Reference
< XAxis
> xAxis
, const XclChExtTypeInfo
& rTypeInfo
, sal_Int32 nApiAxesSetIdx
,
2455 ScfPropertySet
aAxisProp( xAxis
);
2456 bool bCategoryAxis
= ((GetAxisType() == EXC_CHAXIS_X
) && rTypeInfo
.mbCategoryAxis
) || (GetAxisType() == EXC_CHAXIS_Z
);
2458 // axis line format -------------------------------------------------------
2460 mxAxisLine
.reset( new XclExpChLineFormat( GetChRoot() ) );
2461 mxAxisLine
->Convert( GetChRoot(), aAxisProp
, EXC_CHOBJTYPE_AXISLINE
);
2462 // #i58688# axis enabled
2463 mxAxisLine
->SetShowAxis( aAxisProp
.GetBoolProperty( EXC_CHPROP_SHOW
) );
2465 // axis scaling and increment ---------------------------------------------
2469 mxLabelRange
.reset( new XclExpChLabelRange( GetChRoot() ) );
2470 mxLabelRange
->SetTicksBetweenCateg( rTypeInfo
.mbTicksBetweenCateg
);
2472 // #i71684# radar charts have reversed rotation direction
2473 mxLabelRange
->Convert( xAxis
->getScaleData(), (GetAxisType() == EXC_CHAXIS_X
) && (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_RADAR
) );
2474 // swap max-cross flag for secondary X axis to have the secondary Y axis at right side
2475 if( (GetAxisType() == EXC_CHAXIS_X
) && (nApiAxesSetIdx
== EXC_CHAXESSET_SECONDARY
) )
2476 mxLabelRange
->SwapAxisMaxCross();
2480 mxValueRange
.reset( new XclExpChValueRange( GetChRoot() ) );
2482 mxValueRange
->Convert( xAxis
->getScaleData(), bPercent
);
2485 // axis caption text ------------------------------------------------------
2487 // axis ticks properties
2488 mxTick
.reset( new XclExpChTick( GetChRoot() ) );
2489 mxTick
->Convert( aAxisProp
);
2491 // existence and position of axis labels
2492 sal_uInt8 nLabelPos
= EXC_CHTICK_NOLABEL
;
2493 if( rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_RADAR
)
2494 /* Radar charts disable their category labels via chart type, not via
2495 axis, and axis labels are always 'near axis' in Chart2. */
2496 nLabelPos
= EXC_CHTICK_NEXT
;
2497 else if( aAxisProp
.GetBoolProperty( EXC_CHPROP_DISPLAYLABELS
) )
2498 /* #i85862# Axis labels in other chart types always have position 'low'
2499 in Chart2, but Excel expects 'near axis' at Y axes in 3D charts. */
2500 nLabelPos
= (rTypeInfo
.mb3dChart
&& (GetAxisType() == EXC_CHAXIS_Y
)) ? EXC_CHTICK_NEXT
: EXC_CHTICK_LOW
;
2501 mxTick
->SetLabelPos( nLabelPos
);
2503 // axis label formatting and rotation
2504 ConvertFontBase( GetChRoot(), aAxisProp
);
2505 ConvertRotationBase( GetChRoot(), aAxisProp
);
2507 // axis number format
2508 sal_Int32 nApiNumFmt
= 0;
2509 if( !bCategoryAxis
&& aAxisProp
.GetProperty( nApiNumFmt
, EXC_CHPROP_NUMBERFORMAT
) )
2510 mnNumFmtIdx
= GetNumFmtBuffer().Insert( static_cast< sal_uInt32
>( nApiNumFmt
) );
2512 // grid -------------------------------------------------------------------
2517 ScfPropertySet
aGridProp( xAxis
->getGridProperties() );
2518 if( aGridProp
.GetBoolProperty( EXC_CHPROP_SHOW
) )
2519 mxMajorGrid
= lclCreateLineFormat( GetChRoot(), aGridProp
, EXC_CHOBJTYPE_GRIDLINE
);
2521 Sequence
< Reference
< XPropertySet
> > aSubGridPropSeq
= xAxis
->getSubGridProperties();
2522 if( aSubGridPropSeq
.hasElements() )
2524 ScfPropertySet
aSubGridProp( aSubGridPropSeq
[ 0 ] );
2525 if( aSubGridProp
.GetBoolProperty( EXC_CHPROP_SHOW
) )
2526 mxMinorGrid
= lclCreateLineFormat( GetChRoot(), aSubGridProp
, EXC_CHOBJTYPE_GRIDLINE
);
2531 void XclExpChAxis::ConvertWall( XDiagramRef xDiagram
)
2533 if( xDiagram
.is() ) switch( GetAxisType() )
2537 ScfPropertySet
aWallProp( xDiagram
->getWall() );
2538 mxWallFrame
= lclCreateFrame( GetChRoot(), aWallProp
, EXC_CHOBJTYPE_WALL3D
);
2543 ScfPropertySet
aFloorProp( xDiagram
->getFloor() );
2544 mxWallFrame
= lclCreateFrame( GetChRoot(), aFloorProp
, EXC_CHOBJTYPE_FLOOR3D
);
2548 mxWallFrame
.reset();
2552 void XclExpChAxis::WriteSubRecords( XclExpStream
& rStrm
)
2554 lclSaveRecord( rStrm
, mxLabelRange
);
2555 lclSaveRecord( rStrm
, mxValueRange
);
2556 if( mnNumFmtIdx
!= EXC_FORMAT_NOTFOUND
)
2557 XclExpUInt16Record( EXC_ID_CHFORMAT
, mnNumFmtIdx
).Save( rStrm
);
2558 lclSaveRecord( rStrm
, mxTick
);
2559 lclSaveRecord( rStrm
, mxFont
);
2560 lclSaveRecord( rStrm
, mxAxisLine
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_AXISLINE
);
2561 lclSaveRecord( rStrm
, mxMajorGrid
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_MAJORGRID
);
2562 lclSaveRecord( rStrm
, mxMinorGrid
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_MINORGRID
);
2563 lclSaveRecord( rStrm
, mxWallFrame
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_WALLS
);
2566 void XclExpChAxis::WriteBody( XclExpStream
& rStrm
)
2568 rStrm
<< maData
.mnType
<< maData
.maRect
;
2571 // ----------------------------------------------------------------------------
2573 XclExpChAxesSet::XclExpChAxesSet( const XclExpChRoot
& rRoot
, sal_uInt16 nAxesSetId
) :
2574 XclExpChGroupBase( EXC_ID_CHAXESSET
, 18 ),
2575 XclExpChRoot( rRoot
)
2577 maData
.mnAxesSetId
= nAxesSetId
;
2580 sal_uInt16
XclExpChAxesSet::Convert( Reference
< XDiagram
> xDiagram
, sal_uInt16 nFirstGroupIdx
)
2582 /* First unused chart type group index is passed to be able to continue
2583 counting of chart type groups for secondary axes set. */
2584 sal_uInt16 nGroupIdx
= nFirstGroupIdx
;
2585 Reference
< XCoordinateSystemContainer
> xCoordSysCont( xDiagram
, UNO_QUERY
);
2586 if( xCoordSysCont
.is() )
2588 Sequence
< Reference
< XCoordinateSystem
> > aCoordSysSeq
= xCoordSysCont
->getCoordinateSystems();
2589 if( aCoordSysSeq
.getLength() > 0 )
2591 /* Process first coordinate system only. Import filter puts all
2592 chart types into one coordinate system. */
2593 Reference
< XCoordinateSystem
> xCoordSystem
= aCoordSysSeq
[ 0 ];
2594 sal_Int32 nApiAxesSetIdx
= GetApiAxesSetIndex();
2597 bool b3dChart
= xCoordSystem
.is() && (xCoordSystem
->getDimension() == 3);
2600 namespace ApiAxisType
= ::com::sun::star::chart2::AxisType
;
2601 Reference
< XAxis
> xApiYAxis
= lclGetApiAxis( xCoordSystem
, EXC_CHART_AXIS_Y
, nApiAxesSetIdx
);
2602 bool bPercent
= xApiYAxis
.is() && (xApiYAxis
->getScaleData().AxisType
== ApiAxisType::PERCENT
);
2604 // connector lines in bar charts
2605 ScfPropertySet
aDiaProp( xDiagram
);
2606 bool bConnectBars
= aDiaProp
.GetBoolProperty( EXC_CHPROP_CONNECTBARS
);
2608 // swapped axes sets
2609 ScfPropertySet
aCoordSysProp( xCoordSystem
);
2610 bool bSwappedAxesSet
= aCoordSysProp
.GetBoolProperty( EXC_CHPROP_SWAPXANDYAXIS
);
2612 // X axis for later use
2613 Reference
< XAxis
> xApiXAxis
= lclGetApiAxis( xCoordSystem
, EXC_CHART_AXIS_X
, nApiAxesSetIdx
);
2615 ScfPropertySet
aXAxisProp( xApiXAxis
);
2616 bool bHasXLabels
= aXAxisProp
.GetBoolProperty( EXC_CHPROP_DISPLAYLABELS
);
2618 // process chart types
2619 Reference
< XChartTypeContainer
> xChartTypeCont( xCoordSystem
, UNO_QUERY
);
2620 if( xChartTypeCont
.is() )
2622 Sequence
< Reference
< XChartType
> > aChartTypeSeq
= xChartTypeCont
->getChartTypes();
2623 const Reference
< XChartType
>* pBeg
= aChartTypeSeq
.getConstArray();
2624 const Reference
< XChartType
>* pEnd
= pBeg
+ aChartTypeSeq
.getLength();
2625 for( const Reference
< XChartType
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
2627 XclExpChTypeGroupRef
xTypeGroup( new XclExpChTypeGroup( GetChRoot(), nGroupIdx
) );
2628 xTypeGroup
->ConvertType( xDiagram
, *pIt
, nApiAxesSetIdx
, b3dChart
, bSwappedAxesSet
, bHasXLabels
);
2629 /* If new chart type group cannot be inserted into a combination
2630 chart with existing type groups, insert all series into last
2631 contained chart type group instead of creating a new group. */
2632 XclExpChTypeGroupRef xLastGroup
= GetLastTypeGroup();
2633 if( xLastGroup
.is() && !(xTypeGroup
->IsCombinable2d() && xLastGroup
->IsCombinable2d()) )
2635 xLastGroup
->ConvertSeries( xDiagram
, *pIt
, nApiAxesSetIdx
, bPercent
, bConnectBars
);
2639 xTypeGroup
->ConvertSeries( xDiagram
, *pIt
, nApiAxesSetIdx
, bPercent
, bConnectBars
);
2640 if( xTypeGroup
->IsValidGroup() )
2642 maTypeGroups
.AppendRecord( xTypeGroup
);
2649 if( XclExpChTypeGroup
* pGroup
= GetFirstTypeGroup().get() )
2651 const XclChExtTypeInfo
& rTypeInfo
= pGroup
->GetTypeInfo();
2653 // create axes according to chart type (no axes for pie and donut charts)
2654 if( rTypeInfo
.meTypeCateg
!= EXC_CHTYPECATEG_PIE
)
2656 ConvertAxis( mxXAxis
, EXC_CHAXIS_X
, mxXAxisTitle
, EXC_CHOBJLINK_XAXIS
, xCoordSystem
, rTypeInfo
, bPercent
);
2657 ConvertAxis( mxYAxis
, EXC_CHAXIS_Y
, mxYAxisTitle
, EXC_CHOBJLINK_YAXIS
, xCoordSystem
, rTypeInfo
, bPercent
);
2658 if( pGroup
->Is3dDeepChart() )
2659 ConvertAxis( mxZAxis
, EXC_CHAXIS_Z
, mxZAxisTitle
, EXC_CHOBJLINK_ZAXIS
, xCoordSystem
, rTypeInfo
, bPercent
);
2662 // X axis category ranges
2663 if( rTypeInfo
.mbCategoryAxis
&& xApiXAxis
.is() )
2665 const ScaleData aScaleData
= xApiXAxis
->getScaleData();
2666 for( size_t nIdx
= 0, nSize
= maTypeGroups
.GetSize(); nIdx
< nSize
; ++nIdx
)
2667 maTypeGroups
.GetRecord( nIdx
)->ConvertCategSequence( aScaleData
.Categories
);
2671 if( xDiagram
.is() && (GetAxesSetId() == EXC_CHAXESSET_PRIMARY
) )
2673 Reference
< XLegend
> xLegend
= xDiagram
->getLegend();
2676 ScfPropertySet
aLegendProp( xLegend
);
2677 pGroup
->ConvertLegend( aLegendProp
);
2684 // wall/floor/diagram frame formatting
2685 if( xDiagram
.is() && (GetAxesSetId() == EXC_CHAXESSET_PRIMARY
) )
2687 XclExpChTypeGroupRef xTypeGroup
= GetFirstTypeGroup();
2688 if( xTypeGroup
.is() && xTypeGroup
->Is3dWallChart() )
2690 // wall/floor formatting (3D charts)
2692 mxXAxis
->ConvertWall( xDiagram
);
2694 mxYAxis
->ConvertWall( xDiagram
);
2698 // diagram background formatting
2699 ScfPropertySet
aWallProp( xDiagram
->getWall() );
2700 mxPlotFrame
= lclCreateFrame( GetChRoot(), aWallProp
, EXC_CHOBJTYPE_PLOTFRAME
);
2704 // return first unused chart type group index for next axes set
2708 bool XclExpChAxesSet::Is3dChart() const
2710 XclExpChTypeGroupRef xTypeGroup
= GetFirstTypeGroup();
2711 return xTypeGroup
.is() && xTypeGroup
->Is3dChart();
2714 void XclExpChAxesSet::WriteSubRecords( XclExpStream
& rStrm
)
2716 lclSaveRecord( rStrm
, mxXAxis
);
2717 lclSaveRecord( rStrm
, mxYAxis
);
2718 lclSaveRecord( rStrm
, mxZAxis
);
2719 lclSaveRecord( rStrm
, mxXAxisTitle
);
2720 lclSaveRecord( rStrm
, mxYAxisTitle
);
2721 lclSaveRecord( rStrm
, mxZAxisTitle
);
2722 if( mxPlotFrame
.is() )
2724 XclExpEmptyRecord( EXC_ID_CHPLOTFRAME
).Save( rStrm
);
2725 mxPlotFrame
->Save( rStrm
);
2727 maTypeGroups
.Save( rStrm
);
2730 XclExpChTypeGroupRef
XclExpChAxesSet::GetFirstTypeGroup() const
2732 return maTypeGroups
.GetFirstRecord();
2735 XclExpChTypeGroupRef
XclExpChAxesSet::GetLastTypeGroup() const
2737 return maTypeGroups
.GetLastRecord();
2740 void XclExpChAxesSet::ConvertAxis(
2741 XclExpChAxisRef
& rxChAxis
, sal_uInt16 nAxisType
,
2742 XclExpChTextRef
& rxChAxisTitle
, sal_uInt16 nTitleTarget
,
2743 Reference
< XCoordinateSystem
> xCoordSystem
, const XclChExtTypeInfo
& rTypeInfo
,
2746 // create and convert axis object
2747 rxChAxis
.reset( new XclExpChAxis( GetChRoot(), nAxisType
) );
2748 sal_Int32 nApiAxisDim
= rxChAxis
->GetApiAxisDimension();
2749 sal_Int32 nApiAxesSetIdx
= GetApiAxesSetIndex();
2750 Reference
< XAxis
> xAxis
= lclGetApiAxis( xCoordSystem
, nApiAxisDim
, nApiAxesSetIdx
);
2751 rxChAxis
->Convert( xAxis
, rTypeInfo
, nApiAxesSetIdx
, bPercent
);
2753 // create and convert axis title
2754 Reference
< XTitled
> xTitled( xAxis
, UNO_QUERY
);
2755 rxChAxisTitle
= lclCreateTitle( GetChRoot(), xTitled
, nTitleTarget
);
2758 void XclExpChAxesSet::WriteBody( XclExpStream
& rStrm
)
2760 rStrm
<< maData
.mnAxesSetId
<< maData
.maRect
;
2763 // The chart object ===========================================================
2765 static void lcl_getChartSubTitle(const Reference
<XChartDocument
>& xChartDoc
,
2768 Reference
< ::com::sun::star::chart::XChartDocument
> xChartDoc1(xChartDoc
, UNO_QUERY
);
2769 if (!xChartDoc1
.is())
2772 Reference
< XPropertySet
> xProp(xChartDoc1
->getSubTitle(), UNO_QUERY
);
2777 Any any
= xProp
->getPropertyValue( OUString::createFromAscii("String") );
2782 XclExpChChart::XclExpChChart( const XclExpRoot
& rRoot
,
2783 Reference
< XChartDocument
> xChartDoc
, const Size
& rSize
) :
2784 XclExpChGroupBase( EXC_ID_CHCHART
, 16 ),
2785 XclExpChRoot( rRoot
, this )
2787 Size aPtSize
= OutputDevice::LogicToLogic( rSize
, MapMode( MAP_100TH_MM
), MapMode( MAP_POINT
) );
2788 // rectangle is stored in 16.16 fixed-point format
2789 maRect
.mnX
= maRect
.mnY
= 0;
2790 maRect
.mnWidth
= static_cast< sal_Int32
>( aPtSize
.Width() << 16 );
2791 maRect
.mnHeight
= static_cast< sal_Int32
>( aPtSize
.Height() << 16 );
2793 // global chart properties (default values)
2794 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_MANSERIES
);
2795 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_SHOWVISCELLS
, false );
2796 maProps
.mnEmptyMode
= EXC_CHPROPS_EMPTY_SKIP
;
2798 // always create both axes set objects
2799 mxPrimAxesSet
.reset( new XclExpChAxesSet( GetChRoot(), EXC_CHAXESSET_PRIMARY
) );
2800 mxSecnAxesSet
.reset( new XclExpChAxesSet( GetChRoot(), EXC_CHAXESSET_SECONDARY
) );
2802 if( xChartDoc
.is() )
2804 Reference
< XDiagram
> xDiagram
= xChartDoc
->getFirstDiagram();
2806 // global chart properties (only 'include hidden cells' attribute for now)
2807 ScfPropertySet
aDiagramProp( xDiagram
);
2808 bool bIncludeHidden
= aDiagramProp
.GetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS
);
2809 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_SHOWVISCELLS
, !bIncludeHidden
);
2811 // initialize API conversion (remembers xChartDoc internally)
2812 InitConversion( xChartDoc
);
2815 ScfPropertySet
aFrameProp( xChartDoc
->getPageBackground() );
2816 mxFrame
= lclCreateFrame( GetChRoot(), aFrameProp
, EXC_CHOBJTYPE_BACKGROUND
);
2819 Reference
< XTitled
> xTitled( xChartDoc
, UNO_QUERY
);
2821 lcl_getChartSubTitle(xChartDoc
, aSubTitle
);
2822 mxTitle
= lclCreateTitle( GetChRoot(), xTitled
, EXC_CHOBJLINK_TITLE
,
2823 aSubTitle
.Len() ? &aSubTitle
: NULL
);
2825 // diagrams (axes sets)
2826 sal_uInt16 nFreeGroupIdx
= mxPrimAxesSet
->Convert( xDiagram
, 0 );
2827 if( !mxPrimAxesSet
->Is3dChart() )
2828 mxSecnAxesSet
->Convert( xDiagram
, nFreeGroupIdx
);
2830 // finish API conversion
2835 XclExpChSeriesRef
XclExpChChart::CreateSeries()
2837 XclExpChSeriesRef xSeries
;
2838 sal_uInt16 nSeriesIdx
= static_cast< sal_uInt16
>( maSeries
.GetSize() );
2839 if( nSeriesIdx
<= EXC_CHSERIES_MAXSERIES
)
2841 xSeries
.reset( new XclExpChSeries( GetChRoot(), nSeriesIdx
) );
2842 maSeries
.AppendRecord( xSeries
);
2847 void XclExpChChart::RemoveLastSeries()
2849 if( !maSeries
.IsEmpty() )
2850 maSeries
.RemoveRecord( maSeries
.GetSize() - 1 );
2853 void XclExpChChart::SetDataLabel( XclExpChTextRef xText
)
2856 maLabels
.AppendRecord( xText
);
2859 void XclExpChChart::WriteSubRecords( XclExpStream
& rStrm
)
2861 // background format
2862 lclSaveRecord( rStrm
, mxFrame
);
2865 maSeries
.Save( rStrm
);
2867 // CHPROPERTIES record
2868 rStrm
.StartRecord( EXC_ID_CHPROPERTIES
, 4 );
2869 rStrm
<< maProps
.mnFlags
<< maProps
.mnEmptyMode
<< sal_uInt8( 0 );
2872 // axes sets (always save primary axes set)
2873 sal_uInt16 nUsedAxesSets
= mxSecnAxesSet
->IsValidAxesSet() ? 2 : 1;
2874 XclExpUInt16Record( EXC_ID_CHUSEDAXESSETS
, nUsedAxesSets
).Save( rStrm
);
2875 mxPrimAxesSet
->Save( rStrm
);
2876 if( mxSecnAxesSet
->IsValidAxesSet() )
2877 mxSecnAxesSet
->Save( rStrm
);
2879 // chart title and data labels
2880 lclSaveRecord( rStrm
, mxTitle
);
2881 maLabels
.Save( rStrm
);
2884 void XclExpChChart::WriteBody( XclExpStream
& rStrm
)
2889 // ----------------------------------------------------------------------------
2891 XclExpChart::XclExpChart( const XclExpRoot
& rRoot
, Reference
< XModel
> xModel
, const Size
& rSize
) :
2892 XclExpSubStream( EXC_BOF_CHART
),
2895 AppendNewRecord( new XclExpChartPageSettings( rRoot
) );
2896 AppendNewRecord( new XclExpBoolRecord( EXC_ID_PROTECT
, false ) );
2897 AppendNewRecord( new XclExpUInt16Record( EXC_ID_CHUNITS
, EXC_CHUNITS_TWIPS
) );
2899 Reference
< XChartDocument
> xChartDoc( xModel
, UNO_QUERY
);
2900 AppendNewRecord( new XclExpChChart( rRoot
, xChartDoc
, rSize
) );
2903 // ============================================================================