1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "xechart.hxx"
23 #include <com/sun/star/i18n/XBreakIterator.hpp>
24 #include <com/sun/star/i18n/ScriptType.hpp>
25 #include <com/sun/star/drawing/FillStyle.hpp>
26 #include <com/sun/star/drawing/XShapes.hpp>
27 #include <com/sun/star/chart/XChartDocument.hpp>
28 #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
29 #include <com/sun/star/chart/ChartAxisPosition.hpp>
30 #include <com/sun/star/chart/ChartLegendExpansion.hpp>
31 #include <com/sun/star/chart/DataLabelPlacement.hpp>
32 #include <com/sun/star/chart/ErrorBarStyle.hpp>
33 #include <com/sun/star/chart/MissingValueTreatment.hpp>
34 #include <com/sun/star/chart/TimeInterval.hpp>
35 #include <com/sun/star/chart/TimeUnit.hpp>
36 #include <com/sun/star/chart/XAxisSupplier.hpp>
37 #include <com/sun/star/chart/XDiagramPositioning.hpp>
38 #include <com/sun/star/chart2/XChartDocument.hpp>
39 #include <com/sun/star/chart2/XDiagram.hpp>
40 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
41 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
42 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
43 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
44 #include <com/sun/star/chart2/XTitled.hpp>
45 #include <com/sun/star/chart2/XColorScheme.hpp>
46 #include <com/sun/star/chart2/data/XDataSource.hpp>
47 #include <com/sun/star/chart2/AxisType.hpp>
48 #include <com/sun/star/chart2/CurveStyle.hpp>
49 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
50 #include <com/sun/star/chart2/DataPointLabel.hpp>
51 #include <com/sun/star/chart2/LegendPosition.hpp>
52 #include <com/sun/star/chart2/RelativePosition.hpp>
53 #include <com/sun/star/chart2/RelativeSize.hpp>
54 #include <com/sun/star/chart2/StackingDirection.hpp>
55 #include <com/sun/star/chart2/TickmarkStyle.hpp>
57 #include <tools/gen.hxx>
58 #include <vcl/outdev.hxx>
59 #include <filter/msfilter/escherex.hxx>
61 #include "document.hxx"
62 #include "rangelst.hxx"
63 #include "rangeutl.hxx"
64 #include "compiler.hxx"
65 #include "tokenarray.hxx"
67 #include "xeescher.hxx"
68 #include "xeformula.hxx"
69 #include "xehelper.hxx"
71 #include "xestyle.hxx"
73 using ::com::sun::star::uno::Any
;
74 using ::com::sun::star::uno::Reference
;
75 using ::com::sun::star::uno::Sequence
;
76 using ::com::sun::star::uno::UNO_QUERY
;
77 using ::com::sun::star::uno::UNO_QUERY_THROW
;
78 using ::com::sun::star::uno::UNO_SET_THROW
;
79 using ::com::sun::star::uno::Exception
;
80 using ::com::sun::star::beans::XPropertySet
;
81 using ::com::sun::star::i18n::XBreakIterator
;
82 using ::com::sun::star::frame::XModel
;
83 using ::com::sun::star::drawing::XShape
;
84 using ::com::sun::star::drawing::XShapes
;
86 using ::com::sun::star::chart2::IncrementData
;
87 using ::com::sun::star::chart2::RelativePosition
;
88 using ::com::sun::star::chart2::RelativeSize
;
89 using ::com::sun::star::chart2::ScaleData
;
90 using ::com::sun::star::chart2::SubIncrement
;
91 using ::com::sun::star::chart2::XAxis
;
92 using ::com::sun::star::chart2::XChartDocument
;
93 using ::com::sun::star::chart2::XChartTypeContainer
;
94 using ::com::sun::star::chart2::XColorScheme
;
95 using ::com::sun::star::chart2::XCoordinateSystem
;
96 using ::com::sun::star::chart2::XCoordinateSystemContainer
;
97 using ::com::sun::star::chart2::XChartType
;
98 using ::com::sun::star::chart2::XDataSeries
;
99 using ::com::sun::star::chart2::XDataSeriesContainer
;
100 using ::com::sun::star::chart2::XDiagram
;
101 using ::com::sun::star::chart2::XFormattedString
;
102 using ::com::sun::star::chart2::XLegend
;
103 using ::com::sun::star::chart2::XRegressionCurve
;
104 using ::com::sun::star::chart2::XRegressionCurveContainer
;
105 using ::com::sun::star::chart2::XScaling
;
106 using ::com::sun::star::chart2::XTitle
;
107 using ::com::sun::star::chart2::XTitled
;
109 using ::com::sun::star::chart2::data::XDataSequence
;
110 using ::com::sun::star::chart2::data::XDataSource
;
111 using ::com::sun::star::chart2::data::XLabeledDataSequence
;
113 using ::formula::FormulaGrammar
;
114 using ::formula::FormulaToken
;
116 namespace cssc
= ::com::sun::star::chart
;
117 namespace cssc2
= ::com::sun::star::chart2
;
119 // Helpers ====================================================================
123 XclExpStream
& operator<<( XclExpStream
& rStrm
, const XclChRectangle
& rRect
)
125 return rStrm
<< rRect
.mnX
<< rRect
.mnY
<< rRect
.mnWidth
<< rRect
.mnHeight
;
128 inline void lclSaveRecord( XclExpStream
& rStrm
, XclExpRecordRef xRec
)
134 /** Saves the passed record (group) together with a leading value record. */
135 template< typename Type
>
136 void lclSaveRecord( XclExpStream
& rStrm
, XclExpRecordRef xRec
, sal_uInt16 nRecId
, Type nValue
)
140 XclExpValueRecord
< Type
>( nRecId
, nValue
).Save( rStrm
);
145 template<typename ValueType
, typename KeyType
>
146 void lclSaveRecord(XclExpStream
& rStrm
, ValueType
* pRec
, sal_uInt16 nRecId
, KeyType nValue
)
150 XclExpValueRecord
<KeyType
>(nRecId
, nValue
).Save(rStrm
);
155 void lclWriteChFrBlockRecord( XclExpStream
& rStrm
, const XclChFrBlock
& rFrBlock
, bool bBegin
)
157 sal_uInt16 nRecId
= bBegin
? EXC_ID_CHFRBLOCKBEGIN
: EXC_ID_CHFRBLOCKEND
;
158 rStrm
.StartRecord( nRecId
, 12 );
159 rStrm
<< nRecId
<< EXC_FUTUREREC_EMPTYFLAGS
<< rFrBlock
.mnType
<< rFrBlock
.mnContext
<< rFrBlock
.mnValue1
<< rFrBlock
.mnValue2
;
163 template< typename Type
>
164 inline bool lclIsAutoAnyOrGetValue( Type
& rValue
, const Any
& rAny
)
166 return !rAny
.hasValue() || !(rAny
>>= rValue
);
169 bool lclIsAutoAnyOrGetScaledValue( double& rfValue
, const Any
& rAny
, bool bLogScale
)
171 bool bIsAuto
= lclIsAutoAnyOrGetValue( rfValue
, rAny
);
172 if( !bIsAuto
&& bLogScale
)
173 rfValue
= log( rfValue
) / log( 10.0 );
177 sal_uInt16
lclGetTimeValue( const XclExpRoot
& rRoot
, double fSerialDate
, sal_uInt16 nTimeUnit
)
179 DateTime aDateTime
= rRoot
.GetDateTimeFromDouble( fSerialDate
);
182 case EXC_CHDATERANGE_DAYS
:
183 return ::limit_cast
< sal_uInt16
, double >( fSerialDate
, 0, SAL_MAX_UINT16
);
184 case EXC_CHDATERANGE_MONTHS
:
185 return ::limit_cast
< sal_uInt16
, sal_uInt16
>( 12 * (aDateTime
.GetYear() - rRoot
.GetBaseYear()) + aDateTime
.GetMonth() - 1, 0, SAL_MAX_INT16
);
186 case EXC_CHDATERANGE_YEARS
:
187 return ::limit_cast
< sal_uInt16
, sal_uInt16
>( aDateTime
.GetYear() - rRoot
.GetBaseYear(), 0, SAL_MAX_INT16
);
189 OSL_ENSURE( false, "lclGetTimeValue - unexpected time unit" );
191 return ::limit_cast
< sal_uInt16
, double >( fSerialDate
, 0, SAL_MAX_UINT16
);
194 bool lclConvertTimeValue( const XclExpRoot
& rRoot
, sal_uInt16
& rnValue
, const Any
& rAny
, sal_uInt16 nTimeUnit
)
196 double fSerialDate
= 0;
197 bool bAuto
= lclIsAutoAnyOrGetValue( fSerialDate
, rAny
);
199 rnValue
= lclGetTimeValue( rRoot
, fSerialDate
, nTimeUnit
);
203 sal_uInt16
lclGetTimeUnit( sal_Int32 nApiTimeUnit
)
205 switch( nApiTimeUnit
)
207 case cssc::TimeUnit::DAY
: return EXC_CHDATERANGE_DAYS
;
208 case cssc::TimeUnit::MONTH
: return EXC_CHDATERANGE_MONTHS
;
209 case cssc::TimeUnit::YEAR
: return EXC_CHDATERANGE_YEARS
;
210 default: OSL_ENSURE( false, "lclGetTimeUnit - unexpected time unit" );
212 return EXC_CHDATERANGE_DAYS
;
215 bool lclConvertTimeInterval( sal_uInt16
& rnValue
, sal_uInt16
& rnTimeUnit
, const Any
& rAny
)
217 cssc::TimeInterval aInterval
;
218 bool bAuto
= lclIsAutoAnyOrGetValue( aInterval
, rAny
);
221 rnValue
= ::limit_cast
< sal_uInt16
, sal_Int32
>( aInterval
.Number
, 1, SAL_MAX_UINT16
);
222 rnTimeUnit
= lclGetTimeUnit( aInterval
.TimeUnit
);
229 // Common =====================================================================
231 /** Stores global data needed in various classes of the Chart export filter. */
232 struct XclExpChRootData
: public XclChRootData
234 typedef ::std::vector
< XclChFrBlock
> XclChFrBlockVector
;
236 XclExpChChart
& mrChartData
; /// The chart data object.
237 XclChFrBlockVector maWrittenFrBlocks
; /// Stack of future record levels already written out.
238 XclChFrBlockVector maUnwrittenFrBlocks
; /// Stack of future record levels not yet written out.
240 inline explicit XclExpChRootData( XclExpChChart
& rChartData
) : mrChartData( rChartData
) {}
242 /** Registers a new future record level. */
243 void RegisterFutureRecBlock( const XclChFrBlock
& rFrBlock
);
244 /** Initializes the current future record level (writes all unwritten CHFRBLOCKBEGIN records). */
245 void InitializeFutureRecBlock( XclExpStream
& rStrm
);
246 /** Finalizes the current future record level (writes CHFRBLOCKEND record if needed). */
247 void FinalizeFutureRecBlock( XclExpStream
& rStrm
);
250 // ----------------------------------------------------------------------------
252 void XclExpChRootData::RegisterFutureRecBlock( const XclChFrBlock
& rFrBlock
)
254 maUnwrittenFrBlocks
.push_back( rFrBlock
);
257 void XclExpChRootData::InitializeFutureRecBlock( XclExpStream
& rStrm
)
259 // first call from a future record writes all missing CHFRBLOCKBEGIN records
260 if( !maUnwrittenFrBlocks
.empty() )
262 // write the leading CHFRINFO record
263 if( maWrittenFrBlocks
.empty() )
265 rStrm
.StartRecord( EXC_ID_CHFRINFO
, 20 );
266 rStrm
<< EXC_ID_CHFRINFO
<< EXC_FUTUREREC_EMPTYFLAGS
<< EXC_CHFRINFO_EXCELXP2003
<< EXC_CHFRINFO_EXCELXP2003
<< sal_uInt16( 3 );
267 rStrm
<< sal_uInt16( 0x0850 ) << sal_uInt16( 0x085A ) << sal_uInt16( 0x0861 ) << sal_uInt16( 0x0861 ) << sal_uInt16( 0x086A ) << sal_uInt16( 0x086B );
270 // write all unwritten CHFRBLOCKBEGIN records
271 for( XclChFrBlockVector::const_iterator aIt
= maUnwrittenFrBlocks
.begin(), aEnd
= maUnwrittenFrBlocks
.end(); aIt
!= aEnd
; ++aIt
)
273 OSL_ENSURE( aIt
->mnType
!= EXC_CHFRBLOCK_TYPE_UNKNOWN
, "XclExpChRootData::InitializeFutureRecBlock - unknown future record block type" );
274 lclWriteChFrBlockRecord( rStrm
, *aIt
, true );
276 // move all record infos to vector of written blocks
277 maWrittenFrBlocks
.insert( maWrittenFrBlocks
.end(), maUnwrittenFrBlocks
.begin(), maUnwrittenFrBlocks
.end() );
278 maUnwrittenFrBlocks
.clear();
282 void XclExpChRootData::FinalizeFutureRecBlock( XclExpStream
& rStrm
)
284 OSL_ENSURE( !maUnwrittenFrBlocks
.empty() || !maWrittenFrBlocks
.empty(), "XclExpChRootData::FinalizeFutureRecBlock - no future record level found" );
285 if( !maUnwrittenFrBlocks
.empty() )
287 // no future record has been written, just forget the topmost level
288 maUnwrittenFrBlocks
.pop_back();
290 else if( !maWrittenFrBlocks
.empty() )
292 // write the CHFRBLOCKEND record for the topmost block and delete it
293 lclWriteChFrBlockRecord( rStrm
, maWrittenFrBlocks
.back(), false );
294 maWrittenFrBlocks
.pop_back();
298 // ----------------------------------------------------------------------------
300 XclExpChRoot::XclExpChRoot( const XclExpRoot
& rRoot
, XclExpChChart
& rChartData
) :
302 mxChData( new XclExpChRootData( rChartData
) )
306 XclExpChRoot::~XclExpChRoot()
310 Reference
< XChartDocument
> XclExpChRoot::GetChartDocument() const
312 return mxChData
->mxChartDoc
;
315 XclExpChChart
& XclExpChRoot::GetChartData() const
317 return mxChData
->mrChartData
;
320 const XclChTypeInfo
& XclExpChRoot::GetChartTypeInfo( XclChTypeId eType
) const
322 return mxChData
->mxTypeInfoProv
->GetTypeInfo( eType
);
325 const XclChTypeInfo
& XclExpChRoot::GetChartTypeInfo( const OUString
& rServiceName
) const
327 return mxChData
->mxTypeInfoProv
->GetTypeInfoFromService( rServiceName
);
330 const XclChFormatInfo
& XclExpChRoot::GetFormatInfo( XclChObjectType eObjType
) const
332 return mxChData
->mxFmtInfoProv
->GetFormatInfo( eObjType
);
335 void XclExpChRoot::InitConversion( XChartDocRef xChartDoc
, const Rectangle
& rChartRect
) const
337 mxChData
->InitConversion( GetRoot(), xChartDoc
, rChartRect
);
340 void XclExpChRoot::FinishConversion() const
342 mxChData
->FinishConversion();
345 bool XclExpChRoot::IsSystemColor( const Color
& rColor
, sal_uInt16 nSysColorIdx
) const
347 XclExpPalette
& rPal
= GetPalette();
348 return rPal
.IsSystemColor( nSysColorIdx
) && (rColor
== rPal
.GetDefColor( nSysColorIdx
));
351 void XclExpChRoot::SetSystemColor( Color
& rColor
, sal_uInt32
& rnColorId
, sal_uInt16 nSysColorIdx
) const
353 OSL_ENSURE( GetPalette().IsSystemColor( nSysColorIdx
), "XclExpChRoot::SetSystemColor - invalid color index" );
354 rColor
= GetPalette().GetDefColor( nSysColorIdx
);
355 rnColorId
= XclExpPalette::GetColorIdFromIndex( nSysColorIdx
);
358 sal_Int32
XclExpChRoot::CalcChartXFromHmm( sal_Int32 nPosX
) const
360 return ::limit_cast
< sal_Int32
, double >( (nPosX
- mxChData
->mnBorderGapX
) / mxChData
->mfUnitSizeX
, 0, EXC_CHART_TOTALUNITS
);
363 sal_Int32
XclExpChRoot::CalcChartYFromHmm( sal_Int32 nPosY
) const
365 return ::limit_cast
< sal_Int32
, double >( (nPosY
- mxChData
->mnBorderGapY
) / mxChData
->mfUnitSizeY
, 0, EXC_CHART_TOTALUNITS
);
368 XclChRectangle
XclExpChRoot::CalcChartRectFromHmm( const ::com::sun::star::awt::Rectangle
& rRect
) const
370 XclChRectangle aRect
;
371 aRect
.mnX
= CalcChartXFromHmm( rRect
.X
);
372 aRect
.mnY
= CalcChartYFromHmm( rRect
.Y
);
373 aRect
.mnWidth
= CalcChartXFromHmm( rRect
.Width
);
374 aRect
.mnHeight
= CalcChartYFromHmm( rRect
.Height
);
378 void XclExpChRoot::ConvertLineFormat( XclChLineFormat
& rLineFmt
,
379 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
) const
381 GetChartPropSetHelper().ReadLineProperties(
382 rLineFmt
, *mxChData
->mxLineDashTable
, rPropSet
, ePropMode
);
385 bool XclExpChRoot::ConvertAreaFormat( XclChAreaFormat
& rAreaFmt
,
386 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
) const
388 return GetChartPropSetHelper().ReadAreaProperties( rAreaFmt
, rPropSet
, ePropMode
);
391 void XclExpChRoot::ConvertEscherFormat(
392 XclChEscherFormat
& rEscherFmt
, XclChPicFormat
& rPicFmt
,
393 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
) const
395 GetChartPropSetHelper().ReadEscherProperties( rEscherFmt
, rPicFmt
,
396 *mxChData
->mxGradientTable
, *mxChData
->mxHatchTable
, *mxChData
->mxBitmapTable
, rPropSet
, ePropMode
);
399 sal_uInt16
XclExpChRoot::ConvertFont( const ScfPropertySet
& rPropSet
, sal_Int16 nScript
) const
401 XclFontData aFontData
;
402 GetFontPropSetHelper().ReadFontProperties( aFontData
, rPropSet
, EXC_FONTPROPSET_CHART
, nScript
);
403 return GetFontBuffer().Insert( aFontData
, EXC_COLOR_CHARTTEXT
);
406 sal_uInt16
XclExpChRoot::ConvertPieRotation( const ScfPropertySet
& rPropSet
)
408 sal_Int32 nApiRot
= 0;
409 rPropSet
.GetProperty( nApiRot
, EXC_CHPROP_STARTINGANGLE
);
410 return static_cast< sal_uInt16
>( (450 - (nApiRot
% 360)) % 360 );
413 void XclExpChRoot::RegisterFutureRecBlock( const XclChFrBlock
& rFrBlock
)
415 mxChData
->RegisterFutureRecBlock( rFrBlock
);
418 void XclExpChRoot::InitializeFutureRecBlock( XclExpStream
& rStrm
)
420 mxChData
->InitializeFutureRecBlock( rStrm
);
423 void XclExpChRoot::FinalizeFutureRecBlock( XclExpStream
& rStrm
)
425 mxChData
->FinalizeFutureRecBlock( rStrm
);
428 // ----------------------------------------------------------------------------
430 XclExpChGroupBase::XclExpChGroupBase( const XclExpChRoot
& rRoot
,
431 sal_uInt16 nFrType
, sal_uInt16 nRecId
, sal_Size nRecSize
) :
432 XclExpRecord( nRecId
, nRecSize
),
433 XclExpChRoot( rRoot
),
438 XclExpChGroupBase::~XclExpChGroupBase()
442 void XclExpChGroupBase::Save( XclExpStream
& rStrm
)
445 XclExpRecord::Save( rStrm
);
447 if( HasSubRecords() )
449 // register the future record context corresponding to this record group
450 RegisterFutureRecBlock( maFrBlock
);
452 XclExpEmptyRecord( EXC_ID_CHBEGIN
).Save( rStrm
);
454 WriteSubRecords( rStrm
);
455 // finalize the future records, must be done before the closing CHEND
456 FinalizeFutureRecBlock( rStrm
);
458 XclExpEmptyRecord( EXC_ID_CHEND
).Save( rStrm
);
462 bool XclExpChGroupBase::HasSubRecords() const
467 void XclExpChGroupBase::SetFutureRecordContext( sal_uInt16 nFrContext
, sal_uInt16 nFrValue1
, sal_uInt16 nFrValue2
)
469 maFrBlock
.mnContext
= nFrContext
;
470 maFrBlock
.mnValue1
= nFrValue1
;
471 maFrBlock
.mnValue2
= nFrValue2
;
474 // ----------------------------------------------------------------------------
476 XclExpChFutureRecordBase::XclExpChFutureRecordBase( const XclExpChRoot
& rRoot
,
477 XclFutureRecType eRecType
, sal_uInt16 nRecId
, sal_Size nRecSize
) :
478 XclExpFutureRecord( eRecType
, nRecId
, nRecSize
),
479 XclExpChRoot( rRoot
)
483 void XclExpChFutureRecordBase::Save( XclExpStream
& rStrm
)
485 InitializeFutureRecBlock( rStrm
);
486 XclExpFutureRecord::Save( rStrm
);
489 // Frame formatting ===========================================================
491 XclExpChFramePos::XclExpChFramePos( sal_uInt16 nTLMode
, sal_uInt16 nBRMode
) :
492 XclExpRecord( EXC_ID_CHFRAMEPOS
, 20 )
494 maData
.mnTLMode
= nTLMode
;
495 maData
.mnBRMode
= nBRMode
;
498 void XclExpChFramePos::WriteBody( XclExpStream
& rStrm
)
500 rStrm
<< maData
.mnTLMode
<< maData
.mnBRMode
<< maData
.maRect
;
503 // ----------------------------------------------------------------------------
505 XclExpChLineFormat::XclExpChLineFormat( const XclExpChRoot
& rRoot
) :
506 XclExpRecord( EXC_ID_CHLINEFORMAT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 12 : 10 ),
507 mnColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
511 void XclExpChLineFormat::SetDefault( XclChFrameType eDefFrameType
)
513 switch( eDefFrameType
)
515 case EXC_CHFRAMETYPE_AUTO
:
518 case EXC_CHFRAMETYPE_INVISIBLE
:
520 maData
.mnPattern
= EXC_CHLINEFORMAT_NONE
;
523 OSL_FAIL( "XclExpChLineFormat::SetDefault - unknown frame type" );
527 void XclExpChLineFormat::Convert( const XclExpChRoot
& rRoot
,
528 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
530 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
531 rRoot
.ConvertLineFormat( maData
, rPropSet
, rFmtInfo
.mePropMode
);
534 // detect system color, set color identifier (TODO: detect automatic series line)
535 if( (eObjType
!= EXC_CHOBJTYPE_LINEARSERIES
) && rRoot
.IsSystemColor( maData
.maColor
, rFmtInfo
.mnAutoLineColorIdx
) )
537 // store color index from automatic format data
538 mnColorId
= XclExpPalette::GetColorIdFromIndex( rFmtInfo
.mnAutoLineColorIdx
);
539 // try to set automatic mode
540 bool bAuto
= (maData
.mnPattern
== EXC_CHLINEFORMAT_SOLID
) && (maData
.mnWeight
== rFmtInfo
.mnAutoLineWeight
);
541 ::set_flag( maData
.mnFlags
, EXC_CHLINEFORMAT_AUTO
, bAuto
);
545 // user defined color - register in palette
546 mnColorId
= rRoot
.GetPalette().InsertColor( maData
.maColor
, EXC_COLOR_CHARTLINE
);
551 // no line - set default system color
552 rRoot
.SetSystemColor( maData
.maColor
, mnColorId
, EXC_COLOR_CHWINDOWTEXT
);
556 bool XclExpChLineFormat::IsDefault( XclChFrameType eDefFrameType
) const
559 ((eDefFrameType
== EXC_CHFRAMETYPE_INVISIBLE
) && !HasLine()) ||
560 ((eDefFrameType
== EXC_CHFRAMETYPE_AUTO
) && IsAuto());
563 void XclExpChLineFormat::WriteBody( XclExpStream
& rStrm
)
565 rStrm
<< maData
.maColor
<< maData
.mnPattern
<< maData
.mnWeight
<< maData
.mnFlags
;
566 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
567 rStrm
<< rStrm
.GetRoot().GetPalette().GetColorIndex( mnColorId
);
572 /** Creates a CHLINEFORMAT record from the passed property set. */
573 XclExpChLineFormatRef
lclCreateLineFormat( const XclExpChRoot
& rRoot
,
574 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
576 XclExpChLineFormatRef
xLineFmt( new XclExpChLineFormat( rRoot
) );
577 xLineFmt
->Convert( rRoot
, rPropSet
, eObjType
);
578 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
579 if( rFmtInfo
.mbDeleteDefFrame
&& xLineFmt
->IsDefault( rFmtInfo
.meDefFrameType
) )
586 // ----------------------------------------------------------------------------
588 XclExpChAreaFormat::XclExpChAreaFormat( const XclExpChRoot
& rRoot
) :
589 XclExpRecord( EXC_ID_CHAREAFORMAT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 16 : 12 ),
590 mnPattColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) ),
591 mnBackColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
595 bool XclExpChAreaFormat::Convert( const XclExpChRoot
& rRoot
,
596 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
598 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
599 bool bComplexFill
= rRoot
.ConvertAreaFormat( maData
, rPropSet
, rFmtInfo
.mePropMode
);
602 bool bSolid
= maData
.mnPattern
== EXC_PATT_SOLID
;
603 // detect system color, set color identifier (TODO: detect automatic series area)
604 if( (eObjType
!= EXC_CHOBJTYPE_FILLEDSERIES
) && rRoot
.IsSystemColor( maData
.maPattColor
, rFmtInfo
.mnAutoPattColorIdx
) )
606 // store color index from automatic format data
607 mnPattColorId
= XclExpPalette::GetColorIdFromIndex( rFmtInfo
.mnAutoPattColorIdx
);
608 // set automatic mode
609 ::set_flag( maData
.mnFlags
, EXC_CHAREAFORMAT_AUTO
, bSolid
);
613 // user defined color - register color in palette
614 mnPattColorId
= rRoot
.GetPalette().InsertColor( maData
.maPattColor
, EXC_COLOR_CHARTAREA
);
616 // background color (default system color for solid fills)
618 rRoot
.SetSystemColor( maData
.maBackColor
, mnBackColorId
, EXC_COLOR_CHWINDOWTEXT
);
620 mnBackColorId
= rRoot
.GetPalette().InsertColor( maData
.maBackColor
, EXC_COLOR_CHARTAREA
);
624 // no area - set default system colors
625 rRoot
.SetSystemColor( maData
.maPattColor
, mnPattColorId
, EXC_COLOR_CHWINDOWBACK
);
626 rRoot
.SetSystemColor( maData
.maBackColor
, mnBackColorId
, EXC_COLOR_CHWINDOWTEXT
);
631 void XclExpChAreaFormat::SetDefault( XclChFrameType eDefFrameType
)
633 switch( eDefFrameType
)
635 case EXC_CHFRAMETYPE_AUTO
:
638 case EXC_CHFRAMETYPE_INVISIBLE
:
640 maData
.mnPattern
= EXC_PATT_NONE
;
643 OSL_FAIL( "XclExpChAreaFormat::SetDefault - unknown frame type" );
647 bool XclExpChAreaFormat::IsDefault( XclChFrameType eDefFrameType
) const
650 ((eDefFrameType
== EXC_CHFRAMETYPE_INVISIBLE
) && !HasArea()) ||
651 ((eDefFrameType
== EXC_CHFRAMETYPE_AUTO
) && IsAuto());
654 void XclExpChAreaFormat::WriteBody( XclExpStream
& rStrm
)
656 rStrm
<< maData
.maPattColor
<< maData
.maBackColor
<< maData
.mnPattern
<< maData
.mnFlags
;
657 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
659 const XclExpPalette
& rPal
= rStrm
.GetRoot().GetPalette();
660 rStrm
<< rPal
.GetColorIndex( mnPattColorId
) << rPal
.GetColorIndex( mnBackColorId
);
664 // ----------------------------------------------------------------------------
666 XclExpChEscherFormat::XclExpChEscherFormat( const XclExpChRoot
& rRoot
) :
667 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_UNKNOWN
, EXC_ID_CHESCHERFORMAT
),
668 mnColor1Id( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) ),
669 mnColor2Id( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) )
671 OSL_ENSURE_BIFF( GetBiff() == EXC_BIFF8
);
674 void XclExpChEscherFormat::Convert( const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
676 const XclChFormatInfo
& rFmtInfo
= GetFormatInfo( eObjType
);
677 ConvertEscherFormat( maData
, maPicFmt
, rPropSet
, rFmtInfo
.mePropMode
);
678 // register colors in palette
679 mnColor1Id
= RegisterColor( ESCHER_Prop_fillColor
);
680 mnColor2Id
= RegisterColor( ESCHER_Prop_fillBackColor
);
683 bool XclExpChEscherFormat::IsValid() const
685 return static_cast< bool >(maData
.mxEscherSet
);
688 void XclExpChEscherFormat::Save( XclExpStream
& rStrm
)
690 if( maData
.mxEscherSet
)
692 // replace RGB colors with palette indexes in the Escher container
693 const XclExpPalette
& rPal
= GetPalette();
694 maData
.mxEscherSet
->AddOpt( ESCHER_Prop_fillColor
, 0x08000000 | rPal
.GetColorIndex( mnColor1Id
) );
695 maData
.mxEscherSet
->AddOpt( ESCHER_Prop_fillBackColor
, 0x08000000 | rPal
.GetColorIndex( mnColor2Id
) );
697 // save the record group
698 XclExpChGroupBase::Save( rStrm
);
702 bool XclExpChEscherFormat::HasSubRecords() const
704 // no subrecords for gradients
705 return maPicFmt
.mnBmpMode
!= EXC_CHPICFORMAT_NONE
;
708 void XclExpChEscherFormat::WriteSubRecords( XclExpStream
& rStrm
)
710 rStrm
.StartRecord( EXC_ID_CHPICFORMAT
, 14 );
711 rStrm
<< maPicFmt
.mnBmpMode
<< sal_uInt16( 0 ) << maPicFmt
.mnFlags
<< maPicFmt
.mfScale
;
715 sal_uInt32
XclExpChEscherFormat::RegisterColor( sal_uInt16 nPropId
)
717 sal_uInt32 nBGRValue
;
718 if( maData
.mxEscherSet
&& maData
.mxEscherSet
->GetOpt( nPropId
, nBGRValue
) )
721 Color
aColor( RGB_COLORDATA(
722 COLORDATA_BLUE( nBGRValue
),
723 COLORDATA_GREEN( nBGRValue
),
724 COLORDATA_RED( nBGRValue
) ) );
725 return GetPalette().InsertColor( aColor
, EXC_COLOR_CHARTAREA
);
727 return XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
);
730 void XclExpChEscherFormat::WriteBody( XclExpStream
& rStrm
)
732 OSL_ENSURE( maData
.mxEscherSet
, "XclExpChEscherFormat::WriteBody - missing property container" );
733 // write Escher property container via temporary memory stream
734 SvMemoryStream aMemStrm
;
735 maData
.mxEscherSet
->Commit( aMemStrm
);
736 aMemStrm
.Seek( STREAM_SEEK_TO_BEGIN
);
737 rStrm
.CopyFromStream( aMemStrm
);
740 // ----------------------------------------------------------------------------
742 XclExpChFrameBase::XclExpChFrameBase()
746 XclExpChFrameBase::~XclExpChFrameBase()
750 void XclExpChFrameBase::ConvertFrameBase( const XclExpChRoot
& rRoot
,
751 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
754 mxLineFmt
.reset( new XclExpChLineFormat( rRoot
) );
755 mxLineFmt
->Convert( rRoot
, rPropSet
, eObjType
);
756 // area format (only for frame objects)
757 if( rRoot
.GetFormatInfo( eObjType
).mbIsFrame
)
759 mxAreaFmt
.reset( new XclExpChAreaFormat( rRoot
) );
760 bool bComplexFill
= mxAreaFmt
->Convert( rRoot
, rPropSet
, eObjType
);
761 if( (rRoot
.GetBiff() == EXC_BIFF8
) && bComplexFill
)
763 mxEscherFmt
.reset( new XclExpChEscherFormat( rRoot
) );
764 mxEscherFmt
->Convert( rPropSet
, eObjType
);
765 if( mxEscherFmt
->IsValid() )
766 mxAreaFmt
->SetAuto( false );
773 void XclExpChFrameBase::SetDefaultFrameBase( const XclExpChRoot
& rRoot
,
774 XclChFrameType eDefFrameType
, bool bIsFrame
)
777 mxLineFmt
.reset( new XclExpChLineFormat( rRoot
) );
778 mxLineFmt
->SetDefault( eDefFrameType
);
779 // area format (only for frame objects)
782 mxAreaFmt
.reset( new XclExpChAreaFormat( rRoot
) );
783 mxAreaFmt
->SetDefault( eDefFrameType
);
788 bool XclExpChFrameBase::IsDefaultFrameBase( XclChFrameType eDefFrameType
) const
791 (!mxLineFmt
|| mxLineFmt
->IsDefault( eDefFrameType
)) &&
792 (!mxAreaFmt
|| mxAreaFmt
->IsDefault( eDefFrameType
));
795 void XclExpChFrameBase::WriteFrameRecords( XclExpStream
& rStrm
)
797 lclSaveRecord( rStrm
, mxLineFmt
);
798 lclSaveRecord( rStrm
, mxAreaFmt
);
799 lclSaveRecord( rStrm
, mxEscherFmt
);
802 // ----------------------------------------------------------------------------
804 XclExpChFrame::XclExpChFrame( const XclExpChRoot
& rRoot
, XclChObjectType eObjType
) :
805 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_FRAME
, EXC_ID_CHFRAME
, 4 ),
806 meObjType( eObjType
)
810 void XclExpChFrame::Convert( const ScfPropertySet
& rPropSet
)
812 ConvertFrameBase( GetChRoot(), rPropSet
, meObjType
);
815 void XclExpChFrame::SetAutoFlags( bool bAutoPos
, bool bAutoSize
)
817 ::set_flag( maData
.mnFlags
, EXC_CHFRAME_AUTOPOS
, bAutoPos
);
818 ::set_flag( maData
.mnFlags
, EXC_CHFRAME_AUTOSIZE
, bAutoSize
);
821 bool XclExpChFrame::IsDefault() const
823 return IsDefaultFrameBase( GetFormatInfo( meObjType
).meDefFrameType
);
826 bool XclExpChFrame::IsDeleteable() const
828 return IsDefault() && GetFormatInfo( meObjType
).mbDeleteDefFrame
;
831 void XclExpChFrame::Save( XclExpStream
& rStrm
)
835 // wall/floor frame without CHFRAME header record
836 case EXC_CHOBJTYPE_WALL3D
:
837 case EXC_CHOBJTYPE_FLOOR3D
:
838 WriteFrameRecords( rStrm
);
841 XclExpChGroupBase::Save( rStrm
);
845 void XclExpChFrame::WriteSubRecords( XclExpStream
& rStrm
)
847 WriteFrameRecords( rStrm
);
850 void XclExpChFrame::WriteBody( XclExpStream
& rStrm
)
852 rStrm
<< maData
.mnFormat
<< maData
.mnFlags
;
857 /** Creates a CHFRAME record from the passed property set. */
858 XclExpChFrameRef
lclCreateFrame( const XclExpChRoot
& rRoot
,
859 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
861 XclExpChFrameRef
xFrame( new XclExpChFrame( rRoot
, eObjType
) );
862 xFrame
->Convert( rPropSet
);
863 if( xFrame
->IsDeleteable() )
870 // Source links ===============================================================
874 void lclAddDoubleRefData(
875 ScTokenArray
& orArray
, const FormulaToken
& rToken
,
876 SCsTAB nScTab1
, SCsCOL nScCol1
, SCsROW nScRow1
,
877 SCsTAB nScTab2
, SCsCOL nScCol2
, SCsROW nScRow2
)
879 ScComplexRefData aComplexRef
;
880 aComplexRef
.InitFlags();
881 aComplexRef
.Ref1
.SetFlag3D( true );
882 aComplexRef
.Ref1
.nTab
= nScTab1
;
883 aComplexRef
.Ref1
.nCol
= nScCol1
;
884 aComplexRef
.Ref1
.nRow
= nScRow1
;
885 aComplexRef
.Ref2
.nTab
= nScTab2
;
886 aComplexRef
.Ref2
.nCol
= nScCol2
;
887 aComplexRef
.Ref2
.nRow
= nScRow2
;
889 if( orArray
.GetLen() > 0 )
890 orArray
.AddOpCode( ocUnion
);
892 OSL_ENSURE( (rToken
.GetType() == ::formula::svDoubleRef
) || (rToken
.GetType() == ::formula::svExternalDoubleRef
),
893 "lclAddDoubleRefData - double reference token expected");
894 if( rToken
.GetType() == ::formula::svExternalDoubleRef
)
895 orArray
.AddExternalDoubleReference( rToken
.GetIndex(), rToken
.GetString(), aComplexRef
);
897 orArray
.AddDoubleReference( aComplexRef
);
902 // ----------------------------------------------------------------------------
904 XclExpChSourceLink::XclExpChSourceLink( const XclExpChRoot
& rRoot
, sal_uInt8 nDestType
) :
905 XclExpRecord( EXC_ID_CHSOURCELINK
),
906 XclExpChRoot( rRoot
)
908 maData
.mnDestType
= nDestType
;
909 maData
.mnLinkType
= EXC_CHSRCLINK_DIRECTLY
;
912 sal_uInt16
XclExpChSourceLink::ConvertDataSequence( Reference
< XDataSequence
> xDataSeq
, bool bSplitToColumns
, sal_uInt16 nDefCount
)
915 maData
.mnLinkType
= EXC_CHSRCLINK_DEFAULT
;
920 // Compile the range representation string into token array. Note that the
921 // source range text depends on the current grammar.
922 OUString aRangeRepr
= xDataSeq
->getSourceRangeRepresentation();
923 ScCompiler
aComp( GetDocPtr(), ScAddress() );
924 aComp
.SetGrammar( GetDocPtr()->GetGrammar() );
925 ScTokenArray
* pArray
= aComp
.CompileString( aRangeRepr
);
930 sal_uInt32 nValueCount
= 0;
932 for( const FormulaToken
* pToken
= pArray
->First(); pToken
; pToken
= pArray
->Next() )
934 switch( pToken
->GetType() )
936 case ::formula::svSingleRef
:
937 case ::formula::svExternalSingleRef
:
938 // for a single ref token, just add it to the new token array as is
939 if( aArray
.GetLen() > 0 )
940 aArray
.AddOpCode( ocUnion
);
941 aArray
.AddToken( *pToken
);
945 case ::formula::svDoubleRef
:
946 case ::formula::svExternalDoubleRef
:
948 // split 3-dimensional ranges into single sheets
949 const ScComplexRefData
& rComplexRef
= static_cast< const ScToken
* >( pToken
)->GetDoubleRef();
950 const ScSingleRefData
& rRef1
= rComplexRef
.Ref1
;
951 const ScSingleRefData
& rRef2
= rComplexRef
.Ref2
;
952 for( SCsTAB nScTab
= rRef1
.nTab
; nScTab
<= rRef2
.nTab
; ++nScTab
)
954 // split 2-dimensional ranges into single columns
955 if( bSplitToColumns
&& (rRef1
.nCol
< rRef2
.nCol
) && (rRef1
.nRow
< rRef2
.nRow
) )
956 for( SCsCOL nScCol
= rRef1
.nCol
; nScCol
<= rRef2
.nCol
; ++nScCol
)
957 lclAddDoubleRefData( aArray
, *pToken
, nScTab
, nScCol
, rRef1
.nRow
, nScTab
, nScCol
, rRef2
.nRow
);
959 lclAddDoubleRefData( aArray
, *pToken
, nScTab
, rRef1
.nCol
, rRef1
.nRow
, nScTab
, rRef2
.nCol
, rRef2
.nRow
);
961 sal_uInt32 nTabs
= static_cast< sal_uInt32
>( rRef2
.nTab
- rRef1
.nTab
+ 1 );
962 sal_uInt32 nCols
= static_cast< sal_uInt32
>( rRef2
.nCol
- rRef1
.nCol
+ 1 );
963 sal_uInt32 nRows
= static_cast< sal_uInt32
>( rRef2
.nRow
- rRef1
.nRow
+ 1 );
964 nValueCount
+= nCols
* nRows
* nTabs
;
972 const ScAddress aBaseCell
;
973 mxLinkFmla
= GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CHART
, aArray
, &aBaseCell
);
974 maData
.mnLinkType
= EXC_CHSRCLINK_WORKSHEET
;
975 return ulimit_cast
< sal_uInt16
>( nValueCount
, EXC_CHDATAFORMAT_MAXPOINTCOUNT
);
978 sal_uInt16
XclExpChSourceLink::ConvertStringSequence( const Sequence
< Reference
< XFormattedString
> >& rStringSeq
)
981 sal_uInt16 nFontIdx
= EXC_FONT_APP
;
982 if( rStringSeq
.hasElements() )
984 mxString
= XclExpStringHelper::CreateString( GetRoot(), String::EmptyString(), EXC_STR_FORCEUNICODE
| EXC_STR_8BITLENGTH
| EXC_STR_SEPARATEFORMATS
);
985 Reference
< XBreakIterator
> xBreakIt
= GetDoc().GetBreakIterator();
986 namespace ApiScriptType
= ::com::sun::star::i18n::ScriptType
;
988 // convert all formatted string entries from the sequence
989 const Reference
< XFormattedString
>* pBeg
= rStringSeq
.getConstArray();
990 const Reference
< XFormattedString
>* pEnd
= pBeg
+ rStringSeq
.getLength();
991 for( const Reference
< XFormattedString
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
995 sal_uInt16 nWstrnFontIdx
= EXC_FONT_NOTFOUND
;
996 sal_uInt16 nAsianFontIdx
= EXC_FONT_NOTFOUND
;
997 sal_uInt16 nCmplxFontIdx
= EXC_FONT_NOTFOUND
;
998 OUString aText
= (*pIt
)->getString();
999 ScfPropertySet
aStrProp( *pIt
);
1001 // #i63255# get script type for leading weak characters
1002 sal_Int16 nLastScript
= XclExpStringHelper::GetLeadingScriptType( GetRoot(), aText
);
1004 // process all script portions
1005 sal_Int32 nPortionPos
= 0;
1006 sal_Int32 nTextLen
= aText
.getLength();
1007 while( nPortionPos
< nTextLen
)
1009 // get script type and end position of next script portion
1010 sal_Int16 nScript
= xBreakIt
->getScriptType( aText
, nPortionPos
);
1011 sal_Int32 nPortionEnd
= xBreakIt
->endOfScript( aText
, nPortionPos
, nScript
);
1013 // reuse previous script for following weak portions
1014 if( nScript
== ApiScriptType::WEAK
)
1015 nScript
= nLastScript
;
1017 // Excel start position of this portion
1018 sal_uInt16 nXclPortionStart
= mxString
->Len();
1019 // add portion text to Excel string
1020 XclExpStringHelper::AppendString( *mxString
, GetRoot(), aText
.copy( nPortionPos
, nPortionEnd
- nPortionPos
) );
1021 if( nXclPortionStart
< mxString
->Len() )
1023 // find font index variable dependent on script type
1024 sal_uInt16
& rnFontIdx
= (nScript
== ApiScriptType::COMPLEX
) ? nCmplxFontIdx
:
1025 ((nScript
== ApiScriptType::ASIAN
) ? nAsianFontIdx
: nWstrnFontIdx
);
1027 // insert font into buffer (if not yet done)
1028 if( rnFontIdx
== EXC_FONT_NOTFOUND
)
1029 rnFontIdx
= ConvertFont( aStrProp
, nScript
);
1031 // insert font index into format run vector
1032 mxString
->AppendFormat( nXclPortionStart
, rnFontIdx
);
1035 // go to next script portion
1036 nLastScript
= nScript
;
1037 nPortionPos
= nPortionEnd
;
1041 if( !mxString
->IsEmpty() )
1043 // get leading font index
1044 const XclFormatRunVec
& rFormats
= mxString
->GetFormats();
1045 OSL_ENSURE( !rFormats
.empty() && (rFormats
.front().mnChar
== 0),
1046 "XclExpChSourceLink::ConvertStringSequenc - missing leading format" );
1047 // remove leading format run, if entire string is equally formatted
1048 if( rFormats
.size() == 1 )
1049 nFontIdx
= mxString
->RemoveLeadingFont();
1050 else if( !rFormats
.empty() )
1051 nFontIdx
= rFormats
.front().mnFontIdx
;
1052 // add trailing format run, if string is rich-formatted
1053 if( mxString
->IsRich() )
1054 mxString
->AppendTrailingFormat( EXC_FONT_APP
);
1060 void XclExpChSourceLink::ConvertNumFmt( const ScfPropertySet
& rPropSet
, bool bPercent
)
1062 sal_Int32 nApiNumFmt
= 0;
1063 if( bPercent
? rPropSet
.GetProperty( nApiNumFmt
, EXC_CHPROP_PERCENTAGENUMFMT
) : rPropSet
.GetProperty( nApiNumFmt
, EXC_CHPROP_NUMBERFORMAT
) )
1065 ::set_flag( maData
.mnFlags
, EXC_CHSRCLINK_NUMFMT
);
1066 maData
.mnNumFmtIdx
= GetNumFmtBuffer().Insert( static_cast< sal_uInt32
>( nApiNumFmt
) );
1070 void XclExpChSourceLink::AppendString( const String
& rStr
)
1074 XclExpStringHelper::AppendString( *mxString
, GetRoot(), rStr
);
1077 void XclExpChSourceLink::Save( XclExpStream
& rStrm
)
1079 // CHFORMATRUNS record
1080 if( mxString
&& mxString
->IsRich() )
1082 sal_Size nRecSize
= (1 + mxString
->GetFormatsCount()) * ((GetBiff() == EXC_BIFF8
) ? 2 : 1);
1083 rStrm
.StartRecord( EXC_ID_CHFORMATRUNS
, nRecSize
);
1084 mxString
->WriteFormats( rStrm
, true );
1087 // CHSOURCELINK record
1088 XclExpRecord::Save( rStrm
);
1090 if( mxString
&& !mxString
->IsEmpty() )
1092 rStrm
.StartRecord( EXC_ID_CHSTRING
, 2 + mxString
->GetSize() );
1093 rStrm
<< sal_uInt16( 0 ) << *mxString
;
1098 void XclExpChSourceLink::WriteBody( XclExpStream
& rStrm
)
1100 rStrm
<< maData
.mnDestType
1101 << maData
.mnLinkType
1103 << maData
.mnNumFmtIdx
1107 // Text =======================================================================
1109 XclExpChFont::XclExpChFont( sal_uInt16 nFontIdx
) :
1110 XclExpUInt16Record( EXC_ID_CHFONT
, nFontIdx
)
1114 // ----------------------------------------------------------------------------
1116 XclExpChObjectLink::XclExpChObjectLink( sal_uInt16 nLinkTarget
, const XclChDataPointPos
& rPointPos
) :
1117 XclExpRecord( EXC_ID_CHOBJECTLINK
, 6 )
1119 maData
.mnTarget
= nLinkTarget
;
1120 maData
.maPointPos
= rPointPos
;
1123 void XclExpChObjectLink::WriteBody( XclExpStream
& rStrm
)
1125 rStrm
<< maData
.mnTarget
<< maData
.maPointPos
.mnSeriesIdx
<< maData
.maPointPos
.mnPointIdx
;
1128 // ----------------------------------------------------------------------------
1130 XclExpChFrLabelProps::XclExpChFrLabelProps( const XclExpChRoot
& rRoot
) :
1131 XclExpChFutureRecordBase( rRoot
, EXC_FUTUREREC_UNUSEDREF
, EXC_ID_CHFRLABELPROPS
, 4 )
1135 void XclExpChFrLabelProps::Convert( const ScfPropertySet
& rPropSet
, bool bShowSeries
,
1136 bool bShowCateg
, bool bShowValue
, bool bShowPercent
, bool bShowBubble
)
1138 // label value flags
1139 ::set_flag( maData
.mnFlags
, EXC_CHFRLABELPROPS_SHOWSERIES
, bShowSeries
);
1140 ::set_flag( maData
.mnFlags
, EXC_CHFRLABELPROPS_SHOWCATEG
, bShowCateg
);
1141 ::set_flag( maData
.mnFlags
, EXC_CHFRLABELPROPS_SHOWVALUE
, bShowValue
);
1142 ::set_flag( maData
.mnFlags
, EXC_CHFRLABELPROPS_SHOWPERCENT
, bShowPercent
);
1143 ::set_flag( maData
.mnFlags
, EXC_CHFRLABELPROPS_SHOWBUBBLE
, bShowBubble
);
1145 // label value separator
1146 maData
.maSeparator
= rPropSet
.GetStringProperty( EXC_CHPROP_LABELSEPARATOR
);
1147 if( maData
.maSeparator
.isEmpty() )
1148 maData
.maSeparator
= OUString(' ');
1151 void XclExpChFrLabelProps::WriteBody( XclExpStream
& rStrm
)
1153 XclExpString
aXclSep( maData
.maSeparator
, EXC_STR_FORCEUNICODE
| EXC_STR_SMARTFLAGS
);
1154 rStrm
<< maData
.mnFlags
<< aXclSep
;
1157 // ----------------------------------------------------------------------------
1159 XclExpChFontBase::~XclExpChFontBase()
1163 void XclExpChFontBase::ConvertFontBase( const XclExpChRoot
& rRoot
, sal_uInt16 nFontIdx
)
1165 if( const XclExpFont
* pFont
= rRoot
.GetFontBuffer().GetFont( nFontIdx
) )
1167 XclExpChFontRef
xFont( new XclExpChFont( nFontIdx
) );
1168 SetFont( xFont
, pFont
->GetFontData().maColor
, pFont
->GetFontColorId() );
1172 void XclExpChFontBase::ConvertFontBase( const XclExpChRoot
& rRoot
, const ScfPropertySet
& rPropSet
)
1174 ConvertFontBase( rRoot
, rRoot
.ConvertFont( rPropSet
, rRoot
.GetDefApiScript() ) );
1177 void XclExpChFontBase::ConvertRotationBase(
1178 const XclExpChRoot
& rRoot
, const ScfPropertySet
& rPropSet
, bool bSupportsStacked
)
1180 sal_uInt16 nRotation
= rRoot
.GetChartPropSetHelper().ReadRotationProperties( rPropSet
, bSupportsStacked
);
1181 SetRotation( nRotation
);
1184 // ----------------------------------------------------------------------------
1186 XclExpChText::XclExpChText( const XclExpChRoot
& rRoot
) :
1187 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_TEXT
, EXC_ID_CHTEXT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 32 : 26 ),
1188 mnTextColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
1192 void XclExpChText::SetFont( XclExpChFontRef xFont
, const Color
& rColor
, sal_uInt32 nColorId
)
1195 maData
.maTextColor
= rColor
;
1196 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOCOLOR
, rColor
== COL_AUTO
);
1197 mnTextColorId
= nColorId
;
1200 void XclExpChText::SetRotation( sal_uInt16 nRotation
)
1202 maData
.mnRotation
= nRotation
;
1203 ::insert_value( maData
.mnFlags
, XclTools::GetXclOrientFromRot( nRotation
), 8, 3 );
1206 void XclExpChText::ConvertTitle( Reference
< XTitle
> xTitle
, sal_uInt16 nTarget
, const String
* pSubTitle
)
1210 case EXC_CHOBJLINK_TITLE
: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_TITLE
); break;
1211 case EXC_CHOBJLINK_YAXIS
: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_AXISTITLE
, 1 ); break;
1212 case EXC_CHOBJLINK_XAXIS
: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_AXISTITLE
, 0 ); break;
1213 case EXC_CHOBJLINK_ZAXIS
: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_AXISTITLE
, 2 ); break;
1217 mxObjLink
.reset( new XclExpChObjectLink( nTarget
, XclChDataPointPos( 0, 0 ) ) );
1221 // title frame formatting
1222 ScfPropertySet
aTitleProp( xTitle
);
1223 mxFrame
= lclCreateFrame( GetChRoot(), aTitleProp
, EXC_CHOBJTYPE_TEXT
);
1226 mxSrcLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1227 sal_uInt16 nFontIdx
= mxSrcLink
->ConvertStringSequence( xTitle
->getText() );
1230 // append subtitle as the 2nd line of the title.
1231 String aSubTitle
= OUString("\n");
1232 aSubTitle
.Append(*pSubTitle
);
1233 mxSrcLink
->AppendString(aSubTitle
);
1236 ConvertFontBase( GetChRoot(), nFontIdx
);
1239 ConvertRotationBase( GetChRoot(), aTitleProp
, true );
1241 // manual text position - only for main title
1242 mxFramePos
.reset( new XclExpChFramePos( EXC_CHFRAMEPOS_PARENT
, EXC_CHFRAMEPOS_PARENT
) );
1243 if( nTarget
== EXC_CHOBJLINK_TITLE
)
1246 if( aTitleProp
.GetAnyProperty( aRelPos
, EXC_CHPROP_RELATIVEPOSITION
) && aRelPos
.has
< RelativePosition
>() ) try
1248 // calculate absolute position for CHTEXT record
1249 Reference
< cssc::XChartDocument
> xChart1Doc( GetChartDocument(), UNO_QUERY_THROW
);
1250 Reference
< XShape
> xTitleShape( xChart1Doc
->getTitle(), UNO_SET_THROW
);
1251 ::com::sun::star::awt::Point aPos
= xTitleShape
->getPosition();
1252 ::com::sun::star::awt::Size aSize
= xTitleShape
->getSize();
1253 ::com::sun::star::awt::Rectangle
aRect( aPos
.X
, aPos
.Y
, aSize
.Width
, aSize
.Height
);
1254 maData
.maRect
= CalcChartRectFromHmm( aRect
);
1255 ::insert_value( maData
.mnFlags2
, EXC_CHTEXT_POS_MOVED
, 0, 4 );
1256 // manual title position implies manual plot area
1257 GetChartData().SetManualPlotArea();
1258 // calculate the default title position in chart units
1259 sal_Int32 nDefPosX
= ::std::max
< sal_Int32
>( (EXC_CHART_TOTALUNITS
- maData
.maRect
.mnWidth
) / 2, 0 );
1260 sal_Int32 nDefPosY
= 85;
1261 // set the position relative to the standard position
1262 XclChRectangle
& rFrameRect
= mxFramePos
->GetFramePosData().maRect
;
1263 rFrameRect
.mnX
= maData
.maRect
.mnX
- nDefPosX
;
1264 rFrameRect
.mnY
= maData
.maRect
.mnY
- nDefPosY
;
1273 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_DELETED
);
1277 void XclExpChText::ConvertLegend( const ScfPropertySet
& rPropSet
)
1279 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOTEXT
);
1280 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOGEN
);
1281 ConvertFontBase( GetChRoot(), rPropSet
);
1284 bool XclExpChText::ConvertDataLabel( const ScfPropertySet
& rPropSet
,
1285 const XclChTypeInfo
& rTypeInfo
, const XclChDataPointPos
& rPointPos
)
1287 SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_DATALABEL
, rPointPos
.mnPointIdx
, rPointPos
.mnSeriesIdx
);
1289 cssc2::DataPointLabel aPointLabel
;
1290 if( !rPropSet
.GetProperty( aPointLabel
, EXC_CHPROP_LABEL
) )
1293 // percentage only allowed in pie and donut charts
1294 bool bIsPie
= rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
;
1295 // bubble sizes only allowed in bubble charts
1296 bool bIsBubble
= rTypeInfo
.meTypeId
== EXC_CHTYPEID_BUBBLES
;
1297 OSL_ENSURE( (GetBiff() == EXC_BIFF8
) || !bIsBubble
, "XclExpChText::ConvertDataLabel - bubble charts only in BIFF8" );
1300 bool bShowValue
= !bIsBubble
&& aPointLabel
.ShowNumber
; // Chart2 uses 'ShowNumber' for bubble size
1301 bool bShowPercent
= bIsPie
&& aPointLabel
.ShowNumberInPercent
; // percentage only in pie/donut charts
1302 bool bShowCateg
= aPointLabel
.ShowCategoryName
;
1303 bool bShowBubble
= bIsBubble
&& aPointLabel
.ShowNumber
; // Chart2 uses 'ShowNumber' for bubble size
1304 bool bShowAny
= bShowValue
|| bShowPercent
|| bShowCateg
|| bShowBubble
;
1306 // create the CHFRLABELPROPS record for extended settings in BIFF8
1307 if( bShowAny
&& (GetBiff() == EXC_BIFF8
) )
1309 mxLabelProps
.reset( new XclExpChFrLabelProps( GetChRoot() ) );
1310 mxLabelProps
->Convert( rPropSet
, false, bShowCateg
, bShowValue
, bShowPercent
, bShowBubble
);
1313 // restrict to combinations allowed in CHTEXT
1314 if( bShowPercent
) bShowValue
= false; // percent wins over value
1315 if( bShowValue
) bShowCateg
= false; // value wins over category
1316 if( bShowValue
|| bShowCateg
) bShowBubble
= false; // value or category wins over bubble size
1319 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOTEXT
);
1320 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWVALUE
, bShowValue
);
1321 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWPERCENT
, bShowPercent
);
1322 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
, bShowCateg
);
1323 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEGPERC
, bShowPercent
&& bShowCateg
);
1324 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWBUBBLE
, bShowBubble
);
1325 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWSYMBOL
, bShowAny
&& aPointLabel
.ShowLegendSymbol
);
1326 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_DELETED
, !bShowAny
);
1331 ConvertFontBase( GetChRoot(), rPropSet
);
1332 ConvertRotationBase( GetChRoot(), rPropSet
, false );
1334 sal_Int32 nPlacement
= 0;
1335 sal_uInt16 nLabelPos
= EXC_CHTEXT_POS_AUTO
;
1336 if( rPropSet
.GetProperty( nPlacement
, EXC_CHPROP_LABELPLACEMENT
) )
1338 using namespace cssc::DataLabelPlacement
;
1339 if( nPlacement
== rTypeInfo
.mnDefaultLabelPos
)
1341 nLabelPos
= EXC_CHTEXT_POS_DEFAULT
;
1343 else switch( nPlacement
)
1345 case AVOID_OVERLAP
: nLabelPos
= EXC_CHTEXT_POS_AUTO
; break;
1346 case CENTER
: nLabelPos
= EXC_CHTEXT_POS_CENTER
; break;
1347 case TOP
: nLabelPos
= EXC_CHTEXT_POS_ABOVE
; break;
1348 case TOP_LEFT
: nLabelPos
= EXC_CHTEXT_POS_LEFT
; break;
1349 case LEFT
: nLabelPos
= EXC_CHTEXT_POS_LEFT
; break;
1350 case BOTTOM_LEFT
: nLabelPos
= EXC_CHTEXT_POS_LEFT
; break;
1351 case BOTTOM
: nLabelPos
= EXC_CHTEXT_POS_BELOW
; break;
1352 case BOTTOM_RIGHT
: nLabelPos
= EXC_CHTEXT_POS_RIGHT
; break;
1353 case RIGHT
: nLabelPos
= EXC_CHTEXT_POS_RIGHT
; break;
1354 case TOP_RIGHT
: nLabelPos
= EXC_CHTEXT_POS_RIGHT
; break;
1355 case INSIDE
: nLabelPos
= EXC_CHTEXT_POS_INSIDE
; break;
1356 case OUTSIDE
: nLabelPos
= EXC_CHTEXT_POS_OUTSIDE
; break;
1357 case NEAR_ORIGIN
: nLabelPos
= EXC_CHTEXT_POS_AXIS
; break;
1358 default: OSL_FAIL( "XclExpChText::ConvertDataLabel - unknown label placement type" );
1361 ::insert_value( maData
.mnFlags2
, nLabelPos
, 0, 4 );
1362 // source link (contains number format)
1363 mxSrcLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1364 if( bShowValue
|| bShowPercent
)
1365 // percentage format wins over value format
1366 mxSrcLink
->ConvertNumFmt( rPropSet
, bShowPercent
);
1368 mxObjLink
.reset( new XclExpChObjectLink( EXC_CHOBJLINK_DATA
, rPointPos
) );
1371 /* Return true to indicate valid label settings:
1372 - for existing labels at entire series
1373 - for any settings at single data point (to be able to delete a point label) */
1374 return bShowAny
|| (rPointPos
.mnPointIdx
!= EXC_CHDATAFORMAT_ALLPOINTS
);
1377 void XclExpChText::ConvertTrendLineEquation( const ScfPropertySet
& rPropSet
, const XclChDataPointPos
& rPointPos
)
1380 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOTEXT
);
1381 if( GetBiff() == EXC_BIFF8
)
1382 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
); // must set this to make equation visible in Excel
1384 mxFrame
= lclCreateFrame( GetChRoot(), rPropSet
, EXC_CHOBJTYPE_TEXT
);
1386 maData
.mnHAlign
= EXC_CHTEXT_ALIGN_TOPLEFT
;
1387 maData
.mnVAlign
= EXC_CHTEXT_ALIGN_TOPLEFT
;
1388 ConvertFontBase( GetChRoot(), rPropSet
);
1389 // source link (contains number format)
1390 mxSrcLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1391 mxSrcLink
->ConvertNumFmt( rPropSet
, false );
1393 mxObjLink
.reset( new XclExpChObjectLink( EXC_CHOBJLINK_DATA
, rPointPos
) );
1396 sal_uInt16
XclExpChText::GetAttLabelFlags() const
1398 sal_uInt16 nFlags
= 0;
1399 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWVALUE
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWVALUE
) );
1400 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWPERCENT
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWPERCENT
) );
1401 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWCATEGPERC
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEGPERC
) );
1402 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWCATEG
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
) );
1406 void XclExpChText::WriteSubRecords( XclExpStream
& rStrm
)
1408 // CHFRAMEPOS record
1409 lclSaveRecord( rStrm
, mxFramePos
);
1411 lclSaveRecord( rStrm
, mxFont
);
1412 // CHSOURCELINK group
1413 lclSaveRecord( rStrm
, mxSrcLink
);
1415 lclSaveRecord( rStrm
, mxFrame
);
1416 // CHOBJECTLINK record
1417 lclSaveRecord( rStrm
, mxObjLink
);
1418 // CHFRLABELPROPS record
1419 lclSaveRecord( rStrm
, mxLabelProps
);
1422 void XclExpChText::WriteBody( XclExpStream
& rStrm
)
1424 rStrm
<< maData
.mnHAlign
1426 << maData
.mnBackMode
1427 << maData
.maTextColor
1431 if( GetBiff() == EXC_BIFF8
)
1433 rStrm
<< GetPalette().GetColorIndex( mnTextColorId
)
1435 << maData
.mnRotation
;
1439 // ----------------------------------------------------------------------------
1443 /** Creates and returns an Excel text object from the passed title. */
1444 XclExpChTextRef
lclCreateTitle( const XclExpChRoot
& rRoot
, Reference
< XTitled
> xTitled
, sal_uInt16 nTarget
,
1445 const String
* pSubTitle
= NULL
)
1447 Reference
< XTitle
> xTitle
;
1449 xTitle
= xTitled
->getTitleObject();
1451 XclExpChTextRef
xText( new XclExpChText( rRoot
) );
1452 xText
->ConvertTitle( xTitle
, nTarget
, pSubTitle
);
1453 /* Do not delete the CHTEXT group for the main title. A missing CHTEXT
1454 will be interpreted as auto-generated title showing the series title in
1455 charts that contain exactly one data series. */
1456 if( (nTarget
!= EXC_CHOBJLINK_TITLE
) && !xText
->HasString() )
1464 // Data series ================================================================
1466 XclExpChMarkerFormat::XclExpChMarkerFormat( const XclExpChRoot
& rRoot
) :
1467 XclExpRecord( EXC_ID_CHMARKERFORMAT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 20 : 12 ),
1468 mnLineColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) ),
1469 mnFillColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) )
1473 void XclExpChMarkerFormat::Convert( const XclExpChRoot
& rRoot
,
1474 const ScfPropertySet
& rPropSet
, sal_uInt16 nFormatIdx
)
1476 rRoot
.GetChartPropSetHelper().ReadMarkerProperties( maData
, rPropSet
, nFormatIdx
);
1477 /* Set marker line/fill color to series line color.
1478 TODO: remove this if OOChart supports own colors in markers. */
1480 if( rPropSet
.GetColorProperty( aLineColor
, EXC_CHPROP_COLOR
) )
1481 maData
.maLineColor
= maData
.maFillColor
= aLineColor
;
1482 // register colors in palette
1483 RegisterColors( rRoot
);
1486 void XclExpChMarkerFormat::ConvertStockSymbol( const XclExpChRoot
& rRoot
,
1487 const ScfPropertySet
& rPropSet
, bool bCloseSymbol
)
1489 // clear the automatic flag
1490 ::set_flag( maData
.mnFlags
, EXC_CHMARKERFORMAT_AUTO
, false );
1491 // symbol type and color
1494 // set symbol type for the 'close' data series
1495 maData
.mnMarkerType
= EXC_CHMARKERFORMAT_DOWJ
;
1496 maData
.mnMarkerSize
= EXC_CHMARKERFORMAT_DOUBLESIZE
;
1497 // set symbol line/fill color to series line color
1499 if( rPropSet
.GetColorProperty( aLineColor
, EXC_CHPROP_COLOR
) )
1501 maData
.maLineColor
= maData
.maFillColor
= aLineColor
;
1502 RegisterColors( rRoot
);
1507 // set invisible symbol
1508 maData
.mnMarkerType
= EXC_CHMARKERFORMAT_NOSYMBOL
;
1512 void XclExpChMarkerFormat::RegisterColors( const XclExpChRoot
& rRoot
)
1516 if( HasLineColor() )
1517 mnLineColorId
= rRoot
.GetPalette().InsertColor( maData
.maLineColor
, EXC_COLOR_CHARTLINE
);
1518 if( HasFillColor() )
1519 mnFillColorId
= rRoot
.GetPalette().InsertColor( maData
.maFillColor
, EXC_COLOR_CHARTAREA
);
1523 void XclExpChMarkerFormat::WriteBody( XclExpStream
& rStrm
)
1525 rStrm
<< maData
.maLineColor
<< maData
.maFillColor
<< maData
.mnMarkerType
<< maData
.mnFlags
;
1526 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
1528 const XclExpPalette
& rPal
= rStrm
.GetRoot().GetPalette();
1529 rStrm
<< rPal
.GetColorIndex( mnLineColorId
) << rPal
.GetColorIndex( mnFillColorId
) << maData
.mnMarkerSize
;
1533 // ----------------------------------------------------------------------------
1535 XclExpChPieFormat::XclExpChPieFormat() :
1536 XclExpUInt16Record( EXC_ID_CHPIEFORMAT
, 0 )
1540 void XclExpChPieFormat::Convert( const ScfPropertySet
& rPropSet
)
1542 double fApiDist(0.0);
1543 if( rPropSet
.GetProperty( fApiDist
, EXC_CHPROP_OFFSET
) )
1544 SetValue( limit_cast
< sal_uInt16
>( fApiDist
* 100.0, 0, 100 ) );
1547 // ----------------------------------------------------------------------------
1549 XclExpCh3dDataFormat::XclExpCh3dDataFormat() :
1550 XclExpRecord( EXC_ID_CH3DDATAFORMAT
, 2 )
1554 void XclExpCh3dDataFormat::Convert( const ScfPropertySet
& rPropSet
)
1556 sal_Int32
nApiType(0);
1557 if( rPropSet
.GetProperty( nApiType
, EXC_CHPROP_GEOMETRY3D
) )
1559 using namespace cssc2::DataPointGeometry3D
;
1563 maData
.mnBase
= EXC_CH3DDATAFORMAT_RECT
;
1564 maData
.mnTop
= EXC_CH3DDATAFORMAT_STRAIGHT
;
1567 maData
.mnBase
= EXC_CH3DDATAFORMAT_RECT
;
1568 maData
.mnTop
= EXC_CH3DDATAFORMAT_SHARP
;
1571 maData
.mnBase
= EXC_CH3DDATAFORMAT_CIRC
;
1572 maData
.mnTop
= EXC_CH3DDATAFORMAT_STRAIGHT
;
1575 maData
.mnBase
= EXC_CH3DDATAFORMAT_CIRC
;
1576 maData
.mnTop
= EXC_CH3DDATAFORMAT_SHARP
;
1579 OSL_FAIL( "XclExpCh3dDataFormat::Convert - unknown 3D bar format" );
1584 void XclExpCh3dDataFormat::WriteBody( XclExpStream
& rStrm
)
1586 rStrm
<< maData
.mnBase
<< maData
.mnTop
;
1589 // ----------------------------------------------------------------------------
1591 XclExpChAttachedLabel::XclExpChAttachedLabel( sal_uInt16 nFlags
) :
1592 XclExpUInt16Record( EXC_ID_CHATTACHEDLABEL
, nFlags
)
1596 // ----------------------------------------------------------------------------
1598 XclExpChDataFormat::XclExpChDataFormat( const XclExpChRoot
& rRoot
,
1599 const XclChDataPointPos
& rPointPos
, sal_uInt16 nFormatIdx
) :
1600 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_DATAFORMAT
, EXC_ID_CHDATAFORMAT
, 8 )
1602 maData
.maPointPos
= rPointPos
;
1603 maData
.mnFormatIdx
= nFormatIdx
;
1606 void XclExpChDataFormat::ConvertDataSeries( const ScfPropertySet
& rPropSet
, const XclChExtTypeInfo
& rTypeInfo
)
1608 // line and area formatting
1609 ConvertFrameBase( GetChRoot(), rPropSet
, rTypeInfo
.GetSeriesObjectType() );
1611 // data point symbols
1612 bool bIsFrame
= rTypeInfo
.IsSeriesFrameFormat();
1615 mxMarkerFmt
.reset( new XclExpChMarkerFormat( GetChRoot() ) );
1616 mxMarkerFmt
->Convert( GetChRoot(), rPropSet
, maData
.mnFormatIdx
);
1620 if( rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
)
1622 mxPieFmt
.reset( new XclExpChPieFormat
);
1623 mxPieFmt
->Convert( rPropSet
);
1626 // 3D bars (only allowed for entire series in BIFF8)
1627 if( IsSeriesFormat() && (GetBiff() == EXC_BIFF8
) && rTypeInfo
.mb3dChart
&& (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_BAR
) )
1629 mx3dDataFmt
.reset( new XclExpCh3dDataFormat
);
1630 mx3dDataFmt
->Convert( rPropSet
);
1634 if( IsSeriesFormat() && rTypeInfo
.mbSpline
&& !bIsFrame
)
1635 mxSeriesFmt
.reset( new XclExpUInt16Record( EXC_ID_CHSERIESFORMAT
, EXC_CHSERIESFORMAT_SMOOTHED
) );
1637 // data point labels
1638 XclExpChTextRef
xLabel( new XclExpChText( GetChRoot() ) );
1639 if( xLabel
->ConvertDataLabel( rPropSet
, rTypeInfo
, maData
.maPointPos
) )
1641 // CHTEXT groups for data labels are stored in global CHCHART group
1642 GetChartData().SetDataLabel( xLabel
);
1643 mxAttLabel
.reset( new XclExpChAttachedLabel( xLabel
->GetAttLabelFlags() ) );
1647 void XclExpChDataFormat::ConvertStockSeries( const ScfPropertySet
& rPropSet
, bool bCloseSymbol
)
1649 // set line format to invisible
1650 SetDefaultFrameBase( GetChRoot(), EXC_CHFRAMETYPE_INVISIBLE
, false );
1651 // set symbols to invisible or to 'close' series symbol
1652 mxMarkerFmt
.reset( new XclExpChMarkerFormat( GetChRoot() ) );
1653 mxMarkerFmt
->ConvertStockSymbol( GetChRoot(), rPropSet
, bCloseSymbol
);
1656 void XclExpChDataFormat::ConvertLine( const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
1658 ConvertFrameBase( GetChRoot(), rPropSet
, eObjType
);
1661 void XclExpChDataFormat::WriteSubRecords( XclExpStream
& rStrm
)
1663 lclSaveRecord( rStrm
, mx3dDataFmt
);
1664 WriteFrameRecords( rStrm
);
1665 lclSaveRecord( rStrm
, mxPieFmt
);
1666 lclSaveRecord( rStrm
, mxMarkerFmt
);
1667 lclSaveRecord( rStrm
, mxSeriesFmt
);
1668 lclSaveRecord( rStrm
, mxAttLabel
);
1671 void XclExpChDataFormat::WriteBody( XclExpStream
& rStrm
)
1673 rStrm
<< maData
.maPointPos
.mnPointIdx
1674 << maData
.maPointPos
.mnSeriesIdx
1675 << maData
.mnFormatIdx
1679 // ----------------------------------------------------------------------------
1681 XclExpChSerTrendLine::XclExpChSerTrendLine( const XclExpChRoot
& rRoot
) :
1682 XclExpRecord( EXC_ID_CHSERTRENDLINE
, 28 ),
1683 XclExpChRoot( rRoot
)
1687 bool XclExpChSerTrendLine::Convert( Reference
< XRegressionCurve
> xRegCurve
, sal_uInt16 nSeriesIdx
)
1689 if( !xRegCurve
.is() )
1693 ScfPropertySet
aCurveProp( xRegCurve
);
1694 OUString aService
= aCurveProp
.GetServiceName();
1695 if( aService
== SERVICE_CHART2_LINEARREGCURVE
)
1697 maData
.mnLineType
= EXC_CHSERTREND_POLYNOMIAL
;
1700 else if( aService
== SERVICE_CHART2_EXPREGCURVE
)
1701 maData
.mnLineType
= EXC_CHSERTREND_EXPONENTIAL
;
1702 else if( aService
== SERVICE_CHART2_LOGREGCURVE
)
1703 maData
.mnLineType
= EXC_CHSERTREND_LOGARITHMIC
;
1704 else if( aService
== SERVICE_CHART2_POTREGCURVE
)
1705 maData
.mnLineType
= EXC_CHSERTREND_POWER
;
1710 XclChDataPointPos
aPointPos( nSeriesIdx
);
1711 mxDataFmt
.reset( new XclExpChDataFormat( GetChRoot(), aPointPos
, 0 ) );
1712 mxDataFmt
->ConvertLine( aCurveProp
, EXC_CHOBJTYPE_TRENDLINE
);
1714 // #i83100# show equation and correlation coefficient
1715 ScfPropertySet
aEquationProp( xRegCurve
->getEquationProperties() );
1716 maData
.mnShowEquation
= aEquationProp
.GetBoolProperty( EXC_CHPROP_SHOWEQUATION
) ? 1 : 0;
1717 maData
.mnShowRSquared
= aEquationProp
.GetBoolProperty( EXC_CHPROP_SHOWCORRELATION
) ? 1 : 0;
1719 // #i83100# formatting of the equation text box
1720 if( (maData
.mnShowEquation
!= 0) || (maData
.mnShowRSquared
!= 0) )
1722 mxLabel
.reset( new XclExpChText( GetChRoot() ) );
1723 mxLabel
->ConvertTrendLineEquation( aEquationProp
, aPointPos
);
1727 // #i20819# polynomial trend lines
1728 // #i66819# moving average trend lines
1729 // #i5085# manual trend line size
1730 // #i34093# manual crossing point
1734 void XclExpChSerTrendLine::WriteBody( XclExpStream
& rStrm
)
1736 rStrm
<< maData
.mnLineType
1738 << maData
.mfIntercept
1739 << maData
.mnShowEquation
1740 << maData
.mnShowRSquared
1741 << maData
.mfForecastFor
1742 << maData
.mfForecastBack
;
1745 // ----------------------------------------------------------------------------
1747 XclExpChSerErrorBar::XclExpChSerErrorBar( const XclExpChRoot
& rRoot
, sal_uInt8 nBarType
) :
1748 XclExpRecord( EXC_ID_CHSERERRORBAR
, 14 ),
1749 XclExpChRoot( rRoot
)
1751 maData
.mnBarType
= nBarType
;
1754 bool XclExpChSerErrorBar::Convert( XclExpChSourceLink
& rValueLink
, sal_uInt16
& rnValueCount
, const ScfPropertySet
& rPropSet
)
1756 sal_Int32 nBarStyle
= 0;
1757 bool bOk
= rPropSet
.GetProperty( nBarStyle
, EXC_CHPROP_ERRORBARSTYLE
);
1762 case cssc::ErrorBarStyle::ABSOLUTE
:
1763 maData
.mnSourceType
= EXC_CHSERERR_FIXED
;
1764 rPropSet
.GetProperty( maData
.mfValue
, EXC_CHPROP_POSITIVEERROR
);
1766 case cssc::ErrorBarStyle::RELATIVE
:
1767 maData
.mnSourceType
= EXC_CHSERERR_PERCENT
;
1768 rPropSet
.GetProperty( maData
.mfValue
, EXC_CHPROP_POSITIVEERROR
);
1770 case cssc::ErrorBarStyle::STANDARD_DEVIATION
:
1771 maData
.mnSourceType
= EXC_CHSERERR_STDDEV
;
1772 rPropSet
.GetProperty( maData
.mfValue
, EXC_CHPROP_WEIGHT
);
1774 case cssc::ErrorBarStyle::STANDARD_ERROR
:
1775 maData
.mnSourceType
= EXC_CHSERERR_STDERR
;
1777 case cssc::ErrorBarStyle::FROM_DATA
:
1780 maData
.mnSourceType
= EXC_CHSERERR_CUSTOM
;
1781 Reference
< XDataSource
> xDataSource( rPropSet
.GetApiPropertySet(), UNO_QUERY
);
1782 if( xDataSource
.is() )
1784 // find first sequence with current role
1785 OUString aRole
= XclChartHelper::GetErrorBarValuesRole( maData
.mnBarType
);
1786 Reference
< XDataSequence
> xValueSeq
;
1788 Sequence
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
= xDataSource
->getDataSequences();
1789 const Reference
< XLabeledDataSequence
>* pBeg
= aLabeledSeqVec
.getConstArray();
1790 const Reference
< XLabeledDataSequence
>* pEnd
= pBeg
+ aLabeledSeqVec
.getLength();
1791 for( const Reference
< XLabeledDataSequence
>* pIt
= pBeg
; !xValueSeq
.is() && (pIt
!= pEnd
); ++pIt
)
1793 Reference
< XDataSequence
> xTmpValueSeq
= (*pIt
)->getValues();
1794 ScfPropertySet
aValueProp( xTmpValueSeq
);
1796 if( aValueProp
.GetProperty( aCurrRole
, EXC_CHPROP_ROLE
) && (aCurrRole
== aRole
) )
1797 xValueSeq
= xTmpValueSeq
;
1799 if( xValueSeq
.is() )
1801 // #i86465# pass value count back to series
1802 rnValueCount
= maData
.mnValueCount
= rValueLink
.ConvertDataSequence( xValueSeq
, true );
1803 bOk
= maData
.mnValueCount
> 0;
1815 void XclExpChSerErrorBar::WriteBody( XclExpStream
& rStrm
)
1817 rStrm
<< maData
.mnBarType
1818 << maData
.mnSourceType
1820 << sal_uInt8( 1 ) // must be 1 to make line visible
1822 << maData
.mnValueCount
;
1825 // ----------------------------------------------------------------------------
1829 /** Returns the property set of the specified data point. */
1830 ScfPropertySet
lclGetPointPropSet( Reference
< XDataSeries
> xDataSeries
, sal_Int32 nPointIdx
)
1832 ScfPropertySet aPropSet
;
1835 aPropSet
.Set( xDataSeries
->getDataPointByIndex( nPointIdx
) );
1839 OSL_FAIL( "lclGetPointPropSet - no data point property set" );
1846 XclExpChSeries::XclExpChSeries( const XclExpChRoot
& rRoot
, sal_uInt16 nSeriesIdx
) :
1847 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_SERIES
, EXC_ID_CHSERIES
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 12 : 8 ),
1848 mnGroupIdx( EXC_CHSERGROUP_NONE
),
1849 mnSeriesIdx( nSeriesIdx
),
1850 mnParentIdx( EXC_CHSERIES_INVALID
)
1852 // CHSOURCELINK records are always required, even if unused
1853 mxTitleLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1854 mxValueLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_VALUES
) );
1855 mxCategLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_CATEGORY
) );
1856 if( GetBiff() == EXC_BIFF8
)
1857 mxBubbleLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_BUBBLES
) );
1860 bool XclExpChSeries::ConvertDataSeries(
1861 Reference
< XDiagram
> xDiagram
, Reference
< XDataSeries
> xDataSeries
,
1862 const XclChExtTypeInfo
& rTypeInfo
, sal_uInt16 nGroupIdx
, sal_uInt16 nFormatIdx
)
1865 Reference
< XDataSource
> xDataSource( xDataSeries
, UNO_QUERY
);
1866 if( xDataSource
.is() )
1868 Reference
< XDataSequence
> xYValueSeq
, xTitleSeq
, xXValueSeq
, xBubbleSeq
;
1870 // find first sequence with role 'values-y'
1871 Sequence
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
= xDataSource
->getDataSequences();
1872 const Reference
< XLabeledDataSequence
>* pBeg
= aLabeledSeqVec
.getConstArray();
1873 const Reference
< XLabeledDataSequence
>* pEnd
= pBeg
+ aLabeledSeqVec
.getLength();
1874 for( const Reference
< XLabeledDataSequence
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
1876 Reference
< XDataSequence
> xTmpValueSeq
= (*pIt
)->getValues();
1877 ScfPropertySet
aValueProp( xTmpValueSeq
);
1879 if( aValueProp
.GetProperty( aRole
, EXC_CHPROP_ROLE
) )
1881 if( !xYValueSeq
.is() && (aRole
== EXC_CHPROP_ROLE_YVALUES
) )
1883 xYValueSeq
= xTmpValueSeq
;
1884 if( !xTitleSeq
.is() )
1885 xTitleSeq
= (*pIt
)->getLabel(); // ignore role of label sequence
1887 else if( !xXValueSeq
.is() && !rTypeInfo
.mbCategoryAxis
&& (aRole
== EXC_CHPROP_ROLE_XVALUES
) )
1889 xXValueSeq
= xTmpValueSeq
;
1891 else if( !xBubbleSeq
.is() && (rTypeInfo
.meTypeId
== EXC_CHTYPEID_BUBBLES
) && (aRole
== EXC_CHPROP_ROLE_SIZEVALUES
) )
1893 xBubbleSeq
= xTmpValueSeq
;
1894 xTitleSeq
= (*pIt
)->getLabel(); // ignore role of label sequence
1899 bOk
= xYValueSeq
.is();
1902 // chart type group index
1903 mnGroupIdx
= nGroupIdx
;
1905 // convert source links
1906 maData
.mnValueCount
= mxValueLink
->ConvertDataSequence( xYValueSeq
, true );
1907 mxTitleLink
->ConvertDataSequence( xTitleSeq
, true );
1909 // X values of XY charts
1910 maData
.mnCategCount
= mxCategLink
->ConvertDataSequence( xXValueSeq
, false, maData
.mnValueCount
);
1912 // size values of bubble charts
1914 mxBubbleLink
->ConvertDataSequence( xBubbleSeq
, false, maData
.mnValueCount
);
1916 // series formatting
1917 XclChDataPointPos
aPointPos( mnSeriesIdx
);
1918 ScfPropertySet
aSeriesProp( xDataSeries
);
1919 mxSeriesFmt
.reset( new XclExpChDataFormat( GetChRoot(), aPointPos
, nFormatIdx
) );
1920 mxSeriesFmt
->ConvertDataSeries( aSeriesProp
, rTypeInfo
);
1923 CreateTrendLines( xDataSeries
);
1926 CreateErrorBars( aSeriesProp
, EXC_CHPROP_ERRORBARX
, EXC_CHSERERR_XPLUS
, EXC_CHSERERR_XMINUS
);
1927 CreateErrorBars( aSeriesProp
, EXC_CHPROP_ERRORBARY
, EXC_CHSERERR_YPLUS
, EXC_CHSERERR_YMINUS
);
1929 if( maData
.mnValueCount
> 0 )
1931 const sal_Int32 nMaxPointCount
= maData
.mnValueCount
;
1933 /* #i91063# Create missing fill properties in pie/doughnut charts.
1934 If freshly created (never saved to ODF), these charts show
1935 varying point colors but do not return these points via API. */
1936 if( xDiagram
.is() && (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
) )
1938 Reference
< XColorScheme
> xColorScheme
= xDiagram
->getDefaultColorScheme();
1939 if( xColorScheme
.is() )
1941 const OUString aFillStyleName
= "FillStyle";
1942 const OUString aColorName
= "Color";
1943 namespace cssd
= ::com::sun::star::drawing
;
1944 for( sal_Int32 nPointIdx
= 0; nPointIdx
< nMaxPointCount
; ++nPointIdx
)
1946 aPointPos
.mnPointIdx
= static_cast< sal_uInt16
>( nPointIdx
);
1947 ScfPropertySet aPointProp
= lclGetPointPropSet( xDataSeries
, nPointIdx
);
1948 // test that the point fill style is solid, but no color is set
1949 cssd::FillStyle eFillStyle
= cssd::FillStyle_NONE
;
1950 if( aPointProp
.GetProperty( eFillStyle
, aFillStyleName
) &&
1951 (eFillStyle
== cssd::FillStyle_SOLID
) &&
1952 !aPointProp
.HasProperty( aColorName
) )
1954 aPointProp
.SetProperty( aColorName
, xColorScheme
->getColorByIndex( nPointIdx
) );
1960 // data point formatting
1961 Sequence
< sal_Int32
> aPointIndexes
;
1962 if( aSeriesProp
.GetProperty( aPointIndexes
, EXC_CHPROP_ATTRIBDATAPOINTS
) && aPointIndexes
.hasElements() )
1964 const sal_Int32
* pnBeg
= aPointIndexes
.getConstArray();
1965 const sal_Int32
* pnEnd
= pnBeg
+ aPointIndexes
.getLength();
1966 for( const sal_Int32
* pnIt
= pnBeg
; (pnIt
!= pnEnd
) && (*pnIt
< nMaxPointCount
); ++pnIt
)
1968 aPointPos
.mnPointIdx
= static_cast< sal_uInt16
>( *pnIt
);
1969 ScfPropertySet aPointProp
= lclGetPointPropSet( xDataSeries
, *pnIt
);
1970 XclExpChDataFormatRef
xPointFmt( new XclExpChDataFormat( GetChRoot(), aPointPos
, nFormatIdx
) );
1971 xPointFmt
->ConvertDataSeries( aPointProp
, rTypeInfo
);
1972 maPointFmts
.AppendRecord( xPointFmt
);
1981 bool XclExpChSeries::ConvertStockSeries( XDataSeriesRef xDataSeries
,
1982 const OUString
& rValueRole
, sal_uInt16 nGroupIdx
, sal_uInt16 nFormatIdx
, bool bCloseSymbol
)
1985 Reference
< XDataSource
> xDataSource( xDataSeries
, UNO_QUERY
);
1986 if( xDataSource
.is() )
1988 Reference
< XDataSequence
> xYValueSeq
, xTitleSeq
;
1990 // find first sequence with passed role
1991 Sequence
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
= xDataSource
->getDataSequences();
1992 const Reference
< XLabeledDataSequence
>* pBeg
= aLabeledSeqVec
.getConstArray();
1993 const Reference
< XLabeledDataSequence
>* pEnd
= pBeg
+ aLabeledSeqVec
.getLength();
1994 for( const Reference
< XLabeledDataSequence
>* pIt
= pBeg
; !xYValueSeq
.is() && (pIt
!= pEnd
); ++pIt
)
1996 Reference
< XDataSequence
> xTmpValueSeq
= (*pIt
)->getValues();
1997 ScfPropertySet
aValueProp( xTmpValueSeq
);
1999 if( aValueProp
.GetProperty( aRole
, EXC_CHPROP_ROLE
) && (aRole
== rValueRole
) )
2001 xYValueSeq
= xTmpValueSeq
;
2002 xTitleSeq
= (*pIt
)->getLabel(); // ignore role of label sequence
2006 bOk
= xYValueSeq
.is();
2009 // chart type group index
2010 mnGroupIdx
= nGroupIdx
;
2011 // convert source links
2012 maData
.mnValueCount
= mxValueLink
->ConvertDataSequence( xYValueSeq
, true );
2013 mxTitleLink
->ConvertDataSequence( xTitleSeq
, true );
2014 // series formatting
2015 ScfPropertySet
aSeriesProp( xDataSeries
);
2016 mxSeriesFmt
.reset( new XclExpChDataFormat( GetChRoot(), XclChDataPointPos( mnSeriesIdx
), nFormatIdx
) );
2017 mxSeriesFmt
->ConvertStockSeries( aSeriesProp
, bCloseSymbol
);
2023 bool XclExpChSeries::ConvertTrendLine( const XclExpChSeries
& rParent
, Reference
< XRegressionCurve
> xRegCurve
)
2025 InitFromParent( rParent
);
2026 mxTrendLine
.reset( new XclExpChSerTrendLine( GetChRoot() ) );
2027 bool bOk
= mxTrendLine
->Convert( xRegCurve
, mnSeriesIdx
);
2030 mxSeriesFmt
= mxTrendLine
->GetDataFormat();
2031 GetChartData().SetDataLabel( mxTrendLine
->GetDataLabel() );
2036 bool XclExpChSeries::ConvertErrorBar( const XclExpChSeries
& rParent
, const ScfPropertySet
& rPropSet
, sal_uInt8 nBarId
)
2038 InitFromParent( rParent
);
2039 // error bar settings
2040 mxErrorBar
.reset( new XclExpChSerErrorBar( GetChRoot(), nBarId
) );
2041 bool bOk
= mxErrorBar
->Convert( *mxValueLink
, maData
.mnValueCount
, rPropSet
);
2044 // error bar formatting
2045 mxSeriesFmt
.reset( new XclExpChDataFormat( GetChRoot(), XclChDataPointPos( mnSeriesIdx
), 0 ) );
2046 mxSeriesFmt
->ConvertLine( rPropSet
, EXC_CHOBJTYPE_ERRORBAR
);
2051 void XclExpChSeries::ConvertCategSequence( Reference
< XLabeledDataSequence
> xCategSeq
)
2053 if( xCategSeq
.is() )
2054 maData
.mnCategCount
= mxCategLink
->ConvertDataSequence( xCategSeq
->getValues(), false );
2057 void XclExpChSeries::WriteSubRecords( XclExpStream
& rStrm
)
2059 lclSaveRecord( rStrm
, mxTitleLink
);
2060 lclSaveRecord( rStrm
, mxValueLink
);
2061 lclSaveRecord( rStrm
, mxCategLink
);
2062 lclSaveRecord( rStrm
, mxBubbleLink
);
2063 lclSaveRecord( rStrm
, mxSeriesFmt
);
2064 maPointFmts
.Save( rStrm
);
2065 if( mnGroupIdx
!= EXC_CHSERGROUP_NONE
)
2066 XclExpUInt16Record( EXC_ID_CHSERGROUP
, mnGroupIdx
).Save( rStrm
);
2067 if( mnParentIdx
!= EXC_CHSERIES_INVALID
)
2068 XclExpUInt16Record( EXC_ID_CHSERPARENT
, mnParentIdx
).Save( rStrm
);
2069 lclSaveRecord( rStrm
, mxTrendLine
);
2070 lclSaveRecord( rStrm
, mxErrorBar
);
2073 void XclExpChSeries::InitFromParent( const XclExpChSeries
& rParent
)
2075 // index to parent series is stored 1-based
2076 mnParentIdx
= rParent
.mnSeriesIdx
+ 1;
2077 /* #i86465# MSO2007 SP1 expects correct point counts in child series
2078 (there was no problem in Excel2003 or Excel2007 without SP1...) */
2079 maData
.mnCategCount
= rParent
.maData
.mnCategCount
;
2080 maData
.mnValueCount
= rParent
.maData
.mnValueCount
;
2083 void XclExpChSeries::CreateTrendLines( XDataSeriesRef xDataSeries
)
2085 Reference
< XRegressionCurveContainer
> xRegCurveCont( xDataSeries
, UNO_QUERY
);
2086 if( xRegCurveCont
.is() )
2088 Sequence
< Reference
< XRegressionCurve
> > aRegCurveSeq
= xRegCurveCont
->getRegressionCurves();
2089 const Reference
< XRegressionCurve
>* pBeg
= aRegCurveSeq
.getConstArray();
2090 const Reference
< XRegressionCurve
>* pEnd
= pBeg
+ aRegCurveSeq
.getLength();
2091 for( const Reference
< XRegressionCurve
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
2093 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
2094 if( xSeries
&& !xSeries
->ConvertTrendLine( *this, *pIt
) )
2095 GetChartData().RemoveLastSeries();
2100 void XclExpChSeries::CreateErrorBars( const ScfPropertySet
& rPropSet
,
2101 const OUString
& rBarPropName
, sal_uInt8 nPosBarId
, sal_uInt8 nNegBarId
)
2103 Reference
< XPropertySet
> xErrorBar
;
2104 if( rPropSet
.GetProperty( xErrorBar
, rBarPropName
) && xErrorBar
.is() )
2106 ScfPropertySet
aErrorProp( xErrorBar
);
2107 CreateErrorBar( aErrorProp
, EXC_CHPROP_SHOWPOSITIVEERROR
, nPosBarId
);
2108 CreateErrorBar( aErrorProp
, EXC_CHPROP_SHOWNEGATIVEERROR
, nNegBarId
);
2112 void XclExpChSeries::CreateErrorBar( const ScfPropertySet
& rPropSet
,
2113 const OUString
& rShowPropName
, sal_uInt8 nBarId
)
2115 if( rPropSet
.GetBoolProperty( rShowPropName
) )
2117 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
2118 if( xSeries
&& !xSeries
->ConvertErrorBar( *this, rPropSet
, nBarId
) )
2119 GetChartData().RemoveLastSeries();
2123 void XclExpChSeries::WriteBody( XclExpStream
& rStrm
)
2125 rStrm
<< maData
.mnCategType
<< maData
.mnValueType
<< maData
.mnCategCount
<< maData
.mnValueCount
;
2126 if( GetBiff() == EXC_BIFF8
)
2127 rStrm
<< maData
.mnBubbleType
<< maData
.mnBubbleCount
;
2130 // Chart type groups ==========================================================
2132 XclExpChType::XclExpChType( const XclExpChRoot
& rRoot
) :
2133 XclExpRecord( EXC_ID_CHUNKNOWN
),
2134 XclExpChRoot( rRoot
),
2135 maTypeInfo( rRoot
.GetChartTypeInfo( EXC_CHTYPEID_UNKNOWN
) )
2139 void XclExpChType::Convert( Reference
< XDiagram
> xDiagram
, Reference
< XChartType
> xChartType
,
2140 sal_Int32 nApiAxesSetIdx
, bool bSwappedAxesSet
, bool bHasXLabels
)
2142 if( xChartType
.is() )
2144 maTypeInfo
= GetChartTypeInfo( xChartType
->getChartType() );
2145 // special handling for some chart types
2146 switch( maTypeInfo
.meTypeCateg
)
2148 case EXC_CHTYPECATEG_BAR
:
2150 maTypeInfo
= GetChartTypeInfo( bSwappedAxesSet
? EXC_CHTYPEID_HORBAR
: EXC_CHTYPEID_BAR
);
2151 ::set_flag( maData
.mnFlags
, EXC_CHBAR_HORIZONTAL
, bSwappedAxesSet
);
2152 ScfPropertySet
aTypeProp( xChartType
);
2153 Sequence
< sal_Int32
> aInt32Seq
;
2154 maData
.mnOverlap
= 0;
2155 if( aTypeProp
.GetProperty( aInt32Seq
, EXC_CHPROP_OVERLAPSEQ
) && (nApiAxesSetIdx
< aInt32Seq
.getLength()) )
2156 maData
.mnOverlap
= limit_cast
< sal_Int16
>( -aInt32Seq
[ nApiAxesSetIdx
], -100, 100 );
2158 if( aTypeProp
.GetProperty( aInt32Seq
, EXC_CHPROP_GAPWIDTHSEQ
) && (nApiAxesSetIdx
< aInt32Seq
.getLength()) )
2159 maData
.mnGap
= limit_cast
< sal_uInt16
>( aInt32Seq
[ nApiAxesSetIdx
], 0, 500 );
2162 case EXC_CHTYPECATEG_RADAR
:
2163 ::set_flag( maData
.mnFlags
, EXC_CHRADAR_AXISLABELS
, bHasXLabels
);
2165 case EXC_CHTYPECATEG_PIE
:
2167 ScfPropertySet
aTypeProp( xChartType
);
2168 bool bDonut
= aTypeProp
.GetBoolProperty( EXC_CHPROP_USERINGS
);
2169 maTypeInfo
= GetChartTypeInfo( bDonut
? EXC_CHTYPEID_DONUT
: EXC_CHTYPEID_PIE
);
2170 maData
.mnPieHole
= bDonut
? 50 : 0;
2171 // #i85166# starting angle of first pie slice
2172 ScfPropertySet
aDiaProp( xDiagram
);
2173 maData
.mnRotation
= XclExpChRoot::ConvertPieRotation( aDiaProp
);
2176 case EXC_CHTYPECATEG_SCATTER
:
2177 if( GetBiff() == EXC_BIFF8
)
2178 ::set_flag( maData
.mnFlags
, EXC_CHSCATTER_BUBBLES
, maTypeInfo
.meTypeId
== EXC_CHTYPEID_BUBBLES
);
2182 SetRecId( maTypeInfo
.mnRecId
);
2186 void XclExpChType::SetStacked( bool bPercent
)
2188 switch( maTypeInfo
.meTypeCateg
)
2190 case EXC_CHTYPECATEG_LINE
:
2191 ::set_flag( maData
.mnFlags
, EXC_CHLINE_STACKED
);
2192 ::set_flag( maData
.mnFlags
, EXC_CHLINE_PERCENT
, bPercent
);
2194 case EXC_CHTYPECATEG_BAR
:
2195 ::set_flag( maData
.mnFlags
, EXC_CHBAR_STACKED
);
2196 ::set_flag( maData
.mnFlags
, EXC_CHBAR_PERCENT
, bPercent
);
2197 maData
.mnOverlap
= -100;
2203 void XclExpChType::WriteBody( XclExpStream
& rStrm
)
2205 switch( GetRecId() )
2208 rStrm
<< maData
.mnOverlap
<< maData
.mnGap
<< maData
.mnFlags
;
2213 case EXC_ID_CHRADARLINE
:
2214 case EXC_ID_CHRADARAREA
:
2215 rStrm
<< maData
.mnFlags
;
2219 rStrm
<< maData
.mnRotation
<< maData
.mnPieHole
;
2220 if( GetBiff() == EXC_BIFF8
)
2221 rStrm
<< maData
.mnFlags
;
2224 case EXC_ID_CHSCATTER
:
2225 if( GetBiff() == EXC_BIFF8
)
2226 rStrm
<< maData
.mnBubbleSize
<< maData
.mnBubbleType
<< maData
.mnFlags
;
2230 OSL_FAIL( "XclExpChType::WriteBody - unknown chart type" );
2234 // ----------------------------------------------------------------------------
2236 XclExpChChart3d::XclExpChChart3d() :
2237 XclExpRecord( EXC_ID_CHCHART3D
, 14 )
2241 void XclExpChChart3d::Convert( const ScfPropertySet
& rPropSet
, bool b3dWallChart
)
2243 sal_Int32 nRotationY
= 0;
2244 rPropSet
.GetProperty( nRotationY
, EXC_CHPROP_ROTATIONVERTICAL
);
2245 sal_Int32 nRotationX
= 0;
2246 rPropSet
.GetProperty( nRotationX
, EXC_CHPROP_ROTATIONHORIZONTAL
);
2247 sal_Int32 nPerspective
= 15;
2248 rPropSet
.GetProperty( nPerspective
, EXC_CHPROP_PERSPECTIVE
);
2252 // Y rotation (Excel [0..359], Chart2 [-179,180])
2253 if( nRotationY
< 0 ) nRotationY
+= 360;
2254 maData
.mnRotation
= static_cast< sal_uInt16
>( nRotationY
);
2255 // X rotation a.k.a. elevation (Excel [-90..90], Chart2 [-179,180])
2256 maData
.mnElevation
= limit_cast
< sal_Int16
>( nRotationX
, -90, 90 );
2257 // perspective (Excel and Chart2 [0,100])
2258 maData
.mnEyeDist
= limit_cast
< sal_uInt16
>( nPerspective
, 0, 100 );
2261 ::set_flag( maData
.mnFlags
, EXC_CHCHART3D_REAL3D
, !rPropSet
.GetBoolProperty( EXC_CHPROP_RIGHTANGLEDAXES
) );
2262 ::set_flag( maData
.mnFlags
, EXC_CHCHART3D_AUTOHEIGHT
);
2263 ::set_flag( maData
.mnFlags
, EXC_CHCHART3D_HASWALLS
);
2267 // Y rotation not used in pie charts, but 'first pie slice angle'
2268 maData
.mnRotation
= XclExpChRoot::ConvertPieRotation( rPropSet
);
2269 // X rotation a.k.a. elevation (map Chart2 [-80,-10] to Excel [10..80])
2270 maData
.mnElevation
= limit_cast
< sal_Int16
>( (nRotationX
+ 270) % 180, 10, 80 );
2271 // perspective (Excel and Chart2 [0,100])
2272 maData
.mnEyeDist
= limit_cast
< sal_uInt16
>( nPerspective
, 0, 100 );
2278 void XclExpChChart3d::WriteBody( XclExpStream
& rStrm
)
2280 rStrm
<< maData
.mnRotation
2281 << maData
.mnElevation
2283 << maData
.mnRelHeight
2284 << maData
.mnRelDepth
2285 << maData
.mnDepthGap
2289 // ----------------------------------------------------------------------------
2291 XclExpChLegend::XclExpChLegend( const XclExpChRoot
& rRoot
) :
2292 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_LEGEND
, EXC_ID_CHLEGEND
, 20 )
2296 void XclExpChLegend::Convert( const ScfPropertySet
& rPropSet
)
2299 mxFrame
= lclCreateFrame( GetChRoot(), rPropSet
, EXC_CHOBJTYPE_LEGEND
);
2301 mxText
.reset( new XclExpChText( GetChRoot() ) );
2302 mxText
->ConvertLegend( rPropSet
);
2304 // legend position and size
2305 Any aRelPosAny
, aRelSizeAny
;
2306 rPropSet
.GetAnyProperty( aRelPosAny
, EXC_CHPROP_RELATIVEPOSITION
);
2307 rPropSet
.GetAnyProperty( aRelSizeAny
, EXC_CHPROP_RELATIVESIZE
);
2308 cssc::ChartLegendExpansion eApiExpand
= cssc::ChartLegendExpansion_CUSTOM
;
2309 rPropSet
.GetProperty( eApiExpand
, EXC_CHPROP_EXPANSION
);
2310 if( aRelPosAny
.has
< RelativePosition
>() || ((eApiExpand
== cssc::ChartLegendExpansion_CUSTOM
) && aRelSizeAny
.has
< RelativeSize
>()) )
2314 /* The 'RelativePosition' or 'RelativeSize' properties are used as
2315 indicator of manually changed legend position/size, but due to
2316 the different anchor modes used by this property (in the
2317 RelativePosition.Anchor member) it cannot be used to calculate
2318 the position easily. For this, the Chart1 API will be used
2320 Reference
< cssc::XChartDocument
> xChart1Doc( GetChartDocument(), UNO_QUERY_THROW
);
2321 Reference
< XShape
> xChart1Legend( xChart1Doc
->getLegend(), UNO_SET_THROW
);
2322 // coordinates in CHLEGEND record written but not used by Excel
2323 mxFramePos
.reset( new XclExpChFramePos( EXC_CHFRAMEPOS_CHARTSIZE
, EXC_CHFRAMEPOS_PARENT
) );
2324 XclChFramePos
& rFramePos
= mxFramePos
->GetFramePosData();
2325 rFramePos
.mnTLMode
= EXC_CHFRAMEPOS_CHARTSIZE
;
2326 ::com::sun::star::awt::Point aLegendPos
= xChart1Legend
->getPosition();
2327 rFramePos
.maRect
.mnX
= maData
.maRect
.mnX
= CalcChartXFromHmm( aLegendPos
.X
);
2328 rFramePos
.maRect
.mnY
= maData
.maRect
.mnY
= CalcChartYFromHmm( aLegendPos
.Y
);
2329 // legend size, Excel expects points in CHFRAMEPOS record
2330 rFramePos
.mnBRMode
= EXC_CHFRAMEPOS_ABSSIZE_POINTS
;
2331 ::com::sun::star::awt::Size aLegendSize
= xChart1Legend
->getSize();
2332 rFramePos
.maRect
.mnWidth
= static_cast< sal_uInt16
>( aLegendSize
.Width
* EXC_POINTS_PER_HMM
+ 0.5 );
2333 rFramePos
.maRect
.mnHeight
= static_cast< sal_uInt16
>( aLegendSize
.Height
* EXC_POINTS_PER_HMM
+ 0.5 );
2334 maData
.maRect
.mnWidth
= CalcChartXFromHmm( aLegendSize
.Width
);
2335 maData
.maRect
.mnHeight
= CalcChartYFromHmm( aLegendSize
.Height
);
2336 eApiExpand
= cssc::ChartLegendExpansion_CUSTOM
;
2337 // manual legend position implies manual plot area
2338 GetChartData().SetManualPlotArea();
2339 maData
.mnDockMode
= EXC_CHLEGEND_NOTDOCKED
;
2340 // a CHFRAME record with cleared auto flags is needed
2342 mxFrame
.reset( new XclExpChFrame( GetChRoot(), EXC_CHOBJTYPE_LEGEND
) );
2343 mxFrame
->SetAutoFlags( false, false );
2347 OSL_FAIL( "XclExpChLegend::Convert - cannot get legend shape" );
2348 maData
.mnDockMode
= EXC_CHLEGEND_RIGHT
;
2349 eApiExpand
= cssc::ChartLegendExpansion_HIGH
;
2354 cssc2::LegendPosition eApiPos
= cssc2::LegendPosition_CUSTOM
;
2355 rPropSet
.GetProperty( eApiPos
, EXC_CHPROP_ANCHORPOSITION
);
2358 case cssc2::LegendPosition_LINE_START
: maData
.mnDockMode
= EXC_CHLEGEND_LEFT
; break;
2359 case cssc2::LegendPosition_LINE_END
: maData
.mnDockMode
= EXC_CHLEGEND_RIGHT
; break;
2360 case cssc2::LegendPosition_PAGE_START
: maData
.mnDockMode
= EXC_CHLEGEND_TOP
; break;
2361 case cssc2::LegendPosition_PAGE_END
: maData
.mnDockMode
= EXC_CHLEGEND_BOTTOM
; break;
2363 OSL_FAIL( "XclExpChLegend::Convert - unrecognized legend position" );
2364 maData
.mnDockMode
= EXC_CHLEGEND_RIGHT
;
2365 eApiExpand
= cssc::ChartLegendExpansion_HIGH
;
2368 ::set_flag( maData
.mnFlags
, EXC_CHLEGEND_STACKED
, eApiExpand
== cssc::ChartLegendExpansion_HIGH
);
2371 ::set_flag( maData
.mnFlags
, EXC_CHLEGEND_AUTOSERIES
);
2372 const sal_uInt16 nAutoFlags
= EXC_CHLEGEND_DOCKED
| EXC_CHLEGEND_AUTOPOSX
| EXC_CHLEGEND_AUTOPOSY
;
2373 ::set_flag( maData
.mnFlags
, nAutoFlags
, maData
.mnDockMode
!= EXC_CHLEGEND_NOTDOCKED
);
2376 void XclExpChLegend::WriteSubRecords( XclExpStream
& rStrm
)
2378 lclSaveRecord( rStrm
, mxFramePos
);
2379 lclSaveRecord( rStrm
, mxText
);
2380 lclSaveRecord( rStrm
, mxFrame
);
2383 void XclExpChLegend::WriteBody( XclExpStream
& rStrm
)
2385 rStrm
<< maData
.maRect
<< maData
.mnDockMode
<< maData
.mnSpacing
<< maData
.mnFlags
;
2388 // ----------------------------------------------------------------------------
2390 XclExpChDropBar::XclExpChDropBar( const XclExpChRoot
& rRoot
, XclChObjectType eObjType
) :
2391 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_DROPBAR
, EXC_ID_CHDROPBAR
, 2 ),
2392 meObjType( eObjType
),
2397 void XclExpChDropBar::Convert( const ScfPropertySet
& rPropSet
)
2400 ConvertFrameBase( GetChRoot(), rPropSet
, meObjType
);
2402 SetDefaultFrameBase( GetChRoot(), EXC_CHFRAMETYPE_INVISIBLE
, true );
2405 void XclExpChDropBar::WriteSubRecords( XclExpStream
& rStrm
)
2407 WriteFrameRecords( rStrm
);
2410 void XclExpChDropBar::WriteBody( XclExpStream
& rStrm
)
2415 // ----------------------------------------------------------------------------
2417 XclExpChTypeGroup::XclExpChTypeGroup( const XclExpChRoot
& rRoot
, sal_uInt16 nGroupIdx
) :
2418 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_TYPEGROUP
, EXC_ID_CHTYPEGROUP
, 20 ),
2420 maTypeInfo( maType
.GetTypeInfo() )
2422 maData
.mnGroupIdx
= nGroupIdx
;
2425 void XclExpChTypeGroup::ConvertType(
2426 Reference
< XDiagram
> xDiagram
, Reference
< XChartType
> xChartType
,
2427 sal_Int32 nApiAxesSetIdx
, bool b3dChart
, bool bSwappedAxesSet
, bool bHasXLabels
)
2429 // chart type settings
2430 maType
.Convert( xDiagram
, xChartType
, nApiAxesSetIdx
, bSwappedAxesSet
, bHasXLabels
);
2432 // spline - TODO: get from single series (#i66858#)
2433 ScfPropertySet
aTypeProp( xChartType
);
2434 cssc2::CurveStyle eCurveStyle
;
2435 bool bSpline
= aTypeProp
.GetProperty( eCurveStyle
, EXC_CHPROP_CURVESTYLE
) &&
2436 (eCurveStyle
!= cssc2::CurveStyle_LINES
);
2438 // extended type info
2439 maTypeInfo
.Set( maType
.GetTypeInfo(), b3dChart
, bSpline
);
2441 // 3d chart settings
2442 if( maTypeInfo
.mb3dChart
) // only true, if Excel chart supports 3d mode
2444 mxChart3d
.reset( new XclExpChChart3d
);
2445 ScfPropertySet
aDiaProp( xDiagram
);
2446 mxChart3d
->Convert( aDiaProp
, Is3dWallChart() );
2450 void XclExpChTypeGroup::ConvertSeries(
2451 Reference
< XDiagram
> xDiagram
, Reference
< XChartType
> xChartType
,
2452 sal_Int32 nGroupAxesSetIdx
, bool bPercent
, bool bConnectBars
)
2454 Reference
< XDataSeriesContainer
> xSeriesCont( xChartType
, UNO_QUERY
);
2455 if( xSeriesCont
.is() )
2457 typedef ::std::vector
< Reference
< XDataSeries
> > XDataSeriesVec
;
2458 XDataSeriesVec aSeriesVec
;
2460 // copy data series attached to the current axes set to the vector
2461 Sequence
< Reference
< XDataSeries
> > aSeriesSeq
= xSeriesCont
->getDataSeries();
2462 const Reference
< XDataSeries
>* pBeg
= aSeriesSeq
.getConstArray();
2463 const Reference
< XDataSeries
>* pEnd
= pBeg
+ aSeriesSeq
.getLength();
2464 for( const Reference
< XDataSeries
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
2466 ScfPropertySet
aSeriesProp( *pIt
);
2467 sal_Int32
nSeriesAxesSetIdx(0);
2468 if( aSeriesProp
.GetProperty( nSeriesAxesSetIdx
, EXC_CHPROP_ATTAXISINDEX
) && (nSeriesAxesSetIdx
== nGroupAxesSetIdx
) )
2469 aSeriesVec
.push_back( *pIt
);
2472 // Are there any series in the current axes set?
2473 if( !aSeriesVec
.empty() )
2475 // stacking direction (stacked/percent/deep 3d) from first series
2476 ScfPropertySet
aSeriesProp( aSeriesVec
.front() );
2477 cssc2::StackingDirection eStacking
;
2478 if( !aSeriesProp
.GetProperty( eStacking
, EXC_CHPROP_STACKINGDIR
) )
2479 eStacking
= cssc2::StackingDirection_NO_STACKING
;
2481 // stacked or percent chart
2482 if( maTypeInfo
.mbSupportsStacking
&& (eStacking
== cssc2::StackingDirection_Y_STACKING
) )
2484 // percent overrides simple stacking
2485 maType
.SetStacked( bPercent
);
2487 // connected data points (only in stacked bar charts)
2488 if (bConnectBars
&& (maTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_BAR
))
2490 sal_uInt16 nKey
= EXC_CHCHARTLINE_CONNECT
;
2491 maChartLines
.insert(nKey
, new XclExpChLineFormat(GetChRoot()));
2496 // reverse series order for some unstacked 2D chart types
2497 if( maTypeInfo
.mbReverseSeries
&& !Is3dChart() )
2498 ::std::reverse( aSeriesVec
.begin(), aSeriesVec
.end() );
2501 // deep 3d chart or clustered 3d chart (stacked is not clustered)
2502 if( (eStacking
== cssc2::StackingDirection_NO_STACKING
) && Is3dWallChart() )
2503 mxChart3d
->SetClustered();
2505 // varied point colors
2506 ::set_flag( maData
.mnFlags
, EXC_CHTYPEGROUP_VARIEDCOLORS
, aSeriesProp
.GetBoolProperty( EXC_CHPROP_VARYCOLORSBY
) );
2508 // process all series
2509 for( XDataSeriesVec::const_iterator aIt
= aSeriesVec
.begin(), aEnd
= aSeriesVec
.end(); aIt
!= aEnd
; ++aIt
)
2511 // create Excel series object, stock charts need special processing
2512 if( maTypeInfo
.meTypeId
== EXC_CHTYPEID_STOCK
)
2513 CreateAllStockSeries( xChartType
, *aIt
);
2515 CreateDataSeries( xDiagram
, *aIt
);
2521 void XclExpChTypeGroup::ConvertCategSequence( Reference
< XLabeledDataSequence
> xCategSeq
)
2523 for( size_t nIdx
= 0, nSize
= maSeries
.GetSize(); nIdx
< nSize
; ++nIdx
)
2524 maSeries
.GetRecord( nIdx
)->ConvertCategSequence( xCategSeq
);
2527 void XclExpChTypeGroup::ConvertLegend( const ScfPropertySet
& rPropSet
)
2529 if( rPropSet
.GetBoolProperty( EXC_CHPROP_SHOW
) )
2531 mxLegend
.reset( new XclExpChLegend( GetChRoot() ) );
2532 mxLegend
->Convert( rPropSet
);
2536 void XclExpChTypeGroup::WriteSubRecords( XclExpStream
& rStrm
)
2538 maType
.Save( rStrm
);
2539 lclSaveRecord( rStrm
, mxChart3d
);
2540 lclSaveRecord( rStrm
, mxLegend
);
2541 lclSaveRecord( rStrm
, mxUpBar
);
2542 lclSaveRecord( rStrm
, mxDownBar
);
2543 for( XclExpChLineFormatMap::iterator aLIt
= maChartLines
.begin(), aLEnd
= maChartLines
.end(); aLIt
!= aLEnd
; ++aLIt
)
2544 lclSaveRecord( rStrm
, aLIt
->second
, EXC_ID_CHCHARTLINE
, aLIt
->first
);
2547 sal_uInt16
XclExpChTypeGroup::GetFreeFormatIdx() const
2549 return static_cast< sal_uInt16
>( maSeries
.GetSize() );
2552 void XclExpChTypeGroup::CreateDataSeries(
2553 Reference
< XDiagram
> xDiagram
, Reference
< XDataSeries
> xDataSeries
)
2555 // let chart create series object with correct series index
2556 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
2559 if( xSeries
->ConvertDataSeries( xDiagram
, xDataSeries
, maTypeInfo
, GetGroupIdx(), GetFreeFormatIdx() ) )
2560 maSeries
.AppendRecord( xSeries
);
2562 GetChartData().RemoveLastSeries();
2566 void XclExpChTypeGroup::CreateAllStockSeries(
2567 Reference
< XChartType
> xChartType
, Reference
< XDataSeries
> xDataSeries
)
2569 // create existing series objects
2570 bool bHasOpen
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_OPENVALUES
, false );
2571 bool bHasHigh
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_HIGHVALUES
, false );
2572 bool bHasLow
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_LOWVALUES
, false );
2573 bool bHasClose
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_CLOSEVALUES
, !bHasOpen
);
2575 // formatting of special stock chart elements
2576 ScfPropertySet
aTypeProp( xChartType
);
2578 if( bHasHigh
&& bHasLow
&& aTypeProp
.GetBoolProperty( EXC_CHPROP_SHOWHIGHLOW
) )
2580 ScfPropertySet
aSeriesProp( xDataSeries
);
2581 XclExpChLineFormatRef
xLineFmt( new XclExpChLineFormat( GetChRoot() ) );
2582 xLineFmt
->Convert( GetChRoot(), aSeriesProp
, EXC_CHOBJTYPE_HILOLINE
);
2583 sal_uInt16 nKey
= EXC_CHCHARTLINE_HILO
;
2584 maChartLines
.insert(nKey
, new XclExpChLineFormat(GetChRoot()));
2587 if( bHasOpen
&& bHasClose
)
2589 // dropbar type is dependent on position in the file - always create both
2590 Reference
< XPropertySet
> xWhitePropSet
, xBlackPropSet
;
2591 // white dropbar format
2592 aTypeProp
.GetProperty( xWhitePropSet
, EXC_CHPROP_WHITEDAY
);
2593 ScfPropertySet
aWhiteProp( xWhitePropSet
);
2594 mxUpBar
.reset( new XclExpChDropBar( GetChRoot(), EXC_CHOBJTYPE_WHITEDROPBAR
) );
2595 mxUpBar
->Convert( aWhiteProp
);
2596 // black dropbar format
2597 aTypeProp
.GetProperty( xBlackPropSet
, EXC_CHPROP_BLACKDAY
);
2598 ScfPropertySet
aBlackProp( xBlackPropSet
);
2599 mxDownBar
.reset( new XclExpChDropBar( GetChRoot(), EXC_CHOBJTYPE_BLACKDROPBAR
) );
2600 mxDownBar
->Convert( aBlackProp
);
2604 bool XclExpChTypeGroup::CreateStockSeries( Reference
< XDataSeries
> xDataSeries
,
2605 const OUString
& rValueRole
, bool bCloseSymbol
)
2608 // let chart create series object with correct series index
2609 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
2612 bOk
= xSeries
->ConvertStockSeries( xDataSeries
,
2613 rValueRole
, GetGroupIdx(), GetFreeFormatIdx(), bCloseSymbol
);
2615 maSeries
.AppendRecord( xSeries
);
2617 GetChartData().RemoveLastSeries();
2622 void XclExpChTypeGroup::WriteBody( XclExpStream
& rStrm
)
2624 rStrm
.WriteZeroBytes( 16 );
2625 rStrm
<< maData
.mnFlags
<< maData
.mnGroupIdx
;
2628 // Axes =======================================================================
2630 XclExpChLabelRange::XclExpChLabelRange( const XclExpChRoot
& rRoot
) :
2631 XclExpRecord( EXC_ID_CHLABELRANGE
, 8 ),
2632 XclExpChRoot( rRoot
)
2636 void XclExpChLabelRange::Convert( const ScaleData
& rScaleData
, const ScfPropertySet
& rChart1Axis
, bool bMirrorOrient
)
2638 /* Base time unit (using the property 'ExplicitTimeIncrement' from the old
2639 chart API allows to detect axis type (date axis, if property exists),
2640 and to receive the base time unit currently used in case the base time
2641 unit is set to 'automatic'. */
2642 cssc::TimeIncrement aTimeIncrement
;
2643 if( rChart1Axis
.GetProperty( aTimeIncrement
, EXC_CHPROP_EXPTIMEINCREMENT
) )
2645 // property exists -> this is a date axis currently
2646 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_DATEAXIS
);
2648 // automatic base time unit, if the UNO Any 'rScaleData.TimeIncrement.TimeResolution' does not contain a valid value...
2649 bool bAutoBase
= !rScaleData
.TimeIncrement
.TimeResolution
.has
< cssc::TimeIncrement
>();
2650 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOBASE
, bAutoBase
);
2652 // ...but get the current base time unit from the property of the old chart API
2653 sal_Int32 nApiTimeUnit
= 0;
2654 bool bValidBaseUnit
= aTimeIncrement
.TimeResolution
>>= nApiTimeUnit
;
2655 OSL_ENSURE( bValidBaseUnit
, "XclExpChLabelRange::Convert - cannot ghet base time unit" );
2656 maDateData
.mnBaseUnit
= bValidBaseUnit
? lclGetTimeUnit( nApiTimeUnit
) : EXC_CHDATERANGE_DAYS
;
2658 /* Min/max values depend on base time unit, they specify the number of
2659 days, months, or years starting from null date. */
2660 bool bAutoMin
= lclConvertTimeValue( GetRoot(), maDateData
.mnMinDate
, rScaleData
.Minimum
, maDateData
.mnBaseUnit
);
2661 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOMIN
, bAutoMin
);
2662 bool bAutoMax
= lclConvertTimeValue( GetRoot(), maDateData
.mnMaxDate
, rScaleData
.Maximum
, maDateData
.mnBaseUnit
);
2663 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOMAX
, bAutoMax
);
2666 // automatic axis type detection
2667 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTODATE
, rScaleData
.AutoDateAxis
);
2670 bool bAutoMajor
= lclConvertTimeInterval( maDateData
.mnMajorStep
, maDateData
.mnMajorUnit
, rScaleData
.TimeIncrement
.MajorTimeInterval
);
2671 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOMAJOR
, bAutoMajor
);
2672 bool bAutoMinor
= lclConvertTimeInterval( maDateData
.mnMinorStep
, maDateData
.mnMinorUnit
, rScaleData
.TimeIncrement
.MinorTimeInterval
);
2673 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOMINOR
, bAutoMinor
);
2676 double fOrigin
= 0.0;
2677 if( !lclIsAutoAnyOrGetValue( fOrigin
, rScaleData
.Origin
) )
2678 maLabelData
.mnCross
= limit_cast
< sal_uInt16
>( fOrigin
, 1, 31999 );
2681 if( (rScaleData
.Orientation
== cssc2::AxisOrientation_REVERSE
) != bMirrorOrient
)
2682 ::set_flag( maLabelData
.mnFlags
, EXC_CHLABELRANGE_REVERSE
);
2685 void XclExpChLabelRange::ConvertAxisPosition( const ScfPropertySet
& rPropSet
)
2687 cssc::ChartAxisPosition eAxisPos
= cssc::ChartAxisPosition_VALUE
;
2688 rPropSet
.GetProperty( eAxisPos
, EXC_CHPROP_CROSSOVERPOSITION
);
2689 double fCrossingPos
= 1.0;
2690 rPropSet
.GetProperty( fCrossingPos
, EXC_CHPROP_CROSSOVERVALUE
);
2692 bool bDateAxis
= ::get_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_DATEAXIS
);
2695 case cssc::ChartAxisPosition_ZERO
:
2696 case cssc::ChartAxisPosition_START
:
2697 maLabelData
.mnCross
= 1;
2698 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOCROSS
);
2700 case cssc::ChartAxisPosition_END
:
2701 ::set_flag( maLabelData
.mnFlags
, EXC_CHLABELRANGE_MAXCROSS
);
2703 case cssc::ChartAxisPosition_VALUE
:
2704 maLabelData
.mnCross
= limit_cast
< sal_uInt16
>( fCrossingPos
, 1, 31999 );
2705 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOCROSS
, false );
2707 maDateData
.mnCross
= lclGetTimeValue( GetRoot(), fCrossingPos
, maDateData
.mnBaseUnit
);
2710 maLabelData
.mnCross
= 1;
2711 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOCROSS
);
2715 void XclExpChLabelRange::Save( XclExpStream
& rStrm
)
2717 // the CHLABELRANGE record
2718 XclExpRecord::Save( rStrm
);
2720 // the CHDATERANGE record with date axis settings (BIFF8 only)
2721 if( GetBiff() == EXC_BIFF8
)
2723 rStrm
.StartRecord( EXC_ID_CHDATERANGE
, 18 );
2724 rStrm
<< maDateData
.mnMinDate
2725 << maDateData
.mnMaxDate
2726 << maDateData
.mnMajorStep
2727 << maDateData
.mnMajorUnit
2728 << maDateData
.mnMinorStep
2729 << maDateData
.mnMinorUnit
2730 << maDateData
.mnBaseUnit
2731 << maDateData
.mnCross
2732 << maDateData
.mnFlags
;
2737 void XclExpChLabelRange::WriteBody( XclExpStream
& rStrm
)
2739 rStrm
<< maLabelData
.mnCross
<< maLabelData
.mnLabelFreq
<< maLabelData
.mnTickFreq
<< maLabelData
.mnFlags
;
2742 // ----------------------------------------------------------------------------
2744 XclExpChValueRange::XclExpChValueRange( const XclExpChRoot
& rRoot
) :
2745 XclExpRecord( EXC_ID_CHVALUERANGE
, 42 ),
2746 XclExpChRoot( rRoot
)
2750 void XclExpChValueRange::Convert( const ScaleData
& rScaleData
)
2752 // scaling algorithm
2753 bool bLogScale
= ScfApiHelper::GetServiceName( rScaleData
.Scaling
) == "com.sun.star.chart2.LogarithmicScaling";
2754 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_LOGSCALE
, bLogScale
);
2757 bool bAutoMin
= lclIsAutoAnyOrGetScaledValue( maData
.mfMin
, rScaleData
.Minimum
, bLogScale
);
2758 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMIN
, bAutoMin
);
2759 bool bAutoMax
= lclIsAutoAnyOrGetScaledValue( maData
.mfMax
, rScaleData
.Maximum
, bLogScale
);
2760 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMAX
, bAutoMax
);
2763 bool bAutoCross
= lclIsAutoAnyOrGetScaledValue( maData
.mfCross
, rScaleData
.Origin
, bLogScale
);
2764 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
, bAutoCross
);
2767 const IncrementData
& rIncrementData
= rScaleData
.IncrementData
;
2768 bool bAutoMajor
= lclIsAutoAnyOrGetValue( maData
.mfMajorStep
, rIncrementData
.Distance
) || (maData
.mfMajorStep
<= 0.0);
2769 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMAJOR
, bAutoMajor
);
2771 const Sequence
< SubIncrement
>& rSubIncrementSeq
= rIncrementData
.SubIncrements
;
2772 sal_Int32 nCount
= 0;
2773 bool bAutoMinor
= bLogScale
|| bAutoMajor
|| (rSubIncrementSeq
.getLength() < 1) ||
2774 lclIsAutoAnyOrGetValue( nCount
, rSubIncrementSeq
[ 0 ].IntervalCount
) || (nCount
< 1);
2776 maData
.mfMinorStep
= maData
.mfMajorStep
/ nCount
;
2777 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMINOR
, bAutoMinor
);
2780 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_REVERSE
, rScaleData
.Orientation
== cssc2::AxisOrientation_REVERSE
);
2783 void XclExpChValueRange::ConvertAxisPosition( const ScfPropertySet
& rPropSet
)
2785 cssc::ChartAxisPosition eAxisPos
= cssc::ChartAxisPosition_VALUE
;
2786 double fCrossingPos
= 0.0;
2787 if( rPropSet
.GetProperty( eAxisPos
, EXC_CHPROP_CROSSOVERPOSITION
) && rPropSet
.GetProperty( fCrossingPos
, EXC_CHPROP_CROSSOVERVALUE
) )
2791 case cssc::ChartAxisPosition_ZERO
:
2792 case cssc::ChartAxisPosition_START
:
2793 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
);
2795 case cssc::ChartAxisPosition_END
:
2796 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_MAXCROSS
);
2798 case cssc::ChartAxisPosition_VALUE
:
2799 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
, false );
2800 maData
.mfCross
= ::get_flagvalue
< double >( maData
.mnFlags
, EXC_CHVALUERANGE_LOGSCALE
, log( fCrossingPos
) / log( 10.0 ), fCrossingPos
);
2803 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
);
2808 void XclExpChValueRange::WriteBody( XclExpStream
& rStrm
)
2810 rStrm
<< maData
.mfMin
2812 << maData
.mfMajorStep
2813 << maData
.mfMinorStep
2818 // ----------------------------------------------------------------------------
2822 sal_uInt8
lclGetXclTickPos( sal_Int32 nApiTickmarks
)
2824 using namespace cssc2::TickmarkStyle
;
2825 sal_uInt8 nXclTickPos
= 0;
2826 ::set_flag( nXclTickPos
, EXC_CHTICK_INSIDE
, ::get_flag( nApiTickmarks
, INNER
) );
2827 ::set_flag( nXclTickPos
, EXC_CHTICK_OUTSIDE
, ::get_flag( nApiTickmarks
, OUTER
) );
2833 XclExpChTick::XclExpChTick( const XclExpChRoot
& rRoot
) :
2834 XclExpRecord( EXC_ID_CHTICK
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 30 : 26 ),
2835 XclExpChRoot( rRoot
),
2836 mnTextColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
2840 void XclExpChTick::Convert( const ScfPropertySet
& rPropSet
, const XclChExtTypeInfo
& rTypeInfo
, sal_uInt16 nAxisType
)
2843 sal_Int32 nApiTickmarks
= 0;
2844 if( rPropSet
.GetProperty( nApiTickmarks
, EXC_CHPROP_MAJORTICKS
) )
2845 maData
.mnMajor
= lclGetXclTickPos( nApiTickmarks
);
2846 if( rPropSet
.GetProperty( nApiTickmarks
, EXC_CHPROP_MINORTICKS
) )
2847 maData
.mnMinor
= lclGetXclTickPos( nApiTickmarks
);
2850 if( (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_RADAR
) && (nAxisType
== EXC_CHAXIS_X
) )
2852 /* Radar charts disable their category labels via chart type, not via
2853 axis, and axis labels are always 'near axis'. */
2854 maData
.mnLabelPos
= EXC_CHTICK_NEXT
;
2856 else if( !rPropSet
.GetBoolProperty( EXC_CHPROP_DISPLAYLABELS
) )
2859 maData
.mnLabelPos
= EXC_CHTICK_NOLABEL
;
2861 else if( rTypeInfo
.mb3dChart
&& (nAxisType
== EXC_CHAXIS_Y
) )
2863 // Excel expects 'near axis' at Y axes in 3D charts
2864 maData
.mnLabelPos
= EXC_CHTICK_NEXT
;
2868 cssc::ChartAxisLabelPosition eApiLabelPos
= cssc::ChartAxisLabelPosition_NEAR_AXIS
;
2869 rPropSet
.GetProperty( eApiLabelPos
, EXC_CHPROP_LABELPOSITION
);
2870 switch( eApiLabelPos
)
2872 case cssc::ChartAxisLabelPosition_NEAR_AXIS
:
2873 case cssc::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE
: maData
.mnLabelPos
= EXC_CHTICK_NEXT
; break;
2874 case cssc::ChartAxisLabelPosition_OUTSIDE_START
: maData
.mnLabelPos
= EXC_CHTICK_LOW
; break;
2875 case cssc::ChartAxisLabelPosition_OUTSIDE_END
: maData
.mnLabelPos
= EXC_CHTICK_HIGH
; break;
2876 default: maData
.mnLabelPos
= EXC_CHTICK_NEXT
;
2881 void XclExpChTick::SetFontColor( const Color
& rColor
, sal_uInt32 nColorId
)
2883 maData
.maTextColor
= rColor
;
2884 ::set_flag( maData
.mnFlags
, EXC_CHTICK_AUTOCOLOR
, rColor
== COL_AUTO
);
2885 mnTextColorId
= nColorId
;
2888 void XclExpChTick::SetRotation( sal_uInt16 nRotation
)
2890 maData
.mnRotation
= nRotation
;
2891 ::set_flag( maData
.mnFlags
, EXC_CHTICK_AUTOROT
, false );
2892 ::insert_value( maData
.mnFlags
, XclTools::GetXclOrientFromRot( nRotation
), 2, 3 );
2895 void XclExpChTick::WriteBody( XclExpStream
& rStrm
)
2897 rStrm
<< maData
.mnMajor
2899 << maData
.mnLabelPos
2900 << maData
.mnBackMode
;
2901 rStrm
.WriteZeroBytes( 16 );
2902 rStrm
<< maData
.maTextColor
2904 if( GetBiff() == EXC_BIFF8
)
2905 rStrm
<< GetPalette().GetColorIndex( mnTextColorId
) << maData
.mnRotation
;
2908 // ----------------------------------------------------------------------------
2912 /** Returns an API axis object from the passed coordinate system. */
2913 Reference
< XAxis
> lclGetApiAxis( Reference
< XCoordinateSystem
> xCoordSystem
,
2914 sal_Int32 nApiAxisDim
, sal_Int32 nApiAxesSetIdx
)
2916 Reference
< XAxis
> xAxis
;
2917 if( (nApiAxisDim
>= 0) && xCoordSystem
.is() ) try
2919 xAxis
= xCoordSystem
->getAxisByDimension( nApiAxisDim
, nApiAxesSetIdx
);
2927 Reference
< cssc::XAxis
> lclGetApiChart1Axis( Reference
< XChartDocument
> xChartDoc
,
2928 sal_Int32 nApiAxisDim
, sal_Int32 nApiAxesSetIdx
)
2930 Reference
< cssc::XAxis
> xChart1Axis
;
2933 Reference
< cssc::XChartDocument
> xChart1Doc( xChartDoc
, UNO_QUERY_THROW
);
2934 Reference
< cssc::XAxisSupplier
> xChart1AxisSupp( xChart1Doc
->getDiagram(), UNO_QUERY_THROW
);
2935 switch( nApiAxesSetIdx
)
2937 case EXC_CHART_AXESSET_PRIMARY
:
2938 xChart1Axis
= xChart1AxisSupp
->getAxis( nApiAxisDim
);
2940 case EXC_CHART_AXESSET_SECONDARY
:
2941 xChart1Axis
= xChart1AxisSupp
->getSecondaryAxis( nApiAxisDim
);
2953 XclExpChAxis::XclExpChAxis( const XclExpChRoot
& rRoot
, sal_uInt16 nAxisType
) :
2954 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_AXIS
, EXC_ID_CHAXIS
, 18 ),
2955 mnNumFmtIdx( EXC_FORMAT_NOTFOUND
)
2957 maData
.mnType
= nAxisType
;
2960 void XclExpChAxis::SetFont( XclExpChFontRef xFont
, const Color
& rColor
, sal_uInt32 nColorId
)
2964 mxTick
->SetFontColor( rColor
, nColorId
);
2967 void XclExpChAxis::SetRotation( sal_uInt16 nRotation
)
2970 mxTick
->SetRotation( nRotation
);
2973 void XclExpChAxis::Convert( Reference
< XAxis
> xAxis
, Reference
< XAxis
> xCrossingAxis
,
2974 Reference
< cssc::XAxis
> xChart1Axis
, const XclChExtTypeInfo
& rTypeInfo
)
2976 ScfPropertySet
aAxisProp( xAxis
);
2977 bool bCategoryAxis
= ((GetAxisType() == EXC_CHAXIS_X
) && rTypeInfo
.mbCategoryAxis
) || (GetAxisType() == EXC_CHAXIS_Z
);
2979 // axis line format -------------------------------------------------------
2981 mxAxisLine
.reset( new XclExpChLineFormat( GetChRoot() ) );
2982 mxAxisLine
->Convert( GetChRoot(), aAxisProp
, EXC_CHOBJTYPE_AXISLINE
);
2983 // #i58688# axis enabled
2984 mxAxisLine
->SetShowAxis( aAxisProp
.GetBoolProperty( EXC_CHPROP_SHOW
) );
2986 // axis scaling and increment ---------------------------------------------
2988 ScfPropertySet
aCrossingProp( xCrossingAxis
);
2991 mxLabelRange
.reset( new XclExpChLabelRange( GetChRoot() ) );
2992 mxLabelRange
->SetTicksBetweenCateg( rTypeInfo
.mbTicksBetweenCateg
);
2995 ScfPropertySet
aChart1AxisProp( xChart1Axis
);
2996 // #i71684# radar charts have reversed rotation direction
2997 mxLabelRange
->Convert( xAxis
->getScaleData(), aChart1AxisProp
, (GetAxisType() == EXC_CHAXIS_X
) && (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_RADAR
) );
2999 // get position of crossing axis on this axis from passed axis object
3000 if( aCrossingProp
.Is() )
3001 mxLabelRange
->ConvertAxisPosition( aCrossingProp
);
3005 mxValueRange
.reset( new XclExpChValueRange( GetChRoot() ) );
3007 mxValueRange
->Convert( xAxis
->getScaleData() );
3008 // get position of crossing axis on this axis from passed axis object
3009 if( aCrossingProp
.Is() )
3010 mxValueRange
->ConvertAxisPosition( aCrossingProp
);
3013 // axis caption text ------------------------------------------------------
3015 // axis ticks properties
3016 mxTick
.reset( new XclExpChTick( GetChRoot() ) );
3017 mxTick
->Convert( aAxisProp
, rTypeInfo
, GetAxisType() );
3019 // axis label formatting and rotation
3020 ConvertFontBase( GetChRoot(), aAxisProp
);
3021 ConvertRotationBase( GetChRoot(), aAxisProp
, true );
3023 // axis number format
3024 sal_Int32 nApiNumFmt
= 0;
3025 if( !bCategoryAxis
&& aAxisProp
.GetProperty( nApiNumFmt
, EXC_CHPROP_NUMBERFORMAT
) )
3026 mnNumFmtIdx
= GetNumFmtBuffer().Insert( static_cast< sal_uInt32
>( nApiNumFmt
) );
3028 // grid -------------------------------------------------------------------
3033 ScfPropertySet
aGridProp( xAxis
->getGridProperties() );
3034 if( aGridProp
.GetBoolProperty( EXC_CHPROP_SHOW
) )
3035 mxMajorGrid
= lclCreateLineFormat( GetChRoot(), aGridProp
, EXC_CHOBJTYPE_GRIDLINE
);
3037 Sequence
< Reference
< XPropertySet
> > aSubGridPropSeq
= xAxis
->getSubGridProperties();
3038 if( aSubGridPropSeq
.hasElements() )
3040 ScfPropertySet
aSubGridProp( aSubGridPropSeq
[ 0 ] );
3041 if( aSubGridProp
.GetBoolProperty( EXC_CHPROP_SHOW
) )
3042 mxMinorGrid
= lclCreateLineFormat( GetChRoot(), aSubGridProp
, EXC_CHOBJTYPE_GRIDLINE
);
3047 void XclExpChAxis::ConvertWall( XDiagramRef xDiagram
)
3049 if( xDiagram
.is() ) switch( GetAxisType() )
3053 ScfPropertySet
aWallProp( xDiagram
->getWall() );
3054 mxWallFrame
= lclCreateFrame( GetChRoot(), aWallProp
, EXC_CHOBJTYPE_WALL3D
);
3059 ScfPropertySet
aFloorProp( xDiagram
->getFloor() );
3060 mxWallFrame
= lclCreateFrame( GetChRoot(), aFloorProp
, EXC_CHOBJTYPE_FLOOR3D
);
3064 mxWallFrame
.reset();
3068 void XclExpChAxis::WriteSubRecords( XclExpStream
& rStrm
)
3070 lclSaveRecord( rStrm
, mxLabelRange
);
3071 lclSaveRecord( rStrm
, mxValueRange
);
3072 if( mnNumFmtIdx
!= EXC_FORMAT_NOTFOUND
)
3073 XclExpUInt16Record( EXC_ID_CHFORMAT
, mnNumFmtIdx
).Save( rStrm
);
3074 lclSaveRecord( rStrm
, mxTick
);
3075 lclSaveRecord( rStrm
, mxFont
);
3076 lclSaveRecord( rStrm
, mxAxisLine
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_AXISLINE
);
3077 lclSaveRecord( rStrm
, mxMajorGrid
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_MAJORGRID
);
3078 lclSaveRecord( rStrm
, mxMinorGrid
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_MINORGRID
);
3079 lclSaveRecord( rStrm
, mxWallFrame
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_WALLS
);
3082 void XclExpChAxis::WriteBody( XclExpStream
& rStrm
)
3084 rStrm
<< maData
.mnType
;
3085 rStrm
.WriteZeroBytes( 16 );
3088 // ----------------------------------------------------------------------------
3090 XclExpChAxesSet::XclExpChAxesSet( const XclExpChRoot
& rRoot
, sal_uInt16 nAxesSetId
) :
3091 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_AXESSET
, EXC_ID_CHAXESSET
, 18 )
3093 maData
.mnAxesSetId
= nAxesSetId
;
3094 SetFutureRecordContext( 0, nAxesSetId
);
3096 /* Need to set a reasonable size for the plot area, otherwise Excel will
3097 move away embedded shapes while auto-sizing the plot area. This is just
3098 a wild guess, but will be fixed with implementing manual positioning of
3100 maData
.maRect
.mnX
= 262;
3101 maData
.maRect
.mnY
= 626;
3102 maData
.maRect
.mnWidth
= 3187;
3103 maData
.maRect
.mnHeight
= 2633;
3106 sal_uInt16
XclExpChAxesSet::Convert( Reference
< XDiagram
> xDiagram
, sal_uInt16 nFirstGroupIdx
)
3108 /* First unused chart type group index is passed to be able to continue
3109 counting of chart type groups for secondary axes set. */
3110 sal_uInt16 nGroupIdx
= nFirstGroupIdx
;
3111 Reference
< XCoordinateSystemContainer
> xCoordSysCont( xDiagram
, UNO_QUERY
);
3112 if( xCoordSysCont
.is() )
3114 Sequence
< Reference
< XCoordinateSystem
> > aCoordSysSeq
= xCoordSysCont
->getCoordinateSystems();
3115 if( aCoordSysSeq
.getLength() > 0 )
3117 /* Process first coordinate system only. Import filter puts all
3118 chart types into one coordinate system. */
3119 Reference
< XCoordinateSystem
> xCoordSystem
= aCoordSysSeq
[ 0 ];
3120 sal_Int32 nApiAxesSetIdx
= GetApiAxesSetIndex();
3123 bool b3dChart
= xCoordSystem
.is() && (xCoordSystem
->getDimension() == 3);
3126 namespace ApiAxisType
= cssc2::AxisType
;
3127 Reference
< XAxis
> xApiYAxis
= lclGetApiAxis( xCoordSystem
, EXC_CHART_AXIS_Y
, nApiAxesSetIdx
);
3128 bool bPercent
= xApiYAxis
.is() && (xApiYAxis
->getScaleData().AxisType
== ApiAxisType::PERCENT
);
3130 // connector lines in bar charts
3131 ScfPropertySet
aDiaProp( xDiagram
);
3132 bool bConnectBars
= aDiaProp
.GetBoolProperty( EXC_CHPROP_CONNECTBARS
);
3134 // swapped axes sets
3135 ScfPropertySet
aCoordSysProp( xCoordSystem
);
3136 bool bSwappedAxesSet
= aCoordSysProp
.GetBoolProperty( EXC_CHPROP_SWAPXANDYAXIS
);
3138 // X axis for later use
3139 Reference
< XAxis
> xApiXAxis
= lclGetApiAxis( xCoordSystem
, EXC_CHART_AXIS_X
, nApiAxesSetIdx
);
3141 ScfPropertySet
aXAxisProp( xApiXAxis
);
3142 bool bHasXLabels
= aXAxisProp
.GetBoolProperty( EXC_CHPROP_DISPLAYLABELS
);
3144 // process chart types
3145 Reference
< XChartTypeContainer
> xChartTypeCont( xCoordSystem
, UNO_QUERY
);
3146 if( xChartTypeCont
.is() )
3148 Sequence
< Reference
< XChartType
> > aChartTypeSeq
= xChartTypeCont
->getChartTypes();
3149 const Reference
< XChartType
>* pBeg
= aChartTypeSeq
.getConstArray();
3150 const Reference
< XChartType
>* pEnd
= pBeg
+ aChartTypeSeq
.getLength();
3151 for( const Reference
< XChartType
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
3153 XclExpChTypeGroupRef
xTypeGroup( new XclExpChTypeGroup( GetChRoot(), nGroupIdx
) );
3154 xTypeGroup
->ConvertType( xDiagram
, *pIt
, nApiAxesSetIdx
, b3dChart
, bSwappedAxesSet
, bHasXLabels
);
3155 /* If new chart type group cannot be inserted into a combination
3156 chart with existing type groups, insert all series into last
3157 contained chart type group instead of creating a new group. */
3158 XclExpChTypeGroupRef xLastGroup
= GetLastTypeGroup();
3159 if( xLastGroup
&& !(xTypeGroup
->IsCombinable2d() && xLastGroup
->IsCombinable2d()) )
3161 xLastGroup
->ConvertSeries( xDiagram
, *pIt
, nApiAxesSetIdx
, bPercent
, bConnectBars
);
3165 xTypeGroup
->ConvertSeries( xDiagram
, *pIt
, nApiAxesSetIdx
, bPercent
, bConnectBars
);
3166 if( xTypeGroup
->IsValidGroup() )
3168 maTypeGroups
.AppendRecord( xTypeGroup
);
3175 if( XclExpChTypeGroup
* pGroup
= GetFirstTypeGroup().get() )
3177 const XclChExtTypeInfo
& rTypeInfo
= pGroup
->GetTypeInfo();
3179 // create axes according to chart type (no axes for pie and donut charts)
3180 if( rTypeInfo
.meTypeCateg
!= EXC_CHTYPECATEG_PIE
)
3182 ConvertAxis( mxXAxis
, EXC_CHAXIS_X
, mxXAxisTitle
, EXC_CHOBJLINK_XAXIS
, xCoordSystem
, rTypeInfo
, EXC_CHART_AXIS_Y
);
3183 ConvertAxis( mxYAxis
, EXC_CHAXIS_Y
, mxYAxisTitle
, EXC_CHOBJLINK_YAXIS
, xCoordSystem
, rTypeInfo
, EXC_CHART_AXIS_X
);
3184 if( pGroup
->Is3dDeepChart() )
3185 ConvertAxis( mxZAxis
, EXC_CHAXIS_Z
, mxZAxisTitle
, EXC_CHOBJLINK_ZAXIS
, xCoordSystem
, rTypeInfo
, EXC_CHART_AXIS_NONE
);
3188 // X axis category ranges
3189 if( rTypeInfo
.mbCategoryAxis
&& xApiXAxis
.is() )
3191 const ScaleData aScaleData
= xApiXAxis
->getScaleData();
3192 for( size_t nIdx
= 0, nSize
= maTypeGroups
.GetSize(); nIdx
< nSize
; ++nIdx
)
3193 maTypeGroups
.GetRecord( nIdx
)->ConvertCategSequence( aScaleData
.Categories
);
3197 if( xDiagram
.is() && (GetAxesSetId() == EXC_CHAXESSET_PRIMARY
) )
3199 Reference
< XLegend
> xLegend
= xDiagram
->getLegend();
3202 ScfPropertySet
aLegendProp( xLegend
);
3203 pGroup
->ConvertLegend( aLegendProp
);
3210 // wall/floor/diagram frame formatting
3211 if( xDiagram
.is() && (GetAxesSetId() == EXC_CHAXESSET_PRIMARY
) )
3213 XclExpChTypeGroupRef xTypeGroup
= GetFirstTypeGroup();
3214 if( xTypeGroup
&& xTypeGroup
->Is3dWallChart() )
3216 // wall/floor formatting (3D charts)
3218 mxXAxis
->ConvertWall( xDiagram
);
3220 mxYAxis
->ConvertWall( xDiagram
);
3224 // diagram background formatting
3225 ScfPropertySet
aWallProp( xDiagram
->getWall() );
3226 mxPlotFrame
= lclCreateFrame( GetChRoot(), aWallProp
, EXC_CHOBJTYPE_PLOTFRAME
);
3230 // inner and outer plot area position and size
3233 Reference
< cssc::XChartDocument
> xChart1Doc( GetChartDocument(), UNO_QUERY_THROW
);
3234 Reference
< cssc::XDiagramPositioning
> xPositioning( xChart1Doc
->getDiagram(), UNO_QUERY_THROW
);
3235 // set manual flag in chart data
3236 if( !xPositioning
->isAutomaticDiagramPositioning() )
3237 GetChartData().SetManualPlotArea();
3238 // the CHAXESSET record contains the inner plot area
3239 maData
.maRect
= CalcChartRectFromHmm( xPositioning
->calculateDiagramPositionExcludingAxes() );
3240 // the embedded CHFRAMEPOS record contains the outer plot area
3241 mxFramePos
.reset( new XclExpChFramePos( EXC_CHFRAMEPOS_PARENT
, EXC_CHFRAMEPOS_PARENT
) );
3242 // for pie charts, always use inner plot area size to exclude the data labels as Excel does
3243 const XclExpChTypeGroup
* pFirstTypeGroup
= GetFirstTypeGroup().get();
3244 bool bPieChart
= pFirstTypeGroup
&& (pFirstTypeGroup
->GetTypeInfo().meTypeCateg
== EXC_CHTYPECATEG_PIE
);
3245 mxFramePos
->GetFramePosData().maRect
= bPieChart
? maData
.maRect
:
3246 CalcChartRectFromHmm( xPositioning
->calculateDiagramPositionIncludingAxes() );
3252 // return first unused chart type group index for next axes set
3256 bool XclExpChAxesSet::Is3dChart() const
3258 XclExpChTypeGroupRef xTypeGroup
= GetFirstTypeGroup();
3259 return xTypeGroup
&& xTypeGroup
->Is3dChart();
3262 void XclExpChAxesSet::WriteSubRecords( XclExpStream
& rStrm
)
3264 lclSaveRecord( rStrm
, mxFramePos
);
3265 lclSaveRecord( rStrm
, mxXAxis
);
3266 lclSaveRecord( rStrm
, mxYAxis
);
3267 lclSaveRecord( rStrm
, mxZAxis
);
3268 lclSaveRecord( rStrm
, mxXAxisTitle
);
3269 lclSaveRecord( rStrm
, mxYAxisTitle
);
3270 lclSaveRecord( rStrm
, mxZAxisTitle
);
3273 XclExpEmptyRecord( EXC_ID_CHPLOTFRAME
).Save( rStrm
);
3274 mxPlotFrame
->Save( rStrm
);
3276 maTypeGroups
.Save( rStrm
);
3279 XclExpChTypeGroupRef
XclExpChAxesSet::GetFirstTypeGroup() const
3281 return maTypeGroups
.GetFirstRecord();
3284 XclExpChTypeGroupRef
XclExpChAxesSet::GetLastTypeGroup() const
3286 return maTypeGroups
.GetLastRecord();
3289 void XclExpChAxesSet::ConvertAxis(
3290 XclExpChAxisRef
& rxChAxis
, sal_uInt16 nAxisType
,
3291 XclExpChTextRef
& rxChAxisTitle
, sal_uInt16 nTitleTarget
,
3292 Reference
< XCoordinateSystem
> xCoordSystem
, const XclChExtTypeInfo
& rTypeInfo
,
3293 sal_Int32 nCrossingAxisDim
)
3295 // create and convert axis object
3296 rxChAxis
.reset( new XclExpChAxis( GetChRoot(), nAxisType
) );
3297 sal_Int32 nApiAxisDim
= rxChAxis
->GetApiAxisDimension();
3298 sal_Int32 nApiAxesSetIdx
= GetApiAxesSetIndex();
3299 Reference
< XAxis
> xAxis
= lclGetApiAxis( xCoordSystem
, nApiAxisDim
, nApiAxesSetIdx
);
3300 Reference
< XAxis
> xCrossingAxis
= lclGetApiAxis( xCoordSystem
, nCrossingAxisDim
, nApiAxesSetIdx
);
3301 Reference
< cssc::XAxis
> xChart1Axis
= lclGetApiChart1Axis( GetChartDocument(), nApiAxisDim
, nApiAxesSetIdx
);
3302 rxChAxis
->Convert( xAxis
, xCrossingAxis
, xChart1Axis
, rTypeInfo
);
3304 // create and convert axis title
3305 Reference
< XTitled
> xTitled( xAxis
, UNO_QUERY
);
3306 rxChAxisTitle
= lclCreateTitle( GetChRoot(), xTitled
, nTitleTarget
);
3309 void XclExpChAxesSet::WriteBody( XclExpStream
& rStrm
)
3311 rStrm
<< maData
.mnAxesSetId
<< maData
.maRect
;
3314 // The chart object ===========================================================
3316 static void lcl_getChartSubTitle(const Reference
<XChartDocument
>& xChartDoc
,
3319 Reference
< ::com::sun::star::chart::XChartDocument
> xChartDoc1(xChartDoc
, UNO_QUERY
);
3320 if (!xChartDoc1
.is())
3323 Reference
< XPropertySet
> xProp(xChartDoc1
->getSubTitle(), UNO_QUERY
);
3328 Any any
= xProp
->getPropertyValue( OUString("String") );
3333 XclExpChChart::XclExpChChart( const XclExpRoot
& rRoot
,
3334 Reference
< XChartDocument
> xChartDoc
, const Rectangle
& rChartRect
) :
3335 XclExpChGroupBase( XclExpChRoot( rRoot
, *this ), EXC_CHFRBLOCK_TYPE_CHART
, EXC_ID_CHCHART
, 16 )
3337 Size aPtSize
= OutputDevice::LogicToLogic( rChartRect
.GetSize(), MapMode( MAP_100TH_MM
), MapMode( MAP_POINT
) );
3338 // rectangle is stored in 16.16 fixed-point format
3339 maRect
.mnX
= maRect
.mnY
= 0;
3340 maRect
.mnWidth
= static_cast< sal_Int32
>( aPtSize
.Width() << 16 );
3341 maRect
.mnHeight
= static_cast< sal_Int32
>( aPtSize
.Height() << 16 );
3343 // global chart properties (default values)
3344 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_SHOWVISIBLEONLY
, false );
3345 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_MANPLOTAREA
);
3346 maProps
.mnEmptyMode
= EXC_CHPROPS_EMPTY_SKIP
;
3348 // always create both axes set objects
3349 mxPrimAxesSet
.reset( new XclExpChAxesSet( GetChRoot(), EXC_CHAXESSET_PRIMARY
) );
3350 mxSecnAxesSet
.reset( new XclExpChAxesSet( GetChRoot(), EXC_CHAXESSET_SECONDARY
) );
3352 if( xChartDoc
.is() )
3354 Reference
< XDiagram
> xDiagram
= xChartDoc
->getFirstDiagram();
3356 // global chart properties (only 'include hidden cells' attribute for now)
3357 ScfPropertySet
aDiagramProp( xDiagram
);
3358 bool bIncludeHidden
= aDiagramProp
.GetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS
);
3359 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_SHOWVISIBLEONLY
, !bIncludeHidden
);
3361 // initialize API conversion (remembers xChartDoc and rChartRect internally)
3362 InitConversion( xChartDoc
, rChartRect
);
3365 ScfPropertySet
aFrameProp( xChartDoc
->getPageBackground() );
3366 mxFrame
= lclCreateFrame( GetChRoot(), aFrameProp
, EXC_CHOBJTYPE_BACKGROUND
);
3369 Reference
< XTitled
> xTitled( xChartDoc
, UNO_QUERY
);
3371 lcl_getChartSubTitle(xChartDoc
, aSubTitle
);
3372 mxTitle
= lclCreateTitle( GetChRoot(), xTitled
, EXC_CHOBJLINK_TITLE
,
3373 aSubTitle
.Len() ? &aSubTitle
: NULL
);
3375 // diagrams (axes sets)
3376 sal_uInt16 nFreeGroupIdx
= mxPrimAxesSet
->Convert( xDiagram
, 0 );
3377 if( !mxPrimAxesSet
->Is3dChart() )
3378 mxSecnAxesSet
->Convert( xDiagram
, nFreeGroupIdx
);
3380 // treatment of missing values
3381 ScfPropertySet
aDiaProp( xDiagram
);
3382 sal_Int32 nMissingValues
= 0;
3383 if( aDiaProp
.GetProperty( nMissingValues
, EXC_CHPROP_MISSINGVALUETREATMENT
) )
3385 using namespace cssc::MissingValueTreatment
;
3386 switch( nMissingValues
)
3388 case LEAVE_GAP
: maProps
.mnEmptyMode
= EXC_CHPROPS_EMPTY_SKIP
; break;
3389 case USE_ZERO
: maProps
.mnEmptyMode
= EXC_CHPROPS_EMPTY_ZERO
; break;
3390 case CONTINUE
: maProps
.mnEmptyMode
= EXC_CHPROPS_EMPTY_INTERPOLATE
; break;
3394 // finish API conversion
3399 XclExpChSeriesRef
XclExpChChart::CreateSeries()
3401 XclExpChSeriesRef xSeries
;
3402 sal_uInt16 nSeriesIdx
= static_cast< sal_uInt16
>( maSeries
.GetSize() );
3403 if( nSeriesIdx
<= EXC_CHSERIES_MAXSERIES
)
3405 xSeries
.reset( new XclExpChSeries( GetChRoot(), nSeriesIdx
) );
3406 maSeries
.AppendRecord( xSeries
);
3411 void XclExpChChart::RemoveLastSeries()
3413 if( !maSeries
.IsEmpty() )
3414 maSeries
.RemoveRecord( maSeries
.GetSize() - 1 );
3417 void XclExpChChart::SetDataLabel( XclExpChTextRef xText
)
3420 maLabels
.AppendRecord( xText
);
3423 void XclExpChChart::SetManualPlotArea()
3425 // this flag does not exist in BIFF5
3426 if( GetBiff() == EXC_BIFF8
)
3427 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_USEMANPLOTAREA
);
3430 void XclExpChChart::WriteSubRecords( XclExpStream
& rStrm
)
3432 // background format
3433 lclSaveRecord( rStrm
, mxFrame
);
3436 maSeries
.Save( rStrm
);
3438 // CHPROPERTIES record
3439 rStrm
.StartRecord( EXC_ID_CHPROPERTIES
, 4 );
3440 rStrm
<< maProps
.mnFlags
<< maProps
.mnEmptyMode
<< sal_uInt8( 0 );
3443 // axes sets (always save primary axes set)
3444 sal_uInt16 nUsedAxesSets
= mxSecnAxesSet
->IsValidAxesSet() ? 2 : 1;
3445 XclExpUInt16Record( EXC_ID_CHUSEDAXESSETS
, nUsedAxesSets
).Save( rStrm
);
3446 mxPrimAxesSet
->Save( rStrm
);
3447 if( mxSecnAxesSet
->IsValidAxesSet() )
3448 mxSecnAxesSet
->Save( rStrm
);
3450 // chart title and data labels
3451 lclSaveRecord( rStrm
, mxTitle
);
3452 maLabels
.Save( rStrm
);
3455 void XclExpChChart::WriteBody( XclExpStream
& rStrm
)
3460 // ----------------------------------------------------------------------------
3462 XclExpChartDrawing::XclExpChartDrawing( const XclExpRoot
& rRoot
,
3463 const Reference
< XModel
>& rxModel
, const Size
& rChartSize
) :
3466 if( (rChartSize
.Width() > 0) && (rChartSize
.Height() > 0) )
3468 ScfPropertySet
aPropSet( rxModel
);
3469 Reference
< XShapes
> xShapes
;
3470 if( aPropSet
.GetProperty( xShapes
, EXC_CHPROP_ADDITIONALSHAPES
) && xShapes
.is() && (xShapes
->getCount() > 0) )
3472 /* Create a new independent object manager with own DFF stream for the
3473 DGCONTAINER, pass global manager as parent for shared usage of
3474 global DFF data (picture container etc.). */
3475 mxObjMgr
.reset( new XclExpEmbeddedObjectManager( GetObjectManager(), rChartSize
, EXC_CHART_TOTALUNITS
, EXC_CHART_TOTALUNITS
) );
3476 // initialize the drawing object list
3477 mxObjMgr
->StartSheet();
3478 // process the draw page (convert all shapes)
3479 mxObjRecs
= mxObjMgr
->ProcessDrawing( xShapes
);
3480 // finalize the DFF stream
3481 mxObjMgr
->EndDocument();
3486 XclExpChartDrawing::~XclExpChartDrawing()
3490 void XclExpChartDrawing::Save( XclExpStream
& rStrm
)
3493 mxObjRecs
->Save( rStrm
);
3496 // ----------------------------------------------------------------------------
3498 XclExpChart::XclExpChart( const XclExpRoot
& rRoot
, Reference
< XModel
> xModel
, const Rectangle
& rChartRect
) :
3499 XclExpSubStream( EXC_BOF_CHART
),
3502 AppendNewRecord( new XclExpChartPageSettings( rRoot
) );
3503 AppendNewRecord( new XclExpBoolRecord( EXC_ID_PROTECT
, false ) );
3504 AppendNewRecord( new XclExpChartDrawing( rRoot
, xModel
, rChartRect
.GetSize() ) );
3505 AppendNewRecord( new XclExpUInt16Record( EXC_ID_CHUNITS
, EXC_CHUNITS_TWIPS
) );
3507 Reference
< XChartDocument
> xChartDoc( xModel
, UNO_QUERY
);
3508 AppendNewRecord( new XclExpChChart( rRoot
, xChartDoc
, rChartRect
) );
3511 // ============================================================================
3513 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */