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 "xechart.hxx"
36 #include <com/sun/star/i18n/XBreakIterator.hpp>
37 #include <com/sun/star/i18n/ScriptType.hpp>
38 #include <com/sun/star/drawing/FillStyle.hpp>
39 #include <com/sun/star/chart/XChartDocument.hpp>
40 #include <com/sun/star/chart2/XChartDocument.hpp>
41 #include <com/sun/star/chart2/XDiagram.hpp>
42 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
43 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
44 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
45 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
46 #include <com/sun/star/chart2/XTitled.hpp>
47 #include <com/sun/star/chart2/XColorScheme.hpp>
48 #include <com/sun/star/chart2/data/XDataSource.hpp>
49 #include <com/sun/star/chart2/AxisType.hpp>
50 #include <com/sun/star/chart2/CurveStyle.hpp>
51 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
52 #include <com/sun/star/chart2/DataPointLabel.hpp>
53 #include <com/sun/star/chart2/StackingDirection.hpp>
54 #include <com/sun/star/chart2/TickmarkStyle.hpp>
55 #include <com/sun/star/chart/DataLabelPlacement.hpp>
56 #include <com/sun/star/chart/ErrorBarStyle.hpp>
58 #include <vcl/outdev.hxx>
59 #include <svx/escherex.hxx>
61 #include "document.hxx"
62 #include "rangelst.hxx"
63 #include "rangeutl.hxx"
64 #include "xeformula.hxx"
65 #include "xehelper.hxx"
67 #include "xestyle.hxx"
68 #include "compiler.hxx"
69 #include "tokenarray.hxx"
72 using ::rtl::OUString
;
73 using ::com::sun::star::uno::Any
;
74 using ::com::sun::star::uno::Reference
;
75 using ::com::sun::star::uno::Sequence
;
76 using ::com::sun::star::uno::UNO_QUERY
;
77 using ::com::sun::star::uno::Exception
;
78 using ::com::sun::star::beans::XPropertySet
;
79 using ::com::sun::star::i18n::XBreakIterator
;
80 using ::com::sun::star::frame::XModel
;
81 using ::com::sun::star::chart2::XChartDocument
;
82 using ::com::sun::star::chart2::XDiagram
;
83 using ::com::sun::star::chart2::XCoordinateSystemContainer
;
84 using ::com::sun::star::chart2::XCoordinateSystem
;
85 using ::com::sun::star::chart2::XChartTypeContainer
;
86 using ::com::sun::star::chart2::XChartType
;
87 using ::com::sun::star::chart2::XDataSeriesContainer
;
88 using ::com::sun::star::chart2::XDataSeries
;
89 using ::com::sun::star::chart2::XRegressionCurveContainer
;
90 using ::com::sun::star::chart2::XRegressionCurve
;
91 using ::com::sun::star::chart2::XAxis
;
92 using ::com::sun::star::chart2::XScaling
;
93 using ::com::sun::star::chart2::ScaleData
;
94 using ::com::sun::star::chart2::IncrementData
;
95 using ::com::sun::star::chart2::SubIncrement
;
96 using ::com::sun::star::chart2::XLegend
;
97 using ::com::sun::star::chart2::XTitled
;
98 using ::com::sun::star::chart2::XTitle
;
99 using ::com::sun::star::chart2::XFormattedString
;
100 using ::com::sun::star::chart2::XColorScheme
;
102 using ::com::sun::star::chart2::data::XDataSource
;
103 using ::com::sun::star::chart2::data::XLabeledDataSequence
;
104 using ::com::sun::star::chart2::data::XDataSequence
;
106 // Helpers ====================================================================
110 XclExpStream
& operator<<( XclExpStream
& rStrm
, const XclChRectangle
& rRect
)
112 return rStrm
<< rRect
.mnX
<< rRect
.mnY
<< rRect
.mnWidth
<< rRect
.mnHeight
;
115 inline void lclSaveRecord( XclExpStream
& rStrm
, XclExpRecordRef xRec
)
121 /** Saves the passed record (group) together with a leading value record. */
122 template< typename Type
>
123 void lclSaveRecord( XclExpStream
& rStrm
, XclExpRecordRef xRec
, sal_uInt16 nRecId
, Type nValue
)
127 XclExpValueRecord
< Type
>( nRecId
, nValue
).Save( rStrm
);
132 template< typename Type
>
133 inline bool lclIsAutoAnyOrGetValue( Type
& rValue
, const Any
& rAny
, bool bPercent
)
135 if (!rAny
.hasValue())
148 bool lclIsAutoAnyOrGetScaledValue( double& rfValue
, const Any
& rAny
, Reference
< XScaling
> xScaling
, bool bPercent
)
150 bool bIsAuto
= lclIsAutoAnyOrGetValue( rfValue
, rAny
, bPercent
);
151 if( !bIsAuto
&& xScaling
.is() )
152 rfValue
= xScaling
->doScaling( rfValue
);
159 // Common =====================================================================
161 /** Stores global data needed in various classes of the Chart export filter. */
162 class XclExpChRootData
: public XclChRootData
165 explicit XclExpChRootData( XclExpChChart
* pChartData
);
167 /** Returns a reference to the parent chart data object. */
168 inline XclExpChChart
& GetChartData() const { return *mpChartData
; }
171 XclExpChChart
* mpChartData
; /// Pointer to the chart data object.
174 XclExpChRootData::XclExpChRootData( XclExpChChart
* pChartData
) :
175 mpChartData( pChartData
)
179 // ----------------------------------------------------------------------------
181 XclExpChRoot::XclExpChRoot( const XclExpRoot
& rRoot
, XclExpChChart
* pChartData
) :
183 mxChData( new XclExpChRootData( pChartData
) )
187 XclExpChRoot::~XclExpChRoot()
191 XclExpChChart
& XclExpChRoot::GetChartData() const
193 return mxChData
->GetChartData();
196 const XclChTypeInfo
& XclExpChRoot::GetChartTypeInfo( XclChTypeId eType
) const
198 return mxChData
->GetTypeInfoProvider().GetTypeInfo( eType
);
201 const XclChTypeInfo
& XclExpChRoot::GetChartTypeInfo( const OUString
& rServiceName
) const
203 return mxChData
->GetTypeInfoProvider().GetTypeInfoFromService( rServiceName
);
206 const XclChFormatInfo
& XclExpChRoot::GetFormatInfo( XclChObjectType eObjType
) const
208 return mxChData
->GetFormatInfoProvider().GetFormatInfo( eObjType
);
211 void XclExpChRoot::InitConversion( XChartDocRef xChartDoc
) const
213 mxChData
->InitConversion( xChartDoc
);
216 void XclExpChRoot::FinishConversion() const
218 mxChData
->FinishConversion();
221 bool XclExpChRoot::IsSystemColor( const Color
& rColor
, sal_uInt16 nSysColorIdx
) const
223 XclExpPalette
& rPal
= GetPalette();
224 return rPal
.IsSystemColor( nSysColorIdx
) && (rColor
== rPal
.GetDefColor( nSysColorIdx
));
227 void XclExpChRoot::SetSystemColor( Color
& rColor
, sal_uInt32
& rnColorId
, sal_uInt16 nSysColorIdx
) const
229 DBG_ASSERT( GetPalette().IsSystemColor( nSysColorIdx
), "XclExpChRoot::SetSystemColor - invalid color index" );
230 rColor
= GetPalette().GetDefColor( nSysColorIdx
);
231 rnColorId
= XclExpPalette::GetColorIdFromIndex( nSysColorIdx
);
234 void XclExpChRoot::ConvertLineFormat( XclChLineFormat
& rLineFmt
,
235 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
) const
237 GetChartPropSetHelper().ReadLineProperties(
238 rLineFmt
, mxChData
->GetLineDashTable(), rPropSet
, ePropMode
);
241 bool XclExpChRoot::ConvertAreaFormat( XclChAreaFormat
& rAreaFmt
,
242 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
) const
244 return GetChartPropSetHelper().ReadAreaProperties( rAreaFmt
, rPropSet
, ePropMode
);
247 void XclExpChRoot::ConvertEscherFormat(
248 XclChEscherFormat
& rEscherFmt
, XclChPicFormat
& rPicFmt
,
249 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
) const
251 GetChartPropSetHelper().ReadEscherProperties( rEscherFmt
, rPicFmt
,
252 mxChData
->GetGradientTable(), mxChData
->GetHatchTable(), mxChData
->GetBitmapTable(), rPropSet
, ePropMode
);
255 sal_uInt16
XclExpChRoot::ConvertFont( const ScfPropertySet
& rPropSet
, sal_Int16 nScript
) const
257 XclFontData aFontData
;
258 GetFontPropSetHelper().ReadFontProperties( aFontData
, rPropSet
, EXC_FONTPROPSET_CHART
, nScript
);
259 return GetFontBuffer().Insert( aFontData
, EXC_COLOR_CHARTTEXT
);
262 sal_uInt16
XclExpChRoot::ConvertPieRotation( const ScfPropertySet
& rPropSet
)
264 sal_Int32 nApiRot
= 0;
265 rPropSet
.GetProperty( nApiRot
, EXC_CHPROP_STARTINGANGLE
);
266 return static_cast< sal_uInt16
>( (450 - (nApiRot
% 360)) % 360 );
269 // ----------------------------------------------------------------------------
271 XclExpChGroupBase::XclExpChGroupBase( sal_uInt16 nRecId
, sal_Size nRecSize
) :
272 XclExpRecord( nRecId
, nRecSize
)
276 XclExpChGroupBase::~XclExpChGroupBase()
280 void XclExpChGroupBase::Save( XclExpStream
& rStrm
)
283 XclExpRecord::Save( rStrm
);
285 if( HasSubRecords() )
288 XclExpEmptyRecord( EXC_ID_CHBEGIN
).Save( rStrm
);
290 WriteSubRecords( rStrm
);
292 XclExpEmptyRecord( EXC_ID_CHEND
).Save( rStrm
);
296 bool XclExpChGroupBase::HasSubRecords() const
301 // Frame formatting ===========================================================
303 XclExpChLineFormat::XclExpChLineFormat( const XclExpChRoot
& rRoot
) :
304 XclExpRecord( EXC_ID_CHLINEFORMAT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 12 : 10 ),
305 mnColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
309 void XclExpChLineFormat::SetDefault( XclChFrameType eDefFrameType
)
311 switch( eDefFrameType
)
313 case EXC_CHFRAMETYPE_AUTO
:
316 case EXC_CHFRAMETYPE_INVISIBLE
:
318 maData
.mnPattern
= EXC_CHLINEFORMAT_NONE
;
321 DBG_ERRORFILE( "XclExpChLineFormat::SetDefault - unknown frame type" );
325 void XclExpChLineFormat::Convert( const XclExpChRoot
& rRoot
,
326 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
328 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
329 rRoot
.ConvertLineFormat( maData
, rPropSet
, rFmtInfo
.mePropMode
);
332 // detect system color, set color identifier (TODO: detect automatic series line)
333 if( (eObjType
!= EXC_CHOBJTYPE_LINEARSERIES
) && rRoot
.IsSystemColor( maData
.maColor
, rFmtInfo
.mnAutoLineColorIdx
) )
335 // store color index from automatic format data
336 mnColorId
= XclExpPalette::GetColorIdFromIndex( rFmtInfo
.mnAutoLineColorIdx
);
337 // try to set automatic mode
338 bool bAuto
= (maData
.mnPattern
== EXC_CHLINEFORMAT_SOLID
) && (maData
.mnWeight
== rFmtInfo
.mnAutoLineWeight
);
339 ::set_flag( maData
.mnFlags
, EXC_CHLINEFORMAT_AUTO
, bAuto
);
343 // user defined color - register in palette
344 mnColorId
= rRoot
.GetPalette().InsertColor( maData
.maColor
, EXC_COLOR_CHARTLINE
);
349 // no line - set default system color
350 rRoot
.SetSystemColor( maData
.maColor
, mnColorId
, EXC_COLOR_CHWINDOWTEXT
);
354 bool XclExpChLineFormat::IsDefault( XclChFrameType eDefFrameType
) const
357 ((eDefFrameType
== EXC_CHFRAMETYPE_INVISIBLE
) && !HasLine()) ||
358 ((eDefFrameType
== EXC_CHFRAMETYPE_AUTO
) && IsAuto());
361 void XclExpChLineFormat::WriteBody( XclExpStream
& rStrm
)
363 rStrm
<< maData
.maColor
<< maData
.mnPattern
<< maData
.mnWeight
<< maData
.mnFlags
;
364 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
365 rStrm
<< rStrm
.GetRoot().GetPalette().GetColorIndex( mnColorId
);
370 /** Creates a CHLINEFORMAT record from the passed property set. */
371 XclExpChLineFormatRef
lclCreateLineFormat( const XclExpChRoot
& rRoot
,
372 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
374 XclExpChLineFormatRef
xLineFmt( new XclExpChLineFormat( rRoot
) );
375 xLineFmt
->Convert( rRoot
, rPropSet
, eObjType
);
376 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
377 if( rFmtInfo
.mbDeleteDefFrame
&& xLineFmt
->IsDefault( rFmtInfo
.meDefFrameType
) )
384 // ----------------------------------------------------------------------------
386 XclExpChAreaFormat::XclExpChAreaFormat( const XclExpChRoot
& rRoot
) :
387 XclExpRecord( EXC_ID_CHAREAFORMAT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 16 : 12 ),
388 mnPattColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) ),
389 mnBackColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
393 bool XclExpChAreaFormat::Convert( const XclExpChRoot
& rRoot
,
394 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
396 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
397 bool bComplexFill
= rRoot
.ConvertAreaFormat( maData
, rPropSet
, rFmtInfo
.mePropMode
);
400 bool bSolid
= maData
.mnPattern
== EXC_PATT_SOLID
;
401 // detect system color, set color identifier (TODO: detect automatic series area)
402 if( (eObjType
!= EXC_CHOBJTYPE_FILLEDSERIES
) && rRoot
.IsSystemColor( maData
.maPattColor
, rFmtInfo
.mnAutoPattColorIdx
) )
404 // store color index from automatic format data
405 mnPattColorId
= XclExpPalette::GetColorIdFromIndex( rFmtInfo
.mnAutoPattColorIdx
);
406 // set automatic mode
407 ::set_flag( maData
.mnFlags
, EXC_CHAREAFORMAT_AUTO
, bSolid
);
411 // user defined color - register color in palette
412 mnPattColorId
= rRoot
.GetPalette().InsertColor( maData
.maPattColor
, EXC_COLOR_CHARTAREA
);
414 // background color (default system color for solid fills)
416 rRoot
.SetSystemColor( maData
.maBackColor
, mnBackColorId
, EXC_COLOR_CHWINDOWTEXT
);
418 mnBackColorId
= rRoot
.GetPalette().InsertColor( maData
.maBackColor
, EXC_COLOR_CHARTAREA
);
422 // no area - set default system colors
423 rRoot
.SetSystemColor( maData
.maPattColor
, mnPattColorId
, EXC_COLOR_CHWINDOWBACK
);
424 rRoot
.SetSystemColor( maData
.maBackColor
, mnBackColorId
, EXC_COLOR_CHWINDOWTEXT
);
429 void XclExpChAreaFormat::SetDefault( XclChFrameType eDefFrameType
)
431 switch( eDefFrameType
)
433 case EXC_CHFRAMETYPE_AUTO
:
436 case EXC_CHFRAMETYPE_INVISIBLE
:
438 maData
.mnPattern
= EXC_PATT_NONE
;
441 DBG_ERRORFILE( "XclExpChAreaFormat::SetDefault - unknown frame type" );
445 bool XclExpChAreaFormat::IsDefault( XclChFrameType eDefFrameType
) const
448 ((eDefFrameType
== EXC_CHFRAMETYPE_INVISIBLE
) && !HasArea()) ||
449 ((eDefFrameType
== EXC_CHFRAMETYPE_AUTO
) && IsAuto());
452 void XclExpChAreaFormat::WriteBody( XclExpStream
& rStrm
)
454 rStrm
<< maData
.maPattColor
<< maData
.maBackColor
<< maData
.mnPattern
<< maData
.mnFlags
;
455 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
457 const XclExpPalette
& rPal
= rStrm
.GetRoot().GetPalette();
458 rStrm
<< rPal
.GetColorIndex( mnPattColorId
) << rPal
.GetColorIndex( mnBackColorId
);
462 // ----------------------------------------------------------------------------
464 XclExpChEscherFormat::XclExpChEscherFormat( const XclExpChRoot
& rRoot
) :
465 XclExpChGroupBase( EXC_ID_CHESCHERFORMAT
),
466 mnColor1Id( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) ),
467 mnColor2Id( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) )
469 DBG_ASSERT_BIFF( rRoot
.GetBiff() == EXC_BIFF8
);
473 void XclExpChEscherFormat::Convert( const XclExpChRoot
& rRoot
,
474 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
476 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
477 rRoot
.ConvertEscherFormat( maData
, maPicFmt
, rPropSet
, rFmtInfo
.mePropMode
);
478 // register colors in palette
479 mnColor1Id
= RegisterColor( rRoot
, ESCHER_Prop_fillColor
);
480 mnColor2Id
= RegisterColor( rRoot
, ESCHER_Prop_fillBackColor
);
483 bool XclExpChEscherFormat::IsValid() const
485 return maData
.mxEscherSet
.is();
488 void XclExpChEscherFormat::Save( XclExpStream
& rStrm
)
490 if( maData
.mxEscherSet
.is() )
492 // replace RGB colors with palette indexes in the Escher container
493 const XclExpPalette
& rPal
= rStrm
.GetRoot().GetPalette();
494 maData
.mxEscherSet
->AddOpt( ESCHER_Prop_fillColor
, 0x08000000 | rPal
.GetColorIndex( mnColor1Id
) );
495 maData
.mxEscherSet
->AddOpt( ESCHER_Prop_fillBackColor
, 0x08000000 | rPal
.GetColorIndex( mnColor2Id
) );
497 // save the record group
498 XclExpChGroupBase::Save( rStrm
);
502 bool XclExpChEscherFormat::HasSubRecords() const
504 // no subrecords for gradients
505 return maPicFmt
.mnBmpMode
!= EXC_CHPICFORMAT_NONE
;
508 void XclExpChEscherFormat::WriteSubRecords( XclExpStream
& rStrm
)
510 rStrm
.StartRecord( EXC_ID_CHPICFORMAT
, 14 );
511 rStrm
<< maPicFmt
.mnBmpMode
<< maPicFmt
.mnFormat
<< maPicFmt
.mnFlags
<< maPicFmt
.mfScale
;
515 sal_uInt32
XclExpChEscherFormat::RegisterColor( const XclExpChRoot
& rRoot
, sal_uInt16 nPropId
)
517 sal_uInt32 nBGRValue
;
518 if( maData
.mxEscherSet
.is() && maData
.mxEscherSet
->GetOpt( nPropId
, nBGRValue
) )
521 Color
aColor( RGB_COLORDATA(
522 COLORDATA_BLUE( nBGRValue
),
523 COLORDATA_GREEN( nBGRValue
),
524 COLORDATA_RED( nBGRValue
) ) );
525 return rRoot
.GetPalette().InsertColor( aColor
, EXC_COLOR_CHARTAREA
);
527 return XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
);
530 void XclExpChEscherFormat::WriteBody( XclExpStream
& rStrm
)
532 DBG_ASSERT( maData
.mxEscherSet
.is(), "XclExpChEscherFormat::WriteBody - missing property container" );
533 // write Escher property container via temporary memory stream
534 SvMemoryStream aMemStrm
;
535 maData
.mxEscherSet
->Commit( aMemStrm
);
536 aMemStrm
.Seek( STREAM_SEEK_TO_BEGIN
);
537 rStrm
.CopyFromStream( aMemStrm
);
540 // ----------------------------------------------------------------------------
542 XclExpChFrameBase::XclExpChFrameBase()
546 XclExpChFrameBase::~XclExpChFrameBase()
550 void XclExpChFrameBase::ConvertFrameBase( const XclExpChRoot
& rRoot
,
551 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
554 mxLineFmt
.reset( new XclExpChLineFormat( rRoot
) );
555 mxLineFmt
->Convert( rRoot
, rPropSet
, eObjType
);
556 // area format (only for frame objects)
557 if( rRoot
.GetFormatInfo( eObjType
).mbIsFrame
)
559 mxAreaFmt
.reset( new XclExpChAreaFormat( rRoot
) );
560 bool bComplexFill
= mxAreaFmt
->Convert( rRoot
, rPropSet
, eObjType
);
561 if( (rRoot
.GetBiff() == EXC_BIFF8
) && bComplexFill
)
563 mxEscherFmt
.reset( new XclExpChEscherFormat( rRoot
) );
564 mxEscherFmt
->Convert( rRoot
, rPropSet
, eObjType
);
565 if( mxEscherFmt
->IsValid() )
566 mxAreaFmt
->SetAuto( false );
573 void XclExpChFrameBase::SetDefaultFrameBase( const XclExpChRoot
& rRoot
,
574 XclChFrameType eDefFrameType
, bool bIsFrame
)
577 mxLineFmt
.reset( new XclExpChLineFormat( rRoot
) );
578 mxLineFmt
->SetDefault( eDefFrameType
);
579 // area format (only for frame objects)
582 mxAreaFmt
.reset( new XclExpChAreaFormat( rRoot
) );
583 mxAreaFmt
->SetDefault( eDefFrameType
);
588 bool XclExpChFrameBase::IsDefaultFrameBase( XclChFrameType eDefFrameType
) const
591 (!mxLineFmt
|| mxLineFmt
->IsDefault( eDefFrameType
)) &&
592 (!mxAreaFmt
|| mxAreaFmt
->IsDefault( eDefFrameType
));
595 void XclExpChFrameBase::WriteFrameRecords( XclExpStream
& rStrm
)
597 lclSaveRecord( rStrm
, mxLineFmt
);
598 lclSaveRecord( rStrm
, mxAreaFmt
);
599 lclSaveRecord( rStrm
, mxEscherFmt
);
602 // ----------------------------------------------------------------------------
604 XclExpChFrame::XclExpChFrame( const XclExpChRoot
& rRoot
, XclChObjectType eObjType
) :
605 XclExpChGroupBase( EXC_ID_CHFRAME
, 4 ),
606 XclExpChRoot( rRoot
),
607 meObjType( eObjType
)
611 void XclExpChFrame::Convert( const ScfPropertySet
& rPropSet
)
613 ConvertFrameBase( GetChRoot(), rPropSet
, meObjType
);
616 bool XclExpChFrame::IsDefault() const
618 return IsDefaultFrameBase( GetFormatInfo( meObjType
).meDefFrameType
);
621 bool XclExpChFrame::IsDeleteable() const
623 return IsDefault() && GetFormatInfo( meObjType
).mbDeleteDefFrame
;
626 void XclExpChFrame::Save( XclExpStream
& rStrm
)
630 // wall/floor frame without CHFRAME header record
631 case EXC_CHOBJTYPE_WALL3D
:
632 case EXC_CHOBJTYPE_FLOOR3D
:
633 WriteFrameRecords( rStrm
);
636 XclExpChGroupBase::Save( rStrm
);
640 void XclExpChFrame::WriteSubRecords( XclExpStream
& rStrm
)
642 WriteFrameRecords( rStrm
);
645 void XclExpChFrame::WriteBody( XclExpStream
& rStrm
)
647 rStrm
<< maData
.mnFormat
<< maData
.mnFlags
;
652 /** Creates a CHFRAME record from the passed property set. */
653 XclExpChFrameRef
lclCreateFrame( const XclExpChRoot
& rRoot
,
654 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
656 XclExpChFrameRef
xFrame( new XclExpChFrame( rRoot
, eObjType
) );
657 xFrame
->Convert( rPropSet
);
658 if( xFrame
->IsDeleteable() )
663 void lclAddDoubleRefData(ScTokenArray
& rArray
, const ::formula::FormulaToken
& rToken
,
664 SCsTAB nTab1
, SCsTAB nTab2
, SCsCOL nCol1
, SCsCOL nCol2
, SCsROW nRow1
, SCsROW nRow2
)
666 using namespace ::formula
;
668 StackVar eType
= rToken
.GetType();
669 bool bExternal
= (eType
== svExternalDoubleRef
);
670 DBG_ASSERT(eType
== svDoubleRef
|| eType
== svExternalDoubleRef
, "not a double ref token!");
672 ScComplexRefData aData
;
675 aData
.Ref1
.SetFlag3D(true);
676 aData
.Ref1
.SetTabRel(false);
677 aData
.Ref1
.SetColRel(false);
678 aData
.Ref1
.SetRowRel(false);
679 aData
.Ref2
.SetFlag3D(false);
680 aData
.Ref2
.SetTabRel(false);
681 aData
.Ref2
.SetColRel(false);
682 aData
.Ref2
.SetRowRel(false);
684 aData
.Ref1
.nTab
= nTab1
;
685 aData
.Ref1
.nCol
= nCol1
;
686 aData
.Ref1
.nRow
= nRow1
;
687 aData
.Ref2
.nTab
= nTab2
;
688 aData
.Ref2
.nCol
= nCol2
;
689 aData
.Ref2
.nRow
= nRow2
;
692 rArray
.AddExternalDoubleReference(rToken
.GetIndex(), rToken
.GetString(), aData
);
694 rArray
.AddDoubleReference(aData
);
699 // Source links ===============================================================
701 XclExpChSourceLink::XclExpChSourceLink( const XclExpChRoot
& rRoot
, sal_uInt8 nDestType
) :
702 XclExpRecord( EXC_ID_CHSOURCELINK
),
703 XclExpChRoot( rRoot
)
705 maData
.mnDestType
= nDestType
;
706 maData
.mnLinkType
= EXC_CHSRCLINK_DIRECTLY
;
709 sal_uInt16
XclExpChSourceLink::ConvertDataSequence( Reference
< XDataSequence
> xDataSeq
, bool bSplitToColumns
, sal_uInt16 nDefCount
)
711 using namespace ::formula
;
714 maData
.mnLinkType
= EXC_CHSRCLINK_DEFAULT
;
715 sal_uInt16 nValueCount
= nDefCount
;
720 // Compile the range representation string into token array. Note that the
721 // source range text depends on the current grammar.
722 OUString aRangeRepr
= xDataSeq
->getSourceRangeRepresentation();
723 ScRangeList aScRanges
;
724 ScCompiler
aComp(GetDocPtr(), ScAddress());
725 aComp
.SetGrammar(GetDocPtr()->GetGrammar());
726 ScTokenArray
* pArray
= aComp
.CompileString(aRangeRepr
);
733 for (const FormulaToken
* p
= pArray
->First(); p
; p
= pArray
->Next())
735 StackVar eType
= p
->GetType();
736 if (eType
== svSingleRef
|| eType
== svExternalSingleRef
)
738 // For a single ref token, just add it to the new token array as is.
742 aArray
.AddOpCode(ocUnion
);
747 if (eType
!= svDoubleRef
&& eType
!= svExternalDoubleRef
)
750 // split 3-dimensional ranges into single sheets.
751 const ScComplexRefData
& r
= static_cast<const ScToken
*>(p
)->GetDoubleRef();
752 const ScSingleRefData
& s
= r
.Ref1
;
753 const ScSingleRefData
& e
= r
.Ref2
;
754 for (SCsTAB nTab
= s
.nTab
; nTab
<= e
.nTab
; ++nTab
)
756 if (bSplitToColumns
&& (s
.nRow
!= e
.nRow
))
758 // split 2-dimensional ranges into single columns.
759 for (SCsCOL nCol
= s
.nCol
; nCol
<= e
.nCol
; ++nCol
)
764 aArray
.AddOpCode(ocUnion
);
766 lclAddDoubleRefData(aArray
, *p
, nTab
, nTab
, nCol
, nCol
, s
.nRow
, e
.nRow
);
774 aArray
.AddOpCode(ocUnion
);
776 lclAddDoubleRefData(aArray
, *p
, nTab
, nTab
, s
.nCol
, e
.nCol
, s
.nRow
, e
.nRow
);
781 const ScAddress
aBaseCell(0,0,0);
782 mxLinkFmla
= GetFormulaCompiler().CreateFormula(EXC_FMLATYPE_CHART
, aArray
, &aBaseCell
);
783 maData
.mnLinkType
= EXC_CHSRCLINK_WORKSHEET
;
784 nValueCount
= ulimit_cast
< sal_uInt16
>( aScRanges
.GetCellCount(), EXC_CHDATAFORMAT_MAXPOINTCOUNT
);
788 sal_uInt16
XclExpChSourceLink::ConvertStringSequence( const Sequence
< Reference
< XFormattedString
> >& rStringSeq
)
791 sal_uInt16 nFontIdx
= EXC_FONT_APP
;
792 if( rStringSeq
.hasElements() )
794 mxString
= XclExpStringHelper::CreateString( GetRoot(), String::EmptyString(), EXC_STR_FORCEUNICODE
| EXC_STR_8BITLENGTH
| EXC_STR_SEPARATEFORMATS
);
795 Reference
< XBreakIterator
> xBreakIt
= GetDoc().GetBreakIterator();
796 namespace ApiScriptType
= ::com::sun::star::i18n::ScriptType
;
798 // convert all formatted string entries from the sequence
799 const Reference
< XFormattedString
>* pBeg
= rStringSeq
.getConstArray();
800 const Reference
< XFormattedString
>* pEnd
= pBeg
+ rStringSeq
.getLength();
801 for( const Reference
< XFormattedString
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
805 sal_uInt16 nWstrnFontIdx
= EXC_FONT_NOTFOUND
;
806 sal_uInt16 nAsianFontIdx
= EXC_FONT_NOTFOUND
;
807 sal_uInt16 nCmplxFontIdx
= EXC_FONT_NOTFOUND
;
808 OUString aText
= (*pIt
)->getString();
809 ScfPropertySet
aStrProp( *pIt
);
811 // #i63255# get script type for leading weak characters
812 sal_Int16 nLastScript
= XclExpStringHelper::GetLeadingScriptType( GetRoot(), aText
);
814 // process all script portions
815 sal_Int32 nPortionPos
= 0;
816 sal_Int32 nTextLen
= aText
.getLength();
817 while( nPortionPos
< nTextLen
)
819 // get script type and end position of next script portion
820 sal_Int16 nScript
= xBreakIt
->getScriptType( aText
, nPortionPos
);
821 sal_Int32 nPortionEnd
= xBreakIt
->endOfScript( aText
, nPortionPos
, nScript
);
823 // reuse previous script for following weak portions
824 if( nScript
== ApiScriptType::WEAK
)
825 nScript
= nLastScript
;
827 // Excel start position of this portion
828 sal_uInt16 nXclPortionStart
= mxString
->Len();
829 // add portion text to Excel string
830 XclExpStringHelper::AppendString( *mxString
, GetRoot(), aText
.copy( nPortionPos
, nPortionEnd
- nPortionPos
) );
831 if( nXclPortionStart
< mxString
->Len() )
833 // find font index variable dependent on script type
834 sal_uInt16
& rnFontIdx
= (nScript
== ApiScriptType::COMPLEX
) ? nCmplxFontIdx
:
835 ((nScript
== ApiScriptType::ASIAN
) ? nAsianFontIdx
: nWstrnFontIdx
);
837 // insert font into buffer (if not yet done)
838 if( rnFontIdx
== EXC_FONT_NOTFOUND
)
839 rnFontIdx
= ConvertFont( aStrProp
, nScript
);
841 // insert font index into format run vector
842 mxString
->AppendFormat( nXclPortionStart
, rnFontIdx
);
845 // go to next script portion
846 nLastScript
= nScript
;
847 nPortionPos
= nPortionEnd
;
851 if( !mxString
->IsEmpty() )
853 // get leading font index
854 const XclFormatRunVec
& rFormats
= mxString
->GetFormats();
855 DBG_ASSERT( !rFormats
.empty() && (rFormats
.front().mnChar
== 0),
856 "XclExpChSourceLink::ConvertStringSequenc - missing leading format" );
857 // remove leading format run, if entire string is equally formatted
858 if( rFormats
.size() == 1 )
859 nFontIdx
= mxString
->RemoveLeadingFont();
860 else if( !rFormats
.empty() )
861 nFontIdx
= rFormats
.front().mnFontIdx
;
862 // add trailing format run, if string is rich-formatted
863 if( mxString
->IsRich() )
864 mxString
->AppendTrailingFormat( EXC_FONT_APP
);
870 void XclExpChSourceLink::ConvertNumFmt( const ScfPropertySet
& rPropSet
, bool bPercent
)
872 sal_Int32 nApiNumFmt
= 0;
873 if( bPercent
? rPropSet
.GetProperty( nApiNumFmt
, EXC_CHPROP_PERCENTAGENUMFMT
) : rPropSet
.GetProperty( nApiNumFmt
, EXC_CHPROP_NUMBERFORMAT
) )
875 ::set_flag( maData
.mnFlags
, EXC_CHSRCLINK_NUMFMT
);
876 maData
.mnNumFmtIdx
= GetNumFmtBuffer().Insert( static_cast< sal_uInt32
>( nApiNumFmt
) );
880 void XclExpChSourceLink::AppendString( const String
& rStr
)
884 XclExpStringHelper::AppendString( *mxString
, GetRoot(), rStr
);
887 void XclExpChSourceLink::Save( XclExpStream
& rStrm
)
889 // CHFORMATRUNS record
890 if( mxString
.is() && mxString
->IsRich() )
892 sal_Size nRecSize
= (1 + mxString
->GetFormatsCount()) * ((GetBiff() == EXC_BIFF8
) ? 2 : 1);
893 rStrm
.StartRecord( EXC_ID_CHFORMATRUNS
, nRecSize
);
894 mxString
->WriteFormats( rStrm
, true );
897 // CHSOURCELINK record
898 XclExpRecord::Save( rStrm
);
900 if( mxString
.is() && !mxString
->IsEmpty() )
902 rStrm
.StartRecord( EXC_ID_CHSTRING
, 2 + mxString
->GetSize() );
903 rStrm
<< sal_uInt16( 0 ) << *mxString
;
908 void XclExpChSourceLink::WriteBody( XclExpStream
& rStrm
)
910 rStrm
<< maData
.mnDestType
913 << maData
.mnNumFmtIdx
917 // Text =======================================================================
919 XclExpChFont::XclExpChFont( sal_uInt16 nFontIdx
) :
920 XclExpUInt16Record( EXC_ID_CHFONT
, nFontIdx
)
924 // ----------------------------------------------------------------------------
926 XclExpChObjectLink::XclExpChObjectLink( sal_uInt16 nLinkTarget
, const XclChDataPointPos
& rPointPos
) :
927 XclExpRecord( EXC_ID_CHOBJECTLINK
, 6 )
929 maData
.mnTarget
= nLinkTarget
;
930 maData
.maPointPos
= rPointPos
;
933 void XclExpChObjectLink::WriteBody( XclExpStream
& rStrm
)
935 rStrm
<< maData
.mnTarget
<< maData
.maPointPos
.mnSeriesIdx
<< maData
.maPointPos
.mnPointIdx
;
938 // ----------------------------------------------------------------------------
940 XclExpChFontBase::~XclExpChFontBase()
944 void XclExpChFontBase::ConvertFontBase( const XclExpChRoot
& rRoot
, sal_uInt16 nFontIdx
)
946 if( const XclExpFont
* pFont
= rRoot
.GetFontBuffer().GetFont( nFontIdx
) )
948 XclExpChFontRef
xFont( new XclExpChFont( nFontIdx
) );
949 SetFont( xFont
, pFont
->GetFontData().maColor
, pFont
->GetFontColorId() );
953 void XclExpChFontBase::ConvertFontBase( const XclExpChRoot
& rRoot
, const ScfPropertySet
& rPropSet
)
955 ConvertFontBase( rRoot
, rRoot
.ConvertFont( rPropSet
, rRoot
.GetDefApiScript() ) );
958 void XclExpChFontBase::ConvertRotationBase(
959 const XclExpChRoot
& rRoot
, const ScfPropertySet
& rPropSet
)
961 sal_uInt16 nRotation
= rRoot
.GetChartPropSetHelper().ReadRotationProperties( rPropSet
);
962 SetRotation( nRotation
);
965 // ----------------------------------------------------------------------------
967 XclExpChText::XclExpChText( const XclExpChRoot
& rRoot
) :
968 XclExpChGroupBase( EXC_ID_CHTEXT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 32 : 26 ),
969 XclExpChRoot( rRoot
),
970 mnTextColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
974 void XclExpChText::SetFont( XclExpChFontRef xFont
, const Color
& rColor
, sal_uInt32 nColorId
)
977 maData
.maTextColor
= rColor
;
978 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOCOLOR
, rColor
== COL_AUTO
);
979 mnTextColorId
= nColorId
;
982 void XclExpChText::SetRotation( sal_uInt16 nRotation
)
984 maData
.mnRotation
= nRotation
;
985 ::insert_value( maData
.mnFlags
, XclTools::GetXclOrientFromRot( nRotation
), 8, 3 );
988 void XclExpChText::ConvertTitle( Reference
< XTitle
> xTitle
, sal_uInt16 nTarget
, const String
* pSubTitle
)
991 mxObjLink
.reset( new XclExpChObjectLink( nTarget
, XclChDataPointPos( 0, 0 ) ) );
995 // title frame formatting
996 ScfPropertySet
aTitleProp( xTitle
);
997 mxFrame
= lclCreateFrame( GetChRoot(), aTitleProp
, EXC_CHOBJTYPE_TEXT
);
1000 mxSrcLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1001 sal_uInt16 nFontIdx
= mxSrcLink
->ConvertStringSequence( xTitle
->getText() );
1004 // append subtitle as the 2nd line of the title.
1005 String aSubTitle
= String::CreateFromAscii("\n");
1006 aSubTitle
.Append(*pSubTitle
);
1007 mxSrcLink
->AppendString(aSubTitle
);
1010 ConvertFontBase( GetChRoot(), nFontIdx
);
1013 ConvertRotationBase( GetChRoot(), aTitleProp
);
1017 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_DELETED
);
1021 void XclExpChText::ConvertLegend( const ScfPropertySet
& rPropSet
)
1023 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOTEXT
);
1024 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOGEN
);
1025 ConvertFontBase( GetChRoot(), rPropSet
);
1028 bool XclExpChText::ConvertDataLabel( const ScfPropertySet
& rPropSet
,
1029 const XclChTypeInfo
& rTypeInfo
, const XclChDataPointPos
& rPointPos
)
1031 namespace cssc
= ::com::sun::star::chart2
;
1032 cssc::DataPointLabel aPointLabel
;
1033 if( rPropSet
.GetProperty( aPointLabel
, EXC_CHPROP_LABEL
) )
1035 //! TODO: make value and percent independent
1036 bool bIsPie
= rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
;
1037 bool bShowValue
= aPointLabel
.ShowNumber
;
1038 bool bShowPercent
= bIsPie
&& !bShowValue
&& aPointLabel
.ShowNumberInPercent
;
1039 bool bShowCateg
= !bShowValue
&& aPointLabel
.ShowCategoryName
;
1040 bool bShowAny
= bShowValue
|| bShowPercent
|| bShowCateg
;
1041 bool bShowSymbol
= bShowAny
&& aPointLabel
.ShowLegendSymbol
;
1043 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOTEXT
);
1044 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWVALUE
, bShowValue
);
1045 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWPERCENT
, bShowPercent
);
1046 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
, bShowCateg
);
1047 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEGPERC
, bShowPercent
&& bShowCateg
);
1048 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWSYMBOL
, bShowSymbol
);
1049 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_DELETED
, !bShowAny
);
1054 ConvertFontBase( GetChRoot(), rPropSet
);
1056 sal_Int32 nPlacement
= 0;
1057 if( rPropSet
.GetProperty( nPlacement
, EXC_CHPROP_LABELPLACEMENT
) )
1059 using namespace ::com::sun::star::chart::DataLabelPlacement
;
1060 if( nPlacement
== rTypeInfo
.mnDefaultLabelPos
)
1062 maData
.mnPlacement
= EXC_CHTEXT_POS_DEFAULT
;
1064 else switch( nPlacement
)
1066 case AVOID_OVERLAP
: maData
.mnPlacement
= EXC_CHTEXT_POS_AUTO
; break;
1067 case CENTER
: maData
.mnPlacement
= EXC_CHTEXT_POS_CENTER
; break;
1068 case TOP
: maData
.mnPlacement
= EXC_CHTEXT_POS_ABOVE
; break;
1069 case TOP_LEFT
: maData
.mnPlacement
= EXC_CHTEXT_POS_LEFT
; break;
1070 case LEFT
: maData
.mnPlacement
= EXC_CHTEXT_POS_LEFT
; break;
1071 case BOTTOM_LEFT
: maData
.mnPlacement
= EXC_CHTEXT_POS_LEFT
; break;
1072 case BOTTOM
: maData
.mnPlacement
= EXC_CHTEXT_POS_BELOW
; break;
1073 case BOTTOM_RIGHT
: maData
.mnPlacement
= EXC_CHTEXT_POS_RIGHT
; break;
1074 case RIGHT
: maData
.mnPlacement
= EXC_CHTEXT_POS_RIGHT
; break;
1075 case TOP_RIGHT
: maData
.mnPlacement
= EXC_CHTEXT_POS_RIGHT
; break;
1076 case INSIDE
: maData
.mnPlacement
= EXC_CHTEXT_POS_INSIDE
; break;
1077 case OUTSIDE
: maData
.mnPlacement
= EXC_CHTEXT_POS_OUTSIDE
; break;
1078 case NEAR_ORIGIN
: maData
.mnPlacement
= EXC_CHTEXT_POS_AXIS
; break;
1079 default: DBG_ERRORFILE( "XclExpChText::ConvertDataLabel - unknown label placement type" );
1082 // source link (contains number format)
1083 mxSrcLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1084 if( bShowValue
|| bShowPercent
)
1085 // percentage format wins over value format
1086 mxSrcLink
->ConvertNumFmt( rPropSet
, bShowPercent
);
1088 mxObjLink
.reset( new XclExpChObjectLink( EXC_CHOBJLINK_DATA
, rPointPos
) );
1089 // return true to indicate existing label
1096 void XclExpChText::ConvertTrendLineEquation( const ScfPropertySet
& rPropSet
, const XclChDataPointPos
& rPointPos
)
1099 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOTEXT
);
1100 if( GetBiff() == EXC_BIFF8
)
1101 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
); // must set this to make equation visible in Excel
1103 mxFrame
= lclCreateFrame( GetChRoot(), rPropSet
, EXC_CHOBJTYPE_TEXT
);
1105 maData
.mnHAlign
= EXC_CHTEXT_ALIGN_TOPLEFT
;
1106 maData
.mnVAlign
= EXC_CHTEXT_ALIGN_TOPLEFT
;
1107 ConvertFontBase( GetChRoot(), rPropSet
);
1108 // source link (contains number format)
1109 mxSrcLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1110 mxSrcLink
->ConvertNumFmt( rPropSet
, false );
1112 mxObjLink
.reset( new XclExpChObjectLink( EXC_CHOBJLINK_DATA
, rPointPos
) );
1115 sal_uInt16
XclExpChText::GetAttLabelFlags() const
1117 sal_uInt16 nFlags
= 0;
1118 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWVALUE
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWVALUE
) );
1119 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWPERCENT
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWPERCENT
) );
1120 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWCATEGPERC
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEGPERC
) );
1121 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWCATEG
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
) );
1125 void XclExpChText::WriteSubRecords( XclExpStream
& rStrm
)
1128 lclSaveRecord( rStrm
, mxFont
);
1129 // CHSOURCELINK group
1130 lclSaveRecord( rStrm
, mxSrcLink
);
1132 lclSaveRecord( rStrm
, mxFrame
);
1133 // CHOBJECTLINK record
1134 lclSaveRecord( rStrm
, mxObjLink
);
1137 void XclExpChText::WriteBody( XclExpStream
& rStrm
)
1139 rStrm
<< maData
.mnHAlign
1141 << maData
.mnBackMode
1142 << maData
.maTextColor
1146 if( GetBiff() == EXC_BIFF8
)
1148 rStrm
<< GetPalette().GetColorIndex( mnTextColorId
)
1149 << maData
.mnPlacement
1150 << maData
.mnRotation
;
1154 // ----------------------------------------------------------------------------
1158 /** Creates and returns an Excel text object from the passed title. */
1159 XclExpChTextRef
lclCreateTitle( const XclExpChRoot
& rRoot
, Reference
< XTitled
> xTitled
, sal_uInt16 nTarget
,
1160 const String
* pSubTitle
= NULL
)
1162 Reference
< XTitle
> xTitle
;
1164 xTitle
= xTitled
->getTitleObject();
1166 XclExpChTextRef
xText( new XclExpChText( rRoot
) );
1167 xText
->ConvertTitle( xTitle
, nTarget
, pSubTitle
);
1168 /* Do not delete the CHTEXT group for the main title. A missing CHTEXT
1169 will be interpreted as auto-generated title showing the series title in
1170 charts that contain exactly one data series. */
1171 if( (nTarget
!= EXC_CHOBJLINK_TITLE
) && !xText
->HasString() )
1179 // Data series ================================================================
1181 XclExpChMarkerFormat::XclExpChMarkerFormat( const XclExpChRoot
& rRoot
) :
1182 XclExpRecord( EXC_ID_CHMARKERFORMAT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 20 : 12 ),
1183 mnLineColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) ),
1184 mnFillColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) )
1188 void XclExpChMarkerFormat::Convert( const XclExpChRoot
& rRoot
,
1189 const ScfPropertySet
& rPropSet
, sal_uInt16 nFormatIdx
)
1191 rRoot
.GetChartPropSetHelper().ReadMarkerProperties( maData
, rPropSet
, nFormatIdx
);
1192 /* Set marker line/fill color to series line color.
1193 TODO: remove this if OOChart supports own colors in markers. */
1195 if( rPropSet
.GetColorProperty( aLineColor
, EXC_CHPROP_COLOR
) )
1196 maData
.maLineColor
= maData
.maFillColor
= aLineColor
;
1197 // register colors in palette
1198 RegisterColors( rRoot
);
1201 void XclExpChMarkerFormat::ConvertStockSymbol( const XclExpChRoot
& rRoot
,
1202 const ScfPropertySet
& rPropSet
, bool bCloseSymbol
)
1204 // clear the automatic flag
1205 ::set_flag( maData
.mnFlags
, EXC_CHMARKERFORMAT_AUTO
, false );
1206 // symbol type and color
1209 // set symbol type for the 'close' data series
1210 maData
.mnMarkerType
= EXC_CHMARKERFORMAT_DOWJ
;
1211 maData
.mnMarkerSize
= EXC_CHMARKERFORMAT_DOUBLESIZE
;
1212 // set symbol line/fill color to series line color
1214 if( rPropSet
.GetColorProperty( aLineColor
, EXC_CHPROP_COLOR
) )
1216 maData
.maLineColor
= maData
.maFillColor
= aLineColor
;
1217 RegisterColors( rRoot
);
1222 // set invisible symbol
1223 maData
.mnMarkerType
= EXC_CHMARKERFORMAT_NOSYMBOL
;
1227 void XclExpChMarkerFormat::RegisterColors( const XclExpChRoot
& rRoot
)
1231 if( HasLineColor() )
1232 mnLineColorId
= rRoot
.GetPalette().InsertColor( maData
.maLineColor
, EXC_COLOR_CHARTLINE
);
1233 if( HasFillColor() )
1234 mnFillColorId
= rRoot
.GetPalette().InsertColor( maData
.maFillColor
, EXC_COLOR_CHARTAREA
);
1238 void XclExpChMarkerFormat::WriteBody( XclExpStream
& rStrm
)
1240 rStrm
<< maData
.maLineColor
<< maData
.maFillColor
<< maData
.mnMarkerType
<< maData
.mnFlags
;
1241 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
1243 const XclExpPalette
& rPal
= rStrm
.GetRoot().GetPalette();
1244 rStrm
<< rPal
.GetColorIndex( mnLineColorId
) << rPal
.GetColorIndex( mnFillColorId
) << maData
.mnMarkerSize
;
1248 // ----------------------------------------------------------------------------
1250 XclExpChPieFormat::XclExpChPieFormat() :
1251 XclExpUInt16Record( EXC_ID_CHPIEFORMAT
, 0 )
1255 void XclExpChPieFormat::Convert( const ScfPropertySet
& rPropSet
)
1257 double fApiDist(0.0);
1258 if( rPropSet
.GetProperty( fApiDist
, EXC_CHPROP_OFFSET
) )
1259 SetValue( limit_cast
< sal_uInt16
>( fApiDist
* 100.0, 0, 100 ) );
1262 // ----------------------------------------------------------------------------
1264 XclExpCh3dDataFormat::XclExpCh3dDataFormat() :
1265 XclExpRecord( EXC_ID_CH3DDATAFORMAT
, 2 )
1269 void XclExpCh3dDataFormat::Convert( const ScfPropertySet
& rPropSet
)
1271 sal_Int32
nApiType(0);
1272 if( rPropSet
.GetProperty( nApiType
, EXC_CHPROP_GEOMETRY3D
) )
1274 using namespace ::com::sun::star::chart2::DataPointGeometry3D
;
1278 maData
.mnBase
= EXC_CH3DDATAFORMAT_RECT
;
1279 maData
.mnTop
= EXC_CH3DDATAFORMAT_STRAIGHT
;
1282 maData
.mnBase
= EXC_CH3DDATAFORMAT_RECT
;
1283 maData
.mnTop
= EXC_CH3DDATAFORMAT_SHARP
;
1286 maData
.mnBase
= EXC_CH3DDATAFORMAT_CIRC
;
1287 maData
.mnTop
= EXC_CH3DDATAFORMAT_STRAIGHT
;
1290 maData
.mnBase
= EXC_CH3DDATAFORMAT_CIRC
;
1291 maData
.mnTop
= EXC_CH3DDATAFORMAT_SHARP
;
1294 DBG_ERRORFILE( "XclExpCh3dDataFormat::Convert - unknown 3D bar format" );
1299 void XclExpCh3dDataFormat::WriteBody( XclExpStream
& rStrm
)
1301 rStrm
<< maData
.mnBase
<< maData
.mnTop
;
1304 // ----------------------------------------------------------------------------
1306 XclExpChAttachedLabel::XclExpChAttachedLabel( sal_uInt16 nFlags
) :
1307 XclExpUInt16Record( EXC_ID_CHATTACHEDLABEL
, nFlags
)
1311 // ----------------------------------------------------------------------------
1313 XclExpChDataFormat::XclExpChDataFormat( const XclExpChRoot
& rRoot
,
1314 const XclChDataPointPos
& rPointPos
, sal_uInt16 nFormatIdx
) :
1315 XclExpChGroupBase( EXC_ID_CHDATAFORMAT
, 8 ),
1316 XclExpChRoot( rRoot
)
1318 maData
.maPointPos
= rPointPos
;
1319 maData
.mnFormatIdx
= nFormatIdx
;
1322 void XclExpChDataFormat::ConvertDataSeries( const ScfPropertySet
& rPropSet
, const XclChExtTypeInfo
& rTypeInfo
)
1324 // line and area formatting
1325 ConvertFrameBase( GetChRoot(), rPropSet
, rTypeInfo
.GetSeriesObjectType() );
1327 // data point symbols
1328 bool bIsFrame
= rTypeInfo
.IsSeriesFrameFormat();
1331 mxMarkerFmt
.reset( new XclExpChMarkerFormat( GetChRoot() ) );
1332 mxMarkerFmt
->Convert( GetChRoot(), rPropSet
, maData
.mnFormatIdx
);
1336 if( rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
)
1338 mxPieFmt
.reset( new XclExpChPieFormat
);
1339 mxPieFmt
->Convert( rPropSet
);
1342 // 3D bars (only allowed for entire series in BIFF8)
1343 if( IsSeriesFormat() && (GetBiff() == EXC_BIFF8
) && rTypeInfo
.mb3dChart
&& (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_BAR
) )
1345 mx3dDataFmt
.reset( new XclExpCh3dDataFormat
);
1346 mx3dDataFmt
->Convert( rPropSet
);
1350 if( IsSeriesFormat() && rTypeInfo
.mbSpline
&& !bIsFrame
)
1351 mxSeriesFmt
.reset( new XclExpUInt16Record( EXC_ID_CHSERIESFORMAT
, EXC_CHSERIESFORMAT_SMOOTHED
) );
1353 // data point labels
1354 XclExpChTextRef
xLabel( new XclExpChText( GetChRoot() ) );
1355 if( xLabel
->ConvertDataLabel( rPropSet
, rTypeInfo
, maData
.maPointPos
) )
1357 // CHTEXT groups for data labels are stored in global CHCHART group
1358 GetChartData().SetDataLabel( xLabel
);
1359 mxAttLabel
.reset( new XclExpChAttachedLabel( xLabel
->GetAttLabelFlags() ) );
1363 void XclExpChDataFormat::ConvertStockSeries( const ScfPropertySet
& rPropSet
, bool bCloseSymbol
)
1365 // set line format to invisible
1366 SetDefaultFrameBase( GetChRoot(), EXC_CHFRAMETYPE_INVISIBLE
, false );
1367 // set symbols to invisible or to 'close' series symbol
1368 mxMarkerFmt
.reset( new XclExpChMarkerFormat( GetChRoot() ) );
1369 mxMarkerFmt
->ConvertStockSymbol( GetChRoot(), rPropSet
, bCloseSymbol
);
1372 void XclExpChDataFormat::ConvertLine( const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
1374 ConvertFrameBase( GetChRoot(), rPropSet
, eObjType
);
1377 void XclExpChDataFormat::WriteSubRecords( XclExpStream
& rStrm
)
1379 lclSaveRecord( rStrm
, mx3dDataFmt
);
1380 WriteFrameRecords( rStrm
);
1381 lclSaveRecord( rStrm
, mxPieFmt
);
1382 lclSaveRecord( rStrm
, mxMarkerFmt
);
1383 lclSaveRecord( rStrm
, mxSeriesFmt
);
1384 lclSaveRecord( rStrm
, mxAttLabel
);
1387 void XclExpChDataFormat::WriteBody( XclExpStream
& rStrm
)
1389 rStrm
<< maData
.maPointPos
.mnPointIdx
1390 << maData
.maPointPos
.mnSeriesIdx
1391 << maData
.mnFormatIdx
1395 // ----------------------------------------------------------------------------
1397 XclExpChSerTrendLine::XclExpChSerTrendLine( const XclExpChRoot
& rRoot
) :
1398 XclExpRecord( EXC_ID_CHSERTRENDLINE
, 28 ),
1399 XclExpChRoot( rRoot
)
1403 bool XclExpChSerTrendLine::Convert( Reference
< XRegressionCurve
> xRegCurve
, sal_uInt16 nSeriesIdx
)
1405 if( !xRegCurve
.is() )
1409 ScfPropertySet
aCurveProp( xRegCurve
);
1410 OUString aService
= aCurveProp
.GetServiceName();
1411 if( aService
== SERVICE_CHART2_LINEARREGCURVE
)
1413 maData
.mnLineType
= EXC_CHSERTREND_POLYNOMIAL
;
1416 else if( aService
== SERVICE_CHART2_EXPREGCURVE
)
1417 maData
.mnLineType
= EXC_CHSERTREND_EXPONENTIAL
;
1418 else if( aService
== SERVICE_CHART2_LOGREGCURVE
)
1419 maData
.mnLineType
= EXC_CHSERTREND_LOGARITHMIC
;
1420 else if( aService
== SERVICE_CHART2_POTREGCURVE
)
1421 maData
.mnLineType
= EXC_CHSERTREND_POWER
;
1426 XclChDataPointPos
aPointPos( nSeriesIdx
);
1427 mxDataFmt
.reset( new XclExpChDataFormat( GetChRoot(), aPointPos
, 0 ) );
1428 mxDataFmt
->ConvertLine( aCurveProp
, EXC_CHOBJTYPE_TRENDLINE
);
1430 // #i83100# show equation and correlation coefficient
1431 ScfPropertySet
aEquationProp( xRegCurve
->getEquationProperties() );
1432 maData
.mnShowEquation
= aEquationProp
.GetBoolProperty( EXC_CHPROP_SHOWEQUATION
) ? 1 : 0;
1433 maData
.mnShowRSquared
= aEquationProp
.GetBoolProperty( EXC_CHPROP_SHOWCORRELATION
) ? 1 : 0;
1435 // #i83100# formatting of the equation text box
1436 if( (maData
.mnShowEquation
!= 0) || (maData
.mnShowRSquared
!= 0) )
1438 mxLabel
.reset( new XclExpChText( GetChRoot() ) );
1439 mxLabel
->ConvertTrendLineEquation( aEquationProp
, aPointPos
);
1443 // #i20819# polynomial trend lines
1444 // #i66819# moving average trend lines
1445 // #i5085# manual trend line size
1446 // #i34093# manual crossing point
1450 void XclExpChSerTrendLine::WriteBody( XclExpStream
& rStrm
)
1452 rStrm
<< maData
.mnLineType
1454 << maData
.mfIntercept
1455 << maData
.mnShowEquation
1456 << maData
.mnShowRSquared
1457 << maData
.mfForecastFor
1458 << maData
.mfForecastBack
;
1461 // ----------------------------------------------------------------------------
1463 XclExpChSerErrorBar::XclExpChSerErrorBar( const XclExpChRoot
& rRoot
, sal_uInt8 nBarType
) :
1464 XclExpRecord( EXC_ID_CHSERERRORBAR
, 14 ),
1465 XclExpChRoot( rRoot
)
1467 maData
.mnBarType
= nBarType
;
1470 bool XclExpChSerErrorBar::Convert( XclExpChSourceLink
& rValueLink
, sal_uInt16
& rnValueCount
, const ScfPropertySet
& rPropSet
)
1472 sal_Int32 nBarStyle
= 0;
1473 bool bOk
= rPropSet
.GetProperty( nBarStyle
, EXC_CHPROP_ERRORBARSTYLE
);
1476 namespace cssc
= ::com::sun::star::chart
;
1479 case cssc::ErrorBarStyle::ABSOLUTE
:
1480 maData
.mnSourceType
= EXC_CHSERERR_FIXED
;
1481 rPropSet
.GetProperty( maData
.mfValue
, EXC_CHPROP_POSITIVEERROR
);
1483 case cssc::ErrorBarStyle::RELATIVE
:
1484 maData
.mnSourceType
= EXC_CHSERERR_PERCENT
;
1485 rPropSet
.GetProperty( maData
.mfValue
, EXC_CHPROP_POSITIVEERROR
);
1487 case cssc::ErrorBarStyle::STANDARD_DEVIATION
:
1488 maData
.mnSourceType
= EXC_CHSERERR_STDDEV
;
1489 rPropSet
.GetProperty( maData
.mfValue
, EXC_CHPROP_WEIGHT
);
1491 case cssc::ErrorBarStyle::STANDARD_ERROR
:
1492 maData
.mnSourceType
= EXC_CHSERERR_STDERR
;
1494 case cssc::ErrorBarStyle::FROM_DATA
:
1497 maData
.mnSourceType
= EXC_CHSERERR_CUSTOM
;
1498 Reference
< XDataSource
> xDataSource( rPropSet
.GetApiPropertySet(), UNO_QUERY
);
1499 if( xDataSource
.is() )
1501 // find first sequence with current role
1502 OUString aRole
= XclChartHelper::GetErrorBarValuesRole( maData
.mnBarType
);
1503 Reference
< XDataSequence
> xValueSeq
;
1505 Sequence
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
= xDataSource
->getDataSequences();
1506 const Reference
< XLabeledDataSequence
>* pBeg
= aLabeledSeqVec
.getConstArray();
1507 const Reference
< XLabeledDataSequence
>* pEnd
= pBeg
+ aLabeledSeqVec
.getLength();
1508 for( const Reference
< XLabeledDataSequence
>* pIt
= pBeg
; !xValueSeq
.is() && (pIt
!= pEnd
); ++pIt
)
1510 Reference
< XDataSequence
> xTmpValueSeq
= (*pIt
)->getValues();
1511 ScfPropertySet
aValueProp( xTmpValueSeq
);
1513 if( aValueProp
.GetProperty( aCurrRole
, EXC_CHPROP_ROLE
) && (aCurrRole
== aRole
) )
1514 xValueSeq
= xTmpValueSeq
;
1516 if( xValueSeq
.is() )
1518 // #i86465# pass value count back to series
1519 rnValueCount
= maData
.mnValueCount
= rValueLink
.ConvertDataSequence( xValueSeq
, true );
1520 bOk
= maData
.mnValueCount
> 0;
1532 void XclExpChSerErrorBar::WriteBody( XclExpStream
& rStrm
)
1534 rStrm
<< maData
.mnBarType
1535 << maData
.mnSourceType
1537 << sal_uInt8( 1 ) // must be 1 to make line visible
1539 << maData
.mnValueCount
;
1542 // ----------------------------------------------------------------------------
1546 /** Returns the property set of the specified data point. */
1547 ScfPropertySet
lclGetPointPropSet( Reference
< XDataSeries
> xDataSeries
, sal_Int32 nPointIdx
)
1549 ScfPropertySet aPropSet
;
1552 aPropSet
.Set( xDataSeries
->getDataPointByIndex( nPointIdx
) );
1556 DBG_ERRORFILE( "lclGetPointPropSet - no data point property set" );
1563 XclExpChSeries::XclExpChSeries( const XclExpChRoot
& rRoot
, sal_uInt16 nSeriesIdx
) :
1564 XclExpChGroupBase( EXC_ID_CHSERIES
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 12 : 8 ),
1565 XclExpChRoot( rRoot
),
1566 mnGroupIdx( EXC_CHSERGROUP_NONE
),
1567 mnSeriesIdx( nSeriesIdx
),
1568 mnParentIdx( EXC_CHSERIES_INVALID
)
1570 // CHSOURCELINK records are always required, even if unused
1571 mxTitleLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1572 mxValueLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_VALUES
) );
1573 mxCategLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_CATEGORY
) );
1574 if( GetBiff() == EXC_BIFF8
)
1575 mxBubbleLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_BUBBLES
) );
1578 bool XclExpChSeries::ConvertDataSeries(
1579 Reference
< XDiagram
> xDiagram
, Reference
< XDataSeries
> xDataSeries
,
1580 const XclChExtTypeInfo
& rTypeInfo
, sal_uInt16 nGroupIdx
, sal_uInt16 nFormatIdx
)
1583 Reference
< XDataSource
> xDataSource( xDataSeries
, UNO_QUERY
);
1584 if( xDataSource
.is() )
1586 Reference
< XDataSequence
> xYValueSeq
, xTitleSeq
, xXValueSeq
;
1588 // find first sequence with role 'values-y'
1589 Sequence
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
= xDataSource
->getDataSequences();
1590 const Reference
< XLabeledDataSequence
>* pBeg
= aLabeledSeqVec
.getConstArray();
1591 const Reference
< XLabeledDataSequence
>* pEnd
= pBeg
+ aLabeledSeqVec
.getLength();
1592 for( const Reference
< XLabeledDataSequence
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
1594 Reference
< XDataSequence
> xTmpValueSeq
= (*pIt
)->getValues();
1595 ScfPropertySet
aValueProp( xTmpValueSeq
);
1597 if( aValueProp
.GetProperty( aRole
, EXC_CHPROP_ROLE
) )
1599 if( !xYValueSeq
.is() && (aRole
== EXC_CHPROP_ROLE_YVALUES
) )
1601 xYValueSeq
= xTmpValueSeq
;
1602 xTitleSeq
= (*pIt
)->getLabel(); // ignore role of label sequence
1604 else if( !xXValueSeq
.is() && !rTypeInfo
.mbCategoryAxis
&& (aRole
== EXC_CHPROP_ROLE_XVALUES
) )
1606 xXValueSeq
= xTmpValueSeq
;
1611 bOk
= xYValueSeq
.is();
1614 // chart type group index
1615 mnGroupIdx
= nGroupIdx
;
1617 // convert source links
1618 maData
.mnValueCount
= mxValueLink
->ConvertDataSequence( xYValueSeq
, true );
1619 mxTitleLink
->ConvertDataSequence( xTitleSeq
, true );
1621 // X values of XY charts
1622 maData
.mnCategCount
= mxCategLink
->ConvertDataSequence( xXValueSeq
, false, maData
.mnValueCount
);
1624 // series formatting
1625 XclChDataPointPos
aPointPos( mnSeriesIdx
);
1626 ScfPropertySet
aSeriesProp( xDataSeries
);
1627 mxSeriesFmt
.reset( new XclExpChDataFormat( GetChRoot(), aPointPos
, nFormatIdx
) );
1628 mxSeriesFmt
->ConvertDataSeries( aSeriesProp
, rTypeInfo
);
1631 CreateTrendLines( xDataSeries
);
1634 CreateErrorBars( aSeriesProp
, EXC_CHPROP_ERRORBARX
, EXC_CHSERERR_XPLUS
, EXC_CHSERERR_XMINUS
);
1635 CreateErrorBars( aSeriesProp
, EXC_CHPROP_ERRORBARY
, EXC_CHSERERR_YPLUS
, EXC_CHSERERR_YMINUS
);
1637 if( maData
.mnValueCount
> 0 )
1639 const sal_Int32 nMaxPointCount
= maData
.mnValueCount
;
1641 /* #i91063# Create missing fill properties in pie/doughnut charts.
1642 If freshly created (never saved to ODF), these charts show
1643 varying point colors but do not return these points via API. */
1644 if( xDiagram
.is() && (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
) )
1646 Reference
< XColorScheme
> xColorScheme
= xDiagram
->getDefaultColorScheme();
1647 if( xColorScheme
.is() )
1649 const OUString aFillStyleName
= CREATE_OUSTRING( "FillStyle" );
1650 const OUString aColorName
= CREATE_OUSTRING( "Color" );
1651 namespace csscd
= ::com::sun::star::drawing
;
1652 for( sal_Int32 nPointIdx
= 0; nPointIdx
< nMaxPointCount
; ++nPointIdx
)
1654 aPointPos
.mnPointIdx
= static_cast< sal_uInt16
>( nPointIdx
);
1655 ScfPropertySet aPointProp
= lclGetPointPropSet( xDataSeries
, nPointIdx
);
1656 // test that the point fill style is solid, but no color is set
1657 csscd::FillStyle eFillStyle
= csscd::FillStyle_NONE
;
1658 if( aPointProp
.GetProperty( eFillStyle
, aFillStyleName
) &&
1659 (eFillStyle
== csscd::FillStyle_SOLID
) &&
1660 !aPointProp
.HasProperty( aColorName
) )
1662 aPointProp
.SetProperty( aColorName
, xColorScheme
->getColorByIndex( nPointIdx
) );
1668 // data point formatting
1669 Sequence
< sal_Int32
> aPointIndexes
;
1670 if( aSeriesProp
.GetProperty( aPointIndexes
, EXC_CHPROP_ATTRIBDATAPOINTS
) && aPointIndexes
.hasElements() )
1672 const sal_Int32
* pnBeg
= aPointIndexes
.getConstArray();
1673 const sal_Int32
* pnEnd
= pnBeg
+ aPointIndexes
.getLength();
1674 for( const sal_Int32
* pnIt
= pnBeg
; (pnIt
!= pnEnd
) && (*pnIt
< nMaxPointCount
); ++pnIt
)
1676 aPointPos
.mnPointIdx
= static_cast< sal_uInt16
>( *pnIt
);
1677 ScfPropertySet aPointProp
= lclGetPointPropSet( xDataSeries
, *pnIt
);
1678 XclExpChDataFormatRef
xPointFmt( new XclExpChDataFormat( GetChRoot(), aPointPos
, nFormatIdx
) );
1679 xPointFmt
->ConvertDataSeries( aPointProp
, rTypeInfo
);
1680 maPointFmts
.AppendRecord( xPointFmt
);
1689 bool XclExpChSeries::ConvertStockSeries( XDataSeriesRef xDataSeries
,
1690 const OUString
& rValueRole
, sal_uInt16 nGroupIdx
, sal_uInt16 nFormatIdx
, bool bCloseSymbol
)
1693 Reference
< XDataSource
> xDataSource( xDataSeries
, UNO_QUERY
);
1694 if( xDataSource
.is() )
1696 Reference
< XDataSequence
> xYValueSeq
, xTitleSeq
;
1698 // find first sequence with passed role
1699 Sequence
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
= xDataSource
->getDataSequences();
1700 const Reference
< XLabeledDataSequence
>* pBeg
= aLabeledSeqVec
.getConstArray();
1701 const Reference
< XLabeledDataSequence
>* pEnd
= pBeg
+ aLabeledSeqVec
.getLength();
1702 for( const Reference
< XLabeledDataSequence
>* pIt
= pBeg
; !xYValueSeq
.is() && (pIt
!= pEnd
); ++pIt
)
1704 Reference
< XDataSequence
> xTmpValueSeq
= (*pIt
)->getValues();
1705 ScfPropertySet
aValueProp( xTmpValueSeq
);
1707 if( aValueProp
.GetProperty( aRole
, EXC_CHPROP_ROLE
) && (aRole
== rValueRole
) )
1709 xYValueSeq
= xTmpValueSeq
;
1710 xTitleSeq
= (*pIt
)->getLabel(); // ignore role of label sequence
1714 bOk
= xYValueSeq
.is();
1717 // chart type group index
1718 mnGroupIdx
= nGroupIdx
;
1719 // convert source links
1720 maData
.mnValueCount
= mxValueLink
->ConvertDataSequence( xYValueSeq
, true );
1721 mxTitleLink
->ConvertDataSequence( xTitleSeq
, true );
1722 // series formatting
1723 ScfPropertySet
aSeriesProp( xDataSeries
);
1724 mxSeriesFmt
.reset( new XclExpChDataFormat( GetChRoot(), XclChDataPointPos( mnSeriesIdx
), nFormatIdx
) );
1725 mxSeriesFmt
->ConvertStockSeries( aSeriesProp
, bCloseSymbol
);
1731 bool XclExpChSeries::ConvertTrendLine( const XclExpChSeries
& rParent
, Reference
< XRegressionCurve
> xRegCurve
)
1733 InitFromParent( rParent
);
1734 mxTrendLine
.reset( new XclExpChSerTrendLine( GetChRoot() ) );
1735 bool bOk
= mxTrendLine
->Convert( xRegCurve
, mnSeriesIdx
);
1738 mxSeriesFmt
= mxTrendLine
->GetDataFormat();
1739 GetChartData().SetDataLabel( mxTrendLine
->GetDataLabel() );
1744 bool XclExpChSeries::ConvertErrorBar( const XclExpChSeries
& rParent
, const ScfPropertySet
& rPropSet
, sal_uInt8 nBarId
)
1746 InitFromParent( rParent
);
1747 // error bar settings
1748 mxErrorBar
.reset( new XclExpChSerErrorBar( GetChRoot(), nBarId
) );
1749 bool bOk
= mxErrorBar
->Convert( *mxValueLink
, maData
.mnValueCount
, rPropSet
);
1752 // error bar formatting
1753 mxSeriesFmt
.reset( new XclExpChDataFormat( GetChRoot(), XclChDataPointPos( mnSeriesIdx
), 0 ) );
1754 mxSeriesFmt
->ConvertLine( rPropSet
, EXC_CHOBJTYPE_ERRORBAR
);
1759 void XclExpChSeries::ConvertCategSequence( Reference
< XLabeledDataSequence
> xCategSeq
)
1761 if( xCategSeq
.is() )
1762 maData
.mnCategCount
= mxCategLink
->ConvertDataSequence( xCategSeq
->getValues(), false );
1765 void XclExpChSeries::WriteSubRecords( XclExpStream
& rStrm
)
1767 lclSaveRecord( rStrm
, mxTitleLink
);
1768 lclSaveRecord( rStrm
, mxValueLink
);
1769 lclSaveRecord( rStrm
, mxCategLink
);
1770 lclSaveRecord( rStrm
, mxBubbleLink
);
1771 lclSaveRecord( rStrm
, mxSeriesFmt
);
1772 maPointFmts
.Save( rStrm
);
1773 if( mnGroupIdx
!= EXC_CHSERGROUP_NONE
)
1774 XclExpUInt16Record( EXC_ID_CHSERGROUP
, mnGroupIdx
).Save( rStrm
);
1775 if( mnParentIdx
!= EXC_CHSERIES_INVALID
)
1776 XclExpUInt16Record( EXC_ID_CHSERPARENT
, mnParentIdx
).Save( rStrm
);
1777 lclSaveRecord( rStrm
, mxTrendLine
);
1778 lclSaveRecord( rStrm
, mxErrorBar
);
1781 void XclExpChSeries::InitFromParent( const XclExpChSeries
& rParent
)
1783 // index to parent series is stored 1-based
1784 mnParentIdx
= rParent
.mnSeriesIdx
+ 1;
1785 /* #i86465# MSO2007 SP1 expects correct point counts in child series
1786 (there was no problem in Excel2003 or Excel2007 without SP1...) */
1787 maData
.mnCategCount
= rParent
.maData
.mnCategCount
;
1788 maData
.mnValueCount
= rParent
.maData
.mnValueCount
;
1791 void XclExpChSeries::CreateTrendLines( XDataSeriesRef xDataSeries
)
1793 Reference
< XRegressionCurveContainer
> xRegCurveCont( xDataSeries
, UNO_QUERY
);
1794 if( xRegCurveCont
.is() )
1796 Sequence
< Reference
< XRegressionCurve
> > aRegCurveSeq
= xRegCurveCont
->getRegressionCurves();
1797 const Reference
< XRegressionCurve
>* pBeg
= aRegCurveSeq
.getConstArray();
1798 const Reference
< XRegressionCurve
>* pEnd
= pBeg
+ aRegCurveSeq
.getLength();
1799 for( const Reference
< XRegressionCurve
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
1801 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
1802 if( xSeries
.is() && !xSeries
->ConvertTrendLine( *this, *pIt
) )
1803 GetChartData().RemoveLastSeries();
1808 void XclExpChSeries::CreateErrorBars( const ScfPropertySet
& rPropSet
,
1809 const OUString
& rBarPropName
, sal_uInt8 nPosBarId
, sal_uInt8 nNegBarId
)
1811 Reference
< XPropertySet
> xErrorBar
;
1812 if( rPropSet
.GetProperty( xErrorBar
, rBarPropName
) && xErrorBar
.is() )
1814 ScfPropertySet
aErrorProp( xErrorBar
);
1815 CreateErrorBar( aErrorProp
, EXC_CHPROP_SHOWPOSITIVEERROR
, nPosBarId
);
1816 CreateErrorBar( aErrorProp
, EXC_CHPROP_SHOWNEGATIVEERROR
, nNegBarId
);
1820 void XclExpChSeries::CreateErrorBar( const ScfPropertySet
& rPropSet
,
1821 const OUString
& rShowPropName
, sal_uInt8 nBarId
)
1823 if( rPropSet
.GetBoolProperty( rShowPropName
) )
1825 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
1826 if( xSeries
.is() && !xSeries
->ConvertErrorBar( *this, rPropSet
, nBarId
) )
1827 GetChartData().RemoveLastSeries();
1831 void XclExpChSeries::WriteBody( XclExpStream
& rStrm
)
1833 rStrm
<< maData
.mnCategType
<< maData
.mnValueType
<< maData
.mnCategCount
<< maData
.mnValueCount
;
1834 if( GetBiff() == EXC_BIFF8
)
1835 rStrm
<< maData
.mnBubbleType
<< maData
.mnBubbleCount
;
1838 // Chart type groups ==========================================================
1840 XclExpChType::XclExpChType( const XclExpChRoot
& rRoot
) :
1841 XclExpRecord( EXC_ID_CHUNKNOWN
),
1842 XclExpChRoot( rRoot
),
1843 maTypeInfo( rRoot
.GetChartTypeInfo( EXC_CHTYPEID_UNKNOWN
) )
1847 void XclExpChType::Convert( Reference
< XDiagram
> xDiagram
, Reference
< XChartType
> xChartType
,
1848 sal_Int32 nApiAxesSetIdx
, bool bSwappedAxesSet
, bool bHasXLabels
)
1850 if( xChartType
.is() )
1852 maTypeInfo
= GetChartTypeInfo( xChartType
->getChartType() );
1853 // special handling for some chart types
1854 switch( maTypeInfo
.meTypeCateg
)
1856 case EXC_CHTYPECATEG_BAR
:
1858 maTypeInfo
= GetChartTypeInfo( bSwappedAxesSet
? EXC_CHTYPEID_HORBAR
: EXC_CHTYPEID_BAR
);
1859 ::set_flag( maData
.mnFlags
, EXC_CHBAR_HORIZONTAL
, bSwappedAxesSet
);
1860 ScfPropertySet
aTypeProp( xChartType
);
1861 Sequence
< sal_Int32
> aInt32Seq
;
1862 maData
.mnOverlap
= 0;
1863 if( aTypeProp
.GetProperty( aInt32Seq
, EXC_CHPROP_OVERLAPSEQ
) && (nApiAxesSetIdx
< aInt32Seq
.getLength()) )
1864 maData
.mnOverlap
= limit_cast
< sal_Int16
>( -aInt32Seq
[ nApiAxesSetIdx
], -100, 100 );
1866 if( aTypeProp
.GetProperty( aInt32Seq
, EXC_CHPROP_GAPWIDTHSEQ
) && (nApiAxesSetIdx
< aInt32Seq
.getLength()) )
1867 maData
.mnGap
= limit_cast
< sal_uInt16
>( aInt32Seq
[ nApiAxesSetIdx
], 0, 500 );
1870 case EXC_CHTYPECATEG_RADAR
:
1871 ::set_flag( maData
.mnFlags
, EXC_CHRADAR_AXISLABELS
, bHasXLabels
);
1873 case EXC_CHTYPECATEG_PIE
:
1875 ScfPropertySet
aTypeProp( xChartType
);
1876 bool bDonut
= aTypeProp
.GetBoolProperty( EXC_CHPROP_USERINGS
);
1877 maTypeInfo
= GetChartTypeInfo( bDonut
? EXC_CHTYPEID_DONUT
: EXC_CHTYPEID_PIE
);
1878 maData
.mnPieHole
= bDonut
? 50 : 0;
1879 // #i85166# starting angle of first pie slice
1880 ScfPropertySet
aDiaProp( xDiagram
);
1881 maData
.mnRotation
= XclExpChRoot::ConvertPieRotation( aDiaProp
);
1884 case EXC_CHTYPECATEG_SCATTER
:
1885 if( GetBiff() == EXC_BIFF8
)
1886 ::set_flag( maData
.mnFlags
, EXC_CHSCATTER_BUBBLES
, maTypeInfo
.meTypeId
== EXC_CHTYPEID_BUBBLES
);
1890 SetRecId( maTypeInfo
.mnRecId
);
1894 void XclExpChType::SetStacked( bool bPercent
)
1896 switch( maTypeInfo
.meTypeCateg
)
1898 case EXC_CHTYPECATEG_LINE
:
1899 ::set_flag( maData
.mnFlags
, EXC_CHLINE_STACKED
);
1900 ::set_flag( maData
.mnFlags
, EXC_CHLINE_PERCENT
, bPercent
);
1902 case EXC_CHTYPECATEG_BAR
:
1903 ::set_flag( maData
.mnFlags
, EXC_CHBAR_STACKED
);
1904 ::set_flag( maData
.mnFlags
, EXC_CHBAR_PERCENT
, bPercent
);
1905 maData
.mnOverlap
= -100;
1911 void XclExpChType::WriteBody( XclExpStream
& rStrm
)
1913 switch( GetRecId() )
1916 rStrm
<< maData
.mnOverlap
<< maData
.mnGap
<< maData
.mnFlags
;
1921 case EXC_ID_CHRADARLINE
:
1922 case EXC_ID_CHRADARAREA
:
1923 rStrm
<< maData
.mnFlags
;
1927 rStrm
<< maData
.mnRotation
<< maData
.mnPieHole
;
1928 if( GetBiff() == EXC_BIFF8
)
1929 rStrm
<< maData
.mnFlags
;
1932 case EXC_ID_CHSCATTER
:
1933 if( GetBiff() == EXC_BIFF8
)
1934 rStrm
<< maData
.mnBubbleSize
<< maData
.mnBubbleType
<< maData
.mnFlags
;
1938 DBG_ERRORFILE( "XclExpChType::WriteBody - unknown chart type" );
1942 // ----------------------------------------------------------------------------
1944 XclExpChChart3d::XclExpChChart3d() :
1945 XclExpRecord( EXC_ID_CHCHART3D
, 14 )
1949 void XclExpChChart3d::Convert( const ScfPropertySet
& rPropSet
, bool b3dWallChart
)
1951 sal_Int32 nRotationY
= 0;
1952 rPropSet
.GetProperty( nRotationY
, EXC_CHPROP_ROTATIONVERTICAL
);
1953 sal_Int32 nRotationX
= 0;
1954 rPropSet
.GetProperty( nRotationX
, EXC_CHPROP_ROTATIONHORIZONTAL
);
1955 sal_Int32 nPerspective
= 15;
1956 rPropSet
.GetProperty( nPerspective
, EXC_CHPROP_PERSPECTIVE
);
1960 // Y rotation (Excel [0..359], Chart2 [-179,180])
1961 if( nRotationY
< 0 ) nRotationY
+= 360;
1962 maData
.mnRotation
= static_cast< sal_uInt16
>( nRotationY
);
1963 // X rotation a.k.a. elevation (Excel [-90..90], Chart2 [-179,180])
1964 maData
.mnElevation
= limit_cast
< sal_Int16
>( nRotationX
, -90, 90 );
1965 // perspective (Excel and Chart2 [0,100])
1966 maData
.mnEyeDist
= limit_cast
< sal_uInt16
>( nPerspective
, 0, 100 );
1969 ::set_flag( maData
.mnFlags
, EXC_CHCHART3D_REAL3D
, !rPropSet
.GetBoolProperty( EXC_CHPROP_RIGHTANGLEDAXES
) );
1970 ::set_flag( maData
.mnFlags
, EXC_CHCHART3D_AUTOHEIGHT
);
1971 ::set_flag( maData
.mnFlags
, EXC_CHCHART3D_HASWALLS
);
1975 // Y rotation not used in pie charts, but 'first pie slice angle'
1976 maData
.mnRotation
= XclExpChRoot::ConvertPieRotation( rPropSet
);
1977 // X rotation a.k.a. elevation (map Chart2 [-80,-10] to Excel [10..80])
1978 maData
.mnElevation
= limit_cast
< sal_Int16
>( (nRotationX
+ 270) % 180, 10, 80 );
1979 // perspective (Excel and Chart2 [0,100])
1980 maData
.mnEyeDist
= limit_cast
< sal_uInt16
>( nPerspective
, 0, 100 );
1986 void XclExpChChart3d::WriteBody( XclExpStream
& rStrm
)
1988 rStrm
<< maData
.mnRotation
1989 << maData
.mnElevation
1991 << maData
.mnRelHeight
1992 << maData
.mnRelDepth
1993 << maData
.mnDepthGap
1997 // ----------------------------------------------------------------------------
1999 XclExpChLegend::XclExpChLegend( const XclExpChRoot
& rRoot
) :
2000 XclExpChGroupBase( EXC_ID_CHLEGEND
, 20 ),
2001 XclExpChRoot( rRoot
)
2005 void XclExpChLegend::Convert( const ScfPropertySet
& rPropSet
)
2008 mxFrame
= lclCreateFrame( GetChRoot(), rPropSet
, EXC_CHOBJTYPE_LEGEND
);
2010 mxText
.reset( new XclExpChText( GetChRoot() ) );
2011 mxText
->ConvertLegend( rPropSet
);
2012 // special legend properties
2013 GetChartPropSetHelper().ReadLegendProperties( maData
, rPropSet
);
2016 void XclExpChLegend::WriteSubRecords( XclExpStream
& rStrm
)
2018 lclSaveRecord( rStrm
, mxText
);
2019 lclSaveRecord( rStrm
, mxFrame
);
2022 void XclExpChLegend::WriteBody( XclExpStream
& rStrm
)
2024 rStrm
<< maData
.maRect
<< maData
.mnDockMode
<< maData
.mnSpacing
<< maData
.mnFlags
;
2027 // ----------------------------------------------------------------------------
2029 XclExpChDropBar::XclExpChDropBar( XclChObjectType eObjType
) :
2030 XclExpChGroupBase( EXC_ID_CHDROPBAR
, 2 ),
2031 meObjType( eObjType
),
2036 void XclExpChDropBar::Convert( const XclExpChRoot
& rRoot
, const ScfPropertySet
& rPropSet
)
2039 ConvertFrameBase( rRoot
, rPropSet
, meObjType
);
2041 SetDefaultFrameBase( rRoot
, EXC_CHFRAMETYPE_INVISIBLE
, true );
2044 void XclExpChDropBar::WriteSubRecords( XclExpStream
& rStrm
)
2046 WriteFrameRecords( rStrm
);
2049 void XclExpChDropBar::WriteBody( XclExpStream
& rStrm
)
2054 // ----------------------------------------------------------------------------
2056 XclExpChTypeGroup::XclExpChTypeGroup( const XclExpChRoot
& rRoot
, sal_uInt16 nGroupIdx
) :
2057 XclExpChGroupBase( EXC_ID_CHTYPEGROUP
, 20 ),
2058 XclExpChRoot( rRoot
),
2060 maTypeInfo( maType
.GetTypeInfo() )
2062 maData
.mnGroupIdx
= nGroupIdx
;
2065 void XclExpChTypeGroup::ConvertType(
2066 Reference
< XDiagram
> xDiagram
, Reference
< XChartType
> xChartType
,
2067 sal_Int32 nApiAxesSetIdx
, bool b3dChart
, bool bSwappedAxesSet
, bool bHasXLabels
)
2069 // chart type settings
2070 maType
.Convert( xDiagram
, xChartType
, nApiAxesSetIdx
, bSwappedAxesSet
, bHasXLabels
);
2072 // spline - TODO: get from single series (#i66858#)
2073 ScfPropertySet
aTypeProp( xChartType
);
2074 ::com::sun::star::chart2::CurveStyle eCurveStyle
;
2075 bool bSpline
= aTypeProp
.GetProperty( eCurveStyle
, EXC_CHPROP_CURVESTYLE
) &&
2076 (eCurveStyle
!= ::com::sun::star::chart2::CurveStyle_LINES
);
2078 // extended type info
2079 maTypeInfo
.Set( maType
.GetTypeInfo(), b3dChart
, bSpline
);
2081 // 3d chart settings
2082 if( maTypeInfo
.mb3dChart
) // only true, if Excel chart supports 3d mode
2084 mxChart3d
.reset( new XclExpChChart3d
);
2085 ScfPropertySet
aDiaProp( xDiagram
);
2086 mxChart3d
->Convert( aDiaProp
, Is3dWallChart() );
2090 void XclExpChTypeGroup::ConvertSeries(
2091 Reference
< XDiagram
> xDiagram
, Reference
< XChartType
> xChartType
,
2092 sal_Int32 nGroupAxesSetIdx
, bool bPercent
, bool bConnectBars
)
2094 Reference
< XDataSeriesContainer
> xSeriesCont( xChartType
, UNO_QUERY
);
2095 if( xSeriesCont
.is() )
2097 typedef ::std::vector
< Reference
< XDataSeries
> > XDataSeriesVec
;
2098 XDataSeriesVec aSeriesVec
;
2100 // copy data series attached to the current axes set to the vector
2101 Sequence
< Reference
< XDataSeries
> > aSeriesSeq
= xSeriesCont
->getDataSeries();
2102 const Reference
< XDataSeries
>* pBeg
= aSeriesSeq
.getConstArray();
2103 const Reference
< XDataSeries
>* pEnd
= pBeg
+ aSeriesSeq
.getLength();
2104 for( const Reference
< XDataSeries
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
2106 ScfPropertySet
aSeriesProp( *pIt
);
2107 sal_Int32
nSeriesAxesSetIdx(0);
2108 if( aSeriesProp
.GetProperty( nSeriesAxesSetIdx
, EXC_CHPROP_ATTAXISINDEX
) && (nSeriesAxesSetIdx
== nGroupAxesSetIdx
) )
2109 aSeriesVec
.push_back( *pIt
);
2112 // Are there any series in the current axes set?
2113 if( !aSeriesVec
.empty() )
2115 // stacking direction (stacked/percent/deep 3d) from first series
2116 ScfPropertySet
aSeriesProp( aSeriesVec
.front() );
2117 namespace cssc
= ::com::sun::star::chart2
;
2118 cssc::StackingDirection eStacking
;
2119 if( !aSeriesProp
.GetProperty( eStacking
, EXC_CHPROP_STACKINGDIR
) )
2120 eStacking
= cssc::StackingDirection_NO_STACKING
;
2122 // stacked or percent chart
2123 if( maTypeInfo
.mbSupportsStacking
&& (eStacking
== cssc::StackingDirection_Y_STACKING
) )
2125 // percent overrides simple stacking
2126 maType
.SetStacked( bPercent
);
2128 // connected data points (only in stacked bar charts)
2129 if( bConnectBars
&& (maTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_BAR
) )
2130 maChartLines
[ EXC_CHCHARTLINE_CONNECT
].reset( new XclExpChLineFormat( GetChRoot() ) );
2134 // reverse series order for some unstacked 2D chart types
2135 if( maTypeInfo
.mbReverseSeries
&& !Is3dChart() )
2136 ::std::reverse( aSeriesVec
.begin(), aSeriesVec
.end() );
2139 // deep 3d chart or clustered 3d chart (stacked is not clustered)
2140 if( (eStacking
== cssc::StackingDirection_NO_STACKING
) && Is3dWallChart() )
2141 mxChart3d
->SetClustered();
2143 // varied point colors
2144 ::set_flag( maData
.mnFlags
, EXC_CHTYPEGROUP_VARIEDCOLORS
, aSeriesProp
.GetBoolProperty( EXC_CHPROP_VARYCOLORSBY
) );
2146 // process all series
2147 for( XDataSeriesVec::const_iterator aIt
= aSeriesVec
.begin(), aEnd
= aSeriesVec
.end(); aIt
!= aEnd
; ++aIt
)
2149 // create Excel series object, stock charts need special processing
2150 if( maTypeInfo
.meTypeId
== EXC_CHTYPEID_STOCK
)
2151 CreateAllStockSeries( xChartType
, *aIt
);
2153 CreateDataSeries( xDiagram
, *aIt
);
2159 void XclExpChTypeGroup::ConvertCategSequence( Reference
< XLabeledDataSequence
> xCategSeq
)
2161 for( size_t nIdx
= 0, nSize
= maSeries
.GetSize(); nIdx
< nSize
; ++nIdx
)
2162 maSeries
.GetRecord( nIdx
)->ConvertCategSequence( xCategSeq
);
2165 void XclExpChTypeGroup::ConvertLegend( const ScfPropertySet
& rPropSet
)
2167 if( rPropSet
.GetBoolProperty( EXC_CHPROP_SHOW
) )
2169 mxLegend
.reset( new XclExpChLegend( GetChRoot() ) );
2170 mxLegend
->Convert( rPropSet
);
2174 void XclExpChTypeGroup::WriteSubRecords( XclExpStream
& rStrm
)
2176 maType
.Save( rStrm
);
2177 lclSaveRecord( rStrm
, mxChart3d
);
2178 lclSaveRecord( rStrm
, mxLegend
);
2179 lclSaveRecord( rStrm
, mxUpBar
);
2180 lclSaveRecord( rStrm
, mxDownBar
);
2181 for( XclExpChLineFormatMap::iterator aLIt
= maChartLines
.begin(), aLEnd
= maChartLines
.end(); aLIt
!= aLEnd
; ++aLIt
)
2182 lclSaveRecord( rStrm
, aLIt
->second
, EXC_ID_CHCHARTLINE
, aLIt
->first
);
2185 sal_uInt16
XclExpChTypeGroup::GetFreeFormatIdx() const
2187 return static_cast< sal_uInt16
>( maSeries
.GetSize() );
2190 void XclExpChTypeGroup::CreateDataSeries(
2191 Reference
< XDiagram
> xDiagram
, Reference
< XDataSeries
> xDataSeries
)
2193 // let chart create series object with correct series index
2194 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
2197 if( xSeries
->ConvertDataSeries( xDiagram
, xDataSeries
, maTypeInfo
, GetGroupIdx(), GetFreeFormatIdx() ) )
2198 maSeries
.AppendRecord( xSeries
);
2200 GetChartData().RemoveLastSeries();
2204 void XclExpChTypeGroup::CreateAllStockSeries(
2205 Reference
< XChartType
> xChartType
, Reference
< XDataSeries
> xDataSeries
)
2207 // create existing series objects
2208 bool bHasOpen
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_OPENVALUES
, false );
2209 bool bHasHigh
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_HIGHVALUES
, false );
2210 bool bHasLow
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_LOWVALUES
, false );
2211 bool bHasClose
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_CLOSEVALUES
, !bHasOpen
);
2213 // formatting of special stock chart elements
2214 ScfPropertySet
aTypeProp( xChartType
);
2216 if( bHasHigh
&& bHasLow
&& aTypeProp
.GetBoolProperty( EXC_CHPROP_SHOWHIGHLOW
) )
2218 ScfPropertySet
aSeriesProp( xDataSeries
);
2219 XclExpChLineFormatRef
xLineFmt( new XclExpChLineFormat( GetChRoot() ) );
2220 xLineFmt
->Convert( GetChRoot(), aSeriesProp
, EXC_CHOBJTYPE_HILOLINE
);
2221 maChartLines
[ EXC_CHCHARTLINE_HILO
] = xLineFmt
;
2224 if( bHasOpen
&& bHasClose
)
2226 // dropbar type is dependent on position in the file - always create both
2227 Reference
< XPropertySet
> xWhitePropSet
, xBlackPropSet
;
2228 // white dropbar format
2229 aTypeProp
.GetProperty( xWhitePropSet
, EXC_CHPROP_WHITEDAY
);
2230 ScfPropertySet
aWhiteProp( xWhitePropSet
);
2231 mxUpBar
.reset( new XclExpChDropBar( EXC_CHOBJTYPE_WHITEDROPBAR
) );
2232 mxUpBar
->Convert( GetChRoot(), aWhiteProp
);
2233 // black dropbar format
2234 aTypeProp
.GetProperty( xBlackPropSet
, EXC_CHPROP_BLACKDAY
);
2235 ScfPropertySet
aBlackProp( xBlackPropSet
);
2236 mxDownBar
.reset( new XclExpChDropBar( EXC_CHOBJTYPE_BLACKDROPBAR
) );
2237 mxDownBar
->Convert( GetChRoot(), aBlackProp
);
2241 bool XclExpChTypeGroup::CreateStockSeries( Reference
< XDataSeries
> xDataSeries
,
2242 const OUString
& rValueRole
, bool bCloseSymbol
)
2245 // let chart create series object with correct series index
2246 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
2249 bOk
= xSeries
->ConvertStockSeries( xDataSeries
,
2250 rValueRole
, GetGroupIdx(), GetFreeFormatIdx(), bCloseSymbol
);
2252 maSeries
.AppendRecord( xSeries
);
2254 GetChartData().RemoveLastSeries();
2259 void XclExpChTypeGroup::WriteBody( XclExpStream
& rStrm
)
2261 rStrm
<< maData
.maRect
<< maData
.mnFlags
<< maData
.mnGroupIdx
;
2264 // Axes =======================================================================
2266 XclExpChLabelRange::XclExpChLabelRange( const XclExpChRoot
& rRoot
) :
2267 XclExpRecord( EXC_ID_CHLABELRANGE
, 8 ),
2268 XclExpChRoot( rRoot
)
2272 void XclExpChLabelRange::Convert( const ScaleData
& rScaleData
, bool bMirrorOrient
)
2275 double fOrigin
= 0.0;
2276 if( !lclIsAutoAnyOrGetValue( fOrigin
, rScaleData
.Origin
, false ) )
2277 maData
.mnCross
= limit_cast
< sal_uInt16
>( fOrigin
, 1, 32767 );
2280 if( (rScaleData
.Orientation
== ::com::sun::star::chart2::AxisOrientation_REVERSE
) != bMirrorOrient
)
2282 ::set_flag( maData
.mnFlags
, EXC_CHLABELRANGE_REVERSE
);
2287 void XclExpChLabelRange::WriteBody( XclExpStream
& rStrm
)
2289 rStrm
<< maData
.mnCross
<< maData
.mnLabelFreq
<< maData
.mnTickFreq
<< maData
.mnFlags
;
2292 // ----------------------------------------------------------------------------
2294 XclExpChValueRange::XclExpChValueRange( const XclExpChRoot
& rRoot
) :
2295 XclExpRecord( EXC_ID_CHVALUERANGE
, 42 ),
2296 XclExpChRoot( rRoot
)
2300 void XclExpChValueRange::Convert( const ScaleData
& rScaleData
, bool bPercent
)
2302 // scaling algorithm
2303 bool bLogScale
= ScfApiHelper::GetServiceName( rScaleData
.Scaling
) == SERVICE_CHART2_LOGSCALING
;
2304 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_LOGSCALE
, bLogScale
);
2305 Reference
< XScaling
> xLogScaling
;
2307 xLogScaling
= rScaleData
.Scaling
;
2310 bool bAutoMin
= lclIsAutoAnyOrGetScaledValue( maData
.mfMin
, rScaleData
.Minimum
, xLogScaling
, bPercent
);
2311 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMIN
, bAutoMin
);
2312 bool bAutoMax
= lclIsAutoAnyOrGetScaledValue( maData
.mfMax
, rScaleData
.Maximum
, xLogScaling
, bPercent
);
2313 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMAX
, bAutoMax
);
2316 bool bAutoCross
= lclIsAutoAnyOrGetScaledValue( maData
.mfCross
, rScaleData
.Origin
, xLogScaling
, bPercent
);
2317 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
, bAutoCross
);
2320 const IncrementData
& rIncrementData
= rScaleData
.IncrementData
;
2321 bool bAutoMajor
= lclIsAutoAnyOrGetValue( maData
.mfMajorStep
, rIncrementData
.Distance
, bPercent
) || (maData
.mfMajorStep
<= 0.0);
2322 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMAJOR
, bAutoMajor
);
2324 const Sequence
< SubIncrement
>& rSubIncrementSeq
= rIncrementData
.SubIncrements
;
2325 sal_Int32 nCount
= 0;
2326 bool bAutoMinor
= bAutoMajor
|| (rSubIncrementSeq
.getLength() < 1) ||
2327 lclIsAutoAnyOrGetValue( nCount
, rSubIncrementSeq
[ 0 ].IntervalCount
, false ) || (nCount
< 1);
2329 maData
.mfMinorStep
= maData
.mfMajorStep
/ nCount
;
2330 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMINOR
, bAutoMinor
);
2333 namespace cssc
= ::com::sun::star::chart2
;
2334 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_REVERSE
, rScaleData
.Orientation
== cssc::AxisOrientation_REVERSE
);
2337 void XclExpChValueRange::WriteBody( XclExpStream
& rStrm
)
2339 rStrm
<< maData
.mfMin
2341 << maData
.mfMajorStep
2342 << maData
.mfMinorStep
2347 // ----------------------------------------------------------------------------
2351 sal_uInt8
lclGetXclTickPos( sal_Int32 nApiTickmarks
)
2353 using namespace ::com::sun::star::chart2::TickmarkStyle
;
2354 sal_uInt8 nXclTickPos
= 0;
2355 ::set_flag( nXclTickPos
, EXC_CHTICK_INSIDE
, ::get_flag( nApiTickmarks
, INNER
) );
2356 ::set_flag( nXclTickPos
, EXC_CHTICK_OUTSIDE
, ::get_flag( nApiTickmarks
, OUTER
) );
2362 XclExpChTick::XclExpChTick( const XclExpChRoot
& rRoot
) :
2363 XclExpRecord( EXC_ID_CHTICK
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 30 : 26 ),
2364 XclExpChRoot( rRoot
),
2365 mnTextColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
2369 void XclExpChTick::Convert( const ScfPropertySet
& rPropSet
)
2372 sal_Int32
nApiTickmarks(0);
2373 if( rPropSet
.GetProperty( nApiTickmarks
, EXC_CHPROP_MAJORTICKS
) )
2374 maData
.mnMajor
= lclGetXclTickPos( nApiTickmarks
);
2375 if( rPropSet
.GetProperty( nApiTickmarks
, EXC_CHPROP_MINORTICKS
) )
2376 maData
.mnMinor
= lclGetXclTickPos( nApiTickmarks
);
2379 void XclExpChTick::SetFontColor( const Color
& rColor
, sal_uInt32 nColorId
)
2381 maData
.maTextColor
= rColor
;
2382 ::set_flag( maData
.mnFlags
, EXC_CHTICK_AUTOCOLOR
, rColor
== COL_AUTO
);
2383 mnTextColorId
= nColorId
;
2386 void XclExpChTick::SetRotation( sal_uInt16 nRotation
)
2388 maData
.mnRotation
= nRotation
;
2389 ::set_flag( maData
.mnFlags
, EXC_CHTICK_AUTOROT
, false );
2390 ::insert_value( maData
.mnFlags
, XclTools::GetXclOrientFromRot( nRotation
), 2, 3 );
2393 void XclExpChTick::WriteBody( XclExpStream
& rStrm
)
2395 rStrm
<< maData
.mnMajor
2397 << maData
.mnLabelPos
2398 << maData
.mnBackMode
2400 << maData
.maTextColor
2402 if( GetBiff() == EXC_BIFF8
)
2403 rStrm
<< GetPalette().GetColorIndex( mnTextColorId
) << maData
.mnRotation
;
2406 // ----------------------------------------------------------------------------
2410 /** Returns an API axis object from the passed coordinate system. */
2411 Reference
< XAxis
> lclGetApiAxis( Reference
< XCoordinateSystem
> xCoordSystem
,
2412 sal_Int32 nApiAxisDim
, sal_Int32 nApiAxesSetIdx
)
2414 Reference
< XAxis
> xAxis
;
2417 if( xCoordSystem
.is() )
2418 xAxis
= xCoordSystem
->getAxisByDimension( nApiAxisDim
, nApiAxesSetIdx
);
2428 XclExpChAxis::XclExpChAxis( const XclExpChRoot
& rRoot
, sal_uInt16 nAxisType
) :
2429 XclExpChGroupBase( EXC_ID_CHAXIS
, 18 ),
2430 XclExpChRoot( rRoot
),
2431 mnNumFmtIdx( EXC_FORMAT_NOTFOUND
)
2433 maData
.mnType
= nAxisType
;
2436 void XclExpChAxis::SetFont( XclExpChFontRef xFont
, const Color
& rColor
, sal_uInt32 nColorId
)
2440 mxTick
->SetFontColor( rColor
, nColorId
);
2443 void XclExpChAxis::SetRotation( sal_uInt16 nRotation
)
2446 mxTick
->SetRotation( nRotation
);
2449 void XclExpChAxis::Convert( Reference
< XAxis
> xAxis
, const XclChExtTypeInfo
& rTypeInfo
, sal_Int32 nApiAxesSetIdx
,
2452 ScfPropertySet
aAxisProp( xAxis
);
2453 bool bCategoryAxis
= ((GetAxisType() == EXC_CHAXIS_X
) && rTypeInfo
.mbCategoryAxis
) || (GetAxisType() == EXC_CHAXIS_Z
);
2455 // axis line format -------------------------------------------------------
2457 mxAxisLine
.reset( new XclExpChLineFormat( GetChRoot() ) );
2458 mxAxisLine
->Convert( GetChRoot(), aAxisProp
, EXC_CHOBJTYPE_AXISLINE
);
2459 // #i58688# axis enabled
2460 mxAxisLine
->SetShowAxis( aAxisProp
.GetBoolProperty( EXC_CHPROP_SHOW
) );
2462 // axis scaling and increment ---------------------------------------------
2466 mxLabelRange
.reset( new XclExpChLabelRange( GetChRoot() ) );
2467 mxLabelRange
->SetTicksBetweenCateg( rTypeInfo
.mbTicksBetweenCateg
);
2469 // #i71684# radar charts have reversed rotation direction
2470 mxLabelRange
->Convert( xAxis
->getScaleData(), (GetAxisType() == EXC_CHAXIS_X
) && (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_RADAR
) );
2471 // swap max-cross flag for secondary X axis to have the secondary Y axis at right side
2472 if( (GetAxisType() == EXC_CHAXIS_X
) && (nApiAxesSetIdx
== EXC_CHAXESSET_SECONDARY
) )
2473 mxLabelRange
->SwapAxisMaxCross();
2477 mxValueRange
.reset( new XclExpChValueRange( GetChRoot() ) );
2479 mxValueRange
->Convert( xAxis
->getScaleData(), bPercent
);
2482 // axis caption text ------------------------------------------------------
2484 // axis ticks properties
2485 mxTick
.reset( new XclExpChTick( GetChRoot() ) );
2486 mxTick
->Convert( aAxisProp
);
2488 // existence and position of axis labels
2489 sal_uInt8 nLabelPos
= EXC_CHTICK_NOLABEL
;
2490 if( rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_RADAR
)
2491 /* Radar charts disable their category labels via chart type, not via
2492 axis, and axis labels are always 'near axis' in Chart2. */
2493 nLabelPos
= EXC_CHTICK_NEXT
;
2494 else if( aAxisProp
.GetBoolProperty( EXC_CHPROP_DISPLAYLABELS
) )
2495 /* #i85862# Axis labels in other chart types always have position 'low'
2496 in Chart2, but Excel expects 'near axis' at Y axes in 3D charts. */
2497 nLabelPos
= (rTypeInfo
.mb3dChart
&& (GetAxisType() == EXC_CHAXIS_Y
)) ? EXC_CHTICK_NEXT
: EXC_CHTICK_LOW
;
2498 mxTick
->SetLabelPos( nLabelPos
);
2500 // axis label formatting and rotation
2501 ConvertFontBase( GetChRoot(), aAxisProp
);
2502 ConvertRotationBase( GetChRoot(), aAxisProp
);
2504 // axis number format
2505 sal_Int32 nApiNumFmt
= 0;
2506 if( !bCategoryAxis
&& aAxisProp
.GetProperty( nApiNumFmt
, EXC_CHPROP_NUMBERFORMAT
) )
2507 mnNumFmtIdx
= GetNumFmtBuffer().Insert( static_cast< sal_uInt32
>( nApiNumFmt
) );
2509 // grid -------------------------------------------------------------------
2514 ScfPropertySet
aGridProp( xAxis
->getGridProperties() );
2515 if( aGridProp
.GetBoolProperty( EXC_CHPROP_SHOW
) )
2516 mxMajorGrid
= lclCreateLineFormat( GetChRoot(), aGridProp
, EXC_CHOBJTYPE_GRIDLINE
);
2518 Sequence
< Reference
< XPropertySet
> > aSubGridPropSeq
= xAxis
->getSubGridProperties();
2519 if( aSubGridPropSeq
.hasElements() )
2521 ScfPropertySet
aSubGridProp( aSubGridPropSeq
[ 0 ] );
2522 if( aSubGridProp
.GetBoolProperty( EXC_CHPROP_SHOW
) )
2523 mxMinorGrid
= lclCreateLineFormat( GetChRoot(), aSubGridProp
, EXC_CHOBJTYPE_GRIDLINE
);
2528 void XclExpChAxis::ConvertWall( XDiagramRef xDiagram
)
2530 if( xDiagram
.is() ) switch( GetAxisType() )
2534 ScfPropertySet
aWallProp( xDiagram
->getWall() );
2535 mxWallFrame
= lclCreateFrame( GetChRoot(), aWallProp
, EXC_CHOBJTYPE_WALL3D
);
2540 ScfPropertySet
aFloorProp( xDiagram
->getFloor() );
2541 mxWallFrame
= lclCreateFrame( GetChRoot(), aFloorProp
, EXC_CHOBJTYPE_FLOOR3D
);
2545 mxWallFrame
.reset();
2549 void XclExpChAxis::WriteSubRecords( XclExpStream
& rStrm
)
2551 lclSaveRecord( rStrm
, mxLabelRange
);
2552 lclSaveRecord( rStrm
, mxValueRange
);
2553 if( mnNumFmtIdx
!= EXC_FORMAT_NOTFOUND
)
2554 XclExpUInt16Record( EXC_ID_CHFORMAT
, mnNumFmtIdx
).Save( rStrm
);
2555 lclSaveRecord( rStrm
, mxTick
);
2556 lclSaveRecord( rStrm
, mxFont
);
2557 lclSaveRecord( rStrm
, mxAxisLine
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_AXISLINE
);
2558 lclSaveRecord( rStrm
, mxMajorGrid
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_MAJORGRID
);
2559 lclSaveRecord( rStrm
, mxMinorGrid
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_MINORGRID
);
2560 lclSaveRecord( rStrm
, mxWallFrame
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_WALLS
);
2563 void XclExpChAxis::WriteBody( XclExpStream
& rStrm
)
2565 rStrm
<< maData
.mnType
<< maData
.maRect
;
2568 // ----------------------------------------------------------------------------
2570 XclExpChAxesSet::XclExpChAxesSet( const XclExpChRoot
& rRoot
, sal_uInt16 nAxesSetId
) :
2571 XclExpChGroupBase( EXC_ID_CHAXESSET
, 18 ),
2572 XclExpChRoot( rRoot
)
2574 maData
.mnAxesSetId
= nAxesSetId
;
2577 sal_uInt16
XclExpChAxesSet::Convert( Reference
< XDiagram
> xDiagram
, sal_uInt16 nFirstGroupIdx
)
2579 /* First unused chart type group index is passed to be able to continue
2580 counting of chart type groups for secondary axes set. */
2581 sal_uInt16 nGroupIdx
= nFirstGroupIdx
;
2582 Reference
< XCoordinateSystemContainer
> xCoordSysCont( xDiagram
, UNO_QUERY
);
2583 if( xCoordSysCont
.is() )
2585 Sequence
< Reference
< XCoordinateSystem
> > aCoordSysSeq
= xCoordSysCont
->getCoordinateSystems();
2586 if( aCoordSysSeq
.getLength() > 0 )
2588 /* Process first coordinate system only. Import filter puts all
2589 chart types into one coordinate system. */
2590 Reference
< XCoordinateSystem
> xCoordSystem
= aCoordSysSeq
[ 0 ];
2591 sal_Int32 nApiAxesSetIdx
= GetApiAxesSetIndex();
2594 bool b3dChart
= xCoordSystem
.is() && (xCoordSystem
->getDimension() == 3);
2597 namespace ApiAxisType
= ::com::sun::star::chart2::AxisType
;
2598 Reference
< XAxis
> xApiYAxis
= lclGetApiAxis( xCoordSystem
, EXC_CHART_AXIS_Y
, nApiAxesSetIdx
);
2599 bool bPercent
= xApiYAxis
.is() && (xApiYAxis
->getScaleData().AxisType
== ApiAxisType::PERCENT
);
2601 // connector lines in bar charts
2602 ScfPropertySet
aDiaProp( xDiagram
);
2603 bool bConnectBars
= aDiaProp
.GetBoolProperty( EXC_CHPROP_CONNECTBARS
);
2605 // swapped axes sets
2606 ScfPropertySet
aCoordSysProp( xCoordSystem
);
2607 bool bSwappedAxesSet
= aCoordSysProp
.GetBoolProperty( EXC_CHPROP_SWAPXANDYAXIS
);
2609 // X axis for later use
2610 Reference
< XAxis
> xApiXAxis
= lclGetApiAxis( xCoordSystem
, EXC_CHART_AXIS_X
, nApiAxesSetIdx
);
2612 ScfPropertySet
aXAxisProp( xApiXAxis
);
2613 bool bHasXLabels
= aXAxisProp
.GetBoolProperty( EXC_CHPROP_DISPLAYLABELS
);
2615 // process chart types
2616 Reference
< XChartTypeContainer
> xChartTypeCont( xCoordSystem
, UNO_QUERY
);
2617 if( xChartTypeCont
.is() )
2619 Sequence
< Reference
< XChartType
> > aChartTypeSeq
= xChartTypeCont
->getChartTypes();
2620 const Reference
< XChartType
>* pBeg
= aChartTypeSeq
.getConstArray();
2621 const Reference
< XChartType
>* pEnd
= pBeg
+ aChartTypeSeq
.getLength();
2622 for( const Reference
< XChartType
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
2624 XclExpChTypeGroupRef
xTypeGroup( new XclExpChTypeGroup( GetChRoot(), nGroupIdx
) );
2625 xTypeGroup
->ConvertType( xDiagram
, *pIt
, nApiAxesSetIdx
, b3dChart
, bSwappedAxesSet
, bHasXLabels
);
2626 /* If new chart type group cannot be inserted into a combination
2627 chart with existing type groups, insert all series into last
2628 contained chart type group instead of creating a new group. */
2629 XclExpChTypeGroupRef xLastGroup
= GetLastTypeGroup();
2630 if( xLastGroup
.is() && !(xTypeGroup
->IsCombinable2d() && xLastGroup
->IsCombinable2d()) )
2632 xLastGroup
->ConvertSeries( xDiagram
, *pIt
, nApiAxesSetIdx
, bPercent
, bConnectBars
);
2636 xTypeGroup
->ConvertSeries( xDiagram
, *pIt
, nApiAxesSetIdx
, bPercent
, bConnectBars
);
2637 if( xTypeGroup
->IsValidGroup() )
2639 maTypeGroups
.AppendRecord( xTypeGroup
);
2646 if( XclExpChTypeGroup
* pGroup
= GetFirstTypeGroup().get() )
2648 const XclChExtTypeInfo
& rTypeInfo
= pGroup
->GetTypeInfo();
2650 // create axes according to chart type (no axes for pie and donut charts)
2651 if( rTypeInfo
.meTypeCateg
!= EXC_CHTYPECATEG_PIE
)
2653 ConvertAxis( mxXAxis
, EXC_CHAXIS_X
, mxXAxisTitle
, EXC_CHOBJLINK_XAXIS
, xCoordSystem
, rTypeInfo
, bPercent
);
2654 ConvertAxis( mxYAxis
, EXC_CHAXIS_Y
, mxYAxisTitle
, EXC_CHOBJLINK_YAXIS
, xCoordSystem
, rTypeInfo
, bPercent
);
2655 if( pGroup
->Is3dDeepChart() )
2656 ConvertAxis( mxZAxis
, EXC_CHAXIS_Z
, mxZAxisTitle
, EXC_CHOBJLINK_ZAXIS
, xCoordSystem
, rTypeInfo
, bPercent
);
2659 // X axis category ranges
2660 if( rTypeInfo
.mbCategoryAxis
&& xApiXAxis
.is() )
2662 const ScaleData aScaleData
= xApiXAxis
->getScaleData();
2663 for( size_t nIdx
= 0, nSize
= maTypeGroups
.GetSize(); nIdx
< nSize
; ++nIdx
)
2664 maTypeGroups
.GetRecord( nIdx
)->ConvertCategSequence( aScaleData
.Categories
);
2668 if( xDiagram
.is() && (GetAxesSetId() == EXC_CHAXESSET_PRIMARY
) )
2670 Reference
< XLegend
> xLegend
= xDiagram
->getLegend();
2673 ScfPropertySet
aLegendProp( xLegend
);
2674 pGroup
->ConvertLegend( aLegendProp
);
2681 // wall/floor/diagram frame formatting
2682 if( xDiagram
.is() && (GetAxesSetId() == EXC_CHAXESSET_PRIMARY
) )
2684 XclExpChTypeGroupRef xTypeGroup
= GetFirstTypeGroup();
2685 if( xTypeGroup
.is() && xTypeGroup
->Is3dWallChart() )
2687 // wall/floor formatting (3D charts)
2689 mxXAxis
->ConvertWall( xDiagram
);
2691 mxYAxis
->ConvertWall( xDiagram
);
2695 // diagram background formatting
2696 ScfPropertySet
aWallProp( xDiagram
->getWall() );
2697 mxPlotFrame
= lclCreateFrame( GetChRoot(), aWallProp
, EXC_CHOBJTYPE_PLOTFRAME
);
2701 // return first unused chart type group index for next axes set
2705 bool XclExpChAxesSet::Is3dChart() const
2707 XclExpChTypeGroupRef xTypeGroup
= GetFirstTypeGroup();
2708 return xTypeGroup
.is() && xTypeGroup
->Is3dChart();
2711 void XclExpChAxesSet::WriteSubRecords( XclExpStream
& rStrm
)
2713 lclSaveRecord( rStrm
, mxXAxis
);
2714 lclSaveRecord( rStrm
, mxYAxis
);
2715 lclSaveRecord( rStrm
, mxZAxis
);
2716 lclSaveRecord( rStrm
, mxXAxisTitle
);
2717 lclSaveRecord( rStrm
, mxYAxisTitle
);
2718 lclSaveRecord( rStrm
, mxZAxisTitle
);
2719 if( mxPlotFrame
.is() )
2721 XclExpEmptyRecord( EXC_ID_CHPLOTFRAME
).Save( rStrm
);
2722 mxPlotFrame
->Save( rStrm
);
2724 maTypeGroups
.Save( rStrm
);
2727 XclExpChTypeGroupRef
XclExpChAxesSet::GetFirstTypeGroup() const
2729 return maTypeGroups
.GetFirstRecord();
2732 XclExpChTypeGroupRef
XclExpChAxesSet::GetLastTypeGroup() const
2734 return maTypeGroups
.GetLastRecord();
2737 void XclExpChAxesSet::ConvertAxis(
2738 XclExpChAxisRef
& rxChAxis
, sal_uInt16 nAxisType
,
2739 XclExpChTextRef
& rxChAxisTitle
, sal_uInt16 nTitleTarget
,
2740 Reference
< XCoordinateSystem
> xCoordSystem
, const XclChExtTypeInfo
& rTypeInfo
,
2743 // create and convert axis object
2744 rxChAxis
.reset( new XclExpChAxis( GetChRoot(), nAxisType
) );
2745 sal_Int32 nApiAxisDim
= rxChAxis
->GetApiAxisDimension();
2746 sal_Int32 nApiAxesSetIdx
= GetApiAxesSetIndex();
2747 Reference
< XAxis
> xAxis
= lclGetApiAxis( xCoordSystem
, nApiAxisDim
, nApiAxesSetIdx
);
2748 rxChAxis
->Convert( xAxis
, rTypeInfo
, nApiAxesSetIdx
, bPercent
);
2750 // create and convert axis title
2751 Reference
< XTitled
> xTitled( xAxis
, UNO_QUERY
);
2752 rxChAxisTitle
= lclCreateTitle( GetChRoot(), xTitled
, nTitleTarget
);
2755 void XclExpChAxesSet::WriteBody( XclExpStream
& rStrm
)
2757 rStrm
<< maData
.mnAxesSetId
<< maData
.maRect
;
2760 // The chart object ===========================================================
2762 static void lcl_getChartSubTitle(const Reference
<XChartDocument
>& xChartDoc
,
2765 Reference
< ::com::sun::star::chart::XChartDocument
> xChartDoc1(xChartDoc
, UNO_QUERY
);
2766 if (!xChartDoc1
.is())
2769 Reference
< XPropertySet
> xProp(xChartDoc1
->getSubTitle(), UNO_QUERY
);
2774 Any any
= xProp
->getPropertyValue( OUString::createFromAscii("String") );
2779 XclExpChChart::XclExpChChart( const XclExpRoot
& rRoot
,
2780 Reference
< XChartDocument
> xChartDoc
, const Size
& rSize
) :
2781 XclExpChGroupBase( EXC_ID_CHCHART
, 16 ),
2782 XclExpChRoot( rRoot
, this )
2784 Size aPtSize
= OutputDevice::LogicToLogic( rSize
, MapMode( MAP_100TH_MM
), MapMode( MAP_POINT
) );
2785 // rectangle is stored in 16.16 fixed-point format
2786 maRect
.mnX
= maRect
.mnY
= 0;
2787 maRect
.mnWidth
= static_cast< sal_Int32
>( aPtSize
.Width() << 16 );
2788 maRect
.mnHeight
= static_cast< sal_Int32
>( aPtSize
.Height() << 16 );
2790 // global chart properties (default values)
2791 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_MANSERIES
);
2792 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_SHOWVISCELLS
, false );
2793 maProps
.mnEmptyMode
= EXC_CHPROPS_EMPTY_SKIP
;
2795 // always create both axes set objects
2796 mxPrimAxesSet
.reset( new XclExpChAxesSet( GetChRoot(), EXC_CHAXESSET_PRIMARY
) );
2797 mxSecnAxesSet
.reset( new XclExpChAxesSet( GetChRoot(), EXC_CHAXESSET_SECONDARY
) );
2799 if( xChartDoc
.is() )
2801 Reference
< XDiagram
> xDiagram
= xChartDoc
->getFirstDiagram();
2803 // global chart properties (only 'include hidden cells' attribute for now)
2804 ScfPropertySet
aDiagramProp( xDiagram
);
2805 bool bIncludeHidden
= aDiagramProp
.GetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS
);
2806 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_SHOWVISCELLS
, !bIncludeHidden
);
2808 // initialize API conversion (remembers xChartDoc internally)
2809 InitConversion( xChartDoc
);
2812 ScfPropertySet
aFrameProp( xChartDoc
->getPageBackground() );
2813 mxFrame
= lclCreateFrame( GetChRoot(), aFrameProp
, EXC_CHOBJTYPE_BACKGROUND
);
2816 Reference
< XTitled
> xTitled( xChartDoc
, UNO_QUERY
);
2818 lcl_getChartSubTitle(xChartDoc
, aSubTitle
);
2819 mxTitle
= lclCreateTitle( GetChRoot(), xTitled
, EXC_CHOBJLINK_TITLE
,
2820 aSubTitle
.Len() ? &aSubTitle
: NULL
);
2822 // diagrams (axes sets)
2823 sal_uInt16 nFreeGroupIdx
= mxPrimAxesSet
->Convert( xDiagram
, 0 );
2824 if( !mxPrimAxesSet
->Is3dChart() )
2825 mxSecnAxesSet
->Convert( xDiagram
, nFreeGroupIdx
);
2827 // finish API conversion
2832 XclExpChSeriesRef
XclExpChChart::CreateSeries()
2834 XclExpChSeriesRef xSeries
;
2835 sal_uInt16 nSeriesIdx
= static_cast< sal_uInt16
>( maSeries
.GetSize() );
2836 if( nSeriesIdx
<= EXC_CHSERIES_MAXSERIES
)
2838 xSeries
.reset( new XclExpChSeries( GetChRoot(), nSeriesIdx
) );
2839 maSeries
.AppendRecord( xSeries
);
2844 void XclExpChChart::RemoveLastSeries()
2846 if( !maSeries
.IsEmpty() )
2847 maSeries
.RemoveRecord( maSeries
.GetSize() - 1 );
2850 void XclExpChChart::SetDataLabel( XclExpChTextRef xText
)
2853 maLabels
.AppendRecord( xText
);
2856 void XclExpChChart::WriteSubRecords( XclExpStream
& rStrm
)
2858 // background format
2859 lclSaveRecord( rStrm
, mxFrame
);
2862 maSeries
.Save( rStrm
);
2864 // CHPROPERTIES record
2865 rStrm
.StartRecord( EXC_ID_CHPROPERTIES
, 4 );
2866 rStrm
<< maProps
.mnFlags
<< maProps
.mnEmptyMode
<< sal_uInt8( 0 );
2869 // axes sets (always save primary axes set)
2870 sal_uInt16 nUsedAxesSets
= mxSecnAxesSet
->IsValidAxesSet() ? 2 : 1;
2871 XclExpUInt16Record( EXC_ID_CHUSEDAXESSETS
, nUsedAxesSets
).Save( rStrm
);
2872 mxPrimAxesSet
->Save( rStrm
);
2873 if( mxSecnAxesSet
->IsValidAxesSet() )
2874 mxSecnAxesSet
->Save( rStrm
);
2876 // chart title and data labels
2877 lclSaveRecord( rStrm
, mxTitle
);
2878 maLabels
.Save( rStrm
);
2881 void XclExpChChart::WriteBody( XclExpStream
& rStrm
)
2886 // ----------------------------------------------------------------------------
2888 XclExpChart::XclExpChart( const XclExpRoot
& rRoot
, Reference
< XModel
> xModel
, const Size
& rSize
) :
2889 XclExpSubStream( EXC_BOF_CHART
),
2892 AppendNewRecord( new XclExpChartPageSettings( rRoot
) );
2893 AppendNewRecord( new XclExpBoolRecord( EXC_ID_PROTECT
, false ) );
2894 AppendNewRecord( new XclExpUInt16Record( EXC_ID_CHUNITS
, EXC_CHUNITS_TWIPS
) );
2896 Reference
< XChartDocument
> xChartDoc( xModel
, UNO_QUERY
);
2897 AppendNewRecord( new XclExpChChart( rRoot
, xChartDoc
, rSize
) );
2900 // ============================================================================