1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "xechart.hxx"
22 #include <com/sun/star/i18n/XBreakIterator.hpp>
23 #include <com/sun/star/i18n/ScriptType.hpp>
24 #include <com/sun/star/drawing/FillStyle.hpp>
25 #include <com/sun/star/drawing/XShapes.hpp>
26 #include <com/sun/star/chart/XChartDocument.hpp>
27 #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
28 #include <com/sun/star/chart/ChartAxisPosition.hpp>
29 #include <com/sun/star/chart/ChartLegendExpansion.hpp>
30 #include <com/sun/star/chart/DataLabelPlacement.hpp>
31 #include <com/sun/star/chart/ErrorBarStyle.hpp>
32 #include <com/sun/star/chart/MissingValueTreatment.hpp>
33 #include <com/sun/star/chart/TimeInterval.hpp>
34 #include <com/sun/star/chart/TimeUnit.hpp>
35 #include <com/sun/star/chart/XAxisSupplier.hpp>
36 #include <com/sun/star/chart/XDiagramPositioning.hpp>
37 #include <com/sun/star/chart2/XChartDocument.hpp>
38 #include <com/sun/star/chart2/XDiagram.hpp>
39 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
40 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
41 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
42 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
43 #include <com/sun/star/chart2/XTitled.hpp>
44 #include <com/sun/star/chart2/XColorScheme.hpp>
45 #include <com/sun/star/chart2/data/XDataSource.hpp>
46 #include <com/sun/star/chart2/AxisType.hpp>
47 #include <com/sun/star/chart2/CurveStyle.hpp>
48 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
49 #include <com/sun/star/chart2/DataPointLabel.hpp>
50 #include <com/sun/star/chart2/LegendPosition.hpp>
51 #include <com/sun/star/chart2/RelativePosition.hpp>
52 #include <com/sun/star/chart2/RelativeSize.hpp>
53 #include <com/sun/star/chart2/StackingDirection.hpp>
54 #include <com/sun/star/chart2/TickmarkStyle.hpp>
56 #include <tools/gen.hxx>
57 #include <vcl/outdev.hxx>
58 #include <filter/msfilter/escherex.hxx>
60 #include "document.hxx"
61 #include "rangelst.hxx"
62 #include "rangeutl.hxx"
63 #include "compiler.hxx"
64 #include "tokenarray.hxx"
66 #include "xeescher.hxx"
67 #include "xeformula.hxx"
68 #include "xehelper.hxx"
70 #include "xestyle.hxx"
72 #include <boost/scoped_ptr.hpp>
74 using ::com::sun::star::uno::Any
;
75 using ::com::sun::star::uno::Reference
;
76 using ::com::sun::star::uno::Sequence
;
77 using ::com::sun::star::uno::UNO_QUERY
;
78 using ::com::sun::star::uno::UNO_QUERY_THROW
;
79 using ::com::sun::star::uno::UNO_SET_THROW
;
80 using ::com::sun::star::uno::Exception
;
81 using ::com::sun::star::beans::XPropertySet
;
82 using ::com::sun::star::i18n::XBreakIterator
;
83 using ::com::sun::star::frame::XModel
;
84 using ::com::sun::star::drawing::XShape
;
85 using ::com::sun::star::drawing::XShapes
;
87 using ::com::sun::star::chart2::IncrementData
;
88 using ::com::sun::star::chart2::RelativePosition
;
89 using ::com::sun::star::chart2::RelativeSize
;
90 using ::com::sun::star::chart2::ScaleData
;
91 using ::com::sun::star::chart2::SubIncrement
;
92 using ::com::sun::star::chart2::XAxis
;
93 using ::com::sun::star::chart2::XChartDocument
;
94 using ::com::sun::star::chart2::XChartTypeContainer
;
95 using ::com::sun::star::chart2::XColorScheme
;
96 using ::com::sun::star::chart2::XCoordinateSystem
;
97 using ::com::sun::star::chart2::XCoordinateSystemContainer
;
98 using ::com::sun::star::chart2::XChartType
;
99 using ::com::sun::star::chart2::XDataSeries
;
100 using ::com::sun::star::chart2::XDataSeriesContainer
;
101 using ::com::sun::star::chart2::XDiagram
;
102 using ::com::sun::star::chart2::XFormattedString
;
103 using ::com::sun::star::chart2::XLegend
;
104 using ::com::sun::star::chart2::XRegressionCurve
;
105 using ::com::sun::star::chart2::XRegressionCurveContainer
;
106 using ::com::sun::star::chart2::XScaling
;
107 using ::com::sun::star::chart2::XTitle
;
108 using ::com::sun::star::chart2::XTitled
;
110 using ::com::sun::star::chart2::data::XDataSequence
;
111 using ::com::sun::star::chart2::data::XDataSource
;
112 using ::com::sun::star::chart2::data::XLabeledDataSequence
;
114 using ::formula::FormulaGrammar
;
115 using ::formula::FormulaToken
;
117 namespace cssc
= ::com::sun::star::chart
;
118 namespace cssc2
= ::com::sun::star::chart2
;
120 // Helpers ====================================================================
124 XclExpStream
& operator<<( XclExpStream
& rStrm
, const XclChRectangle
& rRect
)
126 return rStrm
<< rRect
.mnX
<< rRect
.mnY
<< rRect
.mnWidth
<< rRect
.mnHeight
;
129 inline void lclSaveRecord( XclExpStream
& rStrm
, XclExpRecordRef xRec
)
135 /** Saves the passed record (group) together with a leading value record. */
136 template< typename Type
>
137 void lclSaveRecord( XclExpStream
& rStrm
, XclExpRecordRef xRec
, sal_uInt16 nRecId
, Type nValue
)
141 XclExpValueRecord
< Type
>( nRecId
, nValue
).Save( rStrm
);
146 template<typename ValueType
, typename KeyType
>
147 void lclSaveRecord(XclExpStream
& rStrm
, ValueType
* pRec
, sal_uInt16 nRecId
, KeyType nValue
)
151 XclExpValueRecord
<KeyType
>(nRecId
, nValue
).Save(rStrm
);
156 void lclWriteChFrBlockRecord( XclExpStream
& rStrm
, const XclChFrBlock
& rFrBlock
, bool bBegin
)
158 sal_uInt16 nRecId
= bBegin
? EXC_ID_CHFRBLOCKBEGIN
: EXC_ID_CHFRBLOCKEND
;
159 rStrm
.StartRecord( nRecId
, 12 );
160 rStrm
<< nRecId
<< EXC_FUTUREREC_EMPTYFLAGS
<< rFrBlock
.mnType
<< rFrBlock
.mnContext
<< rFrBlock
.mnValue1
<< rFrBlock
.mnValue2
;
164 template< typename Type
>
165 inline bool lclIsAutoAnyOrGetValue( Type
& rValue
, const Any
& rAny
)
167 return !rAny
.hasValue() || !(rAny
>>= rValue
);
170 bool lclIsAutoAnyOrGetScaledValue( double& rfValue
, const Any
& rAny
, bool bLogScale
)
172 bool bIsAuto
= lclIsAutoAnyOrGetValue( rfValue
, rAny
);
173 if( !bIsAuto
&& bLogScale
)
174 rfValue
= log( rfValue
) / log( 10.0 );
178 sal_uInt16
lclGetTimeValue( const XclExpRoot
& rRoot
, double fSerialDate
, sal_uInt16 nTimeUnit
)
180 DateTime aDateTime
= rRoot
.GetDateTimeFromDouble( fSerialDate
);
183 case EXC_CHDATERANGE_DAYS
:
184 return ::limit_cast
< sal_uInt16
, double >( fSerialDate
, 0, SAL_MAX_UINT16
);
185 case EXC_CHDATERANGE_MONTHS
:
186 return ::limit_cast
< sal_uInt16
, sal_uInt16
>( 12 * (aDateTime
.GetYear() - rRoot
.GetBaseYear()) + aDateTime
.GetMonth() - 1, 0, SAL_MAX_INT16
);
187 case EXC_CHDATERANGE_YEARS
:
188 return ::limit_cast
< sal_uInt16
, sal_uInt16
>( aDateTime
.GetYear() - rRoot
.GetBaseYear(), 0, SAL_MAX_INT16
);
190 OSL_ENSURE( false, "lclGetTimeValue - unexpected time unit" );
192 return ::limit_cast
< sal_uInt16
, double >( fSerialDate
, 0, SAL_MAX_UINT16
);
195 bool lclConvertTimeValue( const XclExpRoot
& rRoot
, sal_uInt16
& rnValue
, const Any
& rAny
, sal_uInt16 nTimeUnit
)
197 double fSerialDate
= 0;
198 bool bAuto
= lclIsAutoAnyOrGetValue( fSerialDate
, rAny
);
200 rnValue
= lclGetTimeValue( rRoot
, fSerialDate
, nTimeUnit
);
204 sal_uInt16
lclGetTimeUnit( sal_Int32 nApiTimeUnit
)
206 switch( nApiTimeUnit
)
208 case cssc::TimeUnit::DAY
: return EXC_CHDATERANGE_DAYS
;
209 case cssc::TimeUnit::MONTH
: return EXC_CHDATERANGE_MONTHS
;
210 case cssc::TimeUnit::YEAR
: return EXC_CHDATERANGE_YEARS
;
211 default: OSL_ENSURE( false, "lclGetTimeUnit - unexpected time unit" );
213 return EXC_CHDATERANGE_DAYS
;
216 bool lclConvertTimeInterval( sal_uInt16
& rnValue
, sal_uInt16
& rnTimeUnit
, const Any
& rAny
)
218 cssc::TimeInterval aInterval
;
219 bool bAuto
= lclIsAutoAnyOrGetValue( aInterval
, rAny
);
222 rnValue
= ::limit_cast
< sal_uInt16
, sal_Int32
>( aInterval
.Number
, 1, SAL_MAX_UINT16
);
223 rnTimeUnit
= lclGetTimeUnit( aInterval
.TimeUnit
);
230 // Common =====================================================================
232 /** Stores global data needed in various classes of the Chart export filter. */
233 struct XclExpChRootData
: public XclChRootData
235 typedef ::std::vector
< XclChFrBlock
> XclChFrBlockVector
;
237 XclExpChChart
& mrChartData
; /// The chart data object.
238 XclChFrBlockVector maWrittenFrBlocks
; /// Stack of future record levels already written out.
239 XclChFrBlockVector maUnwrittenFrBlocks
; /// Stack of future record levels not yet written out.
241 inline explicit XclExpChRootData( XclExpChChart
& rChartData
) : mrChartData( rChartData
) {}
243 /** Registers a new future record level. */
244 void RegisterFutureRecBlock( const XclChFrBlock
& rFrBlock
);
245 /** Initializes the current future record level (writes all unwritten CHFRBLOCKBEGIN records). */
246 void InitializeFutureRecBlock( XclExpStream
& rStrm
);
247 /** Finalizes the current future record level (writes CHFRBLOCKEND record if needed). */
248 void FinalizeFutureRecBlock( XclExpStream
& rStrm
);
251 void XclExpChRootData::RegisterFutureRecBlock( const XclChFrBlock
& rFrBlock
)
253 maUnwrittenFrBlocks
.push_back( rFrBlock
);
256 void XclExpChRootData::InitializeFutureRecBlock( XclExpStream
& rStrm
)
258 // first call from a future record writes all missing CHFRBLOCKBEGIN records
259 if( !maUnwrittenFrBlocks
.empty() )
261 // write the leading CHFRINFO record
262 if( maWrittenFrBlocks
.empty() )
264 rStrm
.StartRecord( EXC_ID_CHFRINFO
, 20 );
265 rStrm
<< EXC_ID_CHFRINFO
<< EXC_FUTUREREC_EMPTYFLAGS
<< EXC_CHFRINFO_EXCELXP2003
<< EXC_CHFRINFO_EXCELXP2003
<< sal_uInt16( 3 );
266 rStrm
<< sal_uInt16( 0x0850 ) << sal_uInt16( 0x085A ) << sal_uInt16( 0x0861 ) << sal_uInt16( 0x0861 ) << sal_uInt16( 0x086A ) << sal_uInt16( 0x086B );
269 // write all unwritten CHFRBLOCKBEGIN records
270 for( XclChFrBlockVector::const_iterator aIt
= maUnwrittenFrBlocks
.begin(), aEnd
= maUnwrittenFrBlocks
.end(); aIt
!= aEnd
; ++aIt
)
272 OSL_ENSURE( aIt
->mnType
!= EXC_CHFRBLOCK_TYPE_UNKNOWN
, "XclExpChRootData::InitializeFutureRecBlock - unknown future record block type" );
273 lclWriteChFrBlockRecord( rStrm
, *aIt
, true );
275 // move all record infos to vector of written blocks
276 maWrittenFrBlocks
.insert( maWrittenFrBlocks
.end(), maUnwrittenFrBlocks
.begin(), maUnwrittenFrBlocks
.end() );
277 maUnwrittenFrBlocks
.clear();
281 void XclExpChRootData::FinalizeFutureRecBlock( XclExpStream
& rStrm
)
283 OSL_ENSURE( !maUnwrittenFrBlocks
.empty() || !maWrittenFrBlocks
.empty(), "XclExpChRootData::FinalizeFutureRecBlock - no future record level found" );
284 if( !maUnwrittenFrBlocks
.empty() )
286 // no future record has been written, just forget the topmost level
287 maUnwrittenFrBlocks
.pop_back();
289 else if( !maWrittenFrBlocks
.empty() )
291 // write the CHFRBLOCKEND record for the topmost block and delete it
292 lclWriteChFrBlockRecord( rStrm
, maWrittenFrBlocks
.back(), false );
293 maWrittenFrBlocks
.pop_back();
297 XclExpChRoot::XclExpChRoot( const XclExpRoot
& rRoot
, XclExpChChart
& rChartData
) :
299 mxChData( new XclExpChRootData( rChartData
) )
303 XclExpChRoot::~XclExpChRoot()
307 Reference
< XChartDocument
> XclExpChRoot::GetChartDocument() const
309 return mxChData
->mxChartDoc
;
312 XclExpChChart
& XclExpChRoot::GetChartData() const
314 return mxChData
->mrChartData
;
317 const XclChTypeInfo
& XclExpChRoot::GetChartTypeInfo( XclChTypeId eType
) const
319 return mxChData
->mxTypeInfoProv
->GetTypeInfo( eType
);
322 const XclChTypeInfo
& XclExpChRoot::GetChartTypeInfo( const OUString
& rServiceName
) const
324 return mxChData
->mxTypeInfoProv
->GetTypeInfoFromService( rServiceName
);
327 const XclChFormatInfo
& XclExpChRoot::GetFormatInfo( XclChObjectType eObjType
) const
329 return mxChData
->mxFmtInfoProv
->GetFormatInfo( eObjType
);
332 void XclExpChRoot::InitConversion( XChartDocRef xChartDoc
, const Rectangle
& rChartRect
) const
334 mxChData
->InitConversion( GetRoot(), xChartDoc
, rChartRect
);
337 void XclExpChRoot::FinishConversion() const
339 mxChData
->FinishConversion();
342 bool XclExpChRoot::IsSystemColor( const Color
& rColor
, sal_uInt16 nSysColorIdx
) const
344 XclExpPalette
& rPal
= GetPalette();
345 return rPal
.IsSystemColor( nSysColorIdx
) && (rColor
== rPal
.GetDefColor( nSysColorIdx
));
348 void XclExpChRoot::SetSystemColor( Color
& rColor
, sal_uInt32
& rnColorId
, sal_uInt16 nSysColorIdx
) const
350 OSL_ENSURE( GetPalette().IsSystemColor( nSysColorIdx
), "XclExpChRoot::SetSystemColor - invalid color index" );
351 rColor
= GetPalette().GetDefColor( nSysColorIdx
);
352 rnColorId
= XclExpPalette::GetColorIdFromIndex( nSysColorIdx
);
355 sal_Int32
XclExpChRoot::CalcChartXFromHmm( sal_Int32 nPosX
) const
357 return ::limit_cast
< sal_Int32
, double >( (nPosX
- mxChData
->mnBorderGapX
) / mxChData
->mfUnitSizeX
, 0, EXC_CHART_TOTALUNITS
);
360 sal_Int32
XclExpChRoot::CalcChartYFromHmm( sal_Int32 nPosY
) const
362 return ::limit_cast
< sal_Int32
, double >( (nPosY
- mxChData
->mnBorderGapY
) / mxChData
->mfUnitSizeY
, 0, EXC_CHART_TOTALUNITS
);
365 XclChRectangle
XclExpChRoot::CalcChartRectFromHmm( const ::com::sun::star::awt::Rectangle
& rRect
) const
367 XclChRectangle aRect
;
368 aRect
.mnX
= CalcChartXFromHmm( rRect
.X
);
369 aRect
.mnY
= CalcChartYFromHmm( rRect
.Y
);
370 aRect
.mnWidth
= CalcChartXFromHmm( rRect
.Width
);
371 aRect
.mnHeight
= CalcChartYFromHmm( rRect
.Height
);
375 void XclExpChRoot::ConvertLineFormat( XclChLineFormat
& rLineFmt
,
376 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
) const
378 GetChartPropSetHelper().ReadLineProperties(
379 rLineFmt
, *mxChData
->mxLineDashTable
, rPropSet
, ePropMode
);
382 bool XclExpChRoot::ConvertAreaFormat( XclChAreaFormat
& rAreaFmt
,
383 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
) const
385 return GetChartPropSetHelper().ReadAreaProperties( rAreaFmt
, rPropSet
, ePropMode
);
388 void XclExpChRoot::ConvertEscherFormat(
389 XclChEscherFormat
& rEscherFmt
, XclChPicFormat
& rPicFmt
,
390 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
) const
392 GetChartPropSetHelper().ReadEscherProperties( rEscherFmt
, rPicFmt
,
393 *mxChData
->mxGradientTable
, *mxChData
->mxHatchTable
, *mxChData
->mxBitmapTable
, rPropSet
, ePropMode
);
396 sal_uInt16
XclExpChRoot::ConvertFont( const ScfPropertySet
& rPropSet
, sal_Int16 nScript
) const
398 XclFontData aFontData
;
399 GetFontPropSetHelper().ReadFontProperties( aFontData
, rPropSet
, EXC_FONTPROPSET_CHART
, nScript
);
400 return GetFontBuffer().Insert( aFontData
, EXC_COLOR_CHARTTEXT
);
403 sal_uInt16
XclExpChRoot::ConvertPieRotation( const ScfPropertySet
& rPropSet
)
405 sal_Int32 nApiRot
= 0;
406 rPropSet
.GetProperty( nApiRot
, EXC_CHPROP_STARTINGANGLE
);
407 return static_cast< sal_uInt16
>( (450 - (nApiRot
% 360)) % 360 );
410 void XclExpChRoot::RegisterFutureRecBlock( const XclChFrBlock
& rFrBlock
)
412 mxChData
->RegisterFutureRecBlock( rFrBlock
);
415 void XclExpChRoot::InitializeFutureRecBlock( XclExpStream
& rStrm
)
417 mxChData
->InitializeFutureRecBlock( rStrm
);
420 void XclExpChRoot::FinalizeFutureRecBlock( XclExpStream
& rStrm
)
422 mxChData
->FinalizeFutureRecBlock( rStrm
);
425 XclExpChGroupBase::XclExpChGroupBase( const XclExpChRoot
& rRoot
,
426 sal_uInt16 nFrType
, sal_uInt16 nRecId
, sal_Size nRecSize
) :
427 XclExpRecord( nRecId
, nRecSize
),
428 XclExpChRoot( rRoot
),
433 XclExpChGroupBase::~XclExpChGroupBase()
437 void XclExpChGroupBase::Save( XclExpStream
& rStrm
)
440 XclExpRecord::Save( rStrm
);
442 if( HasSubRecords() )
444 // register the future record context corresponding to this record group
445 RegisterFutureRecBlock( maFrBlock
);
447 XclExpEmptyRecord( EXC_ID_CHBEGIN
).Save( rStrm
);
449 WriteSubRecords( rStrm
);
450 // finalize the future records, must be done before the closing CHEND
451 FinalizeFutureRecBlock( rStrm
);
453 XclExpEmptyRecord( EXC_ID_CHEND
).Save( rStrm
);
457 bool XclExpChGroupBase::HasSubRecords() const
462 void XclExpChGroupBase::SetFutureRecordContext( sal_uInt16 nFrContext
, sal_uInt16 nFrValue1
, sal_uInt16 nFrValue2
)
464 maFrBlock
.mnContext
= nFrContext
;
465 maFrBlock
.mnValue1
= nFrValue1
;
466 maFrBlock
.mnValue2
= nFrValue2
;
469 XclExpChFutureRecordBase::XclExpChFutureRecordBase( const XclExpChRoot
& rRoot
,
470 XclFutureRecType eRecType
, sal_uInt16 nRecId
, sal_Size nRecSize
) :
471 XclExpFutureRecord( eRecType
, nRecId
, nRecSize
),
472 XclExpChRoot( rRoot
)
476 void XclExpChFutureRecordBase::Save( XclExpStream
& rStrm
)
478 InitializeFutureRecBlock( rStrm
);
479 XclExpFutureRecord::Save( rStrm
);
482 // Frame formatting ===========================================================
484 XclExpChFramePos::XclExpChFramePos( sal_uInt16 nTLMode
, sal_uInt16 nBRMode
) :
485 XclExpRecord( EXC_ID_CHFRAMEPOS
, 20 )
487 maData
.mnTLMode
= nTLMode
;
488 maData
.mnBRMode
= nBRMode
;
491 void XclExpChFramePos::WriteBody( XclExpStream
& rStrm
)
493 rStrm
<< maData
.mnTLMode
<< maData
.mnBRMode
<< maData
.maRect
;
496 XclExpChLineFormat::XclExpChLineFormat( const XclExpChRoot
& rRoot
) :
497 XclExpRecord( EXC_ID_CHLINEFORMAT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 12 : 10 ),
498 mnColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
502 void XclExpChLineFormat::SetDefault( XclChFrameType eDefFrameType
)
504 switch( eDefFrameType
)
506 case EXC_CHFRAMETYPE_AUTO
:
509 case EXC_CHFRAMETYPE_INVISIBLE
:
511 maData
.mnPattern
= EXC_CHLINEFORMAT_NONE
;
514 OSL_FAIL( "XclExpChLineFormat::SetDefault - unknown frame type" );
518 void XclExpChLineFormat::Convert( const XclExpChRoot
& rRoot
,
519 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
521 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
522 rRoot
.ConvertLineFormat( maData
, rPropSet
, rFmtInfo
.mePropMode
);
525 // detect system color, set color identifier (TODO: detect automatic series line)
526 if( (eObjType
!= EXC_CHOBJTYPE_LINEARSERIES
) && rRoot
.IsSystemColor( maData
.maColor
, rFmtInfo
.mnAutoLineColorIdx
) )
528 // store color index from automatic format data
529 mnColorId
= XclExpPalette::GetColorIdFromIndex( rFmtInfo
.mnAutoLineColorIdx
);
530 // try to set automatic mode
531 bool bAuto
= (maData
.mnPattern
== EXC_CHLINEFORMAT_SOLID
) && (maData
.mnWeight
== rFmtInfo
.mnAutoLineWeight
);
532 ::set_flag( maData
.mnFlags
, EXC_CHLINEFORMAT_AUTO
, bAuto
);
536 // user defined color - register in palette
537 mnColorId
= rRoot
.GetPalette().InsertColor( maData
.maColor
, EXC_COLOR_CHARTLINE
);
542 // no line - set default system color
543 rRoot
.SetSystemColor( maData
.maColor
, mnColorId
, EXC_COLOR_CHWINDOWTEXT
);
547 bool XclExpChLineFormat::IsDefault( XclChFrameType eDefFrameType
) const
550 ((eDefFrameType
== EXC_CHFRAMETYPE_INVISIBLE
) && !HasLine()) ||
551 ((eDefFrameType
== EXC_CHFRAMETYPE_AUTO
) && IsAuto());
554 void XclExpChLineFormat::WriteBody( XclExpStream
& rStrm
)
556 rStrm
<< maData
.maColor
<< maData
.mnPattern
<< maData
.mnWeight
<< maData
.mnFlags
;
557 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
558 rStrm
<< rStrm
.GetRoot().GetPalette().GetColorIndex( mnColorId
);
563 /** Creates a CHLINEFORMAT record from the passed property set. */
564 XclExpChLineFormatRef
lclCreateLineFormat( const XclExpChRoot
& rRoot
,
565 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
567 XclExpChLineFormatRef
xLineFmt( new XclExpChLineFormat( rRoot
) );
568 xLineFmt
->Convert( rRoot
, rPropSet
, eObjType
);
569 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
570 if( rFmtInfo
.mbDeleteDefFrame
&& xLineFmt
->IsDefault( rFmtInfo
.meDefFrameType
) )
577 XclExpChAreaFormat::XclExpChAreaFormat( const XclExpChRoot
& rRoot
) :
578 XclExpRecord( EXC_ID_CHAREAFORMAT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 16 : 12 ),
579 mnPattColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) ),
580 mnBackColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
584 bool XclExpChAreaFormat::Convert( const XclExpChRoot
& rRoot
,
585 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
587 const XclChFormatInfo
& rFmtInfo
= rRoot
.GetFormatInfo( eObjType
);
588 bool bComplexFill
= rRoot
.ConvertAreaFormat( maData
, rPropSet
, rFmtInfo
.mePropMode
);
591 bool bSolid
= maData
.mnPattern
== EXC_PATT_SOLID
;
592 // detect system color, set color identifier (TODO: detect automatic series area)
593 if( (eObjType
!= EXC_CHOBJTYPE_FILLEDSERIES
) && rRoot
.IsSystemColor( maData
.maPattColor
, rFmtInfo
.mnAutoPattColorIdx
) )
595 // store color index from automatic format data
596 mnPattColorId
= XclExpPalette::GetColorIdFromIndex( rFmtInfo
.mnAutoPattColorIdx
);
597 // set automatic mode
598 ::set_flag( maData
.mnFlags
, EXC_CHAREAFORMAT_AUTO
, bSolid
);
602 // user defined color - register color in palette
603 mnPattColorId
= rRoot
.GetPalette().InsertColor( maData
.maPattColor
, EXC_COLOR_CHARTAREA
);
605 // background color (default system color for solid fills)
607 rRoot
.SetSystemColor( maData
.maBackColor
, mnBackColorId
, EXC_COLOR_CHWINDOWTEXT
);
609 mnBackColorId
= rRoot
.GetPalette().InsertColor( maData
.maBackColor
, EXC_COLOR_CHARTAREA
);
613 // no area - set default system colors
614 rRoot
.SetSystemColor( maData
.maPattColor
, mnPattColorId
, EXC_COLOR_CHWINDOWBACK
);
615 rRoot
.SetSystemColor( maData
.maBackColor
, mnBackColorId
, EXC_COLOR_CHWINDOWTEXT
);
620 void XclExpChAreaFormat::SetDefault( XclChFrameType eDefFrameType
)
622 switch( eDefFrameType
)
624 case EXC_CHFRAMETYPE_AUTO
:
627 case EXC_CHFRAMETYPE_INVISIBLE
:
629 maData
.mnPattern
= EXC_PATT_NONE
;
632 OSL_FAIL( "XclExpChAreaFormat::SetDefault - unknown frame type" );
636 bool XclExpChAreaFormat::IsDefault( XclChFrameType eDefFrameType
) const
639 ((eDefFrameType
== EXC_CHFRAMETYPE_INVISIBLE
) && !HasArea()) ||
640 ((eDefFrameType
== EXC_CHFRAMETYPE_AUTO
) && IsAuto());
643 void XclExpChAreaFormat::WriteBody( XclExpStream
& rStrm
)
645 rStrm
<< maData
.maPattColor
<< maData
.maBackColor
<< maData
.mnPattern
<< maData
.mnFlags
;
646 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
648 const XclExpPalette
& rPal
= rStrm
.GetRoot().GetPalette();
649 rStrm
<< rPal
.GetColorIndex( mnPattColorId
) << rPal
.GetColorIndex( mnBackColorId
);
653 XclExpChEscherFormat::XclExpChEscherFormat( const XclExpChRoot
& rRoot
) :
654 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_UNKNOWN
, EXC_ID_CHESCHERFORMAT
),
655 mnColor1Id( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) ),
656 mnColor2Id( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) )
658 OSL_ENSURE_BIFF( GetBiff() == EXC_BIFF8
);
661 void XclExpChEscherFormat::Convert( const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
663 const XclChFormatInfo
& rFmtInfo
= GetFormatInfo( eObjType
);
664 ConvertEscherFormat( maData
, maPicFmt
, rPropSet
, rFmtInfo
.mePropMode
);
665 // register colors in palette
666 mnColor1Id
= RegisterColor( ESCHER_Prop_fillColor
);
667 mnColor2Id
= RegisterColor( ESCHER_Prop_fillBackColor
);
670 bool XclExpChEscherFormat::IsValid() const
672 return static_cast< bool >(maData
.mxEscherSet
);
675 void XclExpChEscherFormat::Save( XclExpStream
& rStrm
)
677 if( maData
.mxEscherSet
)
679 // replace RGB colors with palette indexes in the Escher container
680 const XclExpPalette
& rPal
= GetPalette();
681 maData
.mxEscherSet
->AddOpt( ESCHER_Prop_fillColor
, 0x08000000 | rPal
.GetColorIndex( mnColor1Id
) );
682 maData
.mxEscherSet
->AddOpt( ESCHER_Prop_fillBackColor
, 0x08000000 | rPal
.GetColorIndex( mnColor2Id
) );
684 // save the record group
685 XclExpChGroupBase::Save( rStrm
);
689 bool XclExpChEscherFormat::HasSubRecords() const
691 // no subrecords for gradients
692 return maPicFmt
.mnBmpMode
!= EXC_CHPICFORMAT_NONE
;
695 void XclExpChEscherFormat::WriteSubRecords( XclExpStream
& rStrm
)
697 rStrm
.StartRecord( EXC_ID_CHPICFORMAT
, 14 );
698 rStrm
<< maPicFmt
.mnBmpMode
<< sal_uInt16( 0 ) << maPicFmt
.mnFlags
<< maPicFmt
.mfScale
;
702 sal_uInt32
XclExpChEscherFormat::RegisterColor( sal_uInt16 nPropId
)
704 sal_uInt32 nBGRValue
;
705 if( maData
.mxEscherSet
&& maData
.mxEscherSet
->GetOpt( nPropId
, nBGRValue
) )
708 Color
aColor( RGB_COLORDATA(
709 COLORDATA_BLUE( nBGRValue
),
710 COLORDATA_GREEN( nBGRValue
),
711 COLORDATA_RED( nBGRValue
) ) );
712 return GetPalette().InsertColor( aColor
, EXC_COLOR_CHARTAREA
);
714 return XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
);
717 void XclExpChEscherFormat::WriteBody( XclExpStream
& rStrm
)
719 OSL_ENSURE( maData
.mxEscherSet
, "XclExpChEscherFormat::WriteBody - missing property container" );
720 // write Escher property container via temporary memory stream
721 SvMemoryStream aMemStrm
;
722 maData
.mxEscherSet
->Commit( aMemStrm
);
723 aMemStrm
.Seek( STREAM_SEEK_TO_BEGIN
);
724 rStrm
.CopyFromStream( aMemStrm
);
727 XclExpChFrameBase::XclExpChFrameBase()
731 XclExpChFrameBase::~XclExpChFrameBase()
735 void XclExpChFrameBase::ConvertFrameBase( const XclExpChRoot
& rRoot
,
736 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
739 mxLineFmt
.reset( new XclExpChLineFormat( rRoot
) );
740 mxLineFmt
->Convert( rRoot
, rPropSet
, eObjType
);
741 // area format (only for frame objects)
742 if( rRoot
.GetFormatInfo( eObjType
).mbIsFrame
)
744 mxAreaFmt
.reset( new XclExpChAreaFormat( rRoot
) );
745 bool bComplexFill
= mxAreaFmt
->Convert( rRoot
, rPropSet
, eObjType
);
746 if( (rRoot
.GetBiff() == EXC_BIFF8
) && bComplexFill
)
748 mxEscherFmt
.reset( new XclExpChEscherFormat( rRoot
) );
749 mxEscherFmt
->Convert( rPropSet
, eObjType
);
750 if( mxEscherFmt
->IsValid() )
751 mxAreaFmt
->SetAuto( false );
758 void XclExpChFrameBase::SetDefaultFrameBase( const XclExpChRoot
& rRoot
,
759 XclChFrameType eDefFrameType
, bool bIsFrame
)
762 mxLineFmt
.reset( new XclExpChLineFormat( rRoot
) );
763 mxLineFmt
->SetDefault( eDefFrameType
);
764 // area format (only for frame objects)
767 mxAreaFmt
.reset( new XclExpChAreaFormat( rRoot
) );
768 mxAreaFmt
->SetDefault( eDefFrameType
);
773 bool XclExpChFrameBase::IsDefaultFrameBase( XclChFrameType eDefFrameType
) const
776 (!mxLineFmt
|| mxLineFmt
->IsDefault( eDefFrameType
)) &&
777 (!mxAreaFmt
|| mxAreaFmt
->IsDefault( eDefFrameType
));
780 void XclExpChFrameBase::WriteFrameRecords( XclExpStream
& rStrm
)
782 lclSaveRecord( rStrm
, mxLineFmt
);
783 lclSaveRecord( rStrm
, mxAreaFmt
);
784 lclSaveRecord( rStrm
, mxEscherFmt
);
787 XclExpChFrame::XclExpChFrame( const XclExpChRoot
& rRoot
, XclChObjectType eObjType
) :
788 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_FRAME
, EXC_ID_CHFRAME
, 4 ),
789 meObjType( eObjType
)
793 void XclExpChFrame::Convert( const ScfPropertySet
& rPropSet
)
795 ConvertFrameBase( GetChRoot(), rPropSet
, meObjType
);
798 void XclExpChFrame::SetAutoFlags( bool bAutoPos
, bool bAutoSize
)
800 ::set_flag( maData
.mnFlags
, EXC_CHFRAME_AUTOPOS
, bAutoPos
);
801 ::set_flag( maData
.mnFlags
, EXC_CHFRAME_AUTOSIZE
, bAutoSize
);
804 bool XclExpChFrame::IsDefault() const
806 return IsDefaultFrameBase( GetFormatInfo( meObjType
).meDefFrameType
);
809 bool XclExpChFrame::IsDeleteable() const
811 return IsDefault() && GetFormatInfo( meObjType
).mbDeleteDefFrame
;
814 void XclExpChFrame::Save( XclExpStream
& rStrm
)
818 // wall/floor frame without CHFRAME header record
819 case EXC_CHOBJTYPE_WALL3D
:
820 case EXC_CHOBJTYPE_FLOOR3D
:
821 WriteFrameRecords( rStrm
);
824 XclExpChGroupBase::Save( rStrm
);
828 void XclExpChFrame::WriteSubRecords( XclExpStream
& rStrm
)
830 WriteFrameRecords( rStrm
);
833 void XclExpChFrame::WriteBody( XclExpStream
& rStrm
)
835 rStrm
<< maData
.mnFormat
<< maData
.mnFlags
;
840 /** Creates a CHFRAME record from the passed property set. */
841 XclExpChFrameRef
lclCreateFrame( const XclExpChRoot
& rRoot
,
842 const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
844 XclExpChFrameRef
xFrame( new XclExpChFrame( rRoot
, eObjType
) );
845 xFrame
->Convert( rPropSet
);
846 if( xFrame
->IsDeleteable() )
853 // Source links ===============================================================
857 void lclAddDoubleRefData(
858 ScTokenArray
& orArray
, const FormulaToken
& rToken
,
859 SCsTAB nScTab1
, SCsCOL nScCol1
, SCsROW nScRow1
,
860 SCsTAB nScTab2
, SCsCOL nScCol2
, SCsROW nScRow2
)
862 ScComplexRefData aComplexRef
;
863 aComplexRef
.InitRange(ScRange(nScCol1
,nScRow1
,nScTab1
,nScCol2
,nScRow2
,nScTab2
));
864 aComplexRef
.Ref1
.SetFlag3D( true );
866 if( orArray
.GetLen() > 0 )
867 orArray
.AddOpCode( ocUnion
);
869 OSL_ENSURE( (rToken
.GetType() == ::formula::svDoubleRef
) || (rToken
.GetType() == ::formula::svExternalDoubleRef
),
870 "lclAddDoubleRefData - double reference token expected");
871 if( rToken
.GetType() == ::formula::svExternalDoubleRef
)
872 orArray
.AddExternalDoubleReference(
873 rToken
.GetIndex(), rToken
.GetString().getString(), aComplexRef
);
875 orArray
.AddDoubleReference( aComplexRef
);
880 XclExpChSourceLink::XclExpChSourceLink( const XclExpChRoot
& rRoot
, sal_uInt8 nDestType
) :
881 XclExpRecord( EXC_ID_CHSOURCELINK
),
882 XclExpChRoot( rRoot
)
884 maData
.mnDestType
= nDestType
;
885 maData
.mnLinkType
= EXC_CHSRCLINK_DIRECTLY
;
888 sal_uInt16
XclExpChSourceLink::ConvertDataSequence( Reference
< XDataSequence
> xDataSeq
, bool bSplitToColumns
, sal_uInt16 nDefCount
)
891 maData
.mnLinkType
= EXC_CHSRCLINK_DEFAULT
;
896 // Compile the range representation string into token array. Note that the
897 // source range text depends on the current grammar.
898 OUString aRangeRepr
= xDataSeq
->getSourceRangeRepresentation();
899 ScCompiler
aComp( GetDocPtr(), ScAddress() );
900 aComp
.SetGrammar( GetDocPtr()->GetGrammar() );
901 boost::scoped_ptr
<ScTokenArray
> pArray(aComp
.CompileString(aRangeRepr
));
906 sal_uInt32 nValueCount
= 0;
908 for( const FormulaToken
* pToken
= pArray
->First(); pToken
; pToken
= pArray
->Next() )
910 switch( pToken
->GetType() )
912 case ::formula::svSingleRef
:
913 case ::formula::svExternalSingleRef
:
914 // for a single ref token, just add it to the new token array as is
915 if( aArray
.GetLen() > 0 )
916 aArray
.AddOpCode( ocUnion
);
917 aArray
.AddToken( *pToken
);
921 case ::formula::svDoubleRef
:
922 case ::formula::svExternalDoubleRef
:
924 // split 3-dimensional ranges into single sheets
925 const ScComplexRefData
& rComplexRef
= *pToken
->GetDoubleRef();
926 ScAddress aAbs1
= rComplexRef
.Ref1
.toAbs(ScAddress());
927 ScAddress aAbs2
= rComplexRef
.Ref2
.toAbs(ScAddress());
928 for (SCsTAB nScTab
= aAbs1
.Tab(); nScTab
<= aAbs2
.Tab(); ++nScTab
)
930 // split 2-dimensional ranges into single columns
931 if (bSplitToColumns
&& (aAbs1
.Col() < aAbs2
.Col()) && (aAbs1
.Row() < aAbs2
.Row()))
932 for (SCCOL nScCol
= aAbs1
.Col(); nScCol
<= aAbs2
.Col(); ++nScCol
)
933 lclAddDoubleRefData(aArray
, *pToken
, nScTab
, nScCol
, aAbs1
.Row(), nScTab
, nScCol
, aAbs2
.Row());
935 lclAddDoubleRefData(aArray
, *pToken
, nScTab
, aAbs1
.Col(), aAbs1
.Row(), nScTab
, aAbs2
.Col(), aAbs2
.Row());
937 sal_uInt32 nTabs
= static_cast<sal_uInt32
>(aAbs2
.Tab() - aAbs1
.Tab() + 1);
938 sal_uInt32 nCols
= static_cast<sal_uInt32
>(aAbs2
.Col() - aAbs1
.Col() + 1);
939 sal_uInt32 nRows
= static_cast<sal_uInt32
>(aAbs2
.Row() - aAbs1
.Row() + 1);
940 nValueCount
+= nCols
* nRows
* nTabs
;
948 const ScAddress aBaseCell
;
949 mxLinkFmla
= GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CHART
, aArray
, &aBaseCell
);
950 maData
.mnLinkType
= EXC_CHSRCLINK_WORKSHEET
;
951 return ulimit_cast
< sal_uInt16
>( nValueCount
, EXC_CHDATAFORMAT_MAXPOINTCOUNT
);
954 void XclExpChSourceLink::ConvertString( const OUString
& aString
)
956 mxString
= XclExpStringHelper::CreateString( GetRoot(), aString
, EXC_STR_FORCEUNICODE
| EXC_STR_8BITLENGTH
| EXC_STR_SEPARATEFORMATS
);
959 sal_uInt16
XclExpChSourceLink::ConvertStringSequence( const Sequence
< Reference
< XFormattedString
> >& rStringSeq
)
962 sal_uInt16 nFontIdx
= EXC_FONT_APP
;
963 if( rStringSeq
.hasElements() )
965 mxString
= XclExpStringHelper::CreateString( GetRoot(), OUString(), EXC_STR_FORCEUNICODE
| EXC_STR_8BITLENGTH
| EXC_STR_SEPARATEFORMATS
);
966 Reference
< XBreakIterator
> xBreakIt
= GetDoc().GetBreakIterator();
967 namespace ApiScriptType
= ::com::sun::star::i18n::ScriptType
;
969 // convert all formatted string entries from the sequence
970 const Reference
< XFormattedString
>* pBeg
= rStringSeq
.getConstArray();
971 const Reference
< XFormattedString
>* pEnd
= pBeg
+ rStringSeq
.getLength();
972 for( const Reference
< XFormattedString
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
976 sal_uInt16 nWstrnFontIdx
= EXC_FONT_NOTFOUND
;
977 sal_uInt16 nAsianFontIdx
= EXC_FONT_NOTFOUND
;
978 sal_uInt16 nCmplxFontIdx
= EXC_FONT_NOTFOUND
;
979 OUString aText
= (*pIt
)->getString();
980 ScfPropertySet
aStrProp( *pIt
);
982 // #i63255# get script type for leading weak characters
983 sal_Int16 nLastScript
= XclExpStringHelper::GetLeadingScriptType( GetRoot(), aText
);
985 // process all script portions
986 sal_Int32 nPortionPos
= 0;
987 sal_Int32 nTextLen
= aText
.getLength();
988 while( nPortionPos
< nTextLen
)
990 // get script type and end position of next script portion
991 sal_Int16 nScript
= xBreakIt
->getScriptType( aText
, nPortionPos
);
992 sal_Int32 nPortionEnd
= xBreakIt
->endOfScript( aText
, nPortionPos
, nScript
);
994 // reuse previous script for following weak portions
995 if( nScript
== ApiScriptType::WEAK
)
996 nScript
= nLastScript
;
998 // Excel start position of this portion
999 sal_uInt16 nXclPortionStart
= mxString
->Len();
1000 // add portion text to Excel string
1001 XclExpStringHelper::AppendString( *mxString
, GetRoot(), aText
.copy( nPortionPos
, nPortionEnd
- nPortionPos
) );
1002 if( nXclPortionStart
< mxString
->Len() )
1004 // find font index variable dependent on script type
1005 sal_uInt16
& rnFontIdx
= (nScript
== ApiScriptType::COMPLEX
) ? nCmplxFontIdx
:
1006 ((nScript
== ApiScriptType::ASIAN
) ? nAsianFontIdx
: nWstrnFontIdx
);
1008 // insert font into buffer (if not yet done)
1009 if( rnFontIdx
== EXC_FONT_NOTFOUND
)
1010 rnFontIdx
= ConvertFont( aStrProp
, nScript
);
1012 // insert font index into format run vector
1013 mxString
->AppendFormat( nXclPortionStart
, rnFontIdx
);
1016 // go to next script portion
1017 nLastScript
= nScript
;
1018 nPortionPos
= nPortionEnd
;
1022 if( !mxString
->IsEmpty() )
1024 // get leading font index
1025 const XclFormatRunVec
& rFormats
= mxString
->GetFormats();
1026 OSL_ENSURE( !rFormats
.empty() && (rFormats
.front().mnChar
== 0),
1027 "XclExpChSourceLink::ConvertStringSequenc - missing leading format" );
1028 // remove leading format run, if entire string is equally formatted
1029 if( rFormats
.size() == 1 )
1030 nFontIdx
= mxString
->RemoveLeadingFont();
1031 else if( !rFormats
.empty() )
1032 nFontIdx
= rFormats
.front().mnFontIdx
;
1033 // add trailing format run, if string is rich-formatted
1034 if( mxString
->IsRich() )
1035 mxString
->AppendTrailingFormat( EXC_FONT_APP
);
1041 void XclExpChSourceLink::ConvertNumFmt( const ScfPropertySet
& rPropSet
, bool bPercent
)
1043 sal_Int32 nApiNumFmt
= 0;
1044 if( bPercent
? rPropSet
.GetProperty( nApiNumFmt
, EXC_CHPROP_PERCENTAGENUMFMT
) : rPropSet
.GetProperty( nApiNumFmt
, EXC_CHPROP_NUMBERFORMAT
) )
1046 ::set_flag( maData
.mnFlags
, EXC_CHSRCLINK_NUMFMT
);
1047 maData
.mnNumFmtIdx
= GetNumFmtBuffer().Insert( static_cast< sal_uInt32
>( nApiNumFmt
) );
1051 void XclExpChSourceLink::AppendString( const OUString
& rStr
)
1055 XclExpStringHelper::AppendString( *mxString
, GetRoot(), rStr
);
1058 void XclExpChSourceLink::Save( XclExpStream
& rStrm
)
1060 // CHFORMATRUNS record
1061 if( mxString
&& mxString
->IsRich() )
1063 sal_Size nRecSize
= (1 + mxString
->GetFormatsCount()) * ((GetBiff() == EXC_BIFF8
) ? 2 : 1);
1064 rStrm
.StartRecord( EXC_ID_CHFORMATRUNS
, nRecSize
);
1065 mxString
->WriteFormats( rStrm
, true );
1068 // CHSOURCELINK record
1069 XclExpRecord::Save( rStrm
);
1071 if( mxString
&& !mxString
->IsEmpty() )
1073 rStrm
.StartRecord( EXC_ID_CHSTRING
, 2 + mxString
->GetSize() );
1074 rStrm
<< sal_uInt16( 0 ) << *mxString
;
1079 void XclExpChSourceLink::WriteBody( XclExpStream
& rStrm
)
1081 rStrm
<< maData
.mnDestType
1082 << maData
.mnLinkType
1084 << maData
.mnNumFmtIdx
1088 // Text =======================================================================
1090 XclExpChFont::XclExpChFont( sal_uInt16 nFontIdx
) :
1091 XclExpUInt16Record( EXC_ID_CHFONT
, nFontIdx
)
1095 XclExpChObjectLink::XclExpChObjectLink( sal_uInt16 nLinkTarget
, const XclChDataPointPos
& rPointPos
) :
1096 XclExpRecord( EXC_ID_CHOBJECTLINK
, 6 )
1098 maData
.mnTarget
= nLinkTarget
;
1099 maData
.maPointPos
= rPointPos
;
1102 void XclExpChObjectLink::WriteBody( XclExpStream
& rStrm
)
1104 rStrm
<< maData
.mnTarget
<< maData
.maPointPos
.mnSeriesIdx
<< maData
.maPointPos
.mnPointIdx
;
1107 XclExpChFrLabelProps::XclExpChFrLabelProps( const XclExpChRoot
& rRoot
) :
1108 XclExpChFutureRecordBase( rRoot
, EXC_FUTUREREC_UNUSEDREF
, EXC_ID_CHFRLABELPROPS
, 4 )
1112 void XclExpChFrLabelProps::Convert( const ScfPropertySet
& rPropSet
, bool bShowSeries
,
1113 bool bShowCateg
, bool bShowValue
, bool bShowPercent
, bool bShowBubble
)
1115 // label value flags
1116 ::set_flag( maData
.mnFlags
, EXC_CHFRLABELPROPS_SHOWSERIES
, bShowSeries
);
1117 ::set_flag( maData
.mnFlags
, EXC_CHFRLABELPROPS_SHOWCATEG
, bShowCateg
);
1118 ::set_flag( maData
.mnFlags
, EXC_CHFRLABELPROPS_SHOWVALUE
, bShowValue
);
1119 ::set_flag( maData
.mnFlags
, EXC_CHFRLABELPROPS_SHOWPERCENT
, bShowPercent
);
1120 ::set_flag( maData
.mnFlags
, EXC_CHFRLABELPROPS_SHOWBUBBLE
, bShowBubble
);
1122 // label value separator
1123 maData
.maSeparator
= rPropSet
.GetStringProperty( EXC_CHPROP_LABELSEPARATOR
);
1124 if( maData
.maSeparator
.isEmpty() )
1125 maData
.maSeparator
= " ";
1128 void XclExpChFrLabelProps::WriteBody( XclExpStream
& rStrm
)
1130 XclExpString
aXclSep( maData
.maSeparator
, EXC_STR_FORCEUNICODE
| EXC_STR_SMARTFLAGS
);
1131 rStrm
<< maData
.mnFlags
<< aXclSep
;
1134 XclExpChFontBase::~XclExpChFontBase()
1138 void XclExpChFontBase::ConvertFontBase( const XclExpChRoot
& rRoot
, sal_uInt16 nFontIdx
)
1140 if( const XclExpFont
* pFont
= rRoot
.GetFontBuffer().GetFont( nFontIdx
) )
1142 XclExpChFontRef
xFont( new XclExpChFont( nFontIdx
) );
1143 SetFont( xFont
, pFont
->GetFontData().maColor
, pFont
->GetFontColorId() );
1147 void XclExpChFontBase::ConvertFontBase( const XclExpChRoot
& rRoot
, const ScfPropertySet
& rPropSet
)
1149 ConvertFontBase( rRoot
, rRoot
.ConvertFont( rPropSet
, rRoot
.GetDefApiScript() ) );
1152 void XclExpChFontBase::ConvertRotationBase(const ScfPropertySet
& rPropSet
, bool bSupportsStacked
)
1154 sal_uInt16 nRotation
= XclChPropSetHelper::ReadRotationProperties( rPropSet
, bSupportsStacked
);
1155 SetRotation( nRotation
);
1158 XclExpChText::XclExpChText( const XclExpChRoot
& rRoot
) :
1159 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_TEXT
, EXC_ID_CHTEXT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 32 : 26 ),
1160 mnTextColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
1164 void XclExpChText::SetFont( XclExpChFontRef xFont
, const Color
& rColor
, sal_uInt32 nColorId
)
1167 maData
.maTextColor
= rColor
;
1168 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOCOLOR
, rColor
== COL_AUTO
);
1169 mnTextColorId
= nColorId
;
1172 void XclExpChText::SetRotation( sal_uInt16 nRotation
)
1174 maData
.mnRotation
= nRotation
;
1175 ::insert_value( maData
.mnFlags
, XclTools::GetXclOrientFromRot( nRotation
), 8, 3 );
1178 void XclExpChText::ConvertTitle( Reference
< XTitle
> xTitle
, sal_uInt16 nTarget
, const OUString
* pSubTitle
)
1182 case EXC_CHOBJLINK_TITLE
: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_TITLE
); break;
1183 case EXC_CHOBJLINK_YAXIS
: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_AXISTITLE
, 1 ); break;
1184 case EXC_CHOBJLINK_XAXIS
: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_AXISTITLE
, 0 ); break;
1185 case EXC_CHOBJLINK_ZAXIS
: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_AXISTITLE
, 2 ); break;
1189 mxObjLink
.reset( new XclExpChObjectLink( nTarget
, XclChDataPointPos( 0, 0 ) ) );
1193 // title frame formatting
1194 ScfPropertySet
aTitleProp( xTitle
);
1195 mxFrame
= lclCreateFrame( GetChRoot(), aTitleProp
, EXC_CHOBJTYPE_TEXT
);
1198 mxSrcLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1199 sal_uInt16 nFontIdx
= mxSrcLink
->ConvertStringSequence( xTitle
->getText() );
1202 // append subtitle as the 2nd line of the title.
1203 OUString
aSubTitle("\n");
1204 aSubTitle
+= *pSubTitle
;
1205 mxSrcLink
->AppendString(aSubTitle
);
1208 ConvertFontBase( GetChRoot(), nFontIdx
);
1211 ConvertRotationBase( aTitleProp
, true );
1213 // manual text position - only for main title
1214 mxFramePos
.reset( new XclExpChFramePos( EXC_CHFRAMEPOS_PARENT
, EXC_CHFRAMEPOS_PARENT
) );
1215 if( nTarget
== EXC_CHOBJLINK_TITLE
)
1218 if( aTitleProp
.GetAnyProperty( aRelPos
, EXC_CHPROP_RELATIVEPOSITION
) && aRelPos
.has
< RelativePosition
>() ) try
1220 // calculate absolute position for CHTEXT record
1221 Reference
< cssc::XChartDocument
> xChart1Doc( GetChartDocument(), UNO_QUERY_THROW
);
1222 Reference
< XShape
> xTitleShape( xChart1Doc
->getTitle(), UNO_SET_THROW
);
1223 ::com::sun::star::awt::Point aPos
= xTitleShape
->getPosition();
1224 ::com::sun::star::awt::Size aSize
= xTitleShape
->getSize();
1225 ::com::sun::star::awt::Rectangle
aRect( aPos
.X
, aPos
.Y
, aSize
.Width
, aSize
.Height
);
1226 maData
.maRect
= CalcChartRectFromHmm( aRect
);
1227 ::insert_value( maData
.mnFlags2
, EXC_CHTEXT_POS_MOVED
, 0, 4 );
1228 // manual title position implies manual plot area
1229 GetChartData().SetManualPlotArea();
1230 // calculate the default title position in chart units
1231 sal_Int32 nDefPosX
= ::std::max
< sal_Int32
>( (EXC_CHART_TOTALUNITS
- maData
.maRect
.mnWidth
) / 2, 0 );
1232 sal_Int32 nDefPosY
= 85;
1233 // set the position relative to the standard position
1234 XclChRectangle
& rFrameRect
= mxFramePos
->GetFramePosData().maRect
;
1235 rFrameRect
.mnX
= maData
.maRect
.mnX
- nDefPosX
;
1236 rFrameRect
.mnY
= maData
.maRect
.mnY
- nDefPosY
;
1245 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_DELETED
);
1249 void XclExpChText::ConvertLegend( const ScfPropertySet
& rPropSet
)
1251 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOTEXT
);
1252 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOGEN
);
1253 ConvertFontBase( GetChRoot(), rPropSet
);
1256 bool XclExpChText::ConvertDataLabel( const ScfPropertySet
& rPropSet
,
1257 const XclChTypeInfo
& rTypeInfo
, const XclChDataPointPos
& rPointPos
)
1259 SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_DATALABEL
, rPointPos
.mnPointIdx
, rPointPos
.mnSeriesIdx
);
1261 cssc2::DataPointLabel aPointLabel
;
1262 if( !rPropSet
.GetProperty( aPointLabel
, EXC_CHPROP_LABEL
) )
1265 // percentage only allowed in pie and donut charts
1266 bool bIsPie
= rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
;
1267 // bubble sizes only allowed in bubble charts
1268 bool bIsBubble
= rTypeInfo
.meTypeId
== EXC_CHTYPEID_BUBBLES
;
1269 OSL_ENSURE( (GetBiff() == EXC_BIFF8
) || !bIsBubble
, "XclExpChText::ConvertDataLabel - bubble charts only in BIFF8" );
1272 bool bShowValue
= !bIsBubble
&& aPointLabel
.ShowNumber
; // Chart2 uses 'ShowNumber' for bubble size
1273 bool bShowPercent
= bIsPie
&& aPointLabel
.ShowNumberInPercent
; // percentage only in pie/donut charts
1274 bool bShowCateg
= aPointLabel
.ShowCategoryName
;
1275 bool bShowBubble
= bIsBubble
&& aPointLabel
.ShowNumber
; // Chart2 uses 'ShowNumber' for bubble size
1276 bool bShowAny
= bShowValue
|| bShowPercent
|| bShowCateg
|| bShowBubble
;
1278 // create the CHFRLABELPROPS record for extended settings in BIFF8
1279 if( bShowAny
&& (GetBiff() == EXC_BIFF8
) )
1281 mxLabelProps
.reset( new XclExpChFrLabelProps( GetChRoot() ) );
1282 mxLabelProps
->Convert( rPropSet
, false, bShowCateg
, bShowValue
, bShowPercent
, bShowBubble
);
1285 // restrict to combinations allowed in CHTEXT
1286 if( bShowPercent
) bShowValue
= false; // percent wins over value
1287 if( bShowValue
) bShowCateg
= false; // value wins over category
1288 if( bShowValue
|| bShowCateg
) bShowBubble
= false; // value or category wins over bubble size
1291 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOTEXT
);
1292 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWVALUE
, bShowValue
);
1293 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWPERCENT
, bShowPercent
);
1294 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
, bShowCateg
);
1295 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEGPERC
, bShowPercent
&& bShowCateg
);
1296 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWBUBBLE
, bShowBubble
);
1297 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWSYMBOL
, bShowAny
&& aPointLabel
.ShowLegendSymbol
);
1298 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_DELETED
, !bShowAny
);
1303 ConvertFontBase( GetChRoot(), rPropSet
);
1304 ConvertRotationBase( rPropSet
, false );
1306 sal_Int32 nPlacement
= 0;
1307 sal_uInt16 nLabelPos
= EXC_CHTEXT_POS_AUTO
;
1308 if( rPropSet
.GetProperty( nPlacement
, EXC_CHPROP_LABELPLACEMENT
) )
1310 using namespace cssc::DataLabelPlacement
;
1311 if( nPlacement
== rTypeInfo
.mnDefaultLabelPos
)
1313 nLabelPos
= EXC_CHTEXT_POS_DEFAULT
;
1315 else switch( nPlacement
)
1317 case AVOID_OVERLAP
: nLabelPos
= EXC_CHTEXT_POS_AUTO
; break;
1318 case CENTER
: nLabelPos
= EXC_CHTEXT_POS_CENTER
; break;
1319 case TOP
: nLabelPos
= EXC_CHTEXT_POS_ABOVE
; break;
1320 case TOP_LEFT
: nLabelPos
= EXC_CHTEXT_POS_LEFT
; break;
1321 case LEFT
: nLabelPos
= EXC_CHTEXT_POS_LEFT
; break;
1322 case BOTTOM_LEFT
: nLabelPos
= EXC_CHTEXT_POS_LEFT
; break;
1323 case BOTTOM
: nLabelPos
= EXC_CHTEXT_POS_BELOW
; break;
1324 case BOTTOM_RIGHT
: nLabelPos
= EXC_CHTEXT_POS_RIGHT
; break;
1325 case RIGHT
: nLabelPos
= EXC_CHTEXT_POS_RIGHT
; break;
1326 case TOP_RIGHT
: nLabelPos
= EXC_CHTEXT_POS_RIGHT
; break;
1327 case INSIDE
: nLabelPos
= EXC_CHTEXT_POS_INSIDE
; break;
1328 case OUTSIDE
: nLabelPos
= EXC_CHTEXT_POS_OUTSIDE
; break;
1329 case NEAR_ORIGIN
: nLabelPos
= EXC_CHTEXT_POS_AXIS
; break;
1330 default: OSL_FAIL( "XclExpChText::ConvertDataLabel - unknown label placement type" );
1333 ::insert_value( maData
.mnFlags2
, nLabelPos
, 0, 4 );
1334 // source link (contains number format)
1335 mxSrcLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1336 if( bShowValue
|| bShowPercent
)
1337 // percentage format wins over value format
1338 mxSrcLink
->ConvertNumFmt( rPropSet
, bShowPercent
);
1340 mxObjLink
.reset( new XclExpChObjectLink( EXC_CHOBJLINK_DATA
, rPointPos
) );
1343 /* Return true to indicate valid label settings:
1344 - for existing labels at entire series
1345 - for any settings at single data point (to be able to delete a point label) */
1346 return bShowAny
|| (rPointPos
.mnPointIdx
!= EXC_CHDATAFORMAT_ALLPOINTS
);
1349 void XclExpChText::ConvertTrendLineEquation( const ScfPropertySet
& rPropSet
, const XclChDataPointPos
& rPointPos
)
1352 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_AUTOTEXT
);
1353 if( GetBiff() == EXC_BIFF8
)
1354 ::set_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
); // must set this to make equation visible in Excel
1356 mxFrame
= lclCreateFrame( GetChRoot(), rPropSet
, EXC_CHOBJTYPE_TEXT
);
1358 maData
.mnHAlign
= EXC_CHTEXT_ALIGN_TOPLEFT
;
1359 maData
.mnVAlign
= EXC_CHTEXT_ALIGN_TOPLEFT
;
1360 ConvertFontBase( GetChRoot(), rPropSet
);
1361 // source link (contains number format)
1362 mxSrcLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1363 mxSrcLink
->ConvertNumFmt( rPropSet
, false );
1365 mxObjLink
.reset( new XclExpChObjectLink( EXC_CHOBJLINK_DATA
, rPointPos
) );
1368 sal_uInt16
XclExpChText::GetAttLabelFlags() const
1370 sal_uInt16 nFlags
= 0;
1371 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWVALUE
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWVALUE
) );
1372 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWPERCENT
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWPERCENT
) );
1373 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWCATEGPERC
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEGPERC
) );
1374 ::set_flag( nFlags
, EXC_CHATTLABEL_SHOWCATEG
, ::get_flag( maData
.mnFlags
, EXC_CHTEXT_SHOWCATEG
) );
1378 void XclExpChText::WriteSubRecords( XclExpStream
& rStrm
)
1380 // CHFRAMEPOS record
1381 lclSaveRecord( rStrm
, mxFramePos
);
1383 lclSaveRecord( rStrm
, mxFont
);
1384 // CHSOURCELINK group
1385 lclSaveRecord( rStrm
, mxSrcLink
);
1387 lclSaveRecord( rStrm
, mxFrame
);
1388 // CHOBJECTLINK record
1389 lclSaveRecord( rStrm
, mxObjLink
);
1390 // CHFRLABELPROPS record
1391 lclSaveRecord( rStrm
, mxLabelProps
);
1394 void XclExpChText::WriteBody( XclExpStream
& rStrm
)
1396 rStrm
<< maData
.mnHAlign
1398 << maData
.mnBackMode
1399 << maData
.maTextColor
1403 if( GetBiff() == EXC_BIFF8
)
1405 rStrm
<< GetPalette().GetColorIndex( mnTextColorId
)
1407 << maData
.mnRotation
;
1413 /** Creates and returns an Excel text object from the passed title. */
1414 XclExpChTextRef
lclCreateTitle( const XclExpChRoot
& rRoot
, Reference
< XTitled
> xTitled
, sal_uInt16 nTarget
,
1415 const OUString
* pSubTitle
= NULL
)
1417 Reference
< XTitle
> xTitle
;
1419 xTitle
= xTitled
->getTitleObject();
1421 XclExpChTextRef
xText( new XclExpChText( rRoot
) );
1422 xText
->ConvertTitle( xTitle
, nTarget
, pSubTitle
);
1423 /* Do not delete the CHTEXT group for the main title. A missing CHTEXT
1424 will be interpreted as auto-generated title showing the series title in
1425 charts that contain exactly one data series. */
1426 if( (nTarget
!= EXC_CHOBJLINK_TITLE
) && !xText
->HasString() )
1434 // Data series ================================================================
1436 XclExpChMarkerFormat::XclExpChMarkerFormat( const XclExpChRoot
& rRoot
) :
1437 XclExpRecord( EXC_ID_CHMARKERFORMAT
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 20 : 12 ),
1438 mnLineColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) ),
1439 mnFillColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK
) )
1443 void XclExpChMarkerFormat::Convert( const XclExpChRoot
& rRoot
,
1444 const ScfPropertySet
& rPropSet
, sal_uInt16 nFormatIdx
)
1446 XclChPropSetHelper::ReadMarkerProperties( maData
, rPropSet
, nFormatIdx
);
1447 /* Set marker line/fill color to series line color.
1448 TODO: remove this if OOChart supports own colors in markers. */
1450 if( rPropSet
.GetColorProperty( aLineColor
, EXC_CHPROP_COLOR
) )
1451 maData
.maLineColor
= maData
.maFillColor
= aLineColor
;
1452 // register colors in palette
1453 RegisterColors( rRoot
);
1456 void XclExpChMarkerFormat::ConvertStockSymbol( const XclExpChRoot
& rRoot
,
1457 const ScfPropertySet
& rPropSet
, bool bCloseSymbol
)
1459 // clear the automatic flag
1460 ::set_flag( maData
.mnFlags
, EXC_CHMARKERFORMAT_AUTO
, false );
1461 // symbol type and color
1464 // set symbol type for the 'close' data series
1465 maData
.mnMarkerType
= EXC_CHMARKERFORMAT_DOWJ
;
1466 maData
.mnMarkerSize
= EXC_CHMARKERFORMAT_DOUBLESIZE
;
1467 // set symbol line/fill color to series line color
1469 if( rPropSet
.GetColorProperty( aLineColor
, EXC_CHPROP_COLOR
) )
1471 maData
.maLineColor
= maData
.maFillColor
= aLineColor
;
1472 RegisterColors( rRoot
);
1477 // set invisible symbol
1478 maData
.mnMarkerType
= EXC_CHMARKERFORMAT_NOSYMBOL
;
1482 void XclExpChMarkerFormat::RegisterColors( const XclExpChRoot
& rRoot
)
1486 if( HasLineColor() )
1487 mnLineColorId
= rRoot
.GetPalette().InsertColor( maData
.maLineColor
, EXC_COLOR_CHARTLINE
);
1488 if( HasFillColor() )
1489 mnFillColorId
= rRoot
.GetPalette().InsertColor( maData
.maFillColor
, EXC_COLOR_CHARTAREA
);
1493 void XclExpChMarkerFormat::WriteBody( XclExpStream
& rStrm
)
1495 rStrm
<< maData
.maLineColor
<< maData
.maFillColor
<< maData
.mnMarkerType
<< maData
.mnFlags
;
1496 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
1498 const XclExpPalette
& rPal
= rStrm
.GetRoot().GetPalette();
1499 rStrm
<< rPal
.GetColorIndex( mnLineColorId
) << rPal
.GetColorIndex( mnFillColorId
) << maData
.mnMarkerSize
;
1503 XclExpChPieFormat::XclExpChPieFormat() :
1504 XclExpUInt16Record( EXC_ID_CHPIEFORMAT
, 0 )
1508 void XclExpChPieFormat::Convert( const ScfPropertySet
& rPropSet
)
1510 double fApiDist(0.0);
1511 if( rPropSet
.GetProperty( fApiDist
, EXC_CHPROP_OFFSET
) )
1512 SetValue( limit_cast
< sal_uInt16
>( fApiDist
* 100.0, 0, 100 ) );
1515 XclExpCh3dDataFormat::XclExpCh3dDataFormat() :
1516 XclExpRecord( EXC_ID_CH3DDATAFORMAT
, 2 )
1520 void XclExpCh3dDataFormat::Convert( const ScfPropertySet
& rPropSet
)
1522 sal_Int32
nApiType(0);
1523 if( rPropSet
.GetProperty( nApiType
, EXC_CHPROP_GEOMETRY3D
) )
1525 using namespace cssc2::DataPointGeometry3D
;
1529 maData
.mnBase
= EXC_CH3DDATAFORMAT_RECT
;
1530 maData
.mnTop
= EXC_CH3DDATAFORMAT_STRAIGHT
;
1533 maData
.mnBase
= EXC_CH3DDATAFORMAT_RECT
;
1534 maData
.mnTop
= EXC_CH3DDATAFORMAT_SHARP
;
1537 maData
.mnBase
= EXC_CH3DDATAFORMAT_CIRC
;
1538 maData
.mnTop
= EXC_CH3DDATAFORMAT_STRAIGHT
;
1541 maData
.mnBase
= EXC_CH3DDATAFORMAT_CIRC
;
1542 maData
.mnTop
= EXC_CH3DDATAFORMAT_SHARP
;
1545 OSL_FAIL( "XclExpCh3dDataFormat::Convert - unknown 3D bar format" );
1550 void XclExpCh3dDataFormat::WriteBody( XclExpStream
& rStrm
)
1552 rStrm
<< maData
.mnBase
<< maData
.mnTop
;
1555 XclExpChAttachedLabel::XclExpChAttachedLabel( sal_uInt16 nFlags
) :
1556 XclExpUInt16Record( EXC_ID_CHATTACHEDLABEL
, nFlags
)
1560 XclExpChDataFormat::XclExpChDataFormat( const XclExpChRoot
& rRoot
,
1561 const XclChDataPointPos
& rPointPos
, sal_uInt16 nFormatIdx
) :
1562 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_DATAFORMAT
, EXC_ID_CHDATAFORMAT
, 8 )
1564 maData
.maPointPos
= rPointPos
;
1565 maData
.mnFormatIdx
= nFormatIdx
;
1568 void XclExpChDataFormat::ConvertDataSeries( const ScfPropertySet
& rPropSet
, const XclChExtTypeInfo
& rTypeInfo
)
1570 // line and area formatting
1571 ConvertFrameBase( GetChRoot(), rPropSet
, rTypeInfo
.GetSeriesObjectType() );
1573 // data point symbols
1574 bool bIsFrame
= rTypeInfo
.IsSeriesFrameFormat();
1577 mxMarkerFmt
.reset( new XclExpChMarkerFormat( GetChRoot() ) );
1578 mxMarkerFmt
->Convert( GetChRoot(), rPropSet
, maData
.mnFormatIdx
);
1582 if( rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
)
1584 mxPieFmt
.reset( new XclExpChPieFormat
);
1585 mxPieFmt
->Convert( rPropSet
);
1588 // 3D bars (only allowed for entire series in BIFF8)
1589 if( IsSeriesFormat() && (GetBiff() == EXC_BIFF8
) && rTypeInfo
.mb3dChart
&& (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_BAR
) )
1591 mx3dDataFmt
.reset( new XclExpCh3dDataFormat
);
1592 mx3dDataFmt
->Convert( rPropSet
);
1596 if( IsSeriesFormat() && rTypeInfo
.mbSpline
&& !bIsFrame
)
1597 mxSeriesFmt
.reset( new XclExpUInt16Record( EXC_ID_CHSERIESFORMAT
, EXC_CHSERIESFORMAT_SMOOTHED
) );
1599 // data point labels
1600 XclExpChTextRef
xLabel( new XclExpChText( GetChRoot() ) );
1601 if( xLabel
->ConvertDataLabel( rPropSet
, rTypeInfo
, maData
.maPointPos
) )
1603 // CHTEXT groups for data labels are stored in global CHCHART group
1604 GetChartData().SetDataLabel( xLabel
);
1605 mxAttLabel
.reset( new XclExpChAttachedLabel( xLabel
->GetAttLabelFlags() ) );
1609 void XclExpChDataFormat::ConvertStockSeries( const ScfPropertySet
& rPropSet
, bool bCloseSymbol
)
1611 // set line format to invisible
1612 SetDefaultFrameBase( GetChRoot(), EXC_CHFRAMETYPE_INVISIBLE
, false );
1613 // set symbols to invisible or to 'close' series symbol
1614 mxMarkerFmt
.reset( new XclExpChMarkerFormat( GetChRoot() ) );
1615 mxMarkerFmt
->ConvertStockSymbol( GetChRoot(), rPropSet
, bCloseSymbol
);
1618 void XclExpChDataFormat::ConvertLine( const ScfPropertySet
& rPropSet
, XclChObjectType eObjType
)
1620 ConvertFrameBase( GetChRoot(), rPropSet
, eObjType
);
1623 void XclExpChDataFormat::WriteSubRecords( XclExpStream
& rStrm
)
1625 lclSaveRecord( rStrm
, mx3dDataFmt
);
1626 WriteFrameRecords( rStrm
);
1627 lclSaveRecord( rStrm
, mxPieFmt
);
1628 lclSaveRecord( rStrm
, mxMarkerFmt
);
1629 lclSaveRecord( rStrm
, mxSeriesFmt
);
1630 lclSaveRecord( rStrm
, mxAttLabel
);
1633 void XclExpChDataFormat::WriteBody( XclExpStream
& rStrm
)
1635 rStrm
<< maData
.maPointPos
.mnPointIdx
1636 << maData
.maPointPos
.mnSeriesIdx
1637 << maData
.mnFormatIdx
1641 XclExpChSerTrendLine::XclExpChSerTrendLine( const XclExpChRoot
& rRoot
) :
1642 XclExpRecord( EXC_ID_CHSERTRENDLINE
, 28 ),
1643 XclExpChRoot( rRoot
)
1647 bool XclExpChSerTrendLine::Convert( Reference
< XRegressionCurve
> xRegCurve
, sal_uInt16 nSeriesIdx
)
1649 if( !xRegCurve
.is() )
1653 ScfPropertySet
aCurveProp( xRegCurve
);
1655 OUString aService
= aCurveProp
.GetServiceName();
1656 if( aService
== "com.sun.star.chart2.LinearRegressionCurve" )
1658 maData
.mnLineType
= EXC_CHSERTREND_POLYNOMIAL
;
1661 else if( aService
== "com.sun.star.chart2.ExponentialRegressionCurve" )
1663 maData
.mnLineType
= EXC_CHSERTREND_EXPONENTIAL
;
1665 else if( aService
== "com.sun.star.chart2.LogarithmicRegressionCurve" )
1667 maData
.mnLineType
= EXC_CHSERTREND_LOGARITHMIC
;
1669 else if( aService
== "com.sun.star.chart2.PotentialRegressionCurve" )
1671 maData
.mnLineType
= EXC_CHSERTREND_POWER
;
1673 else if( aService
== "com.sun.star.chart2.PolynomialRegressionCurve" )
1675 maData
.mnLineType
= EXC_CHSERTREND_POLYNOMIAL
;
1677 aCurveProp
.GetProperty(aDegree
, EXC_CHPROP_POLYNOMIAL_DEGREE
);
1678 maData
.mnOrder
= static_cast<sal_uInt8
> (aDegree
);
1680 else if( aService
== "com.sun.star.chart2.MovingAverageRegressionCurve" )
1682 maData
.mnLineType
= EXC_CHSERTREND_MOVING_AVG
;
1684 aCurveProp
.GetProperty(aPeriod
, EXC_CHPROP_MOVING_AVERAGE_PERIOD
);
1685 maData
.mnOrder
= static_cast<sal_uInt8
> (aPeriod
);
1692 aCurveProp
.GetProperty(maData
.mfForecastFor
, EXC_CHPROP_EXTRAPOLATE_FORWARD
);
1693 aCurveProp
.GetProperty(maData
.mfForecastBack
, EXC_CHPROP_EXTRAPOLATE_BACKWARD
);
1694 bool bIsForceIntercept
= false;
1695 aCurveProp
.GetProperty(bIsForceIntercept
, EXC_CHPROP_FORCE_INTERCEPT
);
1696 if (bIsForceIntercept
)
1697 aCurveProp
.GetProperty(maData
.mfIntercept
, EXC_CHPROP_INTERCEPT_VALUE
);
1700 XclChDataPointPos
aPointPos( nSeriesIdx
);
1701 mxDataFmt
.reset( new XclExpChDataFormat( GetChRoot(), aPointPos
, 0 ) );
1702 mxDataFmt
->ConvertLine( aCurveProp
, EXC_CHOBJTYPE_TRENDLINE
);
1704 // #i83100# show equation and correlation coefficient
1705 ScfPropertySet
aEquationProp( xRegCurve
->getEquationProperties() );
1706 maData
.mnShowEquation
= aEquationProp
.GetBoolProperty( EXC_CHPROP_SHOWEQUATION
) ? 1 : 0;
1707 maData
.mnShowRSquared
= aEquationProp
.GetBoolProperty( EXC_CHPROP_SHOWCORRELATION
) ? 1 : 0;
1709 // #i83100# formatting of the equation text box
1710 if( (maData
.mnShowEquation
!= 0) || (maData
.mnShowRSquared
!= 0) )
1712 mxLabel
.reset( new XclExpChText( GetChRoot() ) );
1713 mxLabel
->ConvertTrendLineEquation( aEquationProp
, aPointPos
);
1717 // #i5085# manual trend line size
1718 // #i34093# manual crossing point
1722 void XclExpChSerTrendLine::WriteBody( XclExpStream
& rStrm
)
1724 rStrm
<< maData
.mnLineType
1726 << maData
.mfIntercept
1727 << maData
.mnShowEquation
1728 << maData
.mnShowRSquared
1729 << maData
.mfForecastFor
1730 << maData
.mfForecastBack
;
1733 XclExpChSerErrorBar::XclExpChSerErrorBar( const XclExpChRoot
& rRoot
, sal_uInt8 nBarType
) :
1734 XclExpRecord( EXC_ID_CHSERERRORBAR
, 14 ),
1735 XclExpChRoot( rRoot
)
1737 maData
.mnBarType
= nBarType
;
1740 bool XclExpChSerErrorBar::Convert( XclExpChSourceLink
& rValueLink
, sal_uInt16
& rnValueCount
, const ScfPropertySet
& rPropSet
)
1742 sal_Int32 nBarStyle
= 0;
1743 bool bOk
= rPropSet
.GetProperty( nBarStyle
, EXC_CHPROP_ERRORBARSTYLE
);
1748 case cssc::ErrorBarStyle::ABSOLUTE
:
1749 maData
.mnSourceType
= EXC_CHSERERR_FIXED
;
1750 rPropSet
.GetProperty( maData
.mfValue
, EXC_CHPROP_POSITIVEERROR
);
1752 case cssc::ErrorBarStyle::RELATIVE
:
1753 maData
.mnSourceType
= EXC_CHSERERR_PERCENT
;
1754 rPropSet
.GetProperty( maData
.mfValue
, EXC_CHPROP_POSITIVEERROR
);
1756 case cssc::ErrorBarStyle::STANDARD_DEVIATION
:
1757 maData
.mnSourceType
= EXC_CHSERERR_STDDEV
;
1758 rPropSet
.GetProperty( maData
.mfValue
, EXC_CHPROP_WEIGHT
);
1760 case cssc::ErrorBarStyle::STANDARD_ERROR
:
1761 maData
.mnSourceType
= EXC_CHSERERR_STDERR
;
1763 case cssc::ErrorBarStyle::FROM_DATA
:
1766 maData
.mnSourceType
= EXC_CHSERERR_CUSTOM
;
1767 Reference
< XDataSource
> xDataSource( rPropSet
.GetApiPropertySet(), UNO_QUERY
);
1768 if( xDataSource
.is() )
1770 // find first sequence with current role
1771 OUString aRole
= XclChartHelper::GetErrorBarValuesRole( maData
.mnBarType
);
1772 Reference
< XDataSequence
> xValueSeq
;
1774 Sequence
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
= xDataSource
->getDataSequences();
1775 const Reference
< XLabeledDataSequence
>* pBeg
= aLabeledSeqVec
.getConstArray();
1776 const Reference
< XLabeledDataSequence
>* pEnd
= pBeg
+ aLabeledSeqVec
.getLength();
1777 for( const Reference
< XLabeledDataSequence
>* pIt
= pBeg
; !xValueSeq
.is() && (pIt
!= pEnd
); ++pIt
)
1779 Reference
< XDataSequence
> xTmpValueSeq
= (*pIt
)->getValues();
1780 ScfPropertySet
aValueProp( xTmpValueSeq
);
1782 if( aValueProp
.GetProperty( aCurrRole
, EXC_CHPROP_ROLE
) && (aCurrRole
== aRole
) )
1783 xValueSeq
= xTmpValueSeq
;
1785 if( xValueSeq
.is() )
1787 // #i86465# pass value count back to series
1788 rnValueCount
= maData
.mnValueCount
= rValueLink
.ConvertDataSequence( xValueSeq
, true );
1789 bOk
= maData
.mnValueCount
> 0;
1801 void XclExpChSerErrorBar::WriteBody( XclExpStream
& rStrm
)
1803 rStrm
<< maData
.mnBarType
1804 << maData
.mnSourceType
1806 << sal_uInt8( 1 ) // must be 1 to make line visible
1808 << maData
.mnValueCount
;
1813 /** Returns the property set of the specified data point. */
1814 ScfPropertySet
lclGetPointPropSet( Reference
< XDataSeries
> xDataSeries
, sal_Int32 nPointIdx
)
1816 ScfPropertySet aPropSet
;
1819 aPropSet
.Set( xDataSeries
->getDataPointByIndex( nPointIdx
) );
1823 OSL_FAIL( "lclGetPointPropSet - no data point property set" );
1830 XclExpChSeries::XclExpChSeries( const XclExpChRoot
& rRoot
, sal_uInt16 nSeriesIdx
) :
1831 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_SERIES
, EXC_ID_CHSERIES
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 12 : 8 ),
1832 mnGroupIdx( EXC_CHSERGROUP_NONE
),
1833 mnSeriesIdx( nSeriesIdx
),
1834 mnParentIdx( EXC_CHSERIES_INVALID
)
1836 // CHSOURCELINK records are always required, even if unused
1837 mxTitleLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE
) );
1838 mxValueLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_VALUES
) );
1839 mxCategLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_CATEGORY
) );
1840 if( GetBiff() == EXC_BIFF8
)
1841 mxBubbleLink
.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_BUBBLES
) );
1844 bool XclExpChSeries::ConvertDataSeries(
1845 Reference
< XDiagram
> xDiagram
, Reference
< XDataSeries
> xDataSeries
,
1846 const XclChExtTypeInfo
& rTypeInfo
, sal_uInt16 nGroupIdx
, sal_uInt16 nFormatIdx
)
1849 Reference
< XDataSource
> xDataSource( xDataSeries
, UNO_QUERY
);
1850 if( xDataSource
.is() )
1852 Reference
< XDataSequence
> xYValueSeq
, xTitleSeq
, xXValueSeq
, xBubbleSeq
;
1854 // find first sequence with role 'values-y'
1855 Sequence
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
= xDataSource
->getDataSequences();
1856 const Reference
< XLabeledDataSequence
>* pBeg
= aLabeledSeqVec
.getConstArray();
1857 const Reference
< XLabeledDataSequence
>* pEnd
= pBeg
+ aLabeledSeqVec
.getLength();
1858 for( const Reference
< XLabeledDataSequence
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
1860 Reference
< XDataSequence
> xTmpValueSeq
= (*pIt
)->getValues();
1861 ScfPropertySet
aValueProp( xTmpValueSeq
);
1863 if( aValueProp
.GetProperty( aRole
, EXC_CHPROP_ROLE
) )
1865 if( !xYValueSeq
.is() && (aRole
== EXC_CHPROP_ROLE_YVALUES
) )
1867 xYValueSeq
= xTmpValueSeq
;
1868 if( !xTitleSeq
.is() )
1869 xTitleSeq
= (*pIt
)->getLabel(); // ignore role of label sequence
1871 else if( !xXValueSeq
.is() && !rTypeInfo
.mbCategoryAxis
&& (aRole
== EXC_CHPROP_ROLE_XVALUES
) )
1873 xXValueSeq
= xTmpValueSeq
;
1875 else if( !xBubbleSeq
.is() && (rTypeInfo
.meTypeId
== EXC_CHTYPEID_BUBBLES
) && (aRole
== EXC_CHPROP_ROLE_SIZEVALUES
) )
1877 xBubbleSeq
= xTmpValueSeq
;
1878 xTitleSeq
= (*pIt
)->getLabel(); // ignore role of label sequence
1883 bOk
= xYValueSeq
.is();
1886 // chart type group index
1887 mnGroupIdx
= nGroupIdx
;
1889 // convert source links
1890 maData
.mnValueCount
= mxValueLink
->ConvertDataSequence( xYValueSeq
, true );
1891 mxTitleLink
->ConvertDataSequence( xTitleSeq
, true );
1893 // X values of XY charts
1894 maData
.mnCategCount
= mxCategLink
->ConvertDataSequence( xXValueSeq
, false, maData
.mnValueCount
);
1896 // size values of bubble charts
1898 mxBubbleLink
->ConvertDataSequence( xBubbleSeq
, false, maData
.mnValueCount
);
1900 // series formatting
1901 XclChDataPointPos
aPointPos( mnSeriesIdx
);
1902 ScfPropertySet
aSeriesProp( xDataSeries
);
1903 mxSeriesFmt
.reset( new XclExpChDataFormat( GetChRoot(), aPointPos
, nFormatIdx
) );
1904 mxSeriesFmt
->ConvertDataSeries( aSeriesProp
, rTypeInfo
);
1907 CreateTrendLines( xDataSeries
);
1910 CreateErrorBars( aSeriesProp
, EXC_CHPROP_ERRORBARX
, EXC_CHSERERR_XPLUS
, EXC_CHSERERR_XMINUS
);
1911 CreateErrorBars( aSeriesProp
, EXC_CHPROP_ERRORBARY
, EXC_CHSERERR_YPLUS
, EXC_CHSERERR_YMINUS
);
1913 if( maData
.mnValueCount
> 0 )
1915 const sal_Int32 nMaxPointCount
= maData
.mnValueCount
;
1917 /* #i91063# Create missing fill properties in pie/doughnut charts.
1918 If freshly created (never saved to ODF), these charts show
1919 varying point colors but do not return these points via API. */
1920 if( xDiagram
.is() && (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_PIE
) )
1922 Reference
< XColorScheme
> xColorScheme
= xDiagram
->getDefaultColorScheme();
1923 if( xColorScheme
.is() )
1925 const OUString aFillStyleName
= "FillStyle";
1926 const OUString aColorName
= "Color";
1927 namespace cssd
= ::com::sun::star::drawing
;
1928 for( sal_Int32 nPointIdx
= 0; nPointIdx
< nMaxPointCount
; ++nPointIdx
)
1930 aPointPos
.mnPointIdx
= static_cast< sal_uInt16
>( nPointIdx
);
1931 ScfPropertySet aPointProp
= lclGetPointPropSet( xDataSeries
, nPointIdx
);
1932 // test that the point fill style is solid, but no color is set
1933 cssd::FillStyle eFillStyle
= cssd::FillStyle_NONE
;
1934 if( aPointProp
.GetProperty( eFillStyle
, aFillStyleName
) &&
1935 (eFillStyle
== cssd::FillStyle_SOLID
) &&
1936 !aPointProp
.HasProperty( aColorName
) )
1938 aPointProp
.SetProperty( aColorName
, xColorScheme
->getColorByIndex( nPointIdx
) );
1944 // data point formatting
1945 Sequence
< sal_Int32
> aPointIndexes
;
1946 if( aSeriesProp
.GetProperty( aPointIndexes
, EXC_CHPROP_ATTRIBDATAPOINTS
) && aPointIndexes
.hasElements() )
1948 const sal_Int32
* pnBeg
= aPointIndexes
.getConstArray();
1949 const sal_Int32
* pnEnd
= pnBeg
+ aPointIndexes
.getLength();
1950 for( const sal_Int32
* pnIt
= pnBeg
; (pnIt
!= pnEnd
) && (*pnIt
< nMaxPointCount
); ++pnIt
)
1952 aPointPos
.mnPointIdx
= static_cast< sal_uInt16
>( *pnIt
);
1953 ScfPropertySet aPointProp
= lclGetPointPropSet( xDataSeries
, *pnIt
);
1954 XclExpChDataFormatRef
xPointFmt( new XclExpChDataFormat( GetChRoot(), aPointPos
, nFormatIdx
) );
1955 xPointFmt
->ConvertDataSeries( aPointProp
, rTypeInfo
);
1956 maPointFmts
.AppendRecord( xPointFmt
);
1965 bool XclExpChSeries::ConvertStockSeries( XDataSeriesRef xDataSeries
,
1966 const OUString
& rValueRole
, sal_uInt16 nGroupIdx
, sal_uInt16 nFormatIdx
, bool bCloseSymbol
)
1969 Reference
< XDataSource
> xDataSource( xDataSeries
, UNO_QUERY
);
1970 if( xDataSource
.is() )
1972 Reference
< XDataSequence
> xYValueSeq
, xTitleSeq
;
1974 // find first sequence with passed role
1975 Sequence
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
= xDataSource
->getDataSequences();
1976 const Reference
< XLabeledDataSequence
>* pBeg
= aLabeledSeqVec
.getConstArray();
1977 const Reference
< XLabeledDataSequence
>* pEnd
= pBeg
+ aLabeledSeqVec
.getLength();
1978 for( const Reference
< XLabeledDataSequence
>* pIt
= pBeg
; !xYValueSeq
.is() && (pIt
!= pEnd
); ++pIt
)
1980 Reference
< XDataSequence
> xTmpValueSeq
= (*pIt
)->getValues();
1981 ScfPropertySet
aValueProp( xTmpValueSeq
);
1983 if( aValueProp
.GetProperty( aRole
, EXC_CHPROP_ROLE
) && (aRole
== rValueRole
) )
1985 xYValueSeq
= xTmpValueSeq
;
1986 xTitleSeq
= (*pIt
)->getLabel(); // ignore role of label sequence
1990 bOk
= xYValueSeq
.is();
1993 // chart type group index
1994 mnGroupIdx
= nGroupIdx
;
1995 // convert source links
1996 maData
.mnValueCount
= mxValueLink
->ConvertDataSequence( xYValueSeq
, true );
1997 mxTitleLink
->ConvertDataSequence( xTitleSeq
, true );
1998 // series formatting
1999 ScfPropertySet
aSeriesProp( xDataSeries
);
2000 mxSeriesFmt
.reset( new XclExpChDataFormat( GetChRoot(), XclChDataPointPos( mnSeriesIdx
), nFormatIdx
) );
2001 mxSeriesFmt
->ConvertStockSeries( aSeriesProp
, bCloseSymbol
);
2007 bool XclExpChSeries::ConvertTrendLine( const XclExpChSeries
& rParent
, Reference
< XRegressionCurve
> xRegCurve
)
2009 InitFromParent( rParent
);
2011 mxTrendLine
.reset( new XclExpChSerTrendLine( GetChRoot() ) );
2012 bool bOk
= mxTrendLine
->Convert( xRegCurve
, mnSeriesIdx
);
2016 ScfPropertySet
aProperties( xRegCurve
);
2017 aProperties
.GetProperty(aName
, EXC_CHPROP_CURVENAME
);
2018 mxTitleLink
->ConvertString(aName
);
2020 mxSeriesFmt
= mxTrendLine
->GetDataFormat();
2021 GetChartData().SetDataLabel( mxTrendLine
->GetDataLabel() );
2026 bool XclExpChSeries::ConvertErrorBar( const XclExpChSeries
& rParent
, const ScfPropertySet
& rPropSet
, sal_uInt8 nBarId
)
2028 InitFromParent( rParent
);
2029 // error bar settings
2030 mxErrorBar
.reset( new XclExpChSerErrorBar( GetChRoot(), nBarId
) );
2031 bool bOk
= mxErrorBar
->Convert( *mxValueLink
, maData
.mnValueCount
, rPropSet
);
2034 // error bar formatting
2035 mxSeriesFmt
.reset( new XclExpChDataFormat( GetChRoot(), XclChDataPointPos( mnSeriesIdx
), 0 ) );
2036 mxSeriesFmt
->ConvertLine( rPropSet
, EXC_CHOBJTYPE_ERRORBAR
);
2041 void XclExpChSeries::ConvertCategSequence( Reference
< XLabeledDataSequence
> xCategSeq
)
2043 if( xCategSeq
.is() )
2044 maData
.mnCategCount
= mxCategLink
->ConvertDataSequence( xCategSeq
->getValues(), false );
2047 void XclExpChSeries::WriteSubRecords( XclExpStream
& rStrm
)
2049 lclSaveRecord( rStrm
, mxTitleLink
);
2050 lclSaveRecord( rStrm
, mxValueLink
);
2051 lclSaveRecord( rStrm
, mxCategLink
);
2052 lclSaveRecord( rStrm
, mxBubbleLink
);
2053 lclSaveRecord( rStrm
, mxSeriesFmt
);
2054 maPointFmts
.Save( rStrm
);
2055 if( mnGroupIdx
!= EXC_CHSERGROUP_NONE
)
2056 XclExpUInt16Record( EXC_ID_CHSERGROUP
, mnGroupIdx
).Save( rStrm
);
2057 if( mnParentIdx
!= EXC_CHSERIES_INVALID
)
2058 XclExpUInt16Record( EXC_ID_CHSERPARENT
, mnParentIdx
).Save( rStrm
);
2059 lclSaveRecord( rStrm
, mxTrendLine
);
2060 lclSaveRecord( rStrm
, mxErrorBar
);
2063 void XclExpChSeries::InitFromParent( const XclExpChSeries
& rParent
)
2065 // index to parent series is stored 1-based
2066 mnParentIdx
= rParent
.mnSeriesIdx
+ 1;
2067 /* #i86465# MSO2007 SP1 expects correct point counts in child series
2068 (there was no problem in Excel2003 or Excel2007 without SP1...) */
2069 maData
.mnCategCount
= rParent
.maData
.mnCategCount
;
2070 maData
.mnValueCount
= rParent
.maData
.mnValueCount
;
2073 void XclExpChSeries::CreateTrendLines( XDataSeriesRef xDataSeries
)
2075 Reference
< XRegressionCurveContainer
> xRegCurveCont( xDataSeries
, UNO_QUERY
);
2076 if( xRegCurveCont
.is() )
2078 Sequence
< Reference
< XRegressionCurve
> > aRegCurveSeq
= xRegCurveCont
->getRegressionCurves();
2079 const Reference
< XRegressionCurve
>* pBeg
= aRegCurveSeq
.getConstArray();
2080 const Reference
< XRegressionCurve
>* pEnd
= pBeg
+ aRegCurveSeq
.getLength();
2081 for( const Reference
< XRegressionCurve
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
2083 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
2084 if( xSeries
&& !xSeries
->ConvertTrendLine( *this, *pIt
) )
2085 GetChartData().RemoveLastSeries();
2090 void XclExpChSeries::CreateErrorBars( const ScfPropertySet
& rPropSet
,
2091 const OUString
& rBarPropName
, sal_uInt8 nPosBarId
, sal_uInt8 nNegBarId
)
2093 Reference
< XPropertySet
> xErrorBar
;
2094 if( rPropSet
.GetProperty( xErrorBar
, rBarPropName
) && xErrorBar
.is() )
2096 ScfPropertySet
aErrorProp( xErrorBar
);
2097 CreateErrorBar( aErrorProp
, EXC_CHPROP_SHOWPOSITIVEERROR
, nPosBarId
);
2098 CreateErrorBar( aErrorProp
, EXC_CHPROP_SHOWNEGATIVEERROR
, nNegBarId
);
2102 void XclExpChSeries::CreateErrorBar( const ScfPropertySet
& rPropSet
,
2103 const OUString
& rShowPropName
, sal_uInt8 nBarId
)
2105 if( rPropSet
.GetBoolProperty( rShowPropName
) )
2107 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
2108 if( xSeries
&& !xSeries
->ConvertErrorBar( *this, rPropSet
, nBarId
) )
2109 GetChartData().RemoveLastSeries();
2113 void XclExpChSeries::WriteBody( XclExpStream
& rStrm
)
2115 rStrm
<< maData
.mnCategType
<< maData
.mnValueType
<< maData
.mnCategCount
<< maData
.mnValueCount
;
2116 if( GetBiff() == EXC_BIFF8
)
2117 rStrm
<< maData
.mnBubbleType
<< maData
.mnBubbleCount
;
2120 // Chart type groups ==========================================================
2122 XclExpChType::XclExpChType( const XclExpChRoot
& rRoot
) :
2123 XclExpRecord( EXC_ID_CHUNKNOWN
),
2124 XclExpChRoot( rRoot
),
2125 maTypeInfo( rRoot
.GetChartTypeInfo( EXC_CHTYPEID_UNKNOWN
) )
2129 void XclExpChType::Convert( Reference
< XDiagram
> xDiagram
, Reference
< XChartType
> xChartType
,
2130 sal_Int32 nApiAxesSetIdx
, bool bSwappedAxesSet
, bool bHasXLabels
)
2132 if( xChartType
.is() )
2134 maTypeInfo
= GetChartTypeInfo( xChartType
->getChartType() );
2135 // special handling for some chart types
2136 switch( maTypeInfo
.meTypeCateg
)
2138 case EXC_CHTYPECATEG_BAR
:
2140 maTypeInfo
= GetChartTypeInfo( bSwappedAxesSet
? EXC_CHTYPEID_HORBAR
: EXC_CHTYPEID_BAR
);
2141 ::set_flag( maData
.mnFlags
, EXC_CHBAR_HORIZONTAL
, bSwappedAxesSet
);
2142 ScfPropertySet
aTypeProp( xChartType
);
2143 Sequence
< sal_Int32
> aInt32Seq
;
2144 maData
.mnOverlap
= 0;
2145 if( aTypeProp
.GetProperty( aInt32Seq
, EXC_CHPROP_OVERLAPSEQ
) && (nApiAxesSetIdx
< aInt32Seq
.getLength()) )
2146 maData
.mnOverlap
= limit_cast
< sal_Int16
>( -aInt32Seq
[ nApiAxesSetIdx
], -100, 100 );
2148 if( aTypeProp
.GetProperty( aInt32Seq
, EXC_CHPROP_GAPWIDTHSEQ
) && (nApiAxesSetIdx
< aInt32Seq
.getLength()) )
2149 maData
.mnGap
= limit_cast
< sal_uInt16
>( aInt32Seq
[ nApiAxesSetIdx
], 0, 500 );
2152 case EXC_CHTYPECATEG_RADAR
:
2153 ::set_flag( maData
.mnFlags
, EXC_CHRADAR_AXISLABELS
, bHasXLabels
);
2155 case EXC_CHTYPECATEG_PIE
:
2157 ScfPropertySet
aTypeProp( xChartType
);
2158 bool bDonut
= aTypeProp
.GetBoolProperty( EXC_CHPROP_USERINGS
);
2159 maTypeInfo
= GetChartTypeInfo( bDonut
? EXC_CHTYPEID_DONUT
: EXC_CHTYPEID_PIE
);
2160 maData
.mnPieHole
= bDonut
? 50 : 0;
2161 // #i85166# starting angle of first pie slice
2162 ScfPropertySet
aDiaProp( xDiagram
);
2163 maData
.mnRotation
= XclExpChRoot::ConvertPieRotation( aDiaProp
);
2166 case EXC_CHTYPECATEG_SCATTER
:
2167 if( GetBiff() == EXC_BIFF8
)
2168 ::set_flag( maData
.mnFlags
, EXC_CHSCATTER_BUBBLES
, maTypeInfo
.meTypeId
== EXC_CHTYPEID_BUBBLES
);
2172 SetRecId( maTypeInfo
.mnRecId
);
2176 void XclExpChType::SetStacked( bool bPercent
)
2178 switch( maTypeInfo
.meTypeCateg
)
2180 case EXC_CHTYPECATEG_LINE
:
2181 ::set_flag( maData
.mnFlags
, EXC_CHLINE_STACKED
);
2182 ::set_flag( maData
.mnFlags
, EXC_CHLINE_PERCENT
, bPercent
);
2184 case EXC_CHTYPECATEG_BAR
:
2185 ::set_flag( maData
.mnFlags
, EXC_CHBAR_STACKED
);
2186 ::set_flag( maData
.mnFlags
, EXC_CHBAR_PERCENT
, bPercent
);
2187 maData
.mnOverlap
= -100;
2193 void XclExpChType::WriteBody( XclExpStream
& rStrm
)
2195 switch( GetRecId() )
2198 rStrm
<< maData
.mnOverlap
<< maData
.mnGap
<< maData
.mnFlags
;
2203 case EXC_ID_CHRADARLINE
:
2204 case EXC_ID_CHRADARAREA
:
2205 rStrm
<< maData
.mnFlags
;
2209 rStrm
<< maData
.mnRotation
<< maData
.mnPieHole
;
2210 if( GetBiff() == EXC_BIFF8
)
2211 rStrm
<< maData
.mnFlags
;
2214 case EXC_ID_CHSCATTER
:
2215 if( GetBiff() == EXC_BIFF8
)
2216 rStrm
<< maData
.mnBubbleSize
<< maData
.mnBubbleType
<< maData
.mnFlags
;
2220 OSL_FAIL( "XclExpChType::WriteBody - unknown chart type" );
2224 XclExpChChart3d::XclExpChChart3d() :
2225 XclExpRecord( EXC_ID_CHCHART3D
, 14 )
2229 void XclExpChChart3d::Convert( const ScfPropertySet
& rPropSet
, bool b3dWallChart
)
2231 sal_Int32 nRotationY
= 0;
2232 rPropSet
.GetProperty( nRotationY
, EXC_CHPROP_ROTATIONVERTICAL
);
2233 sal_Int32 nRotationX
= 0;
2234 rPropSet
.GetProperty( nRotationX
, EXC_CHPROP_ROTATIONHORIZONTAL
);
2235 sal_Int32 nPerspective
= 15;
2236 rPropSet
.GetProperty( nPerspective
, EXC_CHPROP_PERSPECTIVE
);
2240 // Y rotation (Excel [0..359], Chart2 [-179,180])
2241 if( nRotationY
< 0 ) nRotationY
+= 360;
2242 maData
.mnRotation
= static_cast< sal_uInt16
>( nRotationY
);
2243 // X rotation a.k.a. elevation (Excel [-90..90], Chart2 [-179,180])
2244 maData
.mnElevation
= limit_cast
< sal_Int16
>( nRotationX
, -90, 90 );
2245 // perspective (Excel and Chart2 [0,100])
2246 maData
.mnEyeDist
= limit_cast
< sal_uInt16
>( nPerspective
, 0, 100 );
2249 ::set_flag( maData
.mnFlags
, EXC_CHCHART3D_REAL3D
, !rPropSet
.GetBoolProperty( EXC_CHPROP_RIGHTANGLEDAXES
) );
2250 ::set_flag( maData
.mnFlags
, EXC_CHCHART3D_AUTOHEIGHT
);
2251 ::set_flag( maData
.mnFlags
, EXC_CHCHART3D_HASWALLS
);
2255 // Y rotation not used in pie charts, but 'first pie slice angle'
2256 maData
.mnRotation
= XclExpChRoot::ConvertPieRotation( rPropSet
);
2257 // X rotation a.k.a. elevation (map Chart2 [-80,-10] to Excel [10..80])
2258 maData
.mnElevation
= limit_cast
< sal_Int16
>( (nRotationX
+ 270) % 180, 10, 80 );
2259 // perspective (Excel and Chart2 [0,100])
2260 maData
.mnEyeDist
= limit_cast
< sal_uInt16
>( nPerspective
, 0, 100 );
2266 void XclExpChChart3d::WriteBody( XclExpStream
& rStrm
)
2268 rStrm
<< maData
.mnRotation
2269 << maData
.mnElevation
2271 << maData
.mnRelHeight
2272 << maData
.mnRelDepth
2273 << maData
.mnDepthGap
2277 XclExpChLegend::XclExpChLegend( const XclExpChRoot
& rRoot
) :
2278 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_LEGEND
, EXC_ID_CHLEGEND
, 20 )
2282 void XclExpChLegend::Convert( const ScfPropertySet
& rPropSet
)
2285 mxFrame
= lclCreateFrame( GetChRoot(), rPropSet
, EXC_CHOBJTYPE_LEGEND
);
2287 mxText
.reset( new XclExpChText( GetChRoot() ) );
2288 mxText
->ConvertLegend( rPropSet
);
2290 // legend position and size
2291 Any aRelPosAny
, aRelSizeAny
;
2292 rPropSet
.GetAnyProperty( aRelPosAny
, EXC_CHPROP_RELATIVEPOSITION
);
2293 rPropSet
.GetAnyProperty( aRelSizeAny
, EXC_CHPROP_RELATIVESIZE
);
2294 cssc::ChartLegendExpansion eApiExpand
= cssc::ChartLegendExpansion_CUSTOM
;
2295 rPropSet
.GetProperty( eApiExpand
, EXC_CHPROP_EXPANSION
);
2296 if( aRelPosAny
.has
< RelativePosition
>() || ((eApiExpand
== cssc::ChartLegendExpansion_CUSTOM
) && aRelSizeAny
.has
< RelativeSize
>()) )
2300 /* The 'RelativePosition' or 'RelativeSize' properties are used as
2301 indicator of manually changed legend position/size, but due to
2302 the different anchor modes used by this property (in the
2303 RelativePosition.Anchor member) it cannot be used to calculate
2304 the position easily. For this, the Chart1 API will be used
2306 Reference
< cssc::XChartDocument
> xChart1Doc( GetChartDocument(), UNO_QUERY_THROW
);
2307 Reference
< XShape
> xChart1Legend( xChart1Doc
->getLegend(), UNO_SET_THROW
);
2308 // coordinates in CHLEGEND record written but not used by Excel
2309 mxFramePos
.reset( new XclExpChFramePos( EXC_CHFRAMEPOS_CHARTSIZE
, EXC_CHFRAMEPOS_PARENT
) );
2310 XclChFramePos
& rFramePos
= mxFramePos
->GetFramePosData();
2311 rFramePos
.mnTLMode
= EXC_CHFRAMEPOS_CHARTSIZE
;
2312 ::com::sun::star::awt::Point aLegendPos
= xChart1Legend
->getPosition();
2313 rFramePos
.maRect
.mnX
= maData
.maRect
.mnX
= CalcChartXFromHmm( aLegendPos
.X
);
2314 rFramePos
.maRect
.mnY
= maData
.maRect
.mnY
= CalcChartYFromHmm( aLegendPos
.Y
);
2315 // legend size, Excel expects points in CHFRAMEPOS record
2316 rFramePos
.mnBRMode
= EXC_CHFRAMEPOS_ABSSIZE_POINTS
;
2317 ::com::sun::star::awt::Size aLegendSize
= xChart1Legend
->getSize();
2318 rFramePos
.maRect
.mnWidth
= static_cast< sal_uInt16
>( aLegendSize
.Width
* EXC_POINTS_PER_HMM
+ 0.5 );
2319 rFramePos
.maRect
.mnHeight
= static_cast< sal_uInt16
>( aLegendSize
.Height
* EXC_POINTS_PER_HMM
+ 0.5 );
2320 maData
.maRect
.mnWidth
= CalcChartXFromHmm( aLegendSize
.Width
);
2321 maData
.maRect
.mnHeight
= CalcChartYFromHmm( aLegendSize
.Height
);
2322 eApiExpand
= cssc::ChartLegendExpansion_CUSTOM
;
2323 // manual legend position implies manual plot area
2324 GetChartData().SetManualPlotArea();
2325 maData
.mnDockMode
= EXC_CHLEGEND_NOTDOCKED
;
2326 // a CHFRAME record with cleared auto flags is needed
2328 mxFrame
.reset( new XclExpChFrame( GetChRoot(), EXC_CHOBJTYPE_LEGEND
) );
2329 mxFrame
->SetAutoFlags( false, false );
2333 OSL_FAIL( "XclExpChLegend::Convert - cannot get legend shape" );
2334 maData
.mnDockMode
= EXC_CHLEGEND_RIGHT
;
2335 eApiExpand
= cssc::ChartLegendExpansion_HIGH
;
2340 cssc2::LegendPosition eApiPos
= cssc2::LegendPosition_CUSTOM
;
2341 rPropSet
.GetProperty( eApiPos
, EXC_CHPROP_ANCHORPOSITION
);
2344 case cssc2::LegendPosition_LINE_START
: maData
.mnDockMode
= EXC_CHLEGEND_LEFT
; break;
2345 case cssc2::LegendPosition_LINE_END
: maData
.mnDockMode
= EXC_CHLEGEND_RIGHT
; break;
2346 case cssc2::LegendPosition_PAGE_START
: maData
.mnDockMode
= EXC_CHLEGEND_TOP
; break;
2347 case cssc2::LegendPosition_PAGE_END
: maData
.mnDockMode
= EXC_CHLEGEND_BOTTOM
; break;
2349 OSL_FAIL( "XclExpChLegend::Convert - unrecognized legend position" );
2350 maData
.mnDockMode
= EXC_CHLEGEND_RIGHT
;
2351 eApiExpand
= cssc::ChartLegendExpansion_HIGH
;
2354 ::set_flag( maData
.mnFlags
, EXC_CHLEGEND_STACKED
, eApiExpand
== cssc::ChartLegendExpansion_HIGH
);
2357 ::set_flag( maData
.mnFlags
, EXC_CHLEGEND_AUTOSERIES
);
2358 const sal_uInt16 nAutoFlags
= EXC_CHLEGEND_DOCKED
| EXC_CHLEGEND_AUTOPOSX
| EXC_CHLEGEND_AUTOPOSY
;
2359 ::set_flag( maData
.mnFlags
, nAutoFlags
, maData
.mnDockMode
!= EXC_CHLEGEND_NOTDOCKED
);
2362 void XclExpChLegend::WriteSubRecords( XclExpStream
& rStrm
)
2364 lclSaveRecord( rStrm
, mxFramePos
);
2365 lclSaveRecord( rStrm
, mxText
);
2366 lclSaveRecord( rStrm
, mxFrame
);
2369 void XclExpChLegend::WriteBody( XclExpStream
& rStrm
)
2371 rStrm
<< maData
.maRect
<< maData
.mnDockMode
<< maData
.mnSpacing
<< maData
.mnFlags
;
2374 XclExpChDropBar::XclExpChDropBar( const XclExpChRoot
& rRoot
, XclChObjectType eObjType
) :
2375 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_DROPBAR
, EXC_ID_CHDROPBAR
, 2 ),
2376 meObjType( eObjType
),
2381 void XclExpChDropBar::Convert( const ScfPropertySet
& rPropSet
)
2384 ConvertFrameBase( GetChRoot(), rPropSet
, meObjType
);
2386 SetDefaultFrameBase( GetChRoot(), EXC_CHFRAMETYPE_INVISIBLE
, true );
2389 void XclExpChDropBar::WriteSubRecords( XclExpStream
& rStrm
)
2391 WriteFrameRecords( rStrm
);
2394 void XclExpChDropBar::WriteBody( XclExpStream
& rStrm
)
2399 XclExpChTypeGroup::XclExpChTypeGroup( const XclExpChRoot
& rRoot
, sal_uInt16 nGroupIdx
) :
2400 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_TYPEGROUP
, EXC_ID_CHTYPEGROUP
, 20 ),
2402 maTypeInfo( maType
.GetTypeInfo() )
2404 maData
.mnGroupIdx
= nGroupIdx
;
2407 void XclExpChTypeGroup::ConvertType(
2408 Reference
< XDiagram
> xDiagram
, Reference
< XChartType
> xChartType
,
2409 sal_Int32 nApiAxesSetIdx
, bool b3dChart
, bool bSwappedAxesSet
, bool bHasXLabels
)
2411 // chart type settings
2412 maType
.Convert( xDiagram
, xChartType
, nApiAxesSetIdx
, bSwappedAxesSet
, bHasXLabels
);
2414 // spline - TODO: get from single series (#i66858#)
2415 ScfPropertySet
aTypeProp( xChartType
);
2416 cssc2::CurveStyle eCurveStyle
;
2417 bool bSpline
= aTypeProp
.GetProperty( eCurveStyle
, EXC_CHPROP_CURVESTYLE
) &&
2418 (eCurveStyle
!= cssc2::CurveStyle_LINES
);
2420 // extended type info
2421 maTypeInfo
.Set( maType
.GetTypeInfo(), b3dChart
, bSpline
);
2423 // 3d chart settings
2424 if( maTypeInfo
.mb3dChart
) // only true, if Excel chart supports 3d mode
2426 mxChart3d
.reset( new XclExpChChart3d
);
2427 ScfPropertySet
aDiaProp( xDiagram
);
2428 mxChart3d
->Convert( aDiaProp
, Is3dWallChart() );
2432 void XclExpChTypeGroup::ConvertSeries(
2433 Reference
< XDiagram
> xDiagram
, Reference
< XChartType
> xChartType
,
2434 sal_Int32 nGroupAxesSetIdx
, bool bPercent
, bool bConnectBars
)
2436 Reference
< XDataSeriesContainer
> xSeriesCont( xChartType
, UNO_QUERY
);
2437 if( xSeriesCont
.is() )
2439 typedef ::std::vector
< Reference
< XDataSeries
> > XDataSeriesVec
;
2440 XDataSeriesVec aSeriesVec
;
2442 // copy data series attached to the current axes set to the vector
2443 Sequence
< Reference
< XDataSeries
> > aSeriesSeq
= xSeriesCont
->getDataSeries();
2444 const Reference
< XDataSeries
>* pBeg
= aSeriesSeq
.getConstArray();
2445 const Reference
< XDataSeries
>* pEnd
= pBeg
+ aSeriesSeq
.getLength();
2446 for( const Reference
< XDataSeries
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
2448 ScfPropertySet
aSeriesProp( *pIt
);
2449 sal_Int32
nSeriesAxesSetIdx(0);
2450 if( aSeriesProp
.GetProperty( nSeriesAxesSetIdx
, EXC_CHPROP_ATTAXISINDEX
) && (nSeriesAxesSetIdx
== nGroupAxesSetIdx
) )
2451 aSeriesVec
.push_back( *pIt
);
2454 // Are there any series in the current axes set?
2455 if( !aSeriesVec
.empty() )
2457 // stacking direction (stacked/percent/deep 3d) from first series
2458 ScfPropertySet
aSeriesProp( aSeriesVec
.front() );
2459 cssc2::StackingDirection eStacking
;
2460 if( !aSeriesProp
.GetProperty( eStacking
, EXC_CHPROP_STACKINGDIR
) )
2461 eStacking
= cssc2::StackingDirection_NO_STACKING
;
2463 // stacked or percent chart
2464 if( maTypeInfo
.mbSupportsStacking
&& (eStacking
== cssc2::StackingDirection_Y_STACKING
) )
2466 // percent overrides simple stacking
2467 maType
.SetStacked( bPercent
);
2469 // connected data points (only in stacked bar charts)
2470 if (bConnectBars
&& (maTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_BAR
))
2472 sal_uInt16 nKey
= EXC_CHCHARTLINE_CONNECT
;
2473 maChartLines
.insert(nKey
, new XclExpChLineFormat(GetChRoot()));
2478 // reverse series order for some unstacked 2D chart types
2479 if( maTypeInfo
.mbReverseSeries
&& !Is3dChart() )
2480 ::std::reverse( aSeriesVec
.begin(), aSeriesVec
.end() );
2483 // deep 3d chart or clustered 3d chart (stacked is not clustered)
2484 if( (eStacking
== cssc2::StackingDirection_NO_STACKING
) && Is3dWallChart() )
2485 mxChart3d
->SetClustered();
2487 // varied point colors
2488 ::set_flag( maData
.mnFlags
, EXC_CHTYPEGROUP_VARIEDCOLORS
, aSeriesProp
.GetBoolProperty( EXC_CHPROP_VARYCOLORSBY
) );
2490 // process all series
2491 for( XDataSeriesVec::const_iterator aIt
= aSeriesVec
.begin(), aEnd
= aSeriesVec
.end(); aIt
!= aEnd
; ++aIt
)
2493 // create Excel series object, stock charts need special processing
2494 if( maTypeInfo
.meTypeId
== EXC_CHTYPEID_STOCK
)
2495 CreateAllStockSeries( xChartType
, *aIt
);
2497 CreateDataSeries( xDiagram
, *aIt
);
2503 void XclExpChTypeGroup::ConvertCategSequence( Reference
< XLabeledDataSequence
> xCategSeq
)
2505 for( size_t nIdx
= 0, nSize
= maSeries
.GetSize(); nIdx
< nSize
; ++nIdx
)
2506 maSeries
.GetRecord( nIdx
)->ConvertCategSequence( xCategSeq
);
2509 void XclExpChTypeGroup::ConvertLegend( const ScfPropertySet
& rPropSet
)
2511 if( rPropSet
.GetBoolProperty( EXC_CHPROP_SHOW
) )
2513 mxLegend
.reset( new XclExpChLegend( GetChRoot() ) );
2514 mxLegend
->Convert( rPropSet
);
2518 void XclExpChTypeGroup::WriteSubRecords( XclExpStream
& rStrm
)
2520 maType
.Save( rStrm
);
2521 lclSaveRecord( rStrm
, mxChart3d
);
2522 lclSaveRecord( rStrm
, mxLegend
);
2523 lclSaveRecord( rStrm
, mxUpBar
);
2524 lclSaveRecord( rStrm
, mxDownBar
);
2525 for( XclExpChLineFormatMap::iterator aLIt
= maChartLines
.begin(), aLEnd
= maChartLines
.end(); aLIt
!= aLEnd
; ++aLIt
)
2526 lclSaveRecord( rStrm
, aLIt
->second
, EXC_ID_CHCHARTLINE
, aLIt
->first
);
2529 sal_uInt16
XclExpChTypeGroup::GetFreeFormatIdx() const
2531 return static_cast< sal_uInt16
>( maSeries
.GetSize() );
2534 void XclExpChTypeGroup::CreateDataSeries(
2535 Reference
< XDiagram
> xDiagram
, Reference
< XDataSeries
> xDataSeries
)
2537 // let chart create series object with correct series index
2538 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
2541 if( xSeries
->ConvertDataSeries( xDiagram
, xDataSeries
, maTypeInfo
, GetGroupIdx(), GetFreeFormatIdx() ) )
2542 maSeries
.AppendRecord( xSeries
);
2544 GetChartData().RemoveLastSeries();
2548 void XclExpChTypeGroup::CreateAllStockSeries(
2549 Reference
< XChartType
> xChartType
, Reference
< XDataSeries
> xDataSeries
)
2551 // create existing series objects
2552 bool bHasOpen
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_OPENVALUES
, false );
2553 bool bHasHigh
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_HIGHVALUES
, false );
2554 bool bHasLow
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_LOWVALUES
, false );
2555 bool bHasClose
= CreateStockSeries( xDataSeries
, EXC_CHPROP_ROLE_CLOSEVALUES
, !bHasOpen
);
2557 // formatting of special stock chart elements
2558 ScfPropertySet
aTypeProp( xChartType
);
2560 if( bHasHigh
&& bHasLow
&& aTypeProp
.GetBoolProperty( EXC_CHPROP_SHOWHIGHLOW
) )
2562 ScfPropertySet
aSeriesProp( xDataSeries
);
2563 XclExpChLineFormatRef
xLineFmt( new XclExpChLineFormat( GetChRoot() ) );
2564 xLineFmt
->Convert( GetChRoot(), aSeriesProp
, EXC_CHOBJTYPE_HILOLINE
);
2565 sal_uInt16 nKey
= EXC_CHCHARTLINE_HILO
;
2566 maChartLines
.insert(nKey
, new XclExpChLineFormat(GetChRoot()));
2569 if( bHasOpen
&& bHasClose
)
2571 // dropbar type is dependent on position in the file - always create both
2572 Reference
< XPropertySet
> xWhitePropSet
, xBlackPropSet
;
2573 // white dropbar format
2574 aTypeProp
.GetProperty( xWhitePropSet
, EXC_CHPROP_WHITEDAY
);
2575 ScfPropertySet
aWhiteProp( xWhitePropSet
);
2576 mxUpBar
.reset( new XclExpChDropBar( GetChRoot(), EXC_CHOBJTYPE_WHITEDROPBAR
) );
2577 mxUpBar
->Convert( aWhiteProp
);
2578 // black dropbar format
2579 aTypeProp
.GetProperty( xBlackPropSet
, EXC_CHPROP_BLACKDAY
);
2580 ScfPropertySet
aBlackProp( xBlackPropSet
);
2581 mxDownBar
.reset( new XclExpChDropBar( GetChRoot(), EXC_CHOBJTYPE_BLACKDROPBAR
) );
2582 mxDownBar
->Convert( aBlackProp
);
2586 bool XclExpChTypeGroup::CreateStockSeries( Reference
< XDataSeries
> xDataSeries
,
2587 const OUString
& rValueRole
, bool bCloseSymbol
)
2590 // let chart create series object with correct series index
2591 XclExpChSeriesRef xSeries
= GetChartData().CreateSeries();
2594 bOk
= xSeries
->ConvertStockSeries( xDataSeries
,
2595 rValueRole
, GetGroupIdx(), GetFreeFormatIdx(), bCloseSymbol
);
2597 maSeries
.AppendRecord( xSeries
);
2599 GetChartData().RemoveLastSeries();
2604 void XclExpChTypeGroup::WriteBody( XclExpStream
& rStrm
)
2606 rStrm
.WriteZeroBytes( 16 );
2607 rStrm
<< maData
.mnFlags
<< maData
.mnGroupIdx
;
2610 // Axes =======================================================================
2612 XclExpChLabelRange::XclExpChLabelRange( const XclExpChRoot
& rRoot
) :
2613 XclExpRecord( EXC_ID_CHLABELRANGE
, 8 ),
2614 XclExpChRoot( rRoot
)
2618 void XclExpChLabelRange::Convert( const ScaleData
& rScaleData
, const ScfPropertySet
& rChart1Axis
, bool bMirrorOrient
)
2620 /* Base time unit (using the property 'ExplicitTimeIncrement' from the old
2621 chart API allows to detect axis type (date axis, if property exists),
2622 and to receive the base time unit currently used in case the base time
2623 unit is set to 'automatic'. */
2624 cssc::TimeIncrement aTimeIncrement
;
2625 if( rChart1Axis
.GetProperty( aTimeIncrement
, EXC_CHPROP_EXPTIMEINCREMENT
) )
2627 // property exists -> this is a date axis currently
2628 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_DATEAXIS
);
2630 // automatic base time unit, if the UNO Any 'rScaleData.TimeIncrement.TimeResolution' does not contain a valid value...
2631 bool bAutoBase
= !rScaleData
.TimeIncrement
.TimeResolution
.has
< cssc::TimeIncrement
>();
2632 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOBASE
, bAutoBase
);
2634 // ...but get the current base time unit from the property of the old chart API
2635 sal_Int32 nApiTimeUnit
= 0;
2636 bool bValidBaseUnit
= aTimeIncrement
.TimeResolution
>>= nApiTimeUnit
;
2637 OSL_ENSURE( bValidBaseUnit
, "XclExpChLabelRange::Convert - cannot get base time unit" );
2638 maDateData
.mnBaseUnit
= bValidBaseUnit
? lclGetTimeUnit( nApiTimeUnit
) : EXC_CHDATERANGE_DAYS
;
2640 /* Min/max values depend on base time unit, they specify the number of
2641 days, months, or years starting from null date. */
2642 bool bAutoMin
= lclConvertTimeValue( GetRoot(), maDateData
.mnMinDate
, rScaleData
.Minimum
, maDateData
.mnBaseUnit
);
2643 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOMIN
, bAutoMin
);
2644 bool bAutoMax
= lclConvertTimeValue( GetRoot(), maDateData
.mnMaxDate
, rScaleData
.Maximum
, maDateData
.mnBaseUnit
);
2645 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOMAX
, bAutoMax
);
2648 // automatic axis type detection
2649 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTODATE
, rScaleData
.AutoDateAxis
);
2652 bool bAutoMajor
= lclConvertTimeInterval( maDateData
.mnMajorStep
, maDateData
.mnMajorUnit
, rScaleData
.TimeIncrement
.MajorTimeInterval
);
2653 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOMAJOR
, bAutoMajor
);
2654 bool bAutoMinor
= lclConvertTimeInterval( maDateData
.mnMinorStep
, maDateData
.mnMinorUnit
, rScaleData
.TimeIncrement
.MinorTimeInterval
);
2655 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOMINOR
, bAutoMinor
);
2658 double fOrigin
= 0.0;
2659 if( !lclIsAutoAnyOrGetValue( fOrigin
, rScaleData
.Origin
) )
2660 maLabelData
.mnCross
= limit_cast
< sal_uInt16
>( fOrigin
, 1, 31999 );
2663 if( (rScaleData
.Orientation
== cssc2::AxisOrientation_REVERSE
) != bMirrorOrient
)
2664 ::set_flag( maLabelData
.mnFlags
, EXC_CHLABELRANGE_REVERSE
);
2667 void XclExpChLabelRange::ConvertAxisPosition( const ScfPropertySet
& rPropSet
)
2669 cssc::ChartAxisPosition eAxisPos
= cssc::ChartAxisPosition_VALUE
;
2670 rPropSet
.GetProperty( eAxisPos
, EXC_CHPROP_CROSSOVERPOSITION
);
2671 double fCrossingPos
= 1.0;
2672 rPropSet
.GetProperty( fCrossingPos
, EXC_CHPROP_CROSSOVERVALUE
);
2674 bool bDateAxis
= ::get_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_DATEAXIS
);
2677 case cssc::ChartAxisPosition_ZERO
:
2678 case cssc::ChartAxisPosition_START
:
2679 maLabelData
.mnCross
= 1;
2680 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOCROSS
);
2682 case cssc::ChartAxisPosition_END
:
2683 ::set_flag( maLabelData
.mnFlags
, EXC_CHLABELRANGE_MAXCROSS
);
2685 case cssc::ChartAxisPosition_VALUE
:
2686 maLabelData
.mnCross
= limit_cast
< sal_uInt16
>( fCrossingPos
, 1, 31999 );
2687 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOCROSS
, false );
2689 maDateData
.mnCross
= lclGetTimeValue( GetRoot(), fCrossingPos
, maDateData
.mnBaseUnit
);
2692 maLabelData
.mnCross
= 1;
2693 ::set_flag( maDateData
.mnFlags
, EXC_CHDATERANGE_AUTOCROSS
);
2697 void XclExpChLabelRange::Save( XclExpStream
& rStrm
)
2699 // the CHLABELRANGE record
2700 XclExpRecord::Save( rStrm
);
2702 // the CHDATERANGE record with date axis settings (BIFF8 only)
2703 if( GetBiff() == EXC_BIFF8
)
2705 rStrm
.StartRecord( EXC_ID_CHDATERANGE
, 18 );
2706 rStrm
<< maDateData
.mnMinDate
2707 << maDateData
.mnMaxDate
2708 << maDateData
.mnMajorStep
2709 << maDateData
.mnMajorUnit
2710 << maDateData
.mnMinorStep
2711 << maDateData
.mnMinorUnit
2712 << maDateData
.mnBaseUnit
2713 << maDateData
.mnCross
2714 << maDateData
.mnFlags
;
2719 void XclExpChLabelRange::WriteBody( XclExpStream
& rStrm
)
2721 rStrm
<< maLabelData
.mnCross
<< maLabelData
.mnLabelFreq
<< maLabelData
.mnTickFreq
<< maLabelData
.mnFlags
;
2724 XclExpChValueRange::XclExpChValueRange( const XclExpChRoot
& rRoot
) :
2725 XclExpRecord( EXC_ID_CHVALUERANGE
, 42 ),
2726 XclExpChRoot( rRoot
)
2730 void XclExpChValueRange::Convert( const ScaleData
& rScaleData
)
2732 // scaling algorithm
2733 bool bLogScale
= ScfApiHelper::GetServiceName( rScaleData
.Scaling
) == "com.sun.star.chart2.LogarithmicScaling";
2734 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_LOGSCALE
, bLogScale
);
2737 bool bAutoMin
= lclIsAutoAnyOrGetScaledValue( maData
.mfMin
, rScaleData
.Minimum
, bLogScale
);
2738 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMIN
, bAutoMin
);
2739 bool bAutoMax
= lclIsAutoAnyOrGetScaledValue( maData
.mfMax
, rScaleData
.Maximum
, bLogScale
);
2740 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMAX
, bAutoMax
);
2743 bool bAutoCross
= lclIsAutoAnyOrGetScaledValue( maData
.mfCross
, rScaleData
.Origin
, bLogScale
);
2744 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
, bAutoCross
);
2747 const IncrementData
& rIncrementData
= rScaleData
.IncrementData
;
2748 bool bAutoMajor
= lclIsAutoAnyOrGetValue( maData
.mfMajorStep
, rIncrementData
.Distance
) || (maData
.mfMajorStep
<= 0.0);
2749 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMAJOR
, bAutoMajor
);
2751 const Sequence
< SubIncrement
>& rSubIncrementSeq
= rIncrementData
.SubIncrements
;
2752 sal_Int32 nCount
= 0;
2753 bool bAutoMinor
= bLogScale
|| bAutoMajor
|| (rSubIncrementSeq
.getLength() < 1) ||
2754 lclIsAutoAnyOrGetValue( nCount
, rSubIncrementSeq
[ 0 ].IntervalCount
) || (nCount
< 1);
2756 maData
.mfMinorStep
= maData
.mfMajorStep
/ nCount
;
2757 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOMINOR
, bAutoMinor
);
2760 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_REVERSE
, rScaleData
.Orientation
== cssc2::AxisOrientation_REVERSE
);
2763 void XclExpChValueRange::ConvertAxisPosition( const ScfPropertySet
& rPropSet
)
2765 cssc::ChartAxisPosition eAxisPos
= cssc::ChartAxisPosition_VALUE
;
2766 double fCrossingPos
= 0.0;
2767 if( rPropSet
.GetProperty( eAxisPos
, EXC_CHPROP_CROSSOVERPOSITION
) && rPropSet
.GetProperty( fCrossingPos
, EXC_CHPROP_CROSSOVERVALUE
) )
2771 case cssc::ChartAxisPosition_ZERO
:
2772 case cssc::ChartAxisPosition_START
:
2773 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
);
2775 case cssc::ChartAxisPosition_END
:
2776 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_MAXCROSS
);
2778 case cssc::ChartAxisPosition_VALUE
:
2779 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
, false );
2780 maData
.mfCross
= ::get_flagvalue
< double >( maData
.mnFlags
, EXC_CHVALUERANGE_LOGSCALE
, log( fCrossingPos
) / log( 10.0 ), fCrossingPos
);
2783 ::set_flag( maData
.mnFlags
, EXC_CHVALUERANGE_AUTOCROSS
);
2788 void XclExpChValueRange::WriteBody( XclExpStream
& rStrm
)
2790 rStrm
<< maData
.mfMin
2792 << maData
.mfMajorStep
2793 << maData
.mfMinorStep
2800 sal_uInt8
lclGetXclTickPos( sal_Int32 nApiTickmarks
)
2802 using namespace cssc2::TickmarkStyle
;
2803 sal_uInt8 nXclTickPos
= 0;
2804 ::set_flag( nXclTickPos
, EXC_CHTICK_INSIDE
, ::get_flag( nApiTickmarks
, INNER
) );
2805 ::set_flag( nXclTickPos
, EXC_CHTICK_OUTSIDE
, ::get_flag( nApiTickmarks
, OUTER
) );
2811 XclExpChTick::XclExpChTick( const XclExpChRoot
& rRoot
) :
2812 XclExpRecord( EXC_ID_CHTICK
, (rRoot
.GetBiff() == EXC_BIFF8
) ? 30 : 26 ),
2813 XclExpChRoot( rRoot
),
2814 mnTextColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT
) )
2818 void XclExpChTick::Convert( const ScfPropertySet
& rPropSet
, const XclChExtTypeInfo
& rTypeInfo
, sal_uInt16 nAxisType
)
2821 sal_Int32 nApiTickmarks
= 0;
2822 if( rPropSet
.GetProperty( nApiTickmarks
, EXC_CHPROP_MAJORTICKS
) )
2823 maData
.mnMajor
= lclGetXclTickPos( nApiTickmarks
);
2824 if( rPropSet
.GetProperty( nApiTickmarks
, EXC_CHPROP_MINORTICKS
) )
2825 maData
.mnMinor
= lclGetXclTickPos( nApiTickmarks
);
2828 if( (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_RADAR
) && (nAxisType
== EXC_CHAXIS_X
) )
2830 /* Radar charts disable their category labels via chart type, not via
2831 axis, and axis labels are always 'near axis'. */
2832 maData
.mnLabelPos
= EXC_CHTICK_NEXT
;
2834 else if( !rPropSet
.GetBoolProperty( EXC_CHPROP_DISPLAYLABELS
) )
2837 maData
.mnLabelPos
= EXC_CHTICK_NOLABEL
;
2839 else if( rTypeInfo
.mb3dChart
&& (nAxisType
== EXC_CHAXIS_Y
) )
2841 // Excel expects 'near axis' at Y axes in 3D charts
2842 maData
.mnLabelPos
= EXC_CHTICK_NEXT
;
2846 cssc::ChartAxisLabelPosition eApiLabelPos
= cssc::ChartAxisLabelPosition_NEAR_AXIS
;
2847 rPropSet
.GetProperty( eApiLabelPos
, EXC_CHPROP_LABELPOSITION
);
2848 switch( eApiLabelPos
)
2850 case cssc::ChartAxisLabelPosition_NEAR_AXIS
:
2851 case cssc::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE
: maData
.mnLabelPos
= EXC_CHTICK_NEXT
; break;
2852 case cssc::ChartAxisLabelPosition_OUTSIDE_START
: maData
.mnLabelPos
= EXC_CHTICK_LOW
; break;
2853 case cssc::ChartAxisLabelPosition_OUTSIDE_END
: maData
.mnLabelPos
= EXC_CHTICK_HIGH
; break;
2854 default: maData
.mnLabelPos
= EXC_CHTICK_NEXT
;
2859 void XclExpChTick::SetFontColor( const Color
& rColor
, sal_uInt32 nColorId
)
2861 maData
.maTextColor
= rColor
;
2862 ::set_flag( maData
.mnFlags
, EXC_CHTICK_AUTOCOLOR
, rColor
== COL_AUTO
);
2863 mnTextColorId
= nColorId
;
2866 void XclExpChTick::SetRotation( sal_uInt16 nRotation
)
2868 maData
.mnRotation
= nRotation
;
2869 ::set_flag( maData
.mnFlags
, EXC_CHTICK_AUTOROT
, false );
2870 ::insert_value( maData
.mnFlags
, XclTools::GetXclOrientFromRot( nRotation
), 2, 3 );
2873 void XclExpChTick::WriteBody( XclExpStream
& rStrm
)
2875 rStrm
<< maData
.mnMajor
2877 << maData
.mnLabelPos
2878 << maData
.mnBackMode
;
2879 rStrm
.WriteZeroBytes( 16 );
2880 rStrm
<< maData
.maTextColor
2882 if( GetBiff() == EXC_BIFF8
)
2883 rStrm
<< GetPalette().GetColorIndex( mnTextColorId
) << maData
.mnRotation
;
2888 /** Returns an API axis object from the passed coordinate system. */
2889 Reference
< XAxis
> lclGetApiAxis( Reference
< XCoordinateSystem
> xCoordSystem
,
2890 sal_Int32 nApiAxisDim
, sal_Int32 nApiAxesSetIdx
)
2892 Reference
< XAxis
> xAxis
;
2893 if( (nApiAxisDim
>= 0) && xCoordSystem
.is() ) try
2895 xAxis
= xCoordSystem
->getAxisByDimension( nApiAxisDim
, nApiAxesSetIdx
);
2903 Reference
< cssc::XAxis
> lclGetApiChart1Axis( Reference
< XChartDocument
> xChartDoc
,
2904 sal_Int32 nApiAxisDim
, sal_Int32 nApiAxesSetIdx
)
2906 Reference
< cssc::XAxis
> xChart1Axis
;
2909 Reference
< cssc::XChartDocument
> xChart1Doc( xChartDoc
, UNO_QUERY_THROW
);
2910 Reference
< cssc::XAxisSupplier
> xChart1AxisSupp( xChart1Doc
->getDiagram(), UNO_QUERY_THROW
);
2911 switch( nApiAxesSetIdx
)
2913 case EXC_CHART_AXESSET_PRIMARY
:
2914 xChart1Axis
= xChart1AxisSupp
->getAxis( nApiAxisDim
);
2916 case EXC_CHART_AXESSET_SECONDARY
:
2917 xChart1Axis
= xChart1AxisSupp
->getSecondaryAxis( nApiAxisDim
);
2929 XclExpChAxis::XclExpChAxis( const XclExpChRoot
& rRoot
, sal_uInt16 nAxisType
) :
2930 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_AXIS
, EXC_ID_CHAXIS
, 18 ),
2931 mnNumFmtIdx( EXC_FORMAT_NOTFOUND
)
2933 maData
.mnType
= nAxisType
;
2936 void XclExpChAxis::SetFont( XclExpChFontRef xFont
, const Color
& rColor
, sal_uInt32 nColorId
)
2940 mxTick
->SetFontColor( rColor
, nColorId
);
2943 void XclExpChAxis::SetRotation( sal_uInt16 nRotation
)
2946 mxTick
->SetRotation( nRotation
);
2949 void XclExpChAxis::Convert( Reference
< XAxis
> xAxis
, Reference
< XAxis
> xCrossingAxis
,
2950 Reference
< cssc::XAxis
> xChart1Axis
, const XclChExtTypeInfo
& rTypeInfo
)
2952 ScfPropertySet
aAxisProp( xAxis
);
2953 bool bCategoryAxis
= ((GetAxisType() == EXC_CHAXIS_X
) && rTypeInfo
.mbCategoryAxis
) || (GetAxisType() == EXC_CHAXIS_Z
);
2955 // axis line format -------------------------------------------------------
2957 mxAxisLine
.reset( new XclExpChLineFormat( GetChRoot() ) );
2958 mxAxisLine
->Convert( GetChRoot(), aAxisProp
, EXC_CHOBJTYPE_AXISLINE
);
2959 // #i58688# axis enabled
2960 mxAxisLine
->SetShowAxis( aAxisProp
.GetBoolProperty( EXC_CHPROP_SHOW
) );
2962 // axis scaling and increment ---------------------------------------------
2964 ScfPropertySet
aCrossingProp( xCrossingAxis
);
2967 mxLabelRange
.reset( new XclExpChLabelRange( GetChRoot() ) );
2968 mxLabelRange
->SetTicksBetweenCateg( rTypeInfo
.mbTicksBetweenCateg
);
2971 ScfPropertySet
aChart1AxisProp( xChart1Axis
);
2972 // #i71684# radar charts have reversed rotation direction
2973 mxLabelRange
->Convert( xAxis
->getScaleData(), aChart1AxisProp
, (GetAxisType() == EXC_CHAXIS_X
) && (rTypeInfo
.meTypeCateg
== EXC_CHTYPECATEG_RADAR
) );
2975 // get position of crossing axis on this axis from passed axis object
2976 if( aCrossingProp
.Is() )
2977 mxLabelRange
->ConvertAxisPosition( aCrossingProp
);
2981 mxValueRange
.reset( new XclExpChValueRange( GetChRoot() ) );
2983 mxValueRange
->Convert( xAxis
->getScaleData() );
2984 // get position of crossing axis on this axis from passed axis object
2985 if( aCrossingProp
.Is() )
2986 mxValueRange
->ConvertAxisPosition( aCrossingProp
);
2989 // axis caption text ------------------------------------------------------
2991 // axis ticks properties
2992 mxTick
.reset( new XclExpChTick( GetChRoot() ) );
2993 mxTick
->Convert( aAxisProp
, rTypeInfo
, GetAxisType() );
2995 // axis label formatting and rotation
2996 ConvertFontBase( GetChRoot(), aAxisProp
);
2997 ConvertRotationBase( aAxisProp
, true );
2999 // axis number format
3000 sal_Int32 nApiNumFmt
= 0;
3001 if( !bCategoryAxis
&& aAxisProp
.GetProperty( nApiNumFmt
, EXC_CHPROP_NUMBERFORMAT
) )
3002 mnNumFmtIdx
= GetNumFmtBuffer().Insert( static_cast< sal_uInt32
>( nApiNumFmt
) );
3004 // grid -------------------------------------------------------------------
3009 ScfPropertySet
aGridProp( xAxis
->getGridProperties() );
3010 if( aGridProp
.GetBoolProperty( EXC_CHPROP_SHOW
) )
3011 mxMajorGrid
= lclCreateLineFormat( GetChRoot(), aGridProp
, EXC_CHOBJTYPE_GRIDLINE
);
3013 Sequence
< Reference
< XPropertySet
> > aSubGridPropSeq
= xAxis
->getSubGridProperties();
3014 if( aSubGridPropSeq
.hasElements() )
3016 ScfPropertySet
aSubGridProp( aSubGridPropSeq
[ 0 ] );
3017 if( aSubGridProp
.GetBoolProperty( EXC_CHPROP_SHOW
) )
3018 mxMinorGrid
= lclCreateLineFormat( GetChRoot(), aSubGridProp
, EXC_CHOBJTYPE_GRIDLINE
);
3023 void XclExpChAxis::ConvertWall( XDiagramRef xDiagram
)
3025 if( xDiagram
.is() ) switch( GetAxisType() )
3029 ScfPropertySet
aWallProp( xDiagram
->getWall() );
3030 mxWallFrame
= lclCreateFrame( GetChRoot(), aWallProp
, EXC_CHOBJTYPE_WALL3D
);
3035 ScfPropertySet
aFloorProp( xDiagram
->getFloor() );
3036 mxWallFrame
= lclCreateFrame( GetChRoot(), aFloorProp
, EXC_CHOBJTYPE_FLOOR3D
);
3040 mxWallFrame
.reset();
3044 void XclExpChAxis::WriteSubRecords( XclExpStream
& rStrm
)
3046 lclSaveRecord( rStrm
, mxLabelRange
);
3047 lclSaveRecord( rStrm
, mxValueRange
);
3048 if( mnNumFmtIdx
!= EXC_FORMAT_NOTFOUND
)
3049 XclExpUInt16Record( EXC_ID_CHFORMAT
, mnNumFmtIdx
).Save( rStrm
);
3050 lclSaveRecord( rStrm
, mxTick
);
3051 lclSaveRecord( rStrm
, mxFont
);
3052 lclSaveRecord( rStrm
, mxAxisLine
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_AXISLINE
);
3053 lclSaveRecord( rStrm
, mxMajorGrid
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_MAJORGRID
);
3054 lclSaveRecord( rStrm
, mxMinorGrid
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_MINORGRID
);
3055 lclSaveRecord( rStrm
, mxWallFrame
, EXC_ID_CHAXISLINE
, EXC_CHAXISLINE_WALLS
);
3058 void XclExpChAxis::WriteBody( XclExpStream
& rStrm
)
3060 rStrm
<< maData
.mnType
;
3061 rStrm
.WriteZeroBytes( 16 );
3064 XclExpChAxesSet::XclExpChAxesSet( const XclExpChRoot
& rRoot
, sal_uInt16 nAxesSetId
) :
3065 XclExpChGroupBase( rRoot
, EXC_CHFRBLOCK_TYPE_AXESSET
, EXC_ID_CHAXESSET
, 18 )
3067 maData
.mnAxesSetId
= nAxesSetId
;
3068 SetFutureRecordContext( 0, nAxesSetId
);
3070 /* Need to set a reasonable size for the plot area, otherwise Excel will
3071 move away embedded shapes while auto-sizing the plot area. This is just
3072 a wild guess, but will be fixed with implementing manual positioning of
3074 maData
.maRect
.mnX
= 262;
3075 maData
.maRect
.mnY
= 626;
3076 maData
.maRect
.mnWidth
= 3187;
3077 maData
.maRect
.mnHeight
= 2633;
3080 sal_uInt16
XclExpChAxesSet::Convert( Reference
< XDiagram
> xDiagram
, sal_uInt16 nFirstGroupIdx
)
3082 /* First unused chart type group index is passed to be able to continue
3083 counting of chart type groups for secondary axes set. */
3084 sal_uInt16 nGroupIdx
= nFirstGroupIdx
;
3085 Reference
< XCoordinateSystemContainer
> xCoordSysCont( xDiagram
, UNO_QUERY
);
3086 if( xCoordSysCont
.is() )
3088 Sequence
< Reference
< XCoordinateSystem
> > aCoordSysSeq
= xCoordSysCont
->getCoordinateSystems();
3089 if( aCoordSysSeq
.getLength() > 0 )
3091 /* Process first coordinate system only. Import filter puts all
3092 chart types into one coordinate system. */
3093 Reference
< XCoordinateSystem
> xCoordSystem
= aCoordSysSeq
[ 0 ];
3094 sal_Int32 nApiAxesSetIdx
= GetApiAxesSetIndex();
3097 bool b3dChart
= xCoordSystem
.is() && (xCoordSystem
->getDimension() == 3);
3100 namespace ApiAxisType
= cssc2::AxisType
;
3101 Reference
< XAxis
> xApiYAxis
= lclGetApiAxis( xCoordSystem
, EXC_CHART_AXIS_Y
, nApiAxesSetIdx
);
3102 bool bPercent
= xApiYAxis
.is() && (xApiYAxis
->getScaleData().AxisType
== ApiAxisType::PERCENT
);
3104 // connector lines in bar charts
3105 ScfPropertySet
aDiaProp( xDiagram
);
3106 bool bConnectBars
= aDiaProp
.GetBoolProperty( EXC_CHPROP_CONNECTBARS
);
3108 // swapped axes sets
3109 ScfPropertySet
aCoordSysProp( xCoordSystem
);
3110 bool bSwappedAxesSet
= aCoordSysProp
.GetBoolProperty( EXC_CHPROP_SWAPXANDYAXIS
);
3112 // X axis for later use
3113 Reference
< XAxis
> xApiXAxis
= lclGetApiAxis( xCoordSystem
, EXC_CHART_AXIS_X
, nApiAxesSetIdx
);
3115 ScfPropertySet
aXAxisProp( xApiXAxis
);
3116 bool bHasXLabels
= aXAxisProp
.GetBoolProperty( EXC_CHPROP_DISPLAYLABELS
);
3118 // process chart types
3119 Reference
< XChartTypeContainer
> xChartTypeCont( xCoordSystem
, UNO_QUERY
);
3120 if( xChartTypeCont
.is() )
3122 Sequence
< Reference
< XChartType
> > aChartTypeSeq
= xChartTypeCont
->getChartTypes();
3123 const Reference
< XChartType
>* pBeg
= aChartTypeSeq
.getConstArray();
3124 const Reference
< XChartType
>* pEnd
= pBeg
+ aChartTypeSeq
.getLength();
3125 for( const Reference
< XChartType
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
3127 XclExpChTypeGroupRef
xTypeGroup( new XclExpChTypeGroup( GetChRoot(), nGroupIdx
) );
3128 xTypeGroup
->ConvertType( xDiagram
, *pIt
, nApiAxesSetIdx
, b3dChart
, bSwappedAxesSet
, bHasXLabels
);
3129 /* If new chart type group cannot be inserted into a combination
3130 chart with existing type groups, insert all series into last
3131 contained chart type group instead of creating a new group. */
3132 XclExpChTypeGroupRef xLastGroup
= GetLastTypeGroup();
3133 if( xLastGroup
&& !(xTypeGroup
->IsCombinable2d() && xLastGroup
->IsCombinable2d()) )
3135 xLastGroup
->ConvertSeries( xDiagram
, *pIt
, nApiAxesSetIdx
, bPercent
, bConnectBars
);
3139 xTypeGroup
->ConvertSeries( xDiagram
, *pIt
, nApiAxesSetIdx
, bPercent
, bConnectBars
);
3140 if( xTypeGroup
->IsValidGroup() )
3142 maTypeGroups
.AppendRecord( xTypeGroup
);
3149 if( XclExpChTypeGroup
* pGroup
= GetFirstTypeGroup().get() )
3151 const XclChExtTypeInfo
& rTypeInfo
= pGroup
->GetTypeInfo();
3153 // create axes according to chart type (no axes for pie and donut charts)
3154 if( rTypeInfo
.meTypeCateg
!= EXC_CHTYPECATEG_PIE
)
3156 ConvertAxis( mxXAxis
, EXC_CHAXIS_X
, mxXAxisTitle
, EXC_CHOBJLINK_XAXIS
, xCoordSystem
, rTypeInfo
, EXC_CHART_AXIS_Y
);
3157 ConvertAxis( mxYAxis
, EXC_CHAXIS_Y
, mxYAxisTitle
, EXC_CHOBJLINK_YAXIS
, xCoordSystem
, rTypeInfo
, EXC_CHART_AXIS_X
);
3158 if( pGroup
->Is3dDeepChart() )
3159 ConvertAxis( mxZAxis
, EXC_CHAXIS_Z
, mxZAxisTitle
, EXC_CHOBJLINK_ZAXIS
, xCoordSystem
, rTypeInfo
, EXC_CHART_AXIS_NONE
);
3162 // X axis category ranges
3163 if( rTypeInfo
.mbCategoryAxis
&& xApiXAxis
.is() )
3165 const ScaleData aScaleData
= xApiXAxis
->getScaleData();
3166 for( size_t nIdx
= 0, nSize
= maTypeGroups
.GetSize(); nIdx
< nSize
; ++nIdx
)
3167 maTypeGroups
.GetRecord( nIdx
)->ConvertCategSequence( aScaleData
.Categories
);
3171 if( xDiagram
.is() && (GetAxesSetId() == EXC_CHAXESSET_PRIMARY
) )
3173 Reference
< XLegend
> xLegend
= xDiagram
->getLegend();
3176 ScfPropertySet
aLegendProp( xLegend
);
3177 pGroup
->ConvertLegend( aLegendProp
);
3184 // wall/floor/diagram frame formatting
3185 if( xDiagram
.is() && (GetAxesSetId() == EXC_CHAXESSET_PRIMARY
) )
3187 XclExpChTypeGroupRef xTypeGroup
= GetFirstTypeGroup();
3188 if( xTypeGroup
&& xTypeGroup
->Is3dWallChart() )
3190 // wall/floor formatting (3D charts)
3192 mxXAxis
->ConvertWall( xDiagram
);
3194 mxYAxis
->ConvertWall( xDiagram
);
3198 // diagram background formatting
3199 ScfPropertySet
aWallProp( xDiagram
->getWall() );
3200 mxPlotFrame
= lclCreateFrame( GetChRoot(), aWallProp
, EXC_CHOBJTYPE_PLOTFRAME
);
3204 // inner and outer plot area position and size
3207 Reference
< cssc::XChartDocument
> xChart1Doc( GetChartDocument(), UNO_QUERY_THROW
);
3208 Reference
< cssc::XDiagramPositioning
> xPositioning( xChart1Doc
->getDiagram(), UNO_QUERY_THROW
);
3209 // set manual flag in chart data
3210 if( !xPositioning
->isAutomaticDiagramPositioning() )
3211 GetChartData().SetManualPlotArea();
3212 // the CHAXESSET record contains the inner plot area
3213 maData
.maRect
= CalcChartRectFromHmm( xPositioning
->calculateDiagramPositionExcludingAxes() );
3214 // the embedded CHFRAMEPOS record contains the outer plot area
3215 mxFramePos
.reset( new XclExpChFramePos( EXC_CHFRAMEPOS_PARENT
, EXC_CHFRAMEPOS_PARENT
) );
3216 // for pie charts, always use inner plot area size to exclude the data labels as Excel does
3217 const XclExpChTypeGroup
* pFirstTypeGroup
= GetFirstTypeGroup().get();
3218 bool bPieChart
= pFirstTypeGroup
&& (pFirstTypeGroup
->GetTypeInfo().meTypeCateg
== EXC_CHTYPECATEG_PIE
);
3219 mxFramePos
->GetFramePosData().maRect
= bPieChart
? maData
.maRect
:
3220 CalcChartRectFromHmm( xPositioning
->calculateDiagramPositionIncludingAxes() );
3226 // return first unused chart type group index for next axes set
3230 bool XclExpChAxesSet::Is3dChart() const
3232 XclExpChTypeGroupRef xTypeGroup
= GetFirstTypeGroup();
3233 return xTypeGroup
&& xTypeGroup
->Is3dChart();
3236 void XclExpChAxesSet::WriteSubRecords( XclExpStream
& rStrm
)
3238 lclSaveRecord( rStrm
, mxFramePos
);
3239 lclSaveRecord( rStrm
, mxXAxis
);
3240 lclSaveRecord( rStrm
, mxYAxis
);
3241 lclSaveRecord( rStrm
, mxZAxis
);
3242 lclSaveRecord( rStrm
, mxXAxisTitle
);
3243 lclSaveRecord( rStrm
, mxYAxisTitle
);
3244 lclSaveRecord( rStrm
, mxZAxisTitle
);
3247 XclExpEmptyRecord( EXC_ID_CHPLOTFRAME
).Save( rStrm
);
3248 mxPlotFrame
->Save( rStrm
);
3250 maTypeGroups
.Save( rStrm
);
3253 XclExpChTypeGroupRef
XclExpChAxesSet::GetFirstTypeGroup() const
3255 return maTypeGroups
.GetFirstRecord();
3258 XclExpChTypeGroupRef
XclExpChAxesSet::GetLastTypeGroup() const
3260 return maTypeGroups
.GetLastRecord();
3263 void XclExpChAxesSet::ConvertAxis(
3264 XclExpChAxisRef
& rxChAxis
, sal_uInt16 nAxisType
,
3265 XclExpChTextRef
& rxChAxisTitle
, sal_uInt16 nTitleTarget
,
3266 Reference
< XCoordinateSystem
> xCoordSystem
, const XclChExtTypeInfo
& rTypeInfo
,
3267 sal_Int32 nCrossingAxisDim
)
3269 // create and convert axis object
3270 rxChAxis
.reset( new XclExpChAxis( GetChRoot(), nAxisType
) );
3271 sal_Int32 nApiAxisDim
= rxChAxis
->GetApiAxisDimension();
3272 sal_Int32 nApiAxesSetIdx
= GetApiAxesSetIndex();
3273 Reference
< XAxis
> xAxis
= lclGetApiAxis( xCoordSystem
, nApiAxisDim
, nApiAxesSetIdx
);
3274 Reference
< XAxis
> xCrossingAxis
= lclGetApiAxis( xCoordSystem
, nCrossingAxisDim
, nApiAxesSetIdx
);
3275 Reference
< cssc::XAxis
> xChart1Axis
= lclGetApiChart1Axis( GetChartDocument(), nApiAxisDim
, nApiAxesSetIdx
);
3276 rxChAxis
->Convert( xAxis
, xCrossingAxis
, xChart1Axis
, rTypeInfo
);
3278 // create and convert axis title
3279 Reference
< XTitled
> xTitled( xAxis
, UNO_QUERY
);
3280 rxChAxisTitle
= lclCreateTitle( GetChRoot(), xTitled
, nTitleTarget
);
3283 void XclExpChAxesSet::WriteBody( XclExpStream
& rStrm
)
3285 rStrm
<< maData
.mnAxesSetId
<< maData
.maRect
;
3288 // The chart object ===========================================================
3290 static void lcl_getChartSubTitle(const Reference
<XChartDocument
>& xChartDoc
,
3291 OUString
& rSubTitle
)
3293 Reference
< ::com::sun::star::chart::XChartDocument
> xChartDoc1(xChartDoc
, UNO_QUERY
);
3294 if (!xChartDoc1
.is())
3297 Reference
< XPropertySet
> xProp(xChartDoc1
->getSubTitle(), UNO_QUERY
);
3302 Any any
= xProp
->getPropertyValue("String");
3307 XclExpChChart::XclExpChChart( const XclExpRoot
& rRoot
,
3308 Reference
< XChartDocument
> xChartDoc
, const Rectangle
& rChartRect
) :
3309 XclExpChGroupBase( XclExpChRoot( rRoot
, *this ), EXC_CHFRBLOCK_TYPE_CHART
, EXC_ID_CHCHART
, 16 )
3311 Size aPtSize
= OutputDevice::LogicToLogic( rChartRect
.GetSize(), MapMode( MAP_100TH_MM
), MapMode( MAP_POINT
) );
3312 // rectangle is stored in 16.16 fixed-point format
3313 maRect
.mnX
= maRect
.mnY
= 0;
3314 maRect
.mnWidth
= static_cast< sal_Int32
>( aPtSize
.Width() << 16 );
3315 maRect
.mnHeight
= static_cast< sal_Int32
>( aPtSize
.Height() << 16 );
3317 // global chart properties (default values)
3318 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_SHOWVISIBLEONLY
, false );
3319 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_MANPLOTAREA
);
3320 maProps
.mnEmptyMode
= EXC_CHPROPS_EMPTY_SKIP
;
3322 // always create both axes set objects
3323 mxPrimAxesSet
.reset( new XclExpChAxesSet( GetChRoot(), EXC_CHAXESSET_PRIMARY
) );
3324 mxSecnAxesSet
.reset( new XclExpChAxesSet( GetChRoot(), EXC_CHAXESSET_SECONDARY
) );
3326 if( xChartDoc
.is() )
3328 Reference
< XDiagram
> xDiagram
= xChartDoc
->getFirstDiagram();
3330 // global chart properties (only 'include hidden cells' attribute for now)
3331 ScfPropertySet
aDiagramProp( xDiagram
);
3332 bool bIncludeHidden
= aDiagramProp
.GetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS
);
3333 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_SHOWVISIBLEONLY
, !bIncludeHidden
);
3335 // initialize API conversion (remembers xChartDoc and rChartRect internally)
3336 InitConversion( xChartDoc
, rChartRect
);
3339 ScfPropertySet
aFrameProp( xChartDoc
->getPageBackground() );
3340 mxFrame
= lclCreateFrame( GetChRoot(), aFrameProp
, EXC_CHOBJTYPE_BACKGROUND
);
3343 Reference
< XTitled
> xTitled( xChartDoc
, UNO_QUERY
);
3345 lcl_getChartSubTitle(xChartDoc
, aSubTitle
);
3346 mxTitle
= lclCreateTitle( GetChRoot(), xTitled
, EXC_CHOBJLINK_TITLE
,
3347 !aSubTitle
.isEmpty() ? &aSubTitle
: NULL
);
3349 // diagrams (axes sets)
3350 sal_uInt16 nFreeGroupIdx
= mxPrimAxesSet
->Convert( xDiagram
, 0 );
3351 if( !mxPrimAxesSet
->Is3dChart() )
3352 mxSecnAxesSet
->Convert( xDiagram
, nFreeGroupIdx
);
3354 // treatment of missing values
3355 ScfPropertySet
aDiaProp( xDiagram
);
3356 sal_Int32 nMissingValues
= 0;
3357 if( aDiaProp
.GetProperty( nMissingValues
, EXC_CHPROP_MISSINGVALUETREATMENT
) )
3359 using namespace cssc::MissingValueTreatment
;
3360 switch( nMissingValues
)
3362 case LEAVE_GAP
: maProps
.mnEmptyMode
= EXC_CHPROPS_EMPTY_SKIP
; break;
3363 case USE_ZERO
: maProps
.mnEmptyMode
= EXC_CHPROPS_EMPTY_ZERO
; break;
3364 case CONTINUE
: maProps
.mnEmptyMode
= EXC_CHPROPS_EMPTY_INTERPOLATE
; break;
3368 // finish API conversion
3373 XclExpChSeriesRef
XclExpChChart::CreateSeries()
3375 XclExpChSeriesRef xSeries
;
3376 sal_uInt16 nSeriesIdx
= static_cast< sal_uInt16
>( maSeries
.GetSize() );
3377 if( nSeriesIdx
<= EXC_CHSERIES_MAXSERIES
)
3379 xSeries
.reset( new XclExpChSeries( GetChRoot(), nSeriesIdx
) );
3380 maSeries
.AppendRecord( xSeries
);
3385 void XclExpChChart::RemoveLastSeries()
3387 if( !maSeries
.IsEmpty() )
3388 maSeries
.RemoveRecord( maSeries
.GetSize() - 1 );
3391 void XclExpChChart::SetDataLabel( XclExpChTextRef xText
)
3394 maLabels
.AppendRecord( xText
);
3397 void XclExpChChart::SetManualPlotArea()
3399 // this flag does not exist in BIFF5
3400 if( GetBiff() == EXC_BIFF8
)
3401 ::set_flag( maProps
.mnFlags
, EXC_CHPROPS_USEMANPLOTAREA
);
3404 void XclExpChChart::WriteSubRecords( XclExpStream
& rStrm
)
3406 // background format
3407 lclSaveRecord( rStrm
, mxFrame
);
3410 maSeries
.Save( rStrm
);
3412 // CHPROPERTIES record
3413 rStrm
.StartRecord( EXC_ID_CHPROPERTIES
, 4 );
3414 rStrm
<< maProps
.mnFlags
<< maProps
.mnEmptyMode
<< sal_uInt8( 0 );
3417 // axes sets (always save primary axes set)
3418 sal_uInt16 nUsedAxesSets
= mxSecnAxesSet
->IsValidAxesSet() ? 2 : 1;
3419 XclExpUInt16Record( EXC_ID_CHUSEDAXESSETS
, nUsedAxesSets
).Save( rStrm
);
3420 mxPrimAxesSet
->Save( rStrm
);
3421 if( mxSecnAxesSet
->IsValidAxesSet() )
3422 mxSecnAxesSet
->Save( rStrm
);
3424 // chart title and data labels
3425 lclSaveRecord( rStrm
, mxTitle
);
3426 maLabels
.Save( rStrm
);
3429 void XclExpChChart::WriteBody( XclExpStream
& rStrm
)
3434 XclExpChartDrawing::XclExpChartDrawing( const XclExpRoot
& rRoot
,
3435 const Reference
< XModel
>& rxModel
, const Size
& rChartSize
) :
3438 if( (rChartSize
.Width() > 0) && (rChartSize
.Height() > 0) )
3440 ScfPropertySet
aPropSet( rxModel
);
3441 Reference
< XShapes
> xShapes
;
3442 if( aPropSet
.GetProperty( xShapes
, EXC_CHPROP_ADDITIONALSHAPES
) && xShapes
.is() && (xShapes
->getCount() > 0) )
3444 /* Create a new independent object manager with own DFF stream for the
3445 DGCONTAINER, pass global manager as parent for shared usage of
3446 global DFF data (picture container etc.). */
3447 mxObjMgr
.reset( new XclExpEmbeddedObjectManager( GetObjectManager(), rChartSize
, EXC_CHART_TOTALUNITS
, EXC_CHART_TOTALUNITS
) );
3448 // initialize the drawing object list
3449 mxObjMgr
->StartSheet();
3450 // process the draw page (convert all shapes)
3451 mxObjRecs
= mxObjMgr
->ProcessDrawing( xShapes
);
3452 // finalize the DFF stream
3453 mxObjMgr
->EndDocument();
3458 XclExpChartDrawing::~XclExpChartDrawing()
3462 void XclExpChartDrawing::Save( XclExpStream
& rStrm
)
3465 mxObjRecs
->Save( rStrm
);
3468 XclExpChart::XclExpChart( const XclExpRoot
& rRoot
, Reference
< XModel
> xModel
, const Rectangle
& rChartRect
) :
3469 XclExpSubStream( EXC_BOF_CHART
),
3472 AppendNewRecord( new XclExpChartPageSettings( rRoot
) );
3473 AppendNewRecord( new XclExpBoolRecord( EXC_ID_PROTECT
, false ) );
3474 AppendNewRecord( new XclExpChartDrawing( rRoot
, xModel
, rChartRect
.GetSize() ) );
3475 AppendNewRecord( new XclExpUInt16Record( EXC_ID_CHUNITS
, EXC_CHUNITS_TWIPS
) );
3477 Reference
< XChartDocument
> xChartDoc( xModel
, UNO_QUERY
);
3478 AppendNewRecord( new XclExpChChart( rRoot
, xChartDoc
, rChartRect
) );
3481 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */