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/chart/ChartAxisLabelPosition.hpp>
41 #include <com/sun/star/chart/ChartAxisPosition.hpp>
42 #include <com/sun/star/chart/DataLabelPlacement.hpp>
43 #include <com/sun/star/chart/ErrorBarStyle.hpp>
44 #include <com/sun/star/chart/MissingValueTreatment.hpp>
45 #include <com/sun/star/chart2/XChartDocument.hpp>
46 #include <com/sun/star/chart2/XDiagram.hpp>
47 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
48 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
49 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
50 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
51 #include <com/sun/star/chart2/XTitled.hpp>
52 #include <com/sun/star/chart2/XColorScheme.hpp>
53 #include <com/sun/star/chart2/data/XDataSource.hpp>
54 #include <com/sun/star/chart2/AxisType.hpp>
55 #include <com/sun/star/chart2/CurveStyle.hpp>
56 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
57 #include <com/sun/star/chart2/DataPointLabel.hpp>
58 #include <com/sun/star/chart2/StackingDirection.hpp>
59 #include <com/sun/star/chart2/TickmarkStyle.hpp>
61 #include <vcl/outdev.hxx>
62 #include <svx/escherex.hxx>
64 #include "document.hxx"
65 #include "rangelst.hxx"
66 #include "rangeutl.hxx"
67 #include "compiler.hxx"
68 #include "tokenarray.hxx"
70 #include "xeformula.hxx"
71 #include "xehelper.hxx"
73 #include "xestyle.hxx"
75 using ::rtl::OUString
;
76 using ::com::sun::star::uno::Any
;
77 using ::com::sun::star::uno::Reference
;
78 using ::com::sun::star::uno::Sequence
;
79 using ::com::sun::star::uno::UNO_QUERY
;
80 using ::com::sun::star::uno::Exception
;
81 using ::com::sun::star::beans::XPropertySet
;
82 using ::com::sun::star::i18n::XBreakIterator
;
83 using ::com::sun::star::frame::XModel
;
84 using ::com::sun::star::chart2::XChartDocument
;
85 using ::com::sun::star::chart2::XDiagram
;
86 using ::com::sun::star::chart2::XCoordinateSystemContainer
;
87 using ::com::sun::star::chart2::XCoordinateSystem
;
88 using ::com::sun::star::chart2::XChartTypeContainer
;
89 using ::com::sun::star::chart2::XChartType
;
90 using ::com::sun::star::chart2::XDataSeriesContainer
;
91 using ::com::sun::star::chart2::XDataSeries
;
92 using ::com::sun::star::chart2::XRegressionCurveContainer
;
93 using ::com::sun::star::chart2::XRegressionCurve
;
94 using ::com::sun::star::chart2::XAxis
;
95 using ::com::sun::star::chart2::XScaling
;
96 using ::com::sun::star::chart2::ScaleData
;
97 using ::com::sun::star::chart2::IncrementData
;
98 using ::com::sun::star::chart2::SubIncrement
;
99 using ::com::sun::star::chart2::XLegend
;
100 using ::com::sun::star::chart2::XTitled
;
101 using ::com::sun::star::chart2::XTitle
;
102 using ::com::sun::star::chart2::XFormattedString
;
103 using ::com::sun::star::chart2::XColorScheme
;
105 using ::com::sun::star::chart2::data::XDataSource
;
106 using ::com::sun::star::chart2::data::XLabeledDataSequence
;
107 using ::com::sun::star::chart2::data::XDataSequence
;
109 using ::formula::FormulaGrammar
;
110 using ::formula::FormulaToken
;
112 // Helpers ====================================================================
116 XclExpStream
& operator<<( XclExpStream
& rStrm
, const XclChRectangle
& rRect
)
118 return rStrm
<< rRect
.mnX
<< rRect
.mnY
<< rRect
.mnWidth
<< rRect
.mnHeight
;
121 inline void lclSaveRecord( XclExpStream
& rStrm
, XclExpRecordRef xRec
)
127 /** Saves the passed record (group) together with a leading value record. */
128 template< typename Type
>
129 void lclSaveRecord( XclExpStream
& rStrm
, XclExpRecordRef xRec
, sal_uInt16 nRecId
, Type nValue
)
133 XclExpValueRecord
< Type
>( nRecId
, nValue
).Save( rStrm
);
138 void lclWriteChFrBlockRecord( XclExpStream
& rStrm
, const XclChFrBlock
& rFrBlock
, bool bBegin
)
140 sal_uInt16 nRecId
= bBegin
? EXC_ID_CHFRBLOCKBEGIN
: EXC_ID_CHFRBLOCKEND
;
141 rStrm
.StartRecord( nRecId
, 12 );
142 rStrm
<< nRecId
<< EXC_FUTUREREC_EMPTYFLAGS
<< rFrBlock
.mnType
<< rFrBlock
.mnContext
<< rFrBlock
.mnValue1
<< rFrBlock
.mnValue2
;
146 template< typename Type
>
147 inline bool lclIsAutoAnyOrGetValue( Type
& rValue
, const Any
& rAny
)
149 return !rAny
.hasValue() || !(rAny
>>= rValue
);
152 bool lclIsAutoAnyOrGetScaledValue( double& rfValue
, const Any
& rAny
, bool bLogScale
)
154 bool bIsAuto
= lclIsAutoAnyOrGetValue( rfValue
, rAny
);
155 if( !bIsAuto
&& bLogScale
)
156 rfValue
= log( rfValue
) / log( 10.0 );
162 // Common =====================================================================
164 /** Stores global data needed in various classes of the Chart export filter. */
165 class XclExpChRootData
: public XclChRootData
168 explicit XclExpChRootData( XclExpChChart
* pChartData
);
170 /** Returns a reference to the parent chart data object. */
171 inline XclExpChChart
& GetChartData() const { return *mpChartData
; }
173 /** Registers a new future record level. */
174 void RegisterFutureRecBlock( const XclChFrBlock
& rFrBlock
);
175 /** Initializes the current future record level (writes all unwritten CHFRBLOCKBEGIN records). */
176 void InitializeFutureRecBlock( XclExpStream
& rStrm
);
177 /** Finalizes the current future record level (writes CHFRBLOCKEND record if needed). */
178 void FinalizeFutureRecBlock( XclExpStream
& rStrm
);
181 typedef ::std::vector
< XclChFrBlock
> XclChFrBlockVector
;
183 XclExpChChart
* mpChartData
; /// Pointer to the chart data object.
184 XclChFrBlockVector maWrittenFrBlocks
; /// Stack of future record levels already written out.
185 XclChFrBlockVector maUnwrittenFrBlocks
; /// Stack of future record levels not yet written out.
188 // ----------------------------------------------------------------------------
190 XclExpChRootData::XclExpChRootData( XclExpChChart
* pChartData
) :
191 mpChartData( pChartData
)
195 void XclExpChRootData::RegisterFutureRecBlock( const XclChFrBlock
& rFrBlock
)
197 maUnwrittenFrBlocks
.push_back( rFrBlock
);
200 void XclExpChRootData::InitializeFutureRecBlock( XclExpStream
& rStrm
)
202 // first call from a future record writes all missing CHFRBLOCKBEGIN records
203 if( !maUnwrittenFrBlocks
.empty() )
205 // write the leading CHFRINFO record
206 if( maWrittenFrBlocks
.empty() )
208 rStrm
.StartRecord( EXC_ID_CHFRINFO
, 20 );
209 rStrm
<< EXC_ID_CHFRINFO
<< EXC_FUTUREREC_EMPTYFLAGS
<< EXC_CHFRINFO_EXCELXP2003
<< EXC_CHFRINFO_EXCELXP2003
<< sal_uInt16( 3 );
210 rStrm
<< sal_uInt16( 0x0850 ) << sal_uInt16( 0x085A ) << sal_uInt16( 0x0861 ) << sal_uInt16( 0x0861 ) << sal_uInt16( 0x086A ) << sal_uInt16( 0x086B );
213 // write all unwritten CHFRBLOCKBEGIN records
214 for( XclChFrBlockVector::const_iterator aIt
= maUnwrittenFrBlocks
.begin(), aEnd
= maUnwrittenFrBlocks
.end(); aIt
!= aEnd
; ++aIt
)
216 DBG_ASSERT( aIt
->mnType
!= EXC_CHFRBLOCK_TYPE_UNKNOWN
, "XclExpChRootData::InitializeFutureRecBlock - unknown future record block type" );
217 lclWriteChFrBlockRecord( rStrm
, *aIt
, true );
219 // move all record infos to vector of written blocks
220 maWrittenFrBlocks
.insert( maWrittenFrBlocks
.end(), maUnwrittenFrBlocks
.begin(), maUnwrittenFrBlocks
.end() );
221 maUnwrittenFrBlocks
.clear();
225 void XclExpChRootData::FinalizeFutureRecBlock( XclExpStream
& rStrm
)
227 DBG_ASSERT( !maUnwrittenFrBlocks
.empty() || !maWrittenFrBlocks
.empty(), "XclExpChRootData::FinalizeFutureRecBlock - no future record level found" );
228 if( !maUnwrittenFrBlocks
.empty() )
230 // no future record has been written, just forget the topmost level
231 maUnwrittenFrBlocks
.pop_back();
233 else if( !maWrittenFrBlocks
.empty() )
235 // write the CHFRBLOCKEND record for the topmost block and delete it
236 lclWriteChFrBlockRecord( rStrm
, maWrittenFrBlocks
.back(), false );
237 maWrittenFrBlocks
.pop_back();
241 // ----------------------------------------------------------------------------
243 XclExpChRoot::XclExpChRoot( const XclExpRoot
& rRoot
, XclExpChChart
* pChartData
) :
245 mxChData( new XclExpChRootData( pChartData
) )
249 XclExpChRoot::~XclExpChRoot()
253 XclExpChChart
& XclExpChRoot::GetChartData() const
255 return mxChData
->GetChartData();
258 const XclChTypeInfo
& XclExpChRoot::GetChartTypeInfo( XclChTypeId eType
) const
260 return mxChData
->GetTypeInfoProvider().GetTypeInfo( eType
);
263 const XclChTypeInfo
& XclExpChRoot::GetChartTypeInfo( const OUString
& rServiceName
) const
265 return mxChData
->GetTypeInfoProvider().GetTypeInfoFromService( rServiceName
);
268 const XclChFormatInfo
& XclExpChRoot::GetFormatInfo( XclChObjectType eObjType
) const
270 return mxChData
->GetFormatInfoProvider().GetFormatInfo( eObjType
);
273 void XclExpChRoot::InitConversion( XChartDocRef xChartDoc
) const
275 mxChData
->InitConversion( xChartDoc
);
278 void XclExpChRoot::FinishConversion() const
280 mxChData
->FinishConversion();
283 bool XclExpChRoot::IsSystemColor( const Color
& rColor
, sal_uInt16 nSysColorIdx
) const
285 XclExpPalette
& rPal
= GetPalette();
286 return rPal
.IsSystemColor( nSysColorIdx
) && (rColor
== rPal
.GetDefColor( nSysColorIdx
));
289 void XclExpChRoot::SetSystemColor( Color
& rColor
, sal_uInt32
& rnColorId
, sal_uInt16 nSysColorIdx
) const
291 DBG_ASSERT( GetPalette().IsSystemColor( nSysColorIdx
), "XclExpChRoot::SetSystemColor - invalid color index" );
292 rColor
= GetPalette().GetDefColor( nSysColorIdx
);
293 rnColorId
= XclExpPalette::GetColorIdFromIndex( nSysColorIdx
);
296 void XclExpChRoot::ConvertLineFormat( XclChLineFormat
& rLineFmt
,
297 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
) const
299 GetChartPropSetHelper().ReadLineProperties(
300 rLineFmt
, mxChData
->GetLineDashTable(), rPropSet
, ePropMode
);
303 bool XclExpChRoot::ConvertAreaFormat( XclChAreaFormat
& rAreaFmt
,
304 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
) const
306 return GetChartPropSetHelper().ReadAreaProperties( rAreaFmt
, rPropSet
, ePropMode
);
309 void XclExpChRoot::ConvertEscherFormat(
310 XclChEscherFormat
& rEscherFmt
, XclChPicFormat
& rPicFmt
,
311 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
) const
313 GetChartPropSetHelper().ReadEscherProperties( rEscherFmt
, rPicFmt
,
314 mxChData
->GetGradientTable(), mxChData
->GetHatchTable(), mxChData
->GetBitmapTable(), rPropSet
, ePropMode
);
317 sal_uInt16
XclExpChRoot::ConvertFont( const ScfPropertySet
& rPropSet
, sal_Int16 nScript
) const
319 XclFontData aFontData
;
320 GetFontPropSetHelper().ReadFontProperties( aFontData
, rPropSet
, EXC_FONTPROPSET_CHART
, nScript
);
321 return GetFontBuffer().Insert( aFontData
, EXC_COLOR_CHARTTEXT
);
324 sal_uInt16
XclExpChRoot::ConvertPieRotation( const ScfPropertySet
& rPropSet
)
326 sal_Int32 nApiRot
= 0;
327 rPropSet
.GetProperty( nApiRot
, EXC_CHPROP_STARTINGANGLE
);
328 return static_cast< sal_uInt16
>( (450 - (nApiRot
% 360)) % 360 );
331 void XclExpChRoot::RegisterFutureRecBlock( const XclChFrBlock
& rFrBlock
)
333 mxChData
->RegisterFutureRecBlock( rFrBlock
);
336 void XclExpChRoot::InitializeFutureRecBlock( XclExpStream
& rStrm
)
338 mxChData
->InitializeFutureRecBlock( rStrm
);
341 void XclExpChRoot::FinalizeFutureRecBlock( XclExpStream
& rStrm
)
343 mxChData
->FinalizeFutureRecBlock( rStrm
);
346 // ----------------------------------------------------------------------------
348 XclExpChGroupBase::XclExpChGroupBase( const XclExpChRoot
& rRoot
,
349 sal_uInt16 nFrType
, sal_uInt16 nRecId
, sal_Size nRecSize
) :
350 XclExpRecord( nRecId
, nRecSize
),
351 XclExpChRoot( rRoot
),
356 XclExpChGroupBase::~XclExpChGroupBase()
360 void XclExpChGroupBase::Save( XclExpStream
& rStrm
)
363 XclExpRecord::Save( rStrm
);
365 if( HasSubRecords() )
367 // register the future record context corresponding to this record group
368 RegisterFutureRecBlock( maFrBlock
);
370 XclExpEmptyRecord( EXC_ID_CHBEGIN
).Save( rStrm
);
372 WriteSubRecords( rStrm
);
373 // finalize the future records, must be done before the closing CHEND
374 FinalizeFutureRecBlock( rStrm
);
376 XclExpEmptyRecord( EXC_ID_CHEND
).Save( rStrm
);
380 bool XclExpChGroupBase::HasSubRecords() const
385 void XclExpChGroupBase::SetFutureRecordContext( sal_uInt16 nFrContext
, sal_uInt16 nFrValue1
, sal_uInt16 nFrValue2
)
387 maFrBlock
.mnContext
= nFrContext
;
388 maFrBlock
.mnValue1
= nFrValue1
;
389 maFrBlock
.mnValue2
= nFrValue2
;
392 // ----------------------------------------------------------------------------
394 XclExpChFutureRecordBase::XclExpChFutureRecordBase( const XclExpChRoot
& rRoot
,
395 XclFutureRecType eRecType
, sal_uInt16 nRecId
, sal_Size nRecSize
) :
396 XclExpFutureRecord( eRecType
, nRecId
, nRecSize
),
397 XclExpChRoot( rRoot
)
401 void XclExpChFutureRecordBase::Save( XclExpStream
& rStrm
)
403 InitializeFutureRecBlock( rStrm
);
404 XclExpFutureRecord::Save( rStrm
);
407 // Frame formatting ===========================================================
409 XclExpChLineFormat::XclExpChLineFormat( const XclExpChRoot
& rRoot
) :
410 XclExpRecord( EXC_ID_CHLINEFORMAT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 12 : 10 ),
411 mnColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
415 void XclExpChLineFormat::SetDefault( XclChFrameType eDefFrameType
)
417 switch( eDefFrameType
)
419 case EXC_CHFRAMETYPE_AUTO
:
422 case EXC_CHFRAMETYPE_INVISIBLE
:
424 maData
.mnPattern
= EXC_CHLINEFORMAT_NONE
;
427 DBG_ERRORFILE( "XclExpChLineFormat::SetDefault - unknown frame type" );
431 void XclExpChLineFormat::Convert( const XclExpChRoot
& rRoot
,
432 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
434 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
435 rRoot
.ConvertLineFormat( maData
, rPropSet
, rFmtInfo
.mePropMode
);
438 // detect system color, set color identifier (TODO: detect automatic series line)
439 if( (eObjType
!= EXC_CHOBJTYPE_LINEARSERIES
) && rRoot
.IsSystemColor( maData
.maColor
, rFmtInfo
.mnAutoLineColorIdx
) )
441 // store color index from automatic format data
442 mnColorId
= XclExpPalette::GetColorIdFromIndex( rFmtInfo
.mnAutoLineColorIdx
);
443 // try to set automatic mode
444 bool bAuto
= (maData
.mnPattern
== EXC_CHLINEFORMAT_SOLID
) && (maData
.mnWeight
== rFmtInfo
.mnAutoLineWeight
);
445 ::set_flag( maData
.mnFlags
, EXC_CHLINEFORMAT_AUTO
, bAuto
);
449 // user defined color - register in palette
450 mnColorId
= rRoot
.GetPalette().InsertColor( maData
.maColor
, EXC_COLOR_CHARTLINE
);
455 // no line - set default system color
456 rRoot
.SetSystemColor( maData
.maColor
, mnColorId
, EXC_COLOR_CHWINDOWTEXT
);
460 bool XclExpChLineFormat::IsDefault( XclChFrameType eDefFrameType
) const
463 ((eDefFrameType
== EXC_CHFRAMETYPE_INVISIBLE
) && !HasLine()) ||
464 ((eDefFrameType
== EXC_CHFRAMETYPE_AUTO
) && IsAuto());
467 void XclExpChLineFormat::WriteBody( XclExpStream
& rStrm
)
469 rStrm
<< maData
.maColor
<< maData
.mnPattern
<< maData
.mnWeight
<< maData
.mnFlags
;
470 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
471 rStrm
<< rStrm
.GetRoot().GetPalette().GetColorIndex( mnColorId
);
476 /** Creates a CHLINEFORMAT record from the passed property set. */
477 XclExpChLineFormatRef
lclCreateLineFormat( const XclExpChRoot
& rRoot
,
478 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
480 XclExpChLineFormatRef
xLineFmt( new XclExpChLineFormat( rRoot
) );
481 xLineFmt
->Convert( rRoot
, rPropSet
, eObjType
);
482 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
483 if( rFmtInfo
.mbDeleteDefFrame
&& xLineFmt
->IsDefault( rFmtInfo
.meDefFrameType
) )
490 // ----------------------------------------------------------------------------
492 XclExpChAreaFormat::XclExpChAreaFormat( const XclExpChRoot
& rRoot
) :
493 XclExpRecord( EXC_ID_CHAREAFORMAT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 16 : 12 ),
494 mnPattColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) ),
495 mnBackColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
499 bool XclExpChAreaFormat::Convert( const XclExpChRoot
& rRoot
,
500 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
502 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
503 bool bComplexFill
= rRoot
.ConvertAreaFormat( maData
, rPropSet
, rFmtInfo
.mePropMode
);
506 bool bSolid
= maData
.mnPattern
== EXC_PATT_SOLID
;
507 // detect system color, set color identifier (TODO: detect automatic series area)
508 if( (eObjType
!= EXC_CHOBJTYPE_FILLEDSERIES
) && rRoot
.IsSystemColor( maData
.maPattColor
, rFmtInfo
.mnAutoPattColorIdx
) )
510 // store color index from automatic format data
511 mnPattColorId
= XclExpPalette::GetColorIdFromIndex( rFmtInfo
.mnAutoPattColorIdx
);
512 // set automatic mode
513 ::set_flag( maData
.mnFlags
, EXC_CHAREAFORMAT_AUTO
, bSolid
);
517 // user defined color - register color in palette
518 mnPattColorId
= rRoot
.GetPalette().InsertColor( maData
.maPattColor
, EXC_COLOR_CHARTAREA
);
520 // background color (default system color for solid fills)
522 rRoot
.SetSystemColor( maData
.maBackColor
, mnBackColorId
, EXC_COLOR_CHWINDOWTEXT
);
524 mnBackColorId
= rRoot
.GetPalette().InsertColor( maData
.maBackColor
, EXC_COLOR_CHARTAREA
);
528 // no area - set default system colors
529 rRoot
.SetSystemColor( maData
.maPattColor
, mnPattColorId
, EXC_COLOR_CHWINDOWBACK
);
530 rRoot
.SetSystemColor( maData
.maBackColor
, mnBackColorId
, EXC_COLOR_CHWINDOWTEXT
);
535 void XclExpChAreaFormat::SetDefault( XclChFrameType eDefFrameType
)
537 switch( eDefFrameType
)
539 case EXC_CHFRAMETYPE_AUTO
:
542 case EXC_CHFRAMETYPE_INVISIBLE
:
544 maData
.mnPattern
= EXC_PATT_NONE
;
547 DBG_ERRORFILE( "XclExpChAreaFormat::SetDefault - unknown frame type" );
551 bool XclExpChAreaFormat::IsDefault( XclChFrameType eDefFrameType
) const
554 ((eDefFrameType
== EXC_CHFRAMETYPE_INVISIBLE
) && !HasArea()) ||
555 ((eDefFrameType
== EXC_CHFRAMETYPE_AUTO
) && IsAuto());
558 void XclExpChAreaFormat::WriteBody( XclExpStream
& rStrm
)
560 rStrm
<< maData
.maPattColor
<< maData
.maBackColor
<< maData
.mnPattern
<< maData
.mnFlags
;
561 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
563 const XclExpPalette
& rPal
= rStrm
.GetRoot().GetPalette();
564 rStrm
<< rPal
.GetColorIndex( mnPattColorId
) << rPal
.GetColorIndex( mnBackColorId
);
568 // ----------------------------------------------------------------------------
570 XclExpChEscherFormat::XclExpChEscherFormat( const XclExpChRoot
& rRoot
) :
571 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_UNKNOWN
, EXC_ID_CHESCHERFORMAT
),
572 mnColor1Id( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) ),
573 mnColor2Id( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) )
575 DBG_ASSERT_BIFF( GetBiff() == EXC_BIFF8
);
578 void XclExpChEscherFormat::Convert( const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
580 const XclChFormatInfo
& rFmtInfo
= GetFormatInfo( eObjType
);
581 ConvertEscherFormat( maData
, maPicFmt
, rPropSet
, rFmtInfo
.mePropMode
);
582 // register colors in palette
583 mnColor1Id
= RegisterColor( ESCHER_Prop_fillColor
);
584 mnColor2Id
= RegisterColor( ESCHER_Prop_fillBackColor
);
587 bool XclExpChEscherFormat::IsValid() const
589 return maData
.mxEscherSet
.is();
592 void XclExpChEscherFormat::Save( XclExpStream
& rStrm
)
594 if( maData
.mxEscherSet
.is() )
596 // replace RGB colors with palette indexes in the Escher container
597 const XclExpPalette
& rPal
= GetPalette();
598 maData
.mxEscherSet
->AddOpt( ESCHER_Prop_fillColor
, 0x08000000 | rPal
.GetColorIndex( mnColor1Id
) );
599 maData
.mxEscherSet
->AddOpt( ESCHER_Prop_fillBackColor
, 0x08000000 | rPal
.GetColorIndex( mnColor2Id
) );
601 // save the record group
602 XclExpChGroupBase::Save( rStrm
);
606 bool XclExpChEscherFormat::HasSubRecords() const
608 // no subrecords for gradients
609 return maPicFmt
.mnBmpMode
!= EXC_CHPICFORMAT_NONE
;
612 void XclExpChEscherFormat::WriteSubRecords( XclExpStream
& rStrm
)
614 rStrm
.StartRecord( EXC_ID_CHPICFORMAT
, 14 );
615 rStrm
<< maPicFmt
.mnBmpMode
<< maPicFmt
.mnFormat
<< maPicFmt
.mnFlags
<< maPicFmt
.mfScale
;
619 sal_uInt32
XclExpChEscherFormat::RegisterColor( sal_uInt16 nPropId
)
621 sal_uInt32 nBGRValue
;
622 if( maData
.mxEscherSet
.is() && maData
.mxEscherSet
->GetOpt( nPropId
, nBGRValue
) )
625 Color
aColor( RGB_COLORDATA(
626 COLORDATA_BLUE( nBGRValue
),
627 COLORDATA_GREEN( nBGRValue
),
628 COLORDATA_RED( nBGRValue
) ) );
629 return GetPalette().InsertColor( aColor
, EXC_COLOR_CHARTAREA
);
631 return XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
);
634 void XclExpChEscherFormat::WriteBody( XclExpStream
& rStrm
)
636 DBG_ASSERT( maData
.mxEscherSet
.is(), "XclExpChEscherFormat::WriteBody - missing property container" );
637 // write Escher property container via temporary memory stream
638 SvMemoryStream aMemStrm
;
639 maData
.mxEscherSet
->Commit( aMemStrm
);
640 aMemStrm
.Seek( STREAM_SEEK_TO_BEGIN
);
641 rStrm
.CopyFromStream( aMemStrm
);
644 // ----------------------------------------------------------------------------
646 XclExpChFrameBase::XclExpChFrameBase()
650 XclExpChFrameBase::~XclExpChFrameBase()
654 void XclExpChFrameBase::ConvertFrameBase( const XclExpChRoot
& rRoot
,
655 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
658 mxLineFmt
.reset( new XclExpChLineFormat( rRoot
) );
659 mxLineFmt
->Convert( rRoot
, rPropSet
, eObjType
);
660 // area format (only for frame objects)
661 if( rRoot
.GetFormatInfo( eObjType
).mbIsFrame
)
663 mxAreaFmt
.reset( new XclExpChAreaFormat( rRoot
) );
664 bool bComplexFill
= mxAreaFmt
->Convert( rRoot
, rPropSet
, eObjType
);
665 if( (rRoot
.GetBiff() == EXC_BIFF8
) && bComplexFill
)
667 mxEscherFmt
.reset( new XclExpChEscherFormat( rRoot
) );
668 mxEscherFmt
->Convert( rPropSet
, eObjType
);
669 if( mxEscherFmt
->IsValid() )
670 mxAreaFmt
->SetAuto( false );
677 void XclExpChFrameBase::SetDefaultFrameBase( const XclExpChRoot
& rRoot
,
678 XclChFrameType eDefFrameType
, bool bIsFrame
)
681 mxLineFmt
.reset( new XclExpChLineFormat( rRoot
) );
682 mxLineFmt
->SetDefault( eDefFrameType
);
683 // area format (only for frame objects)
686 mxAreaFmt
.reset( new XclExpChAreaFormat( rRoot
) );
687 mxAreaFmt
->SetDefault( eDefFrameType
);
692 bool XclExpChFrameBase::IsDefaultFrameBase( XclChFrameType eDefFrameType
) const
695 (!mxLineFmt
|| mxLineFmt
->IsDefault( eDefFrameType
)) &&
696 (!mxAreaFmt
|| mxAreaFmt
->IsDefault( eDefFrameType
));
699 void XclExpChFrameBase::WriteFrameRecords( XclExpStream
& rStrm
)
701 lclSaveRecord( rStrm
, mxLineFmt
);
702 lclSaveRecord( rStrm
, mxAreaFmt
);
703 lclSaveRecord( rStrm
, mxEscherFmt
);
706 // ----------------------------------------------------------------------------
708 XclExpChFrame::XclExpChFrame( const XclExpChRoot
& rRoot
, XclChObjectType eObjType
) :
709 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_FRAME
, EXC_ID_CHFRAME
, 4 ),
710 meObjType( eObjType
)
714 void XclExpChFrame::Convert( const ScfPropertySet
& rPropSet
)
716 ConvertFrameBase( GetChRoot(), rPropSet
, meObjType
);
719 bool XclExpChFrame::IsDefault() const
721 return IsDefaultFrameBase( GetFormatInfo( meObjType
).meDefFrameType
);
724 bool XclExpChFrame::IsDeleteable() const
726 return IsDefault() && GetFormatInfo( meObjType
).mbDeleteDefFrame
;
729 void XclExpChFrame::Save( XclExpStream
& rStrm
)
733 // wall/floor frame without CHFRAME header record
734 case EXC_CHOBJTYPE_WALL3D
:
735 case EXC_CHOBJTYPE_FLOOR3D
:
736 WriteFrameRecords( rStrm
);
739 XclExpChGroupBase::Save( rStrm
);
743 void XclExpChFrame::WriteSubRecords( XclExpStream
& rStrm
)
745 WriteFrameRecords( rStrm
);
748 void XclExpChFrame::WriteBody( XclExpStream
& rStrm
)
750 rStrm
<< maData
.mnFormat
<< maData
.mnFlags
;
755 /** Creates a CHFRAME record from the passed property set. */
756 XclExpChFrameRef
lclCreateFrame( const XclExpChRoot
& rRoot
,
757 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
759 XclExpChFrameRef
xFrame( new XclExpChFrame( rRoot
, eObjType
) );
760 xFrame
->Convert( rPropSet
);
761 if( xFrame
->IsDeleteable() )
768 // Source links ===============================================================
772 void lclAddDoubleRefData(
773 ScTokenArray
& orArray
, const FormulaToken
& rToken
,
774 SCsTAB nScTab1
, SCsCOL nScCol1
, SCsROW nScRow1
,
775 SCsTAB nScTab2
, SCsCOL nScCol2
, SCsROW nScRow2
)
777 ScComplexRefData aComplexRef
;
778 aComplexRef
.InitFlags();
779 aComplexRef
.Ref1
.SetFlag3D( true );
780 aComplexRef
.Ref1
.nTab
= nScTab1
;
781 aComplexRef
.Ref1
.nCol
= nScCol1
;
782 aComplexRef
.Ref1
.nRow
= nScRow1
;
783 aComplexRef
.Ref2
.nTab
= nScTab2
;
784 aComplexRef
.Ref2
.nCol
= nScCol2
;
785 aComplexRef
.Ref2
.nRow
= nScRow2
;
787 if( orArray
.GetLen() > 0 )
788 orArray
.AddOpCode( ocUnion
);
790 DBG_ASSERT( (rToken
.GetType() == ::formula::svDoubleRef
) || (rToken
.GetType() == ::formula::svExternalDoubleRef
),
791 "lclAddDoubleRefData - double reference token expected");
792 if( rToken
.GetType() == ::formula::svExternalDoubleRef
)
793 orArray
.AddExternalDoubleReference( rToken
.GetIndex(), rToken
.GetString(), aComplexRef
);
795 orArray
.AddDoubleReference( aComplexRef
);
800 // ----------------------------------------------------------------------------
802 XclExpChSourceLink::XclExpChSourceLink( const XclExpChRoot
& rRoot
, sal_uInt8 nDestType
) :
803 XclExpRecord( EXC_ID_CHSOURCELINK
),
804 XclExpChRoot( rRoot
)
806 maData
.mnDestType
= nDestType
;
807 maData
.mnLinkType
= EXC_CHSRCLINK_DIRECTLY
;
810 sal_uInt16
XclExpChSourceLink::ConvertDataSequence( Reference
< XDataSequence
> xDataSeq
, bool bSplitToColumns
, sal_uInt16 nDefCount
)
813 maData
.mnLinkType
= EXC_CHSRCLINK_DEFAULT
;
818 // Compile the range representation string into token array. Note that the
819 // source range text depends on the current grammar.
820 OUString aRangeRepr
= xDataSeq
->getSourceRangeRepresentation();
821 ScCompiler
aComp( GetDocPtr(), ScAddress() );
822 aComp
.SetGrammar( GetDocPtr()->GetGrammar() );
823 ScTokenArray
* pArray
= aComp
.CompileString( aRangeRepr
);
828 sal_uInt32 nValueCount
= 0;
830 for( const FormulaToken
* pToken
= pArray
->First(); pToken
; pToken
= pArray
->Next() )
832 switch( pToken
->GetType() )
834 case ::formula::svSingleRef
:
835 case ::formula::svExternalSingleRef
:
836 // for a single ref token, just add it to the new token array as is
837 if( aArray
.GetLen() > 0 )
838 aArray
.AddOpCode( ocUnion
);
839 aArray
.AddToken( *pToken
);
843 case ::formula::svDoubleRef
:
844 case ::formula::svExternalDoubleRef
:
846 // split 3-dimensional ranges into single sheets
847 const ScComplexRefData
& rComplexRef
= static_cast< const ScToken
* >( pToken
)->GetDoubleRef();
848 const ScSingleRefData
& rRef1
= rComplexRef
.Ref1
;
849 const ScSingleRefData
& rRef2
= rComplexRef
.Ref2
;
850 for( SCsTAB nScTab
= rRef1
.nTab
; nScTab
<= rRef2
.nTab
; ++nScTab
)
852 // split 2-dimensional ranges into single columns
853 if( bSplitToColumns
&& (rRef1
.nCol
< rRef2
.nCol
) && (rRef1
.nRow
< rRef2
.nRow
) )
854 for( SCsCOL nScCol
= rRef1
.nCol
; nScCol
<= rRef2
.nCol
; ++nScCol
)
855 lclAddDoubleRefData( aArray
, *pToken
, nScTab
, nScCol
, rRef1
.nRow
, nScTab
, nScCol
, rRef2
.nRow
);
857 lclAddDoubleRefData( aArray
, *pToken
, nScTab
, rRef1
.nCol
, rRef1
.nRow
, nScTab
, rRef2
.nCol
, rRef2
.nRow
);
859 sal_uInt32 nTabs
= static_cast< sal_uInt32
>( rRef2
.nTab
- rRef1
.nTab
+ 1 );
860 sal_uInt32 nCols
= static_cast< sal_uInt32
>( rRef2
.nCol
- rRef1
.nCol
+ 1 );
861 sal_uInt32 nRows
= static_cast< sal_uInt32
>( rRef2
.nRow
- rRef1
.nRow
+ 1 );
862 nValueCount
+= nCols
* nRows
* nTabs
;
870 const ScAddress aBaseCell
;
871 mxLinkFmla
= GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CHART
, aArray
, &aBaseCell
);
872 maData
.mnLinkType
= EXC_CHSRCLINK_WORKSHEET
;
873 return ulimit_cast
< sal_uInt16
>( nValueCount
, EXC_CHDATAFORMAT_MAXPOINTCOUNT
);
876 sal_uInt16
XclExpChSourceLink::ConvertStringSequence( const Sequence
< Reference
< XFormattedString
> >& rStringSeq
)
879 sal_uInt16 nFontIdx
= EXC_FONT_APP
;
880 if( rStringSeq
.hasElements() )
882 mxString
= XclExpStringHelper::CreateString( GetRoot(), String::EmptyString(), EXC_STR_FORCEUNICODE
| EXC_STR_8BITLENGTH
| EXC_STR_SEPARATEFORMATS
);
883 Reference
< XBreakIterator
> xBreakIt
= GetDoc().GetBreakIterator();
884 namespace ApiScriptType
= ::com::sun::star::i18n::ScriptType
;
886 // convert all formatted string entries from the sequence
887 const Reference
< XFormattedString
>* pBeg
= rStringSeq
.getConstArray();
888 const Reference
< XFormattedString
>* pEnd
= pBeg
+ rStringSeq
.getLength();
889 for( const Reference
< XFormattedString
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
893 sal_uInt16 nWstrnFontIdx
= EXC_FONT_NOTFOUND
;
894 sal_uInt16 nAsianFontIdx
= EXC_FONT_NOTFOUND
;
895 sal_uInt16 nCmplxFontIdx
= EXC_FONT_NOTFOUND
;
896 OUString aText
= (*pIt
)->getString();
897 ScfPropertySet
aStrProp( *pIt
);
899 // #i63255# get script type for leading weak characters
900 sal_Int16 nLastScript
= XclExpStringHelper::GetLeadingScriptType( GetRoot(), aText
);
902 // process all script portions
903 sal_Int32 nPortionPos
= 0;
904 sal_Int32 nTextLen
= aText
.getLength();
905 while( nPortionPos
< nTextLen
)
907 // get script type and end position of next script portion
908 sal_Int16 nScript
= xBreakIt
->getScriptType( aText
, nPortionPos
);
909 sal_Int32 nPortionEnd
= xBreakIt
->endOfScript( aText
, nPortionPos
, nScript
);
911 // reuse previous script for following weak portions
912 if( nScript
== ApiScriptType::WEAK
)
913 nScript
= nLastScript
;
915 // Excel start position of this portion
916 sal_uInt16 nXclPortionStart
= mxString
->Len();
917 // add portion text to Excel string
918 XclExpStringHelper::AppendString( *mxString
, GetRoot(), aText
.copy( nPortionPos
, nPortionEnd
- nPortionPos
) );
919 if( nXclPortionStart
< mxString
->Len() )
921 // find font index variable dependent on script type
922 sal_uInt16
& rnFontIdx
= (nScript
== ApiScriptType::COMPLEX
) ? nCmplxFontIdx
:
923 ((nScript
== ApiScriptType::ASIAN
) ? nAsianFontIdx
: nWstrnFontIdx
);
925 // insert font into buffer (if not yet done)
926 if( rnFontIdx
== EXC_FONT_NOTFOUND
)
927 rnFontIdx
= ConvertFont( aStrProp
, nScript
);
929 // insert font index into format run vector
930 mxString
->AppendFormat( nXclPortionStart
, rnFontIdx
);
933 // go to next script portion
934 nLastScript
= nScript
;
935 nPortionPos
= nPortionEnd
;
939 if( !mxString
->IsEmpty() )
941 // get leading font index
942 const XclFormatRunVec
& rFormats
= mxString
->GetFormats();
943 DBG_ASSERT( !rFormats
.empty() && (rFormats
.front().mnChar
== 0),
944 "XclExpChSourceLink::ConvertStringSequenc - missing leading format" );
945 // remove leading format run, if entire string is equally formatted
946 if( rFormats
.size() == 1 )
947 nFontIdx
= mxString
->RemoveLeadingFont();
948 else if( !rFormats
.empty() )
949 nFontIdx
= rFormats
.front().mnFontIdx
;
950 // add trailing format run, if string is rich-formatted
951 if( mxString
->IsRich() )
952 mxString
->AppendTrailingFormat( EXC_FONT_APP
);
958 void XclExpChSourceLink::ConvertNumFmt( const ScfPropertySet
& rPropSet
, bool bPercent
)
960 sal_Int32 nApiNumFmt
= 0;
961 if( bPercent
? rPropSet
.GetProperty( nApiNumFmt
, EXC_CHPROP_PERCENTAGENUMFMT
) : rPropSet
.GetProperty( nApiNumFmt
, EXC_CHPROP_NUMBERFORMAT
) )
963 ::set_flag( maData
.mnFlags
, EXC_CHSRCLINK_NUMFMT
);
964 maData
.mnNumFmtIdx
= GetNumFmtBuffer().Insert( static_cast< sal_uInt32
>( nApiNumFmt
) );
968 void XclExpChSourceLink::AppendString( const String
& rStr
)
972 XclExpStringHelper::AppendString( *mxString
, GetRoot(), rStr
);
975 void XclExpChSourceLink::Save( XclExpStream
& rStrm
)
977 // CHFORMATRUNS record
978 if( mxString
.is() && mxString
->IsRich() )
980 sal_Size nRecSize
= (1 + mxString
->GetFormatsCount()) * ((GetBiff() == EXC_BIFF8
) ? 2 : 1);
981 rStrm
.StartRecord( EXC_ID_CHFORMATRUNS
, nRecSize
);
982 mxString
->WriteFormats( rStrm
, true );
985 // CHSOURCELINK record
986 XclExpRecord::Save( rStrm
);
988 if( mxString
.is() && !mxString
->IsEmpty() )
990 rStrm
.StartRecord( EXC_ID_CHSTRING
, 2 + mxString
->GetSize() );
991 rStrm
<< sal_uInt16( 0 ) << *mxString
;
996 void XclExpChSourceLink::WriteBody( XclExpStream
& rStrm
)
998 rStrm
<< maData
.mnDestType
1001 << maData
.mnNumFmtIdx
1005 // Text =======================================================================
1007 XclExpChFont::XclExpChFont( sal_uInt16 nFontIdx
) :
1008 XclExpUInt16Record( EXC_ID_CHFONT
, nFontIdx
)
1012 // ----------------------------------------------------------------------------
1014 XclExpChObjectLink::XclExpChObjectLink( sal_uInt16 nLinkTarget
, const XclChDataPointPos
& rPointPos
) :
1015 XclExpRecord( EXC_ID_CHOBJECTLINK
, 6 )
1017 maData
.mnTarget
= nLinkTarget
;
1018 maData
.maPointPos
= rPointPos
;
1021 void XclExpChObjectLink::WriteBody( XclExpStream
& rStrm
)
1023 rStrm
<< maData
.mnTarget
<< maData
.maPointPos
.mnSeriesIdx
<< maData
.maPointPos
.mnPointIdx
;
1026 // ----------------------------------------------------------------------------
1028 XclExpChFrLabelProps::XclExpChFrLabelProps( const XclExpChRoot
& rRoot
) :
1029 XclExpChFutureRecordBase( rRoot
, EXC_FUTUREREC_UNUSEDREF
, EXC_ID_CHFRLABELPROPS
, 4 )
1033 void XclExpChFrLabelProps::Convert( const ScfPropertySet
& rPropSet
, bool bShowSeries
,
1034 bool bShowCateg
, bool bShowValue
, bool bShowPercent
, bool bShowBubble
)
1036 // label value flags
1037 ::set_flag( maData
.mnFlags
, EXC_CHFRLABELPROPS_SHOWSERIES
, bShowSeries
);
1038 ::set_flag( maData
.mnFlags
, EXC_CHFRLABELPROPS_SHOWCATEG
, bShowCateg
);
1039 ::set_flag( maData
.mnFlags
, EXC_CHFRLABELPROPS_SHOWVALUE
, bShowValue
);
1040 ::set_flag( maData
.mnFlags
, EXC_CHFRLABELPROPS_SHOWPERCENT
, bShowPercent
);
1041 ::set_flag( maData
.mnFlags
, EXC_CHFRLABELPROPS_SHOWBUBBLE
, bShowBubble
);
1043 // label value separator
1044 rPropSet
.GetStringProperty( maData
.maSeparator
, EXC_CHPROP_LABELSEPARATOR
);
1045 if( maData
.maSeparator
.Len() == 0 )
1046 maData
.maSeparator
= String( sal_Unicode( ' ' ) );
1049 void XclExpChFrLabelProps::WriteBody( XclExpStream
& rStrm
)
1051 XclExpString
aXclSep( maData
.maSeparator
, EXC_STR_FORCEUNICODE
| EXC_STR_SMARTFLAGS
);
1052 rStrm
<< maData
.mnFlags
<< aXclSep
;
1055 // ----------------------------------------------------------------------------
1057 XclExpChFontBase::~XclExpChFontBase()
1061 void XclExpChFontBase::ConvertFontBase( const XclExpChRoot
& rRoot
, sal_uInt16 nFontIdx
)
1063 if( const XclExpFont
* pFont
= rRoot
.GetFontBuffer().GetFont( nFontIdx
) )
1065 XclExpChFontRef
xFont( new XclExpChFont( nFontIdx
) );
1066 SetFont( xFont
, pFont
->GetFontData().maColor
, pFont
->GetFontColorId() );
1070 void XclExpChFontBase::ConvertFontBase( const XclExpChRoot
& rRoot
, const ScfPropertySet
& rPropSet
)
1072 ConvertFontBase( rRoot
, rRoot
.ConvertFont( rPropSet
, rRoot
.GetDefApiScript() ) );
1075 void XclExpChFontBase::ConvertRotationBase(
1076 const XclExpChRoot
& rRoot
, const ScfPropertySet
& rPropSet
, bool bSupportsStacked
)
1078 sal_uInt16 nRotation
= rRoot
.GetChartPropSetHelper().ReadRotationProperties( rPropSet
, bSupportsStacked
);
1079 SetRotation( nRotation
);
1082 // ----------------------------------------------------------------------------
1084 XclExpChText::XclExpChText( const XclExpChRoot
& rRoot
) :
1085 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_TEXT
, EXC_ID_CHTEXT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 32 : 26 ),
1086 mnTextColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
1090 void XclExpChText::SetFont( XclExpChFontRef xFont
, const Color
& rColor
, sal_uInt32 nColorId
)
1093 maData
.maTextColor
= rColor
;
1094 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOCOLOR
, rColor
== COL_AUTO
);
1095 mnTextColorId
= nColorId
;
1098 void XclExpChText::SetRotation( sal_uInt16 nRotation
)
1100 maData
.mnRotation
= nRotation
;
1101 ::insert_value( maData
.mnFlags
, XclTools::GetXclOrientFromRot( nRotation
), 8, 3 );
1104 void XclExpChText::ConvertTitle( Reference
< XTitle
> xTitle
, sal_uInt16 nTarget
, const String
* pSubTitle
)
1108 case EXC_CHOBJLINK_TITLE
: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_TITLE
); break;
1109 case EXC_CHOBJLINK_YAXIS
: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_AXISTITLE
, 1 ); break;
1110 case EXC_CHOBJLINK_XAXIS
: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_AXISTITLE
, 0 ); break;
1111 case EXC_CHOBJLINK_ZAXIS
: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_AXISTITLE
, 2 ); break;
1115 mxObjLink
.reset( new XclExpChObjectLink( nTarget
, XclChDataPointPos( 0, 0 ) ) );
1119 // title frame formatting
1120 ScfPropertySet
aTitleProp( xTitle
);
1121 mxFrame
= lclCreateFrame( GetChRoot(), aTitleProp
, EXC_CHOBJTYPE_TEXT
);
1124 mxSrcLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1125 sal_uInt16 nFontIdx
= mxSrcLink
->ConvertStringSequence( xTitle
->getText() );
1128 // append subtitle as the 2nd line of the title.
1129 String aSubTitle
= String::CreateFromAscii("\n");
1130 aSubTitle
.Append(*pSubTitle
);
1131 mxSrcLink
->AppendString(aSubTitle
);
1134 ConvertFontBase( GetChRoot(), nFontIdx
);
1137 ConvertRotationBase( GetChRoot(), aTitleProp
, true );
1141 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_DELETED
);
1145 void XclExpChText::ConvertLegend( const ScfPropertySet
& rPropSet
)
1147 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOTEXT
);
1148 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOGEN
);
1149 ConvertFontBase( GetChRoot(), rPropSet
);
1152 bool XclExpChText::ConvertDataLabel( const ScfPropertySet
& rPropSet
,
1153 const XclChTypeInfo
& rTypeInfo
, const XclChDataPointPos
& rPointPos
)
1155 SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_DATALABEL
, rPointPos
.mnPointIdx
, rPointPos
.mnSeriesIdx
);
1157 namespace cssc
= ::com::sun::star::chart2
;
1158 cssc::DataPointLabel aPointLabel
;
1159 if( !rPropSet
.GetProperty( aPointLabel
, EXC_CHPROP_LABEL
) )
1162 // percentage only allowed in pie and donut charts
1163 bool bIsPie
= rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
;
1164 // bubble sizes only allowed in bubble charts
1165 bool bIsBubble
= rTypeInfo
.meTypeId
== EXC_CHTYPEID_BUBBLES
;
1166 DBG_ASSERT( (GetBiff() == EXC_BIFF8
) || !bIsBubble
, "XclExpChText::ConvertDataLabel - bubble charts only in BIFF8" );
1169 bool bShowValue
= !bIsBubble
&& aPointLabel
.ShowNumber
; // Chart2 uses 'ShowNumber' for bubble size
1170 bool bShowPercent
= bIsPie
&& aPointLabel
.ShowNumberInPercent
; // percentage only in pie/donut charts
1171 bool bShowCateg
= aPointLabel
.ShowCategoryName
;
1172 bool bShowBubble
= bIsBubble
&& aPointLabel
.ShowNumber
; // Chart2 uses 'ShowNumber' for bubble size
1173 bool bShowAny
= bShowValue
|| bShowPercent
|| bShowCateg
|| bShowBubble
;
1175 // create the CHFRLABELPROPS record for extended settings in BIFF8
1176 if( bShowAny
&& (GetBiff() == EXC_BIFF8
) )
1178 mxLabelProps
.reset( new XclExpChFrLabelProps( GetChRoot() ) );
1179 mxLabelProps
->Convert( rPropSet
, false, bShowCateg
, bShowValue
, bShowPercent
, bShowBubble
);
1182 // restrict to combinations allowed in CHTEXT
1183 if( bShowPercent
) bShowValue
= false; // percent wins over value
1184 if( bShowValue
) bShowCateg
= false; // value wins over category
1185 if( bShowValue
|| bShowCateg
) bShowBubble
= false; // value or category wins over bubble size
1188 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOTEXT
);
1189 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWVALUE
, bShowValue
);
1190 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWPERCENT
, bShowPercent
);
1191 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
, bShowCateg
);
1192 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEGPERC
, bShowPercent
&& bShowCateg
);
1193 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWBUBBLE
, bShowBubble
);
1194 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWSYMBOL
, bShowAny
&& aPointLabel
.ShowLegendSymbol
);
1195 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_DELETED
, !bShowAny
);
1200 ConvertFontBase( GetChRoot(), rPropSet
);
1201 ConvertRotationBase( GetChRoot(), rPropSet
, false );
1203 sal_Int32 nPlacement
= 0;
1204 if( rPropSet
.GetProperty( nPlacement
, EXC_CHPROP_LABELPLACEMENT
) )
1206 using namespace ::com::sun::star::chart::DataLabelPlacement
;
1207 if( nPlacement
== rTypeInfo
.mnDefaultLabelPos
)
1209 maData
.mnPlacement
= EXC_CHTEXT_POS_DEFAULT
;
1211 else switch( nPlacement
)
1213 case AVOID_OVERLAP
: maData
.mnPlacement
= EXC_CHTEXT_POS_AUTO
; break;
1214 case CENTER
: maData
.mnPlacement
= EXC_CHTEXT_POS_CENTER
; break;
1215 case TOP
: maData
.mnPlacement
= EXC_CHTEXT_POS_ABOVE
; break;
1216 case TOP_LEFT
: maData
.mnPlacement
= EXC_CHTEXT_POS_LEFT
; break;
1217 case LEFT
: maData
.mnPlacement
= EXC_CHTEXT_POS_LEFT
; break;
1218 case BOTTOM_LEFT
: maData
.mnPlacement
= EXC_CHTEXT_POS_LEFT
; break;
1219 case BOTTOM
: maData
.mnPlacement
= EXC_CHTEXT_POS_BELOW
; break;
1220 case BOTTOM_RIGHT
: maData
.mnPlacement
= EXC_CHTEXT_POS_RIGHT
; break;
1221 case RIGHT
: maData
.mnPlacement
= EXC_CHTEXT_POS_RIGHT
; break;
1222 case TOP_RIGHT
: maData
.mnPlacement
= EXC_CHTEXT_POS_RIGHT
; break;
1223 case INSIDE
: maData
.mnPlacement
= EXC_CHTEXT_POS_INSIDE
; break;
1224 case OUTSIDE
: maData
.mnPlacement
= EXC_CHTEXT_POS_OUTSIDE
; break;
1225 case NEAR_ORIGIN
: maData
.mnPlacement
= EXC_CHTEXT_POS_AXIS
; break;
1226 default: DBG_ERRORFILE( "XclExpChText::ConvertDataLabel - unknown label placement type" );
1229 // source link (contains number format)
1230 mxSrcLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1231 if( bShowValue
|| bShowPercent
)
1232 // percentage format wins over value format
1233 mxSrcLink
->ConvertNumFmt( rPropSet
, bShowPercent
);
1235 mxObjLink
.reset( new XclExpChObjectLink( EXC_CHOBJLINK_DATA
, rPointPos
) );
1238 /* Return true to indicate valid label settings:
1239 - for existing labels at entire series
1240 - for any settings at single data point (to be able to delete a point label) */
1241 return bShowAny
|| (rPointPos
.mnPointIdx
!= EXC_CHDATAFORMAT_ALLPOINTS
);
1244 void XclExpChText::ConvertTrendLineEquation( const ScfPropertySet
& rPropSet
, const XclChDataPointPos
& rPointPos
)
1247 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOTEXT
);
1248 if( GetBiff() == EXC_BIFF8
)
1249 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
); // must set this to make equation visible in Excel
1251 mxFrame
= lclCreateFrame( GetChRoot(), rPropSet
, EXC_CHOBJTYPE_TEXT
);
1253 maData
.mnHAlign
= EXC_CHTEXT_ALIGN_TOPLEFT
;
1254 maData
.mnVAlign
= EXC_CHTEXT_ALIGN_TOPLEFT
;
1255 ConvertFontBase( GetChRoot(), rPropSet
);
1256 // source link (contains number format)
1257 mxSrcLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1258 mxSrcLink
->ConvertNumFmt( rPropSet
, false );
1260 mxObjLink
.reset( new XclExpChObjectLink( EXC_CHOBJLINK_DATA
, rPointPos
) );
1263 sal_uInt16
XclExpChText::GetAttLabelFlags() const
1265 sal_uInt16 nFlags
= 0;
1266 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWVALUE
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWVALUE
) );
1267 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWPERCENT
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWPERCENT
) );
1268 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWCATEGPERC
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEGPERC
) );
1269 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWCATEG
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
) );
1273 void XclExpChText::WriteSubRecords( XclExpStream
& rStrm
)
1276 lclSaveRecord( rStrm
, mxFont
);
1277 // CHSOURCELINK group
1278 lclSaveRecord( rStrm
, mxSrcLink
);
1280 lclSaveRecord( rStrm
, mxFrame
);
1281 // CHOBJECTLINK record
1282 lclSaveRecord( rStrm
, mxObjLink
);
1283 // CHFRLABELPROPS record
1284 lclSaveRecord( rStrm
, mxLabelProps
);
1287 void XclExpChText::WriteBody( XclExpStream
& rStrm
)
1289 rStrm
<< maData
.mnHAlign
1291 << maData
.mnBackMode
1292 << maData
.maTextColor
1296 if( GetBiff() == EXC_BIFF8
)
1298 rStrm
<< GetPalette().GetColorIndex( mnTextColorId
)
1299 << maData
.mnPlacement
1300 << maData
.mnRotation
;
1304 // ----------------------------------------------------------------------------
1308 /** Creates and returns an Excel text object from the passed title. */
1309 XclExpChTextRef
lclCreateTitle( const XclExpChRoot
& rRoot
, Reference
< XTitled
> xTitled
, sal_uInt16 nTarget
,
1310 const String
* pSubTitle
= NULL
)
1312 Reference
< XTitle
> xTitle
;
1314 xTitle
= xTitled
->getTitleObject();
1316 XclExpChTextRef
xText( new XclExpChText( rRoot
) );
1317 xText
->ConvertTitle( xTitle
, nTarget
, pSubTitle
);
1318 /* Do not delete the CHTEXT group for the main title. A missing CHTEXT
1319 will be interpreted as auto-generated title showing the series title in
1320 charts that contain exactly one data series. */
1321 if( (nTarget
!= EXC_CHOBJLINK_TITLE
) && !xText
->HasString() )
1329 // Data series ================================================================
1331 XclExpChMarkerFormat::XclExpChMarkerFormat( const XclExpChRoot
& rRoot
) :
1332 XclExpRecord( EXC_ID_CHMARKERFORMAT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 20 : 12 ),
1333 mnLineColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) ),
1334 mnFillColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) )
1338 void XclExpChMarkerFormat::Convert( const XclExpChRoot
& rRoot
,
1339 const ScfPropertySet
& rPropSet
, sal_uInt16 nFormatIdx
)
1341 rRoot
.GetChartPropSetHelper().ReadMarkerProperties( maData
, rPropSet
, nFormatIdx
);
1342 /* Set marker line/fill color to series line color.
1343 TODO: remove this if OOChart supports own colors in markers. */
1345 if( rPropSet
.GetColorProperty( aLineColor
, EXC_CHPROP_COLOR
) )
1346 maData
.maLineColor
= maData
.maFillColor
= aLineColor
;
1347 // register colors in palette
1348 RegisterColors( rRoot
);
1351 void XclExpChMarkerFormat::ConvertStockSymbol( const XclExpChRoot
& rRoot
,
1352 const ScfPropertySet
& rPropSet
, bool bCloseSymbol
)
1354 // clear the automatic flag
1355 ::set_flag( maData
.mnFlags
, EXC_CHMARKERFORMAT_AUTO
, false );
1356 // symbol type and color
1359 // set symbol type for the 'close' data series
1360 maData
.mnMarkerType
= EXC_CHMARKERFORMAT_DOWJ
;
1361 maData
.mnMarkerSize
= EXC_CHMARKERFORMAT_DOUBLESIZE
;
1362 // set symbol line/fill color to series line color
1364 if( rPropSet
.GetColorProperty( aLineColor
, EXC_CHPROP_COLOR
) )
1366 maData
.maLineColor
= maData
.maFillColor
= aLineColor
;
1367 RegisterColors( rRoot
);
1372 // set invisible symbol
1373 maData
.mnMarkerType
= EXC_CHMARKERFORMAT_NOSYMBOL
;
1377 void XclExpChMarkerFormat::RegisterColors( const XclExpChRoot
& rRoot
)
1381 if( HasLineColor() )
1382 mnLineColorId
= rRoot
.GetPalette().InsertColor( maData
.maLineColor
, EXC_COLOR_CHARTLINE
);
1383 if( HasFillColor() )
1384 mnFillColorId
= rRoot
.GetPalette().InsertColor( maData
.maFillColor
, EXC_COLOR_CHARTAREA
);
1388 void XclExpChMarkerFormat::WriteBody( XclExpStream
& rStrm
)
1390 rStrm
<< maData
.maLineColor
<< maData
.maFillColor
<< maData
.mnMarkerType
<< maData
.mnFlags
;
1391 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
1393 const XclExpPalette
& rPal
= rStrm
.GetRoot().GetPalette();
1394 rStrm
<< rPal
.GetColorIndex( mnLineColorId
) << rPal
.GetColorIndex( mnFillColorId
) << maData
.mnMarkerSize
;
1398 // ----------------------------------------------------------------------------
1400 XclExpChPieFormat::XclExpChPieFormat() :
1401 XclExpUInt16Record( EXC_ID_CHPIEFORMAT
, 0 )
1405 void XclExpChPieFormat::Convert( const ScfPropertySet
& rPropSet
)
1407 double fApiDist(0.0);
1408 if( rPropSet
.GetProperty( fApiDist
, EXC_CHPROP_OFFSET
) )
1409 SetValue( limit_cast
< sal_uInt16
>( fApiDist
* 100.0, 0, 100 ) );
1412 // ----------------------------------------------------------------------------
1414 XclExpCh3dDataFormat::XclExpCh3dDataFormat() :
1415 XclExpRecord( EXC_ID_CH3DDATAFORMAT
, 2 )
1419 void XclExpCh3dDataFormat::Convert( const ScfPropertySet
& rPropSet
)
1421 sal_Int32
nApiType(0);
1422 if( rPropSet
.GetProperty( nApiType
, EXC_CHPROP_GEOMETRY3D
) )
1424 using namespace ::com::sun::star::chart2::DataPointGeometry3D
;
1428 maData
.mnBase
= EXC_CH3DDATAFORMAT_RECT
;
1429 maData
.mnTop
= EXC_CH3DDATAFORMAT_STRAIGHT
;
1432 maData
.mnBase
= EXC_CH3DDATAFORMAT_RECT
;
1433 maData
.mnTop
= EXC_CH3DDATAFORMAT_SHARP
;
1436 maData
.mnBase
= EXC_CH3DDATAFORMAT_CIRC
;
1437 maData
.mnTop
= EXC_CH3DDATAFORMAT_STRAIGHT
;
1440 maData
.mnBase
= EXC_CH3DDATAFORMAT_CIRC
;
1441 maData
.mnTop
= EXC_CH3DDATAFORMAT_SHARP
;
1444 DBG_ERRORFILE( "XclExpCh3dDataFormat::Convert - unknown 3D bar format" );
1449 void XclExpCh3dDataFormat::WriteBody( XclExpStream
& rStrm
)
1451 rStrm
<< maData
.mnBase
<< maData
.mnTop
;
1454 // ----------------------------------------------------------------------------
1456 XclExpChAttachedLabel::XclExpChAttachedLabel( sal_uInt16 nFlags
) :
1457 XclExpUInt16Record( EXC_ID_CHATTACHEDLABEL
, nFlags
)
1461 // ----------------------------------------------------------------------------
1463 XclExpChDataFormat::XclExpChDataFormat( const XclExpChRoot
& rRoot
,
1464 const XclChDataPointPos
& rPointPos
, sal_uInt16 nFormatIdx
) :
1465 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_DATAFORMAT
, EXC_ID_CHDATAFORMAT
, 8 )
1467 maData
.maPointPos
= rPointPos
;
1468 maData
.mnFormatIdx
= nFormatIdx
;
1471 void XclExpChDataFormat::ConvertDataSeries( const ScfPropertySet
& rPropSet
, const XclChExtTypeInfo
& rTypeInfo
)
1473 // line and area formatting
1474 ConvertFrameBase( GetChRoot(), rPropSet
, rTypeInfo
.GetSeriesObjectType() );
1476 // data point symbols
1477 bool bIsFrame
= rTypeInfo
.IsSeriesFrameFormat();
1480 mxMarkerFmt
.reset( new XclExpChMarkerFormat( GetChRoot() ) );
1481 mxMarkerFmt
->Convert( GetChRoot(), rPropSet
, maData
.mnFormatIdx
);
1485 if( rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
)
1487 mxPieFmt
.reset( new XclExpChPieFormat
);
1488 mxPieFmt
->Convert( rPropSet
);
1491 // 3D bars (only allowed for entire series in BIFF8)
1492 if( IsSeriesFormat() && (GetBiff() == EXC_BIFF8
) && rTypeInfo
.mb3dChart
&& (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_BAR
) )
1494 mx3dDataFmt
.reset( new XclExpCh3dDataFormat
);
1495 mx3dDataFmt
->Convert( rPropSet
);
1499 if( IsSeriesFormat() && rTypeInfo
.mbSpline
&& !bIsFrame
)
1500 mxSeriesFmt
.reset( new XclExpUInt16Record( EXC_ID_CHSERIESFORMAT
, EXC_CHSERIESFORMAT_SMOOTHED
) );
1502 // data point labels
1503 XclExpChTextRef
xLabel( new XclExpChText( GetChRoot() ) );
1504 if( xLabel
->ConvertDataLabel( rPropSet
, rTypeInfo
, maData
.maPointPos
) )
1506 // CHTEXT groups for data labels are stored in global CHCHART group
1507 GetChartData().SetDataLabel( xLabel
);
1508 mxAttLabel
.reset( new XclExpChAttachedLabel( xLabel
->GetAttLabelFlags() ) );
1512 void XclExpChDataFormat::ConvertStockSeries( const ScfPropertySet
& rPropSet
, bool bCloseSymbol
)
1514 // set line format to invisible
1515 SetDefaultFrameBase( GetChRoot(), EXC_CHFRAMETYPE_INVISIBLE
, false );
1516 // set symbols to invisible or to 'close' series symbol
1517 mxMarkerFmt
.reset( new XclExpChMarkerFormat( GetChRoot() ) );
1518 mxMarkerFmt
->ConvertStockSymbol( GetChRoot(), rPropSet
, bCloseSymbol
);
1521 void XclExpChDataFormat::ConvertLine( const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
1523 ConvertFrameBase( GetChRoot(), rPropSet
, eObjType
);
1526 void XclExpChDataFormat::WriteSubRecords( XclExpStream
& rStrm
)
1528 lclSaveRecord( rStrm
, mx3dDataFmt
);
1529 WriteFrameRecords( rStrm
);
1530 lclSaveRecord( rStrm
, mxPieFmt
);
1531 lclSaveRecord( rStrm
, mxMarkerFmt
);
1532 lclSaveRecord( rStrm
, mxSeriesFmt
);
1533 lclSaveRecord( rStrm
, mxAttLabel
);
1536 void XclExpChDataFormat::WriteBody( XclExpStream
& rStrm
)
1538 rStrm
<< maData
.maPointPos
.mnPointIdx
1539 << maData
.maPointPos
.mnSeriesIdx
1540 << maData
.mnFormatIdx
1544 // ----------------------------------------------------------------------------
1546 XclExpChSerTrendLine::XclExpChSerTrendLine( const XclExpChRoot
& rRoot
) :
1547 XclExpRecord( EXC_ID_CHSERTRENDLINE
, 28 ),
1548 XclExpChRoot( rRoot
)
1552 bool XclExpChSerTrendLine::Convert( Reference
< XRegressionCurve
> xRegCurve
, sal_uInt16 nSeriesIdx
)
1554 if( !xRegCurve
.is() )
1558 ScfPropertySet
aCurveProp( xRegCurve
);
1559 OUString aService
= aCurveProp
.GetServiceName();
1560 if( aService
== SERVICE_CHART2_LINEARREGCURVE
)
1562 maData
.mnLineType
= EXC_CHSERTREND_POLYNOMIAL
;
1565 else if( aService
== SERVICE_CHART2_EXPREGCURVE
)
1566 maData
.mnLineType
= EXC_CHSERTREND_EXPONENTIAL
;
1567 else if( aService
== SERVICE_CHART2_LOGREGCURVE
)
1568 maData
.mnLineType
= EXC_CHSERTREND_LOGARITHMIC
;
1569 else if( aService
== SERVICE_CHART2_POTREGCURVE
)
1570 maData
.mnLineType
= EXC_CHSERTREND_POWER
;
1575 XclChDataPointPos
aPointPos( nSeriesIdx
);
1576 mxDataFmt
.reset( new XclExpChDataFormat( GetChRoot(), aPointPos
, 0 ) );
1577 mxDataFmt
->ConvertLine( aCurveProp
, EXC_CHOBJTYPE_TRENDLINE
);
1579 // #i83100# show equation and correlation coefficient
1580 ScfPropertySet
aEquationProp( xRegCurve
->getEquationProperties() );
1581 maData
.mnShowEquation
= aEquationProp
.GetBoolProperty( EXC_CHPROP_SHOWEQUATION
) ? 1 : 0;
1582 maData
.mnShowRSquared
= aEquationProp
.GetBoolProperty( EXC_CHPROP_SHOWCORRELATION
) ? 1 : 0;
1584 // #i83100# formatting of the equation text box
1585 if( (maData
.mnShowEquation
!= 0) || (maData
.mnShowRSquared
!= 0) )
1587 mxLabel
.reset( new XclExpChText( GetChRoot() ) );
1588 mxLabel
->ConvertTrendLineEquation( aEquationProp
, aPointPos
);
1592 // #i20819# polynomial trend lines
1593 // #i66819# moving average trend lines
1594 // #i5085# manual trend line size
1595 // #i34093# manual crossing point
1599 void XclExpChSerTrendLine::WriteBody( XclExpStream
& rStrm
)
1601 rStrm
<< maData
.mnLineType
1603 << maData
.mfIntercept
1604 << maData
.mnShowEquation
1605 << maData
.mnShowRSquared
1606 << maData
.mfForecastFor
1607 << maData
.mfForecastBack
;
1610 // ----------------------------------------------------------------------------
1612 XclExpChSerErrorBar::XclExpChSerErrorBar( const XclExpChRoot
& rRoot
, sal_uInt8 nBarType
) :
1613 XclExpRecord( EXC_ID_CHSERERRORBAR
, 14 ),
1614 XclExpChRoot( rRoot
)
1616 maData
.mnBarType
= nBarType
;
1619 bool XclExpChSerErrorBar::Convert( XclExpChSourceLink
& rValueLink
, sal_uInt16
& rnValueCount
, const ScfPropertySet
& rPropSet
)
1621 sal_Int32 nBarStyle
= 0;
1622 bool bOk
= rPropSet
.GetProperty( nBarStyle
, EXC_CHPROP_ERRORBARSTYLE
);
1625 namespace cssc
= ::com::sun::star::chart
;
1628 case cssc::ErrorBarStyle::ABSOLUTE
:
1629 maData
.mnSourceType
= EXC_CHSERERR_FIXED
;
1630 rPropSet
.GetProperty( maData
.mfValue
, EXC_CHPROP_POSITIVEERROR
);
1632 case cssc::ErrorBarStyle::RELATIVE
:
1633 maData
.mnSourceType
= EXC_CHSERERR_PERCENT
;
1634 rPropSet
.GetProperty( maData
.mfValue
, EXC_CHPROP_POSITIVEERROR
);
1636 case cssc::ErrorBarStyle::STANDARD_DEVIATION
:
1637 maData
.mnSourceType
= EXC_CHSERERR_STDDEV
;
1638 rPropSet
.GetProperty( maData
.mfValue
, EXC_CHPROP_WEIGHT
);
1640 case cssc::ErrorBarStyle::STANDARD_ERROR
:
1641 maData
.mnSourceType
= EXC_CHSERERR_STDERR
;
1643 case cssc::ErrorBarStyle::FROM_DATA
:
1646 maData
.mnSourceType
= EXC_CHSERERR_CUSTOM
;
1647 Reference
< XDataSource
> xDataSource( rPropSet
.GetApiPropertySet(), UNO_QUERY
);
1648 if( xDataSource
.is() )
1650 // find first sequence with current role
1651 OUString aRole
= XclChartHelper::GetErrorBarValuesRole( maData
.mnBarType
);
1652 Reference
< XDataSequence
> xValueSeq
;
1654 Sequence
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
= xDataSource
->getDataSequences();
1655 const Reference
< XLabeledDataSequence
>* pBeg
= aLabeledSeqVec
.getConstArray();
1656 const Reference
< XLabeledDataSequence
>* pEnd
= pBeg
+ aLabeledSeqVec
.getLength();
1657 for( const Reference
< XLabeledDataSequence
>* pIt
= pBeg
; !xValueSeq
.is() && (pIt
!= pEnd
); ++pIt
)
1659 Reference
< XDataSequence
> xTmpValueSeq
= (*pIt
)->getValues();
1660 ScfPropertySet
aValueProp( xTmpValueSeq
);
1662 if( aValueProp
.GetProperty( aCurrRole
, EXC_CHPROP_ROLE
) && (aCurrRole
== aRole
) )
1663 xValueSeq
= xTmpValueSeq
;
1665 if( xValueSeq
.is() )
1667 // #i86465# pass value count back to series
1668 rnValueCount
= maData
.mnValueCount
= rValueLink
.ConvertDataSequence( xValueSeq
, true );
1669 bOk
= maData
.mnValueCount
> 0;
1681 void XclExpChSerErrorBar::WriteBody( XclExpStream
& rStrm
)
1683 rStrm
<< maData
.mnBarType
1684 << maData
.mnSourceType
1686 << sal_uInt8( 1 ) // must be 1 to make line visible
1688 << maData
.mnValueCount
;
1691 // ----------------------------------------------------------------------------
1695 /** Returns the property set of the specified data point. */
1696 ScfPropertySet
lclGetPointPropSet( Reference
< XDataSeries
> xDataSeries
, sal_Int32 nPointIdx
)
1698 ScfPropertySet aPropSet
;
1701 aPropSet
.Set( xDataSeries
->getDataPointByIndex( nPointIdx
) );
1705 DBG_ERRORFILE( "lclGetPointPropSet - no data point property set" );
1712 XclExpChSeries::XclExpChSeries( const XclExpChRoot
& rRoot
, sal_uInt16 nSeriesIdx
) :
1713 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_SERIES
, EXC_ID_CHSERIES
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 12 : 8 ),
1714 mnGroupIdx( EXC_CHSERGROUP_NONE
),
1715 mnSeriesIdx( nSeriesIdx
),
1716 mnParentIdx( EXC_CHSERIES_INVALID
)
1718 // CHSOURCELINK records are always required, even if unused
1719 mxTitleLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1720 mxValueLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_VALUES
) );
1721 mxCategLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_CATEGORY
) );
1722 if( GetBiff() == EXC_BIFF8
)
1723 mxBubbleLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_BUBBLES
) );
1726 bool XclExpChSeries::ConvertDataSeries(
1727 Reference
< XDiagram
> xDiagram
, Reference
< XDataSeries
> xDataSeries
,
1728 const XclChExtTypeInfo
& rTypeInfo
, sal_uInt16 nGroupIdx
, sal_uInt16 nFormatIdx
)
1731 Reference
< XDataSource
> xDataSource( xDataSeries
, UNO_QUERY
);
1732 if( xDataSource
.is() )
1734 Reference
< XDataSequence
> xYValueSeq
, xTitleSeq
, xXValueSeq
, xBubbleSeq
;
1736 // find first sequence with role 'values-y'
1737 Sequence
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
= xDataSource
->getDataSequences();
1738 const Reference
< XLabeledDataSequence
>* pBeg
= aLabeledSeqVec
.getConstArray();
1739 const Reference
< XLabeledDataSequence
>* pEnd
= pBeg
+ aLabeledSeqVec
.getLength();
1740 for( const Reference
< XLabeledDataSequence
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
1742 Reference
< XDataSequence
> xTmpValueSeq
= (*pIt
)->getValues();
1743 ScfPropertySet
aValueProp( xTmpValueSeq
);
1745 if( aValueProp
.GetProperty( aRole
, EXC_CHPROP_ROLE
) )
1747 if( !xYValueSeq
.is() && (aRole
== EXC_CHPROP_ROLE_YVALUES
) )
1749 xYValueSeq
= xTmpValueSeq
;
1750 if( !xTitleSeq
.is() )
1751 xTitleSeq
= (*pIt
)->getLabel(); // ignore role of label sequence
1753 else if( !xXValueSeq
.is() && !rTypeInfo
.mbCategoryAxis
&& (aRole
== EXC_CHPROP_ROLE_XVALUES
) )
1755 xXValueSeq
= xTmpValueSeq
;
1757 else if( !xBubbleSeq
.is() && (rTypeInfo
.meTypeId
== EXC_CHTYPEID_BUBBLES
) && (aRole
== EXC_CHPROP_ROLE_SIZEVALUES
) )
1759 xBubbleSeq
= xTmpValueSeq
;
1760 xTitleSeq
= (*pIt
)->getLabel(); // ignore role of label sequence
1765 bOk
= xYValueSeq
.is();
1768 // chart type group index
1769 mnGroupIdx
= nGroupIdx
;
1771 // convert source links
1772 maData
.mnValueCount
= mxValueLink
->ConvertDataSequence( xYValueSeq
, true );
1773 mxTitleLink
->ConvertDataSequence( xTitleSeq
, true );
1775 // X values of XY charts
1776 maData
.mnCategCount
= mxCategLink
->ConvertDataSequence( xXValueSeq
, false, maData
.mnValueCount
);
1778 // size values of bubble charts
1779 if( mxBubbleLink
.is() )
1780 mxBubbleLink
->ConvertDataSequence( xBubbleSeq
, false, maData
.mnValueCount
);
1782 // series formatting
1783 XclChDataPointPos
aPointPos( mnSeriesIdx
);
1784 ScfPropertySet
aSeriesProp( xDataSeries
);
1785 mxSeriesFmt
.reset( new XclExpChDataFormat( GetChRoot(), aPointPos
, nFormatIdx
) );
1786 mxSeriesFmt
->ConvertDataSeries( aSeriesProp
, rTypeInfo
);
1789 CreateTrendLines( xDataSeries
);
1792 CreateErrorBars( aSeriesProp
, EXC_CHPROP_ERRORBARX
, EXC_CHSERERR_XPLUS
, EXC_CHSERERR_XMINUS
);
1793 CreateErrorBars( aSeriesProp
, EXC_CHPROP_ERRORBARY
, EXC_CHSERERR_YPLUS
, EXC_CHSERERR_YMINUS
);
1795 if( maData
.mnValueCount
> 0 )
1797 const sal_Int32 nMaxPointCount
= maData
.mnValueCount
;
1799 /* #i91063# Create missing fill properties in pie/doughnut charts.
1800 If freshly created (never saved to ODF), these charts show
1801 varying point colors but do not return these points via API. */
1802 if( xDiagram
.is() && (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
) )
1804 Reference
< XColorScheme
> xColorScheme
= xDiagram
->getDefaultColorScheme();
1805 if( xColorScheme
.is() )
1807 const OUString aFillStyleName
= CREATE_OUSTRING( "FillStyle" );
1808 const OUString aColorName
= CREATE_OUSTRING( "Color" );
1809 namespace cssd
= ::com::sun::star::drawing
;
1810 for( sal_Int32 nPointIdx
= 0; nPointIdx
< nMaxPointCount
; ++nPointIdx
)
1812 aPointPos
.mnPointIdx
= static_cast< sal_uInt16
>( nPointIdx
);
1813 ScfPropertySet aPointProp
= lclGetPointPropSet( xDataSeries
, nPointIdx
);
1814 // test that the point fill style is solid, but no color is set
1815 cssd::FillStyle eFillStyle
= cssd::FillStyle_NONE
;
1816 if( aPointProp
.GetProperty( eFillStyle
, aFillStyleName
) &&
1817 (eFillStyle
== cssd::FillStyle_SOLID
) &&
1818 !aPointProp
.HasProperty( aColorName
) )
1820 aPointProp
.SetProperty( aColorName
, xColorScheme
->getColorByIndex( nPointIdx
) );
1826 // data point formatting
1827 Sequence
< sal_Int32
> aPointIndexes
;
1828 if( aSeriesProp
.GetProperty( aPointIndexes
, EXC_CHPROP_ATTRIBDATAPOINTS
) && aPointIndexes
.hasElements() )
1830 const sal_Int32
* pnBeg
= aPointIndexes
.getConstArray();
1831 const sal_Int32
* pnEnd
= pnBeg
+ aPointIndexes
.getLength();
1832 for( const sal_Int32
* pnIt
= pnBeg
; (pnIt
!= pnEnd
) && (*pnIt
< nMaxPointCount
); ++pnIt
)
1834 aPointPos
.mnPointIdx
= static_cast< sal_uInt16
>( *pnIt
);
1835 ScfPropertySet aPointProp
= lclGetPointPropSet( xDataSeries
, *pnIt
);
1836 XclExpChDataFormatRef
xPointFmt( new XclExpChDataFormat( GetChRoot(), aPointPos
, nFormatIdx
) );
1837 xPointFmt
->ConvertDataSeries( aPointProp
, rTypeInfo
);
1838 maPointFmts
.AppendRecord( xPointFmt
);
1847 bool XclExpChSeries::ConvertStockSeries( XDataSeriesRef xDataSeries
,
1848 const OUString
& rValueRole
, sal_uInt16 nGroupIdx
, sal_uInt16 nFormatIdx
, bool bCloseSymbol
)
1851 Reference
< XDataSource
> xDataSource( xDataSeries
, UNO_QUERY
);
1852 if( xDataSource
.is() )
1854 Reference
< XDataSequence
> xYValueSeq
, xTitleSeq
;
1856 // find first sequence with passed role
1857 Sequence
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
= xDataSource
->getDataSequences();
1858 const Reference
< XLabeledDataSequence
>* pBeg
= aLabeledSeqVec
.getConstArray();
1859 const Reference
< XLabeledDataSequence
>* pEnd
= pBeg
+ aLabeledSeqVec
.getLength();
1860 for( const Reference
< XLabeledDataSequence
>* pIt
= pBeg
; !xYValueSeq
.is() && (pIt
!= pEnd
); ++pIt
)
1862 Reference
< XDataSequence
> xTmpValueSeq
= (*pIt
)->getValues();
1863 ScfPropertySet
aValueProp( xTmpValueSeq
);
1865 if( aValueProp
.GetProperty( aRole
, EXC_CHPROP_ROLE
) && (aRole
== rValueRole
) )
1867 xYValueSeq
= xTmpValueSeq
;
1868 xTitleSeq
= (*pIt
)->getLabel(); // ignore role of label sequence
1872 bOk
= xYValueSeq
.is();
1875 // chart type group index
1876 mnGroupIdx
= nGroupIdx
;
1877 // convert source links
1878 maData
.mnValueCount
= mxValueLink
->ConvertDataSequence( xYValueSeq
, true );
1879 mxTitleLink
->ConvertDataSequence( xTitleSeq
, true );
1880 // series formatting
1881 ScfPropertySet
aSeriesProp( xDataSeries
);
1882 mxSeriesFmt
.reset( new XclExpChDataFormat( GetChRoot(), XclChDataPointPos( mnSeriesIdx
), nFormatIdx
) );
1883 mxSeriesFmt
->ConvertStockSeries( aSeriesProp
, bCloseSymbol
);
1889 bool XclExpChSeries::ConvertTrendLine( const XclExpChSeries
& rParent
, Reference
< XRegressionCurve
> xRegCurve
)
1891 InitFromParent( rParent
);
1892 mxTrendLine
.reset( new XclExpChSerTrendLine( GetChRoot() ) );
1893 bool bOk
= mxTrendLine
->Convert( xRegCurve
, mnSeriesIdx
);
1896 mxSeriesFmt
= mxTrendLine
->GetDataFormat();
1897 GetChartData().SetDataLabel( mxTrendLine
->GetDataLabel() );
1902 bool XclExpChSeries::ConvertErrorBar( const XclExpChSeries
& rParent
, const ScfPropertySet
& rPropSet
, sal_uInt8 nBarId
)
1904 InitFromParent( rParent
);
1905 // error bar settings
1906 mxErrorBar
.reset( new XclExpChSerErrorBar( GetChRoot(), nBarId
) );
1907 bool bOk
= mxErrorBar
->Convert( *mxValueLink
, maData
.mnValueCount
, rPropSet
);
1910 // error bar formatting
1911 mxSeriesFmt
.reset( new XclExpChDataFormat( GetChRoot(), XclChDataPointPos( mnSeriesIdx
), 0 ) );
1912 mxSeriesFmt
->ConvertLine( rPropSet
, EXC_CHOBJTYPE_ERRORBAR
);
1917 void XclExpChSeries::ConvertCategSequence( Reference
< XLabeledDataSequence
> xCategSeq
)
1919 if( xCategSeq
.is() )
1920 maData
.mnCategCount
= mxCategLink
->ConvertDataSequence( xCategSeq
->getValues(), false );
1923 void XclExpChSeries::WriteSubRecords( XclExpStream
& rStrm
)
1925 lclSaveRecord( rStrm
, mxTitleLink
);
1926 lclSaveRecord( rStrm
, mxValueLink
);
1927 lclSaveRecord( rStrm
, mxCategLink
);
1928 lclSaveRecord( rStrm
, mxBubbleLink
);
1929 lclSaveRecord( rStrm
, mxSeriesFmt
);
1930 maPointFmts
.Save( rStrm
);
1931 if( mnGroupIdx
!= EXC_CHSERGROUP_NONE
)
1932 XclExpUInt16Record( EXC_ID_CHSERGROUP
, mnGroupIdx
).Save( rStrm
);
1933 if( mnParentIdx
!= EXC_CHSERIES_INVALID
)
1934 XclExpUInt16Record( EXC_ID_CHSERPARENT
, mnParentIdx
).Save( rStrm
);
1935 lclSaveRecord( rStrm
, mxTrendLine
);
1936 lclSaveRecord( rStrm
, mxErrorBar
);
1939 void XclExpChSeries::InitFromParent( const XclExpChSeries
& rParent
)
1941 // index to parent series is stored 1-based
1942 mnParentIdx
= rParent
.mnSeriesIdx
+ 1;
1943 /* #i86465# MSO2007 SP1 expects correct point counts in child series
1944 (there was no problem in Excel2003 or Excel2007 without SP1...) */
1945 maData
.mnCategCount
= rParent
.maData
.mnCategCount
;
1946 maData
.mnValueCount
= rParent
.maData
.mnValueCount
;
1949 void XclExpChSeries::CreateTrendLines( XDataSeriesRef xDataSeries
)
1951 Reference
< XRegressionCurveContainer
> xRegCurveCont( xDataSeries
, UNO_QUERY
);
1952 if( xRegCurveCont
.is() )
1954 Sequence
< Reference
< XRegressionCurve
> > aRegCurveSeq
= xRegCurveCont
->getRegressionCurves();
1955 const Reference
< XRegressionCurve
>* pBeg
= aRegCurveSeq
.getConstArray();
1956 const Reference
< XRegressionCurve
>* pEnd
= pBeg
+ aRegCurveSeq
.getLength();
1957 for( const Reference
< XRegressionCurve
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
1959 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
1960 if( xSeries
.is() && !xSeries
->ConvertTrendLine( *this, *pIt
) )
1961 GetChartData().RemoveLastSeries();
1966 void XclExpChSeries::CreateErrorBars( const ScfPropertySet
& rPropSet
,
1967 const OUString
& rBarPropName
, sal_uInt8 nPosBarId
, sal_uInt8 nNegBarId
)
1969 Reference
< XPropertySet
> xErrorBar
;
1970 if( rPropSet
.GetProperty( xErrorBar
, rBarPropName
) && xErrorBar
.is() )
1972 ScfPropertySet
aErrorProp( xErrorBar
);
1973 CreateErrorBar( aErrorProp
, EXC_CHPROP_SHOWPOSITIVEERROR
, nPosBarId
);
1974 CreateErrorBar( aErrorProp
, EXC_CHPROP_SHOWNEGATIVEERROR
, nNegBarId
);
1978 void XclExpChSeries::CreateErrorBar( const ScfPropertySet
& rPropSet
,
1979 const OUString
& rShowPropName
, sal_uInt8 nBarId
)
1981 if( rPropSet
.GetBoolProperty( rShowPropName
) )
1983 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
1984 if( xSeries
.is() && !xSeries
->ConvertErrorBar( *this, rPropSet
, nBarId
) )
1985 GetChartData().RemoveLastSeries();
1989 void XclExpChSeries::WriteBody( XclExpStream
& rStrm
)
1991 rStrm
<< maData
.mnCategType
<< maData
.mnValueType
<< maData
.mnCategCount
<< maData
.mnValueCount
;
1992 if( GetBiff() == EXC_BIFF8
)
1993 rStrm
<< maData
.mnBubbleType
<< maData
.mnBubbleCount
;
1996 // Chart type groups ==========================================================
1998 XclExpChType::XclExpChType( const XclExpChRoot
& rRoot
) :
1999 XclExpRecord( EXC_ID_CHUNKNOWN
),
2000 XclExpChRoot( rRoot
),
2001 maTypeInfo( rRoot
.GetChartTypeInfo( EXC_CHTYPEID_UNKNOWN
) )
2005 void XclExpChType::Convert( Reference
< XDiagram
> xDiagram
, Reference
< XChartType
> xChartType
,
2006 sal_Int32 nApiAxesSetIdx
, bool bSwappedAxesSet
, bool bHasXLabels
)
2008 if( xChartType
.is() )
2010 maTypeInfo
= GetChartTypeInfo( xChartType
->getChartType() );
2011 // special handling for some chart types
2012 switch( maTypeInfo
.meTypeCateg
)
2014 case EXC_CHTYPECATEG_BAR
:
2016 maTypeInfo
= GetChartTypeInfo( bSwappedAxesSet
? EXC_CHTYPEID_HORBAR
: EXC_CHTYPEID_BAR
);
2017 ::set_flag( maData
.mnFlags
, EXC_CHBAR_HORIZONTAL
, bSwappedAxesSet
);
2018 ScfPropertySet
aTypeProp( xChartType
);
2019 Sequence
< sal_Int32
> aInt32Seq
;
2020 maData
.mnOverlap
= 0;
2021 if( aTypeProp
.GetProperty( aInt32Seq
, EXC_CHPROP_OVERLAPSEQ
) && (nApiAxesSetIdx
< aInt32Seq
.getLength()) )
2022 maData
.mnOverlap
= limit_cast
< sal_Int16
>( -aInt32Seq
[ nApiAxesSetIdx
], -100, 100 );
2024 if( aTypeProp
.GetProperty( aInt32Seq
, EXC_CHPROP_GAPWIDTHSEQ
) && (nApiAxesSetIdx
< aInt32Seq
.getLength()) )
2025 maData
.mnGap
= limit_cast
< sal_uInt16
>( aInt32Seq
[ nApiAxesSetIdx
], 0, 500 );
2028 case EXC_CHTYPECATEG_RADAR
:
2029 ::set_flag( maData
.mnFlags
, EXC_CHRADAR_AXISLABELS
, bHasXLabels
);
2031 case EXC_CHTYPECATEG_PIE
:
2033 ScfPropertySet
aTypeProp( xChartType
);
2034 bool bDonut
= aTypeProp
.GetBoolProperty( EXC_CHPROP_USERINGS
);
2035 maTypeInfo
= GetChartTypeInfo( bDonut
? EXC_CHTYPEID_DONUT
: EXC_CHTYPEID_PIE
);
2036 maData
.mnPieHole
= bDonut
? 50 : 0;
2037 // #i85166# starting angle of first pie slice
2038 ScfPropertySet
aDiaProp( xDiagram
);
2039 maData
.mnRotation
= XclExpChRoot::ConvertPieRotation( aDiaProp
);
2042 case EXC_CHTYPECATEG_SCATTER
:
2043 if( GetBiff() == EXC_BIFF8
)
2044 ::set_flag( maData
.mnFlags
, EXC_CHSCATTER_BUBBLES
, maTypeInfo
.meTypeId
== EXC_CHTYPEID_BUBBLES
);
2048 SetRecId( maTypeInfo
.mnRecId
);
2052 void XclExpChType::SetStacked( bool bPercent
)
2054 switch( maTypeInfo
.meTypeCateg
)
2056 case EXC_CHTYPECATEG_LINE
:
2057 ::set_flag( maData
.mnFlags
, EXC_CHLINE_STACKED
);
2058 ::set_flag( maData
.mnFlags
, EXC_CHLINE_PERCENT
, bPercent
);
2060 case EXC_CHTYPECATEG_BAR
:
2061 ::set_flag( maData
.mnFlags
, EXC_CHBAR_STACKED
);
2062 ::set_flag( maData
.mnFlags
, EXC_CHBAR_PERCENT
, bPercent
);
2063 maData
.mnOverlap
= -100;
2069 void XclExpChType::WriteBody( XclExpStream
& rStrm
)
2071 switch( GetRecId() )
2074 rStrm
<< maData
.mnOverlap
<< maData
.mnGap
<< maData
.mnFlags
;
2079 case EXC_ID_CHRADARLINE
:
2080 case EXC_ID_CHRADARAREA
:
2081 rStrm
<< maData
.mnFlags
;
2085 rStrm
<< maData
.mnRotation
<< maData
.mnPieHole
;
2086 if( GetBiff() == EXC_BIFF8
)
2087 rStrm
<< maData
.mnFlags
;
2090 case EXC_ID_CHSCATTER
:
2091 if( GetBiff() == EXC_BIFF8
)
2092 rStrm
<< maData
.mnBubbleSize
<< maData
.mnBubbleType
<< maData
.mnFlags
;
2096 DBG_ERRORFILE( "XclExpChType::WriteBody - unknown chart type" );
2100 // ----------------------------------------------------------------------------
2102 XclExpChChart3d::XclExpChChart3d() :
2103 XclExpRecord( EXC_ID_CHCHART3D
, 14 )
2107 void XclExpChChart3d::Convert( const ScfPropertySet
& rPropSet
, bool b3dWallChart
)
2109 sal_Int32 nRotationY
= 0;
2110 rPropSet
.GetProperty( nRotationY
, EXC_CHPROP_ROTATIONVERTICAL
);
2111 sal_Int32 nRotationX
= 0;
2112 rPropSet
.GetProperty( nRotationX
, EXC_CHPROP_ROTATIONHORIZONTAL
);
2113 sal_Int32 nPerspective
= 15;
2114 rPropSet
.GetProperty( nPerspective
, EXC_CHPROP_PERSPECTIVE
);
2118 // Y rotation (Excel [0..359], Chart2 [-179,180])
2119 if( nRotationY
< 0 ) nRotationY
+= 360;
2120 maData
.mnRotation
= static_cast< sal_uInt16
>( nRotationY
);
2121 // X rotation a.k.a. elevation (Excel [-90..90], Chart2 [-179,180])
2122 maData
.mnElevation
= limit_cast
< sal_Int16
>( nRotationX
, -90, 90 );
2123 // perspective (Excel and Chart2 [0,100])
2124 maData
.mnEyeDist
= limit_cast
< sal_uInt16
>( nPerspective
, 0, 100 );
2127 ::set_flag( maData
.mnFlags
, EXC_CHCHART3D_REAL3D
, !rPropSet
.GetBoolProperty( EXC_CHPROP_RIGHTANGLEDAXES
) );
2128 ::set_flag( maData
.mnFlags
, EXC_CHCHART3D_AUTOHEIGHT
);
2129 ::set_flag( maData
.mnFlags
, EXC_CHCHART3D_HASWALLS
);
2133 // Y rotation not used in pie charts, but 'first pie slice angle'
2134 maData
.mnRotation
= XclExpChRoot::ConvertPieRotation( rPropSet
);
2135 // X rotation a.k.a. elevation (map Chart2 [-80,-10] to Excel [10..80])
2136 maData
.mnElevation
= limit_cast
< sal_Int16
>( (nRotationX
+ 270) % 180, 10, 80 );
2137 // perspective (Excel and Chart2 [0,100])
2138 maData
.mnEyeDist
= limit_cast
< sal_uInt16
>( nPerspective
, 0, 100 );
2144 void XclExpChChart3d::WriteBody( XclExpStream
& rStrm
)
2146 rStrm
<< maData
.mnRotation
2147 << maData
.mnElevation
2149 << maData
.mnRelHeight
2150 << maData
.mnRelDepth
2151 << maData
.mnDepthGap
2155 // ----------------------------------------------------------------------------
2157 XclExpChLegend::XclExpChLegend( const XclExpChRoot
& rRoot
) :
2158 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_LEGEND
, EXC_ID_CHLEGEND
, 20 )
2162 void XclExpChLegend::Convert( const ScfPropertySet
& rPropSet
)
2165 mxFrame
= lclCreateFrame( GetChRoot(), rPropSet
, EXC_CHOBJTYPE_LEGEND
);
2167 mxText
.reset( new XclExpChText( GetChRoot() ) );
2168 mxText
->ConvertLegend( rPropSet
);
2169 // special legend properties
2170 GetChartPropSetHelper().ReadLegendProperties( maData
, rPropSet
);
2173 void XclExpChLegend::WriteSubRecords( XclExpStream
& rStrm
)
2175 lclSaveRecord( rStrm
, mxText
);
2176 lclSaveRecord( rStrm
, mxFrame
);
2179 void XclExpChLegend::WriteBody( XclExpStream
& rStrm
)
2181 rStrm
<< maData
.maRect
<< maData
.mnDockMode
<< maData
.mnSpacing
<< maData
.mnFlags
;
2184 // ----------------------------------------------------------------------------
2186 XclExpChDropBar::XclExpChDropBar( const XclExpChRoot
& rRoot
, XclChObjectType eObjType
) :
2187 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_DROPBAR
, EXC_ID_CHDROPBAR
, 2 ),
2188 meObjType( eObjType
),
2193 void XclExpChDropBar::Convert( const ScfPropertySet
& rPropSet
)
2196 ConvertFrameBase( GetChRoot(), rPropSet
, meObjType
);
2198 SetDefaultFrameBase( GetChRoot(), EXC_CHFRAMETYPE_INVISIBLE
, true );
2201 void XclExpChDropBar::WriteSubRecords( XclExpStream
& rStrm
)
2203 WriteFrameRecords( rStrm
);
2206 void XclExpChDropBar::WriteBody( XclExpStream
& rStrm
)
2211 // ----------------------------------------------------------------------------
2213 XclExpChTypeGroup::XclExpChTypeGroup( const XclExpChRoot
& rRoot
, sal_uInt16 nGroupIdx
) :
2214 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_TYPEGROUP
, EXC_ID_CHTYPEGROUP
, 20 ),
2216 maTypeInfo( maType
.GetTypeInfo() )
2218 maData
.mnGroupIdx
= nGroupIdx
;
2221 void XclExpChTypeGroup::ConvertType(
2222 Reference
< XDiagram
> xDiagram
, Reference
< XChartType
> xChartType
,
2223 sal_Int32 nApiAxesSetIdx
, bool b3dChart
, bool bSwappedAxesSet
, bool bHasXLabels
)
2225 // chart type settings
2226 maType
.Convert( xDiagram
, xChartType
, nApiAxesSetIdx
, bSwappedAxesSet
, bHasXLabels
);
2228 // spline - TODO: get from single series (#i66858#)
2229 ScfPropertySet
aTypeProp( xChartType
);
2230 ::com::sun::star::chart2::CurveStyle eCurveStyle
;
2231 bool bSpline
= aTypeProp
.GetProperty( eCurveStyle
, EXC_CHPROP_CURVESTYLE
) &&
2232 (eCurveStyle
!= ::com::sun::star::chart2::CurveStyle_LINES
);
2234 // extended type info
2235 maTypeInfo
.Set( maType
.GetTypeInfo(), b3dChart
, bSpline
);
2237 // 3d chart settings
2238 if( maTypeInfo
.mb3dChart
) // only true, if Excel chart supports 3d mode
2240 mxChart3d
.reset( new XclExpChChart3d
);
2241 ScfPropertySet
aDiaProp( xDiagram
);
2242 mxChart3d
->Convert( aDiaProp
, Is3dWallChart() );
2246 void XclExpChTypeGroup::ConvertSeries(
2247 Reference
< XDiagram
> xDiagram
, Reference
< XChartType
> xChartType
,
2248 sal_Int32 nGroupAxesSetIdx
, bool bPercent
, bool bConnectBars
)
2250 Reference
< XDataSeriesContainer
> xSeriesCont( xChartType
, UNO_QUERY
);
2251 if( xSeriesCont
.is() )
2253 typedef ::std::vector
< Reference
< XDataSeries
> > XDataSeriesVec
;
2254 XDataSeriesVec aSeriesVec
;
2256 // copy data series attached to the current axes set to the vector
2257 Sequence
< Reference
< XDataSeries
> > aSeriesSeq
= xSeriesCont
->getDataSeries();
2258 const Reference
< XDataSeries
>* pBeg
= aSeriesSeq
.getConstArray();
2259 const Reference
< XDataSeries
>* pEnd
= pBeg
+ aSeriesSeq
.getLength();
2260 for( const Reference
< XDataSeries
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
2262 ScfPropertySet
aSeriesProp( *pIt
);
2263 sal_Int32
nSeriesAxesSetIdx(0);
2264 if( aSeriesProp
.GetProperty( nSeriesAxesSetIdx
, EXC_CHPROP_ATTAXISINDEX
) && (nSeriesAxesSetIdx
== nGroupAxesSetIdx
) )
2265 aSeriesVec
.push_back( *pIt
);
2268 // Are there any series in the current axes set?
2269 if( !aSeriesVec
.empty() )
2271 // stacking direction (stacked/percent/deep 3d) from first series
2272 ScfPropertySet
aSeriesProp( aSeriesVec
.front() );
2273 namespace cssc
= ::com::sun::star::chart2
;
2274 cssc::StackingDirection eStacking
;
2275 if( !aSeriesProp
.GetProperty( eStacking
, EXC_CHPROP_STACKINGDIR
) )
2276 eStacking
= cssc::StackingDirection_NO_STACKING
;
2278 // stacked or percent chart
2279 if( maTypeInfo
.mbSupportsStacking
&& (eStacking
== cssc::StackingDirection_Y_STACKING
) )
2281 // percent overrides simple stacking
2282 maType
.SetStacked( bPercent
);
2284 // connected data points (only in stacked bar charts)
2285 if( bConnectBars
&& (maTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_BAR
) )
2286 maChartLines
[ EXC_CHCHARTLINE_CONNECT
].reset( new XclExpChLineFormat( GetChRoot() ) );
2290 // reverse series order for some unstacked 2D chart types
2291 if( maTypeInfo
.mbReverseSeries
&& !Is3dChart() )
2292 ::std::reverse( aSeriesVec
.begin(), aSeriesVec
.end() );
2295 // deep 3d chart or clustered 3d chart (stacked is not clustered)
2296 if( (eStacking
== cssc::StackingDirection_NO_STACKING
) && Is3dWallChart() )
2297 mxChart3d
->SetClustered();
2299 // varied point colors
2300 ::set_flag( maData
.mnFlags
, EXC_CHTYPEGROUP_VARIEDCOLORS
, aSeriesProp
.GetBoolProperty( EXC_CHPROP_VARYCOLORSBY
) );
2302 // process all series
2303 for( XDataSeriesVec::const_iterator aIt
= aSeriesVec
.begin(), aEnd
= aSeriesVec
.end(); aIt
!= aEnd
; ++aIt
)
2305 // create Excel series object, stock charts need special processing
2306 if( maTypeInfo
.meTypeId
== EXC_CHTYPEID_STOCK
)
2307 CreateAllStockSeries( xChartType
, *aIt
);
2309 CreateDataSeries( xDiagram
, *aIt
);
2315 void XclExpChTypeGroup::ConvertCategSequence( Reference
< XLabeledDataSequence
> xCategSeq
)
2317 for( size_t nIdx
= 0, nSize
= maSeries
.GetSize(); nIdx
< nSize
; ++nIdx
)
2318 maSeries
.GetRecord( nIdx
)->ConvertCategSequence( xCategSeq
);
2321 void XclExpChTypeGroup::ConvertLegend( const ScfPropertySet
& rPropSet
)
2323 if( rPropSet
.GetBoolProperty( EXC_CHPROP_SHOW
) )
2325 mxLegend
.reset( new XclExpChLegend( GetChRoot() ) );
2326 mxLegend
->Convert( rPropSet
);
2330 void XclExpChTypeGroup::WriteSubRecords( XclExpStream
& rStrm
)
2332 maType
.Save( rStrm
);
2333 lclSaveRecord( rStrm
, mxChart3d
);
2334 lclSaveRecord( rStrm
, mxLegend
);
2335 lclSaveRecord( rStrm
, mxUpBar
);
2336 lclSaveRecord( rStrm
, mxDownBar
);
2337 for( XclExpChLineFormatMap::iterator aLIt
= maChartLines
.begin(), aLEnd
= maChartLines
.end(); aLIt
!= aLEnd
; ++aLIt
)
2338 lclSaveRecord( rStrm
, aLIt
->second
, EXC_ID_CHCHARTLINE
, aLIt
->first
);
2341 sal_uInt16
XclExpChTypeGroup::GetFreeFormatIdx() const
2343 return static_cast< sal_uInt16
>( maSeries
.GetSize() );
2346 void XclExpChTypeGroup::CreateDataSeries(
2347 Reference
< XDiagram
> xDiagram
, Reference
< XDataSeries
> xDataSeries
)
2349 // let chart create series object with correct series index
2350 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
2353 if( xSeries
->ConvertDataSeries( xDiagram
, xDataSeries
, maTypeInfo
, GetGroupIdx(), GetFreeFormatIdx() ) )
2354 maSeries
.AppendRecord( xSeries
);
2356 GetChartData().RemoveLastSeries();
2360 void XclExpChTypeGroup::CreateAllStockSeries(
2361 Reference
< XChartType
> xChartType
, Reference
< XDataSeries
> xDataSeries
)
2363 // create existing series objects
2364 bool bHasOpen
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_OPENVALUES
, false );
2365 bool bHasHigh
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_HIGHVALUES
, false );
2366 bool bHasLow
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_LOWVALUES
, false );
2367 bool bHasClose
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_CLOSEVALUES
, !bHasOpen
);
2369 // formatting of special stock chart elements
2370 ScfPropertySet
aTypeProp( xChartType
);
2372 if( bHasHigh
&& bHasLow
&& aTypeProp
.GetBoolProperty( EXC_CHPROP_SHOWHIGHLOW
) )
2374 ScfPropertySet
aSeriesProp( xDataSeries
);
2375 XclExpChLineFormatRef
xLineFmt( new XclExpChLineFormat( GetChRoot() ) );
2376 xLineFmt
->Convert( GetChRoot(), aSeriesProp
, EXC_CHOBJTYPE_HILOLINE
);
2377 maChartLines
[ EXC_CHCHARTLINE_HILO
] = xLineFmt
;
2380 if( bHasOpen
&& bHasClose
)
2382 // dropbar type is dependent on position in the file - always create both
2383 Reference
< XPropertySet
> xWhitePropSet
, xBlackPropSet
;
2384 // white dropbar format
2385 aTypeProp
.GetProperty( xWhitePropSet
, EXC_CHPROP_WHITEDAY
);
2386 ScfPropertySet
aWhiteProp( xWhitePropSet
);
2387 mxUpBar
.reset( new XclExpChDropBar( GetChRoot(), EXC_CHOBJTYPE_WHITEDROPBAR
) );
2388 mxUpBar
->Convert( aWhiteProp
);
2389 // black dropbar format
2390 aTypeProp
.GetProperty( xBlackPropSet
, EXC_CHPROP_BLACKDAY
);
2391 ScfPropertySet
aBlackProp( xBlackPropSet
);
2392 mxDownBar
.reset( new XclExpChDropBar( GetChRoot(), EXC_CHOBJTYPE_BLACKDROPBAR
) );
2393 mxDownBar
->Convert( aBlackProp
);
2397 bool XclExpChTypeGroup::CreateStockSeries( Reference
< XDataSeries
> xDataSeries
,
2398 const OUString
& rValueRole
, bool bCloseSymbol
)
2401 // let chart create series object with correct series index
2402 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
2405 bOk
= xSeries
->ConvertStockSeries( xDataSeries
,
2406 rValueRole
, GetGroupIdx(), GetFreeFormatIdx(), bCloseSymbol
);
2408 maSeries
.AppendRecord( xSeries
);
2410 GetChartData().RemoveLastSeries();
2415 void XclExpChTypeGroup::WriteBody( XclExpStream
& rStrm
)
2417 rStrm
<< maData
.maRect
<< maData
.mnFlags
<< maData
.mnGroupIdx
;
2420 // Axes =======================================================================
2422 XclExpChLabelRange::XclExpChLabelRange( const XclExpChRoot
& rRoot
) :
2423 XclExpRecord( EXC_ID_CHLABELRANGE
, 8 ),
2424 XclExpChRoot( rRoot
)
2428 void XclExpChLabelRange::Convert( const ScaleData
& rScaleData
, bool bMirrorOrient
)
2431 double fOrigin
= 0.0;
2432 if( !lclIsAutoAnyOrGetValue( fOrigin
, rScaleData
.Origin
) )
2433 maData
.mnCross
= limit_cast
< sal_uInt16
>( fOrigin
, 1, 31999 );
2436 if( (rScaleData
.Orientation
== ::com::sun::star::chart2::AxisOrientation_REVERSE
) != bMirrorOrient
)
2437 ::set_flag( maData
.mnFlags
, EXC_CHLABELRANGE_REVERSE
);
2440 void XclExpChLabelRange::ConvertAxisPosition( const ScfPropertySet
& rPropSet
)
2442 namespace cssc
= ::com::sun::star::chart
;
2443 cssc::ChartAxisPosition eAxisPos
= cssc::ChartAxisPosition_VALUE
;
2444 rPropSet
.GetProperty( eAxisPos
, EXC_CHPROP_CROSSOVERPOSITION
);
2445 double fCrossingPos
= 1.0;
2446 rPropSet
.GetProperty( fCrossingPos
, EXC_CHPROP_CROSSOVERVALUE
);
2449 case cssc::ChartAxisPosition_ZERO
: maData
.mnCross
= 1; break;
2450 case cssc::ChartAxisPosition_START
: maData
.mnCross
= 1; break;
2451 case cssc::ChartAxisPosition_END
: ::set_flag( maData
.mnFlags
, EXC_CHLABELRANGE_MAXCROSS
); break;
2452 case cssc::ChartAxisPosition_VALUE
: maData
.mnCross
= limit_cast
< sal_uInt16
>( fCrossingPos
, 1, 31999 ); break;
2453 default: maData
.mnCross
= 1;
2457 void XclExpChLabelRange::WriteBody( XclExpStream
& rStrm
)
2459 rStrm
<< maData
.mnCross
<< maData
.mnLabelFreq
<< maData
.mnTickFreq
<< maData
.mnFlags
;
2462 // ----------------------------------------------------------------------------
2464 XclExpChValueRange::XclExpChValueRange( const XclExpChRoot
& rRoot
) :
2465 XclExpRecord( EXC_ID_CHVALUERANGE
, 42 ),
2466 XclExpChRoot( rRoot
)
2470 void XclExpChValueRange::Convert( const ScaleData
& rScaleData
)
2472 // scaling algorithm
2473 bool bLogScale
= ScfApiHelper::GetServiceName( rScaleData
.Scaling
) == SERVICE_CHART2_LOGSCALING
;
2474 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_LOGSCALE
, bLogScale
);
2477 bool bAutoMin
= lclIsAutoAnyOrGetScaledValue( maData
.mfMin
, rScaleData
.Minimum
, bLogScale
);
2478 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMIN
, bAutoMin
);
2479 bool bAutoMax
= lclIsAutoAnyOrGetScaledValue( maData
.mfMax
, rScaleData
.Maximum
, bLogScale
);
2480 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMAX
, bAutoMax
);
2483 bool bAutoCross
= lclIsAutoAnyOrGetScaledValue( maData
.mfCross
, rScaleData
.Origin
, bLogScale
);
2484 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
, bAutoCross
);
2487 const IncrementData
& rIncrementData
= rScaleData
.IncrementData
;
2488 bool bAutoMajor
= lclIsAutoAnyOrGetValue( maData
.mfMajorStep
, rIncrementData
.Distance
) || (maData
.mfMajorStep
<= 0.0);
2489 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMAJOR
, bAutoMajor
);
2491 const Sequence
< SubIncrement
>& rSubIncrementSeq
= rIncrementData
.SubIncrements
;
2492 sal_Int32 nCount
= 0;
2493 bool bAutoMinor
= bLogScale
|| bAutoMajor
|| (rSubIncrementSeq
.getLength() < 1) ||
2494 lclIsAutoAnyOrGetValue( nCount
, rSubIncrementSeq
[ 0 ].IntervalCount
) || (nCount
< 1);
2496 maData
.mfMinorStep
= maData
.mfMajorStep
/ nCount
;
2497 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMINOR
, bAutoMinor
);
2500 namespace cssc
= ::com::sun::star::chart2
;
2501 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_REVERSE
, rScaleData
.Orientation
== cssc::AxisOrientation_REVERSE
);
2504 void XclExpChValueRange::ConvertAxisPosition( const ScfPropertySet
& rPropSet
)
2506 namespace cssc
= ::com::sun::star::chart
;
2507 cssc::ChartAxisPosition eAxisPos
= cssc::ChartAxisPosition_VALUE
;
2508 double fCrossingPos
= 0.0;
2509 if( rPropSet
.GetProperty( eAxisPos
, EXC_CHPROP_CROSSOVERPOSITION
) && rPropSet
.GetProperty( fCrossingPos
, EXC_CHPROP_CROSSOVERVALUE
) )
2513 case cssc::ChartAxisPosition_ZERO
:
2514 case cssc::ChartAxisPosition_START
:
2515 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
);
2517 case cssc::ChartAxisPosition_END
:
2518 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_MAXCROSS
);
2520 case cssc::ChartAxisPosition_VALUE
:
2521 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
, false );
2522 maData
.mfCross
= ::get_flagvalue
< double >( maData
.mnFlags
, EXC_CHVALUERANGE_LOGSCALE
, log( fCrossingPos
) / log( 10.0 ), fCrossingPos
);
2525 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
);
2530 void XclExpChValueRange::WriteBody( XclExpStream
& rStrm
)
2532 rStrm
<< maData
.mfMin
2534 << maData
.mfMajorStep
2535 << maData
.mfMinorStep
2540 // ----------------------------------------------------------------------------
2544 sal_uInt8
lclGetXclTickPos( sal_Int32 nApiTickmarks
)
2546 using namespace ::com::sun::star::chart2::TickmarkStyle
;
2547 sal_uInt8 nXclTickPos
= 0;
2548 ::set_flag( nXclTickPos
, EXC_CHTICK_INSIDE
, ::get_flag( nApiTickmarks
, INNER
) );
2549 ::set_flag( nXclTickPos
, EXC_CHTICK_OUTSIDE
, ::get_flag( nApiTickmarks
, OUTER
) );
2555 XclExpChTick::XclExpChTick( const XclExpChRoot
& rRoot
) :
2556 XclExpRecord( EXC_ID_CHTICK
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 30 : 26 ),
2557 XclExpChRoot( rRoot
),
2558 mnTextColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
2562 void XclExpChTick::Convert( const ScfPropertySet
& rPropSet
, const XclChExtTypeInfo
& rTypeInfo
, sal_uInt16 nAxisType
)
2565 sal_Int32 nApiTickmarks
= 0;
2566 if( rPropSet
.GetProperty( nApiTickmarks
, EXC_CHPROP_MAJORTICKS
) )
2567 maData
.mnMajor
= lclGetXclTickPos( nApiTickmarks
);
2568 if( rPropSet
.GetProperty( nApiTickmarks
, EXC_CHPROP_MINORTICKS
) )
2569 maData
.mnMinor
= lclGetXclTickPos( nApiTickmarks
);
2572 if( (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_RADAR
) && (nAxisType
== EXC_CHAXIS_X
) )
2574 /* Radar charts disable their category labels via chart type, not via
2575 axis, and axis labels are always 'near axis'. */
2576 maData
.mnLabelPos
= EXC_CHTICK_NEXT
;
2578 else if( !rPropSet
.GetBoolProperty( EXC_CHPROP_DISPLAYLABELS
) )
2581 maData
.mnLabelPos
= EXC_CHTICK_NOLABEL
;
2583 else if( rTypeInfo
.mb3dChart
&& (nAxisType
== EXC_CHAXIS_Y
) )
2585 // Excel expects 'near axis' at Y axes in 3D charts
2586 maData
.mnLabelPos
= EXC_CHTICK_NEXT
;
2590 namespace cssc
= ::com::sun::star::chart
;
2591 cssc::ChartAxisLabelPosition eApiLabelPos
= cssc::ChartAxisLabelPosition_NEAR_AXIS
;
2592 rPropSet
.GetProperty( eApiLabelPos
, EXC_CHPROP_LABELPOSITION
);
2593 switch( eApiLabelPos
)
2595 case cssc::ChartAxisLabelPosition_NEAR_AXIS
:
2596 case cssc::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE
: maData
.mnLabelPos
= EXC_CHTICK_NEXT
; break;
2597 case cssc::ChartAxisLabelPosition_OUTSIDE_START
: maData
.mnLabelPos
= EXC_CHTICK_LOW
; break;
2598 case cssc::ChartAxisLabelPosition_OUTSIDE_END
: maData
.mnLabelPos
= EXC_CHTICK_HIGH
; break;
2599 default: maData
.mnLabelPos
= EXC_CHTICK_NEXT
;
2604 void XclExpChTick::SetFontColor( const Color
& rColor
, sal_uInt32 nColorId
)
2606 maData
.maTextColor
= rColor
;
2607 ::set_flag( maData
.mnFlags
, EXC_CHTICK_AUTOCOLOR
, rColor
== COL_AUTO
);
2608 mnTextColorId
= nColorId
;
2611 void XclExpChTick::SetRotation( sal_uInt16 nRotation
)
2613 maData
.mnRotation
= nRotation
;
2614 ::set_flag( maData
.mnFlags
, EXC_CHTICK_AUTOROT
, false );
2615 ::insert_value( maData
.mnFlags
, XclTools::GetXclOrientFromRot( nRotation
), 2, 3 );
2618 void XclExpChTick::WriteBody( XclExpStream
& rStrm
)
2620 rStrm
<< maData
.mnMajor
2622 << maData
.mnLabelPos
2623 << maData
.mnBackMode
2625 << maData
.maTextColor
2627 if( GetBiff() == EXC_BIFF8
)
2628 rStrm
<< GetPalette().GetColorIndex( mnTextColorId
) << maData
.mnRotation
;
2631 // ----------------------------------------------------------------------------
2635 /** Returns an API axis object from the passed coordinate system. */
2636 Reference
< XAxis
> lclGetApiAxis( Reference
< XCoordinateSystem
> xCoordSystem
,
2637 sal_Int32 nApiAxisDim
, sal_Int32 nApiAxesSetIdx
)
2639 Reference
< XAxis
> xAxis
;
2640 if( (nApiAxisDim
>= 0) && xCoordSystem
.is() ) try
2642 xAxis
= xCoordSystem
->getAxisByDimension( nApiAxisDim
, nApiAxesSetIdx
);
2652 XclExpChAxis::XclExpChAxis( const XclExpChRoot
& rRoot
, sal_uInt16 nAxisType
) :
2653 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_AXIS
, EXC_ID_CHAXIS
, 18 ),
2654 mnNumFmtIdx( EXC_FORMAT_NOTFOUND
)
2656 maData
.mnType
= nAxisType
;
2659 void XclExpChAxis::SetFont( XclExpChFontRef xFont
, const Color
& rColor
, sal_uInt32 nColorId
)
2663 mxTick
->SetFontColor( rColor
, nColorId
);
2666 void XclExpChAxis::SetRotation( sal_uInt16 nRotation
)
2669 mxTick
->SetRotation( nRotation
);
2672 void XclExpChAxis::Convert( Reference
< XAxis
> xAxis
, Reference
< XAxis
> xCrossingAxis
, const XclChExtTypeInfo
& rTypeInfo
)
2674 ScfPropertySet
aAxisProp( xAxis
);
2675 bool bCategoryAxis
= ((GetAxisType() == EXC_CHAXIS_X
) && rTypeInfo
.mbCategoryAxis
) || (GetAxisType() == EXC_CHAXIS_Z
);
2677 // axis line format -------------------------------------------------------
2679 mxAxisLine
.reset( new XclExpChLineFormat( GetChRoot() ) );
2680 mxAxisLine
->Convert( GetChRoot(), aAxisProp
, EXC_CHOBJTYPE_AXISLINE
);
2681 // #i58688# axis enabled
2682 mxAxisLine
->SetShowAxis( aAxisProp
.GetBoolProperty( EXC_CHPROP_SHOW
) );
2684 // axis scaling and increment ---------------------------------------------
2686 ScfPropertySet
aCrossingProp( xCrossingAxis
);
2689 mxLabelRange
.reset( new XclExpChLabelRange( GetChRoot() ) );
2690 mxLabelRange
->SetTicksBetweenCateg( rTypeInfo
.mbTicksBetweenCateg
);
2692 // #i71684# radar charts have reversed rotation direction
2693 mxLabelRange
->Convert( xAxis
->getScaleData(), (GetAxisType() == EXC_CHAXIS_X
) && (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_RADAR
) );
2694 // get position of crossing axis on this axis from passed axis object
2695 if( aCrossingProp
.Is() )
2696 mxLabelRange
->ConvertAxisPosition( aCrossingProp
);
2700 mxValueRange
.reset( new XclExpChValueRange( GetChRoot() ) );
2702 mxValueRange
->Convert( xAxis
->getScaleData() );
2703 // get position of crossing axis on this axis from passed axis object
2704 if( aCrossingProp
.Is() )
2705 mxValueRange
->ConvertAxisPosition( aCrossingProp
);
2708 // axis caption text ------------------------------------------------------
2710 // axis ticks properties
2711 mxTick
.reset( new XclExpChTick( GetChRoot() ) );
2712 mxTick
->Convert( aAxisProp
, rTypeInfo
, GetAxisType() );
2714 // axis label formatting and rotation
2715 ConvertFontBase( GetChRoot(), aAxisProp
);
2716 ConvertRotationBase( GetChRoot(), aAxisProp
, true );
2718 // axis number format
2719 sal_Int32 nApiNumFmt
= 0;
2720 if( !bCategoryAxis
&& aAxisProp
.GetProperty( nApiNumFmt
, EXC_CHPROP_NUMBERFORMAT
) )
2721 mnNumFmtIdx
= GetNumFmtBuffer().Insert( static_cast< sal_uInt32
>( nApiNumFmt
) );
2723 // grid -------------------------------------------------------------------
2728 ScfPropertySet
aGridProp( xAxis
->getGridProperties() );
2729 if( aGridProp
.GetBoolProperty( EXC_CHPROP_SHOW
) )
2730 mxMajorGrid
= lclCreateLineFormat( GetChRoot(), aGridProp
, EXC_CHOBJTYPE_GRIDLINE
);
2732 Sequence
< Reference
< XPropertySet
> > aSubGridPropSeq
= xAxis
->getSubGridProperties();
2733 if( aSubGridPropSeq
.hasElements() )
2735 ScfPropertySet
aSubGridProp( aSubGridPropSeq
[ 0 ] );
2736 if( aSubGridProp
.GetBoolProperty( EXC_CHPROP_SHOW
) )
2737 mxMinorGrid
= lclCreateLineFormat( GetChRoot(), aSubGridProp
, EXC_CHOBJTYPE_GRIDLINE
);
2742 void XclExpChAxis::ConvertWall( XDiagramRef xDiagram
)
2744 if( xDiagram
.is() ) switch( GetAxisType() )
2748 ScfPropertySet
aWallProp( xDiagram
->getWall() );
2749 mxWallFrame
= lclCreateFrame( GetChRoot(), aWallProp
, EXC_CHOBJTYPE_WALL3D
);
2754 ScfPropertySet
aFloorProp( xDiagram
->getFloor() );
2755 mxWallFrame
= lclCreateFrame( GetChRoot(), aFloorProp
, EXC_CHOBJTYPE_FLOOR3D
);
2759 mxWallFrame
.reset();
2763 void XclExpChAxis::WriteSubRecords( XclExpStream
& rStrm
)
2765 lclSaveRecord( rStrm
, mxLabelRange
);
2766 lclSaveRecord( rStrm
, mxValueRange
);
2767 if( mnNumFmtIdx
!= EXC_FORMAT_NOTFOUND
)
2768 XclExpUInt16Record( EXC_ID_CHFORMAT
, mnNumFmtIdx
).Save( rStrm
);
2769 lclSaveRecord( rStrm
, mxTick
);
2770 lclSaveRecord( rStrm
, mxFont
);
2771 lclSaveRecord( rStrm
, mxAxisLine
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_AXISLINE
);
2772 lclSaveRecord( rStrm
, mxMajorGrid
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_MAJORGRID
);
2773 lclSaveRecord( rStrm
, mxMinorGrid
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_MINORGRID
);
2774 lclSaveRecord( rStrm
, mxWallFrame
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_WALLS
);
2777 void XclExpChAxis::WriteBody( XclExpStream
& rStrm
)
2779 rStrm
<< maData
.mnType
<< maData
.maRect
;
2782 // ----------------------------------------------------------------------------
2784 XclExpChAxesSet::XclExpChAxesSet( const XclExpChRoot
& rRoot
, sal_uInt16 nAxesSetId
) :
2785 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_AXESSET
, EXC_ID_CHAXESSET
, 18 )
2787 maData
.mnAxesSetId
= nAxesSetId
;
2788 SetFutureRecordContext( 0, nAxesSetId
);
2791 sal_uInt16
XclExpChAxesSet::Convert( Reference
< XDiagram
> xDiagram
, sal_uInt16 nFirstGroupIdx
)
2793 /* First unused chart type group index is passed to be able to continue
2794 counting of chart type groups for secondary axes set. */
2795 sal_uInt16 nGroupIdx
= nFirstGroupIdx
;
2796 Reference
< XCoordinateSystemContainer
> xCoordSysCont( xDiagram
, UNO_QUERY
);
2797 if( xCoordSysCont
.is() )
2799 Sequence
< Reference
< XCoordinateSystem
> > aCoordSysSeq
= xCoordSysCont
->getCoordinateSystems();
2800 if( aCoordSysSeq
.getLength() > 0 )
2802 /* Process first coordinate system only. Import filter puts all
2803 chart types into one coordinate system. */
2804 Reference
< XCoordinateSystem
> xCoordSystem
= aCoordSysSeq
[ 0 ];
2805 sal_Int32 nApiAxesSetIdx
= GetApiAxesSetIndex();
2808 bool b3dChart
= xCoordSystem
.is() && (xCoordSystem
->getDimension() == 3);
2811 namespace ApiAxisType
= ::com::sun::star::chart2::AxisType
;
2812 Reference
< XAxis
> xApiYAxis
= lclGetApiAxis( xCoordSystem
, EXC_CHART_AXIS_Y
, nApiAxesSetIdx
);
2813 bool bPercent
= xApiYAxis
.is() && (xApiYAxis
->getScaleData().AxisType
== ApiAxisType::PERCENT
);
2815 // connector lines in bar charts
2816 ScfPropertySet
aDiaProp( xDiagram
);
2817 bool bConnectBars
= aDiaProp
.GetBoolProperty( EXC_CHPROP_CONNECTBARS
);
2819 // swapped axes sets
2820 ScfPropertySet
aCoordSysProp( xCoordSystem
);
2821 bool bSwappedAxesSet
= aCoordSysProp
.GetBoolProperty( EXC_CHPROP_SWAPXANDYAXIS
);
2823 // X axis for later use
2824 Reference
< XAxis
> xApiXAxis
= lclGetApiAxis( xCoordSystem
, EXC_CHART_AXIS_X
, nApiAxesSetIdx
);
2826 ScfPropertySet
aXAxisProp( xApiXAxis
);
2827 bool bHasXLabels
= aXAxisProp
.GetBoolProperty( EXC_CHPROP_DISPLAYLABELS
);
2829 // process chart types
2830 Reference
< XChartTypeContainer
> xChartTypeCont( xCoordSystem
, UNO_QUERY
);
2831 if( xChartTypeCont
.is() )
2833 Sequence
< Reference
< XChartType
> > aChartTypeSeq
= xChartTypeCont
->getChartTypes();
2834 const Reference
< XChartType
>* pBeg
= aChartTypeSeq
.getConstArray();
2835 const Reference
< XChartType
>* pEnd
= pBeg
+ aChartTypeSeq
.getLength();
2836 for( const Reference
< XChartType
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
2838 XclExpChTypeGroupRef
xTypeGroup( new XclExpChTypeGroup( GetChRoot(), nGroupIdx
) );
2839 xTypeGroup
->ConvertType( xDiagram
, *pIt
, nApiAxesSetIdx
, b3dChart
, bSwappedAxesSet
, bHasXLabels
);
2840 /* If new chart type group cannot be inserted into a combination
2841 chart with existing type groups, insert all series into last
2842 contained chart type group instead of creating a new group. */
2843 XclExpChTypeGroupRef xLastGroup
= GetLastTypeGroup();
2844 if( xLastGroup
.is() && !(xTypeGroup
->IsCombinable2d() && xLastGroup
->IsCombinable2d()) )
2846 xLastGroup
->ConvertSeries( xDiagram
, *pIt
, nApiAxesSetIdx
, bPercent
, bConnectBars
);
2850 xTypeGroup
->ConvertSeries( xDiagram
, *pIt
, nApiAxesSetIdx
, bPercent
, bConnectBars
);
2851 if( xTypeGroup
->IsValidGroup() )
2853 maTypeGroups
.AppendRecord( xTypeGroup
);
2860 if( XclExpChTypeGroup
* pGroup
= GetFirstTypeGroup().get() )
2862 const XclChExtTypeInfo
& rTypeInfo
= pGroup
->GetTypeInfo();
2864 // create axes according to chart type (no axes for pie and donut charts)
2865 if( rTypeInfo
.meTypeCateg
!= EXC_CHTYPECATEG_PIE
)
2867 ConvertAxis( mxXAxis
, EXC_CHAXIS_X
, mxXAxisTitle
, EXC_CHOBJLINK_XAXIS
, xCoordSystem
, rTypeInfo
, EXC_CHART_AXIS_Y
);
2868 ConvertAxis( mxYAxis
, EXC_CHAXIS_Y
, mxYAxisTitle
, EXC_CHOBJLINK_YAXIS
, xCoordSystem
, rTypeInfo
, EXC_CHART_AXIS_X
);
2869 if( pGroup
->Is3dDeepChart() )
2870 ConvertAxis( mxZAxis
, EXC_CHAXIS_Z
, mxZAxisTitle
, EXC_CHOBJLINK_ZAXIS
, xCoordSystem
, rTypeInfo
, EXC_CHART_AXIS_NONE
);
2873 // X axis category ranges
2874 if( rTypeInfo
.mbCategoryAxis
&& xApiXAxis
.is() )
2876 const ScaleData aScaleData
= xApiXAxis
->getScaleData();
2877 for( size_t nIdx
= 0, nSize
= maTypeGroups
.GetSize(); nIdx
< nSize
; ++nIdx
)
2878 maTypeGroups
.GetRecord( nIdx
)->ConvertCategSequence( aScaleData
.Categories
);
2882 if( xDiagram
.is() && (GetAxesSetId() == EXC_CHAXESSET_PRIMARY
) )
2884 Reference
< XLegend
> xLegend
= xDiagram
->getLegend();
2887 ScfPropertySet
aLegendProp( xLegend
);
2888 pGroup
->ConvertLegend( aLegendProp
);
2895 // wall/floor/diagram frame formatting
2896 if( xDiagram
.is() && (GetAxesSetId() == EXC_CHAXESSET_PRIMARY
) )
2898 XclExpChTypeGroupRef xTypeGroup
= GetFirstTypeGroup();
2899 if( xTypeGroup
.is() && xTypeGroup
->Is3dWallChart() )
2901 // wall/floor formatting (3D charts)
2903 mxXAxis
->ConvertWall( xDiagram
);
2905 mxYAxis
->ConvertWall( xDiagram
);
2909 // diagram background formatting
2910 ScfPropertySet
aWallProp( xDiagram
->getWall() );
2911 mxPlotFrame
= lclCreateFrame( GetChRoot(), aWallProp
, EXC_CHOBJTYPE_PLOTFRAME
);
2915 // return first unused chart type group index for next axes set
2919 bool XclExpChAxesSet::Is3dChart() const
2921 XclExpChTypeGroupRef xTypeGroup
= GetFirstTypeGroup();
2922 return xTypeGroup
.is() && xTypeGroup
->Is3dChart();
2925 void XclExpChAxesSet::WriteSubRecords( XclExpStream
& rStrm
)
2927 lclSaveRecord( rStrm
, mxXAxis
);
2928 lclSaveRecord( rStrm
, mxYAxis
);
2929 lclSaveRecord( rStrm
, mxZAxis
);
2930 lclSaveRecord( rStrm
, mxXAxisTitle
);
2931 lclSaveRecord( rStrm
, mxYAxisTitle
);
2932 lclSaveRecord( rStrm
, mxZAxisTitle
);
2933 if( mxPlotFrame
.is() )
2935 XclExpEmptyRecord( EXC_ID_CHPLOTFRAME
).Save( rStrm
);
2936 mxPlotFrame
->Save( rStrm
);
2938 maTypeGroups
.Save( rStrm
);
2941 XclExpChTypeGroupRef
XclExpChAxesSet::GetFirstTypeGroup() const
2943 return maTypeGroups
.GetFirstRecord();
2946 XclExpChTypeGroupRef
XclExpChAxesSet::GetLastTypeGroup() const
2948 return maTypeGroups
.GetLastRecord();
2951 void XclExpChAxesSet::ConvertAxis(
2952 XclExpChAxisRef
& rxChAxis
, sal_uInt16 nAxisType
,
2953 XclExpChTextRef
& rxChAxisTitle
, sal_uInt16 nTitleTarget
,
2954 Reference
< XCoordinateSystem
> xCoordSystem
, const XclChExtTypeInfo
& rTypeInfo
,
2955 sal_Int32 nCrossingAxisDim
)
2957 // create and convert axis object
2958 rxChAxis
.reset( new XclExpChAxis( GetChRoot(), nAxisType
) );
2959 sal_Int32 nApiAxisDim
= rxChAxis
->GetApiAxisDimension();
2960 sal_Int32 nApiAxesSetIdx
= GetApiAxesSetIndex();
2961 Reference
< XAxis
> xAxis
= lclGetApiAxis( xCoordSystem
, nApiAxisDim
, nApiAxesSetIdx
);
2962 Reference
< XAxis
> xCrossingAxis
= lclGetApiAxis( xCoordSystem
, nCrossingAxisDim
, nApiAxesSetIdx
);
2963 rxChAxis
->Convert( xAxis
, xCrossingAxis
, rTypeInfo
);
2965 // create and convert axis title
2966 Reference
< XTitled
> xTitled( xAxis
, UNO_QUERY
);
2967 rxChAxisTitle
= lclCreateTitle( GetChRoot(), xTitled
, nTitleTarget
);
2970 void XclExpChAxesSet::WriteBody( XclExpStream
& rStrm
)
2972 rStrm
<< maData
.mnAxesSetId
<< maData
.maRect
;
2975 // The chart object ===========================================================
2977 static void lcl_getChartSubTitle(const Reference
<XChartDocument
>& xChartDoc
,
2980 Reference
< ::com::sun::star::chart::XChartDocument
> xChartDoc1(xChartDoc
, UNO_QUERY
);
2981 if (!xChartDoc1
.is())
2984 Reference
< XPropertySet
> xProp(xChartDoc1
->getSubTitle(), UNO_QUERY
);
2989 Any any
= xProp
->getPropertyValue( OUString::createFromAscii("String") );
2994 XclExpChChart::XclExpChChart( const XclExpRoot
& rRoot
,
2995 Reference
< XChartDocument
> xChartDoc
, const Size
& rSize
) :
2996 XclExpChGroupBase( XclExpChRoot( rRoot
, this ), EXC_CHFRBLOCK_TYPE_CHART
, EXC_ID_CHCHART
, 16 )
2998 Size aPtSize
= OutputDevice::LogicToLogic( rSize
, MapMode( MAP_100TH_MM
), MapMode( MAP_POINT
) );
2999 // rectangle is stored in 16.16 fixed-point format
3000 maRect
.mnX
= maRect
.mnY
= 0;
3001 maRect
.mnWidth
= static_cast< sal_Int32
>( aPtSize
.Width() << 16 );
3002 maRect
.mnHeight
= static_cast< sal_Int32
>( aPtSize
.Height() << 16 );
3004 // global chart properties (default values)
3005 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_MANSERIES
);
3006 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_SHOWVISIBLEONLY
, false );
3007 maProps
.mnEmptyMode
= EXC_CHPROPS_EMPTY_SKIP
;
3009 // always create both axes set objects
3010 mxPrimAxesSet
.reset( new XclExpChAxesSet( GetChRoot(), EXC_CHAXESSET_PRIMARY
) );
3011 mxSecnAxesSet
.reset( new XclExpChAxesSet( GetChRoot(), EXC_CHAXESSET_SECONDARY
) );
3013 if( xChartDoc
.is() )
3015 Reference
< XDiagram
> xDiagram
= xChartDoc
->getFirstDiagram();
3017 // global chart properties (only 'include hidden cells' attribute for now)
3018 ScfPropertySet
aDiagramProp( xDiagram
);
3019 bool bIncludeHidden
= aDiagramProp
.GetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS
);
3020 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_SHOWVISIBLEONLY
, !bIncludeHidden
);
3022 // initialize API conversion (remembers xChartDoc internally)
3023 InitConversion( xChartDoc
);
3026 ScfPropertySet
aFrameProp( xChartDoc
->getPageBackground() );
3027 mxFrame
= lclCreateFrame( GetChRoot(), aFrameProp
, EXC_CHOBJTYPE_BACKGROUND
);
3030 Reference
< XTitled
> xTitled( xChartDoc
, UNO_QUERY
);
3032 lcl_getChartSubTitle(xChartDoc
, aSubTitle
);
3033 mxTitle
= lclCreateTitle( GetChRoot(), xTitled
, EXC_CHOBJLINK_TITLE
,
3034 aSubTitle
.Len() ? &aSubTitle
: NULL
);
3036 // diagrams (axes sets)
3037 sal_uInt16 nFreeGroupIdx
= mxPrimAxesSet
->Convert( xDiagram
, 0 );
3038 if( !mxPrimAxesSet
->Is3dChart() )
3039 mxSecnAxesSet
->Convert( xDiagram
, nFreeGroupIdx
);
3041 // treatment of missing values
3042 ScfPropertySet
aDiaProp( xDiagram
);
3043 sal_Int32 nMissingValues
= 0;
3044 if( aDiaProp
.GetProperty( nMissingValues
, EXC_CHPROP_MISSINGVALUETREATMENT
) )
3046 using namespace ::com::sun::star::chart::MissingValueTreatment
;
3047 switch( nMissingValues
)
3049 case LEAVE_GAP
: maProps
.mnEmptyMode
= EXC_CHPROPS_EMPTY_SKIP
; break;
3050 case USE_ZERO
: maProps
.mnEmptyMode
= EXC_CHPROPS_EMPTY_ZERO
; break;
3051 case CONTINUE
: maProps
.mnEmptyMode
= EXC_CHPROPS_EMPTY_INTERPOLATE
; break;
3055 // finish API conversion
3060 XclExpChSeriesRef
XclExpChChart::CreateSeries()
3062 XclExpChSeriesRef xSeries
;
3063 sal_uInt16 nSeriesIdx
= static_cast< sal_uInt16
>( maSeries
.GetSize() );
3064 if( nSeriesIdx
<= EXC_CHSERIES_MAXSERIES
)
3066 xSeries
.reset( new XclExpChSeries( GetChRoot(), nSeriesIdx
) );
3067 maSeries
.AppendRecord( xSeries
);
3072 void XclExpChChart::RemoveLastSeries()
3074 if( !maSeries
.IsEmpty() )
3075 maSeries
.RemoveRecord( maSeries
.GetSize() - 1 );
3078 void XclExpChChart::SetDataLabel( XclExpChTextRef xText
)
3081 maLabels
.AppendRecord( xText
);
3084 void XclExpChChart::WriteSubRecords( XclExpStream
& rStrm
)
3086 // background format
3087 lclSaveRecord( rStrm
, mxFrame
);
3090 maSeries
.Save( rStrm
);
3092 // CHPROPERTIES record
3093 rStrm
.StartRecord( EXC_ID_CHPROPERTIES
, 4 );
3094 rStrm
<< maProps
.mnFlags
<< maProps
.mnEmptyMode
<< sal_uInt8( 0 );
3097 // axes sets (always save primary axes set)
3098 sal_uInt16 nUsedAxesSets
= mxSecnAxesSet
->IsValidAxesSet() ? 2 : 1;
3099 XclExpUInt16Record( EXC_ID_CHUSEDAXESSETS
, nUsedAxesSets
).Save( rStrm
);
3100 mxPrimAxesSet
->Save( rStrm
);
3101 if( mxSecnAxesSet
->IsValidAxesSet() )
3102 mxSecnAxesSet
->Save( rStrm
);
3104 // chart title and data labels
3105 lclSaveRecord( rStrm
, mxTitle
);
3106 maLabels
.Save( rStrm
);
3109 void XclExpChChart::WriteBody( XclExpStream
& rStrm
)
3114 // ----------------------------------------------------------------------------
3116 XclExpChart::XclExpChart( const XclExpRoot
& rRoot
, Reference
< XModel
> xModel
, const Size
& rSize
) :
3117 XclExpSubStream( EXC_BOF_CHART
),
3120 AppendNewRecord( new XclExpChartPageSettings( rRoot
) );
3121 AppendNewRecord( new XclExpBoolRecord( EXC_ID_PROTECT
, false ) );
3122 AppendNewRecord( new XclExpUInt16Record( EXC_ID_CHUNITS
, EXC_CHUNITS_TWIPS
) );
3124 Reference
< XChartDocument
> xChartDoc( xModel
, UNO_QUERY
);
3125 AppendNewRecord( new XclExpChChart( rRoot
, xChartDoc
, rSize
) );
3128 // ============================================================================