LibreOffice Module sc (master)  1
xichart.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <xichart.hxx>
21 
22 #include <algorithm>
23 #include <memory>
24 #include <utility>
25 
26 #include <com/sun/star/frame/XModel.hpp>
27 #include <com/sun/star/drawing/Direction3D.hpp>
28 #include <com/sun/star/drawing/ProjectionMode.hpp>
29 #include <com/sun/star/drawing/ShadeMode.hpp>
30 #include <com/sun/star/drawing/XShape.hpp>
31 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
32 #include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp>
33 #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
34 #include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
35 #include <com/sun/star/chart/ChartAxisPosition.hpp>
36 #include <com/sun/star/chart/ChartLegendExpansion.hpp>
37 #include <com/sun/star/chart/TimeInterval.hpp>
38 #include <com/sun/star/chart/TimeUnit.hpp>
39 #include <com/sun/star/chart/XChartDocument.hpp>
40 #include <com/sun/star/chart/XDiagramPositioning.hpp>
41 #include <com/sun/star/chart/DataLabelPlacement.hpp>
42 #include <com/sun/star/chart/ErrorBarStyle.hpp>
43 #include <com/sun/star/chart/MissingValueTreatment.hpp>
44 #include <com/sun/star/chart2/LinearRegressionCurve.hpp>
45 #include <com/sun/star/chart2/ExponentialRegressionCurve.hpp>
46 #include <com/sun/star/chart2/LogarithmicRegressionCurve.hpp>
47 #include <com/sun/star/chart2/PotentialRegressionCurve.hpp>
48 #include <com/sun/star/chart2/PolynomialRegressionCurve.hpp>
49 #include <com/sun/star/chart2/MovingAverageRegressionCurve.hpp>
50 #include <com/sun/star/chart2/CartesianCoordinateSystem2d.hpp>
51 #include <com/sun/star/chart2/CartesianCoordinateSystem3d.hpp>
52 #include <com/sun/star/chart2/FormattedString.hpp>
53 #include <com/sun/star/chart2/LogarithmicScaling.hpp>
54 #include <com/sun/star/chart2/LinearScaling.hpp>
55 #include <com/sun/star/chart2/PolarCoordinateSystem2d.hpp>
56 #include <com/sun/star/chart2/PolarCoordinateSystem3d.hpp>
57 #include <com/sun/star/chart2/XChartDocument.hpp>
58 #include <com/sun/star/chart2/XDiagram.hpp>
59 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
60 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
61 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
62 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
63 #include <com/sun/star/chart2/XTitled.hpp>
64 #include <com/sun/star/chart2/AxisType.hpp>
65 #include <com/sun/star/chart2/CurveStyle.hpp>
66 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
67 #include <com/sun/star/chart2/DataPointLabel.hpp>
68 #include <com/sun/star/chart2/LegendPosition.hpp>
69 #include <com/sun/star/chart2/StackingDirection.hpp>
70 #include <com/sun/star/chart2/TickmarkStyle.hpp>
71 #include <com/sun/star/chart2/RelativePosition.hpp>
72 #include <com/sun/star/chart2/RelativeSize.hpp>
73 #include <com/sun/star/chart2/data/XDataProvider.hpp>
74 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
75 #include <com/sun/star/chart2/data/XDataSink.hpp>
76 #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
78 #include <o3tl/numeric.hxx>
79 #include <o3tl/unit_conversion.hxx>
80 #include <sfx2/objsh.hxx>
81 #include <svx/svdpage.hxx>
82 #include <svx/unoapi.hxx>
83 #include <sal/log.hxx>
84 #include <tools/helpers.hxx>
85 
86 #include <document.hxx>
87 #include <drwlayer.hxx>
88 #include <tokenarray.hxx>
89 #include <compiler.hxx>
90 #include <reftokenhelper.hxx>
91 #include <chartlis.hxx>
92 #include <globstr.hrc>
93 #include <scresid.hxx>
94 #include <xltracer.hxx>
95 #include <xltools.hxx>
96 #include <xistream.hxx>
97 #include <xiformula.hxx>
98 #include <xistyle.hxx>
99 #include <xipage.hxx>
100 #include <xiview.hxx>
101 
102 using ::com::sun::star::uno::Any;
103 using ::com::sun::star::uno::Reference;
104 using ::com::sun::star::uno::Sequence;
105 using ::com::sun::star::uno::UNO_QUERY;
106 using ::com::sun::star::uno::UNO_QUERY_THROW;
107 using ::com::sun::star::uno::UNO_SET_THROW;
108 using ::com::sun::star::uno::Exception;
109 using ::com::sun::star::beans::XPropertySet;
110 using ::com::sun::star::frame::XModel;
111 using ::com::sun::star::util::XNumberFormatsSupplier;
112 using ::com::sun::star::drawing::XDrawPage;
113 using ::com::sun::star::drawing::XDrawPageSupplier;
114 using ::com::sun::star::drawing::XShape;
115 
116 using namespace ::com::sun::star::chart2;
117 
118 using ::com::sun::star::chart2::data::XDataProvider;
119 using ::com::sun::star::chart2::data::XDataReceiver;
120 using ::com::sun::star::chart2::data::XDataSequence;
121 using ::com::sun::star::chart2::data::XDataSink;
122 using ::com::sun::star::chart2::data::XLabeledDataSequence;
123 using ::com::sun::star::chart2::data::LabeledDataSequence;
124 
125 using ::formula::FormulaToken;
126 using ::formula::FormulaTokenArrayPlainIterator;
127 using ::std::unique_ptr;
128 
129 namespace cssc = ::com::sun::star::chart;
130 namespace cssc2 = ::com::sun::star::chart2;
131 
132 // Helpers ====================================================================
133 
134 namespace {
135 
137 {
138  rRect.mnX = rStrm.ReadInt32();
139  rRect.mnY = rStrm.ReadInt32();
140  rRect.mnWidth = rStrm.ReadInt32();
141  rRect.mnHeight = rStrm.ReadInt32();
142  return rStrm;
143 }
144 
145 void lclSetValueOrClearAny( Any& rAny, double fValue, bool bClear )
146 {
147  if( bClear )
148  rAny.clear();
149  else
150  rAny <<= fValue;
151 }
152 
153 void lclSetExpValueOrClearAny( Any& rAny, double fValue, bool bLogScale, bool bClear )
154 {
155  if( !bClear && bLogScale )
156  fValue = pow( 10.0, fValue );
157  lclSetValueOrClearAny( rAny, fValue, bClear );
158 }
159 
160 double lclGetSerialDay( const XclImpRoot& rRoot, sal_uInt16 nValue, sal_uInt16 nTimeUnit )
161 {
162  switch( nTimeUnit )
163  {
165  return nValue;
167  return rRoot.GetDoubleFromDateTime( Date( 1, static_cast< sal_uInt16 >( 1 + nValue % 12 ), static_cast< sal_uInt16 >( rRoot.GetBaseYear() + nValue / 12 ) ) );
169  return rRoot.GetDoubleFromDateTime( Date( 1, 1, static_cast< sal_uInt16 >( rRoot.GetBaseYear() + nValue ) ) );
170  default:
171  OSL_ENSURE( false, "lclGetSerialDay - unexpected time unit" );
172  }
173  return nValue;
174 }
175 
176 void lclConvertTimeValue( const XclImpRoot& rRoot, Any& rAny, sal_uInt16 nValue, bool bAuto, sal_uInt16 nTimeUnit )
177 {
178  if( bAuto )
179  rAny.clear();
180  else
181  rAny <<= lclGetSerialDay( rRoot, nValue, nTimeUnit );
182 }
183 
184 sal_Int32 lclGetApiTimeUnit( sal_uInt16 nTimeUnit )
185 {
186  switch( nTimeUnit )
187  {
188  case EXC_CHDATERANGE_DAYS: return cssc::TimeUnit::DAY;
189  case EXC_CHDATERANGE_MONTHS: return cssc::TimeUnit::MONTH;
190  case EXC_CHDATERANGE_YEARS: return cssc::TimeUnit::YEAR;
191  default: OSL_ENSURE( false, "lclGetApiTimeUnit - unexpected time unit" );
192  }
193  return cssc::TimeUnit::DAY;
194 }
195 
196 void lclConvertTimeInterval( Any& rInterval, sal_uInt16 nValue, bool bAuto, sal_uInt16 nTimeUnit )
197 {
198  if( bAuto || (nValue == 0) )
199  rInterval.clear();
200  else
201  rInterval <<= cssc::TimeInterval( nValue, lclGetApiTimeUnit( nTimeUnit ) );
202 }
203 
204 } // namespace
205 
206 // Common =====================================================================
207 
210 {
212 
213  explicit XclImpChRootData( XclImpChChart& rChartData ) : mrChartData( rChartData ) {}
214 };
215 
217  XclImpRoot( rRoot ),
218  mxChData( std::make_shared<XclImpChRootData>( rChartData ) )
219 {
220 }
221 
223 {
224 }
225 
227 {
228  return mxChData->mrChartData;
229 }
230 
232 {
233  return mxChData->mxTypeInfoProv->GetTypeInfo( eType );
234 }
235 
236 const XclChTypeInfo& XclImpChRoot::GetChartTypeInfo( sal_uInt16 nRecId ) const
237 {
238  return mxChData->mxTypeInfoProv->GetTypeInfoFromRecId( nRecId );
239 }
240 
242 {
243  return mxChData->mxFmtInfoProv->GetFormatInfo( eObjType );
244 }
245 
247 {
249 }
250 
251 Color XclImpChRoot::GetSeriesLineAutoColor( sal_uInt16 nFormatIdx ) const
252 {
254 }
255 
256 Color XclImpChRoot::GetSeriesFillAutoColor( sal_uInt16 nFormatIdx ) const
257 {
258  const XclImpPalette& rPal = GetPalette();
259  Color aColor = rPal.GetColor( XclChartHelper::GetSeriesFillAutoColorIdx( nFormatIdx ) );
260  sal_uInt8 nTrans = XclChartHelper::GetSeriesFillAutoTransp( nFormatIdx );
261  return ScfTools::GetMixedColor( aColor, rPal.GetColor( EXC_COLOR_CHWINDOWBACK ), nTrans );
262 }
263 
264 void XclImpChRoot::InitConversion( const Reference<XChartDocument>& xChartDoc, const tools::Rectangle& rChartRect ) const
265 {
266  // create formatting object tables
267  mxChData->InitConversion( GetRoot(), xChartDoc, rChartRect );
268 
269  // lock the model to suppress any internal updates
270  if( xChartDoc.is() )
271  xChartDoc->lockControllers();
272 
273  SfxObjectShell* pDocShell = GetDocShell();
274  Reference< XDataReceiver > xDataRec( xChartDoc, UNO_QUERY );
275  if( pDocShell && xDataRec.is() )
276  {
277  // create and register a data provider
278  Reference< XDataProvider > xDataProv(
280  if( xDataProv.is() )
281  xDataRec->attachDataProvider( xDataProv );
282  // attach the number formatter
283  Reference< XNumberFormatsSupplier > xNumFmtSupp( pDocShell->GetModel(), UNO_QUERY );
284  if( xNumFmtSupp.is() )
285  xDataRec->attachNumberFormatsSupplier( xNumFmtSupp );
286  }
287 }
288 
290 {
291  rDffConv.Progress( EXC_CHART_PROGRESS_SIZE );
292  // unlock the model
293  Reference< XModel > xModel = mxChData->mxChartDoc;
294  if( xModel.is() )
295  xModel->unlockControllers();
296  rDffConv.Progress( EXC_CHART_PROGRESS_SIZE );
297 
298  mxChData->FinishConversion();
299 }
300 
301 Reference< XDataProvider > XclImpChRoot::GetDataProvider() const
302 {
303  return mxChData->mxChartDoc->getDataProvider();
304 }
305 
306 Reference< XShape > XclImpChRoot::GetTitleShape( const XclChTextKey& rTitleKey ) const
307 {
308  return mxChData->GetTitleShape( rTitleKey );
309 }
310 
311 sal_Int32 XclImpChRoot::CalcHmmFromChartX( sal_Int32 nPosX ) const
312 {
313  return static_cast< sal_Int32 >( mxChData->mfUnitSizeX * nPosX + mxChData->mnBorderGapX + 0.5 );
314 }
315 
316 sal_Int32 XclImpChRoot::CalcHmmFromChartY( sal_Int32 nPosY ) const
317 {
318  return static_cast< sal_Int32 >( mxChData->mfUnitSizeY * nPosY + mxChData->mnBorderGapY + 0.5 );
319 }
320 
321 css::awt::Rectangle XclImpChRoot::CalcHmmFromChartRect( const XclChRectangle& rRect ) const
322 {
323  return css::awt::Rectangle(
324  CalcHmmFromChartX( rRect.mnX ),
325  CalcHmmFromChartY( rRect.mnY ),
326  CalcHmmFromChartX( rRect.mnWidth ),
327  CalcHmmFromChartY( rRect.mnHeight ) );
328 }
329 
330 double XclImpChRoot::CalcRelativeFromHmmX( sal_Int32 nPosX ) const
331 {
332  const tools::Long nWidth = mxChData->maChartRect.GetWidth();
333  if (!nWidth)
334  throw o3tl::divide_by_zero();
335  return static_cast<double>(nPosX) / nWidth;
336 }
337 
338 double XclImpChRoot::CalcRelativeFromHmmY( sal_Int32 nPosY ) const
339 {
340  const tools::Long nHeight = mxChData->maChartRect.GetHeight();
341  if (!nHeight)
342  throw o3tl::divide_by_zero();
343  return static_cast<double >(nPosY) / nHeight;
344 }
345 
346 double XclImpChRoot::CalcRelativeFromChartX( sal_Int32 nPosX ) const
347 {
348  return CalcRelativeFromHmmX( CalcHmmFromChartX( nPosX ) );
349 }
350 
351 double XclImpChRoot::CalcRelativeFromChartY( sal_Int32 nPosY ) const
352 {
353  return CalcRelativeFromHmmY( CalcHmmFromChartY( nPosY ) );
354 }
355 
357  const XclChLineFormat& rLineFmt, XclChPropertyMode ePropMode ) const
358 {
360  rPropSet, *mxChData->mxLineDashTable, rLineFmt, ePropMode );
361 }
362 
364  const XclChAreaFormat& rAreaFmt, XclChPropertyMode ePropMode ) const
365 {
366  GetChartPropSetHelper().WriteAreaProperties( rPropSet, rAreaFmt, ePropMode );
367 }
368 
370  const XclChEscherFormat& rEscherFmt, const XclChPicFormat* pPicFmt,
371  sal_uInt32 nDffFillType, XclChPropertyMode ePropMode ) const
372 {
374  *mxChData->mxGradientTable, *mxChData->mxBitmapTable,
375  rEscherFmt, pPicFmt, nDffFillType, ePropMode );
376 }
377 
379  sal_uInt16 nFontIdx, const Color* pFontColor ) const
380 {
381  GetFontBuffer().WriteFontProperties( rPropSet, EXC_FONTPROPSET_CHART, nFontIdx, pFontColor );
382 }
383 
384 void XclImpChRoot::ConvertPieRotation( ScfPropertySet& rPropSet, sal_uInt16 nAngle )
385 {
386  sal_Int32 nApiRot = (450 - (nAngle % 360)) % 360;
387  rPropSet.SetProperty( EXC_CHPROP_STARTINGANGLE, nApiRot );
388 }
389 
391 {
392 }
393 
395 {
396  // read contents of the header record
397  ReadHeaderRecord( rStrm );
398 
399  // only read sub records, if the next record is a CHBEGIN
400  if( rStrm.GetNextRecId() != EXC_ID_CHBEGIN )
401  return;
402 
403  // read the CHBEGIN record, may be used for special initial processing
404  rStrm.StartNextRecord();
405  ReadSubRecord( rStrm );
406 
407  // read the nested records
408  bool bLoop = true;
409  while( bLoop && rStrm.StartNextRecord() )
410  {
411  sal_uInt16 nRecId = rStrm.GetRecId();
412  bLoop = nRecId != EXC_ID_CHEND;
413  // skip unsupported nested blocks
414  if( nRecId == EXC_ID_CHBEGIN )
415  SkipBlock( rStrm );
416  else
417  ReadSubRecord( rStrm );
418  }
419  /* Returns with current CHEND record or unchanged stream, if no record
420  group present. In every case another call to StartNextRecord() will go
421  to next record of interest. */
422 }
423 
425 {
426  OSL_ENSURE( rStrm.GetRecId() == EXC_ID_CHBEGIN, "XclImpChGroupBase::SkipBlock - no CHBEGIN record" );
427  // do nothing if current record is not CHBEGIN
428  bool bLoop = rStrm.GetRecId() == EXC_ID_CHBEGIN;
429  while( bLoop && rStrm.StartNextRecord() )
430  {
431  sal_uInt16 nRecId = rStrm.GetRecId();
432  bLoop = nRecId != EXC_ID_CHEND;
433  // skip nested record groups
434  if( nRecId == EXC_ID_CHBEGIN )
435  SkipBlock( rStrm );
436  }
437 }
438 
439 // Frame formatting ===========================================================
440 
442 {
443  maData.mnTLMode = rStrm.ReaduInt16();
444  maData.mnBRMode = rStrm.ReaduInt16();
445  /* According to the spec, the upper 16 bits of all members in the
446  rectangle are unused and may contain garbage. */
447  maData.maRect.mnX = rStrm.ReadInt16(); rStrm.Ignore( 2 );
448  maData.maRect.mnY = rStrm.ReadInt16(); rStrm.Ignore( 2 );
449  maData.maRect.mnWidth = rStrm.ReadInt16(); rStrm.Ignore( 2 );
450  maData.maRect.mnHeight = rStrm.ReadInt16(); rStrm.Ignore( 2 );
451 }
452 
454 {
455  rStrm >> maData.maColor;
456  maData.mnPattern = rStrm.ReaduInt16();
457  maData.mnWeight = rStrm.ReadInt16();
458  maData.mnFlags = rStrm.ReaduInt16();
459 
460  const XclImpRoot& rRoot = rStrm.GetRoot();
461  if( rRoot.GetBiff() == EXC_BIFF8 )
462  // BIFF8: index into palette used instead of RGB data
463  maData.maColor = rRoot.GetPalette().GetColor( rStrm.ReaduInt16() );
464 }
465 
467  ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx ) const
468 {
469  const XclChFormatInfo& rFmtInfo = rRoot.GetFormatInfo( eObjType );
470  if( IsAuto() )
471  {
472  XclChLineFormat aLineFmt;
473  aLineFmt.maColor = (eObjType == EXC_CHOBJTYPE_LINEARSERIES) ?
474  rRoot.GetSeriesLineAutoColor( nFormatIdx ) :
475  rRoot.GetPalette().GetColor( rFmtInfo.mnAutoLineColorIdx );
477  aLineFmt.mnWeight = rFmtInfo.mnAutoLineWeight;
478  rRoot.ConvertLineFormat( rPropSet, aLineFmt, rFmtInfo.mePropMode );
479  }
480  else
481  {
482  rRoot.ConvertLineFormat( rPropSet, maData, rFmtInfo.mePropMode );
483  }
484 }
485 
487 {
488  rStrm >> maData.maPattColor >> maData.maBackColor;
489  maData.mnPattern = rStrm.ReaduInt16();
490  maData.mnFlags = rStrm.ReaduInt16();
491 
492  const XclImpRoot& rRoot = rStrm.GetRoot();
493  if( rRoot.GetBiff() == EXC_BIFF8 )
494  {
495  // BIFF8: index into palette used instead of RGB data
496  const XclImpPalette& rPal = rRoot.GetPalette();
497  maData.maPattColor = rPal.GetColor( rStrm.ReaduInt16() );
498  maData.maBackColor = rPal.GetColor( rStrm.ReaduInt16());
499  }
500 }
501 
503  ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx ) const
504 {
505  const XclChFormatInfo& rFmtInfo = rRoot.GetFormatInfo( eObjType );
506  if( IsAuto() )
507  {
508  XclChAreaFormat aAreaFmt;
509  aAreaFmt.maPattColor = (eObjType == EXC_CHOBJTYPE_FILLEDSERIES) ?
510  rRoot.GetSeriesFillAutoColor( nFormatIdx ) :
511  rRoot.GetPalette().GetColor( rFmtInfo.mnAutoPattColorIdx );
512  aAreaFmt.mnPattern = EXC_PATT_SOLID;
513  rRoot.ConvertAreaFormat( rPropSet, aAreaFmt, rFmtInfo.mePropMode );
514  }
515  else
516  {
517  rRoot.ConvertAreaFormat( rPropSet, maData, rFmtInfo.mePropMode );
518  }
519 }
520 
522  mnDffFillType( mso_fillSolid )
523 {
524  maData.mxItemSet =
525  std::make_shared<SfxItemSet>( rRoot.GetDoc().GetDrawLayer()->GetItemPool() );
526 }
527 
529 {
530  // read from stream - CHESCHERFORMAT uses own ID for record continuation
531  XclImpDffPropSet aPropSet( rStrm.GetRoot() );
532  rStrm.ResetRecord( true, rStrm.GetRecId() );
533  rStrm >> aPropSet;
534  // get the data
535  aPropSet.FillToItemSet( *maData.mxItemSet );
536  // get fill type from DFF property set
537  mnDffFillType = aPropSet.GetPropertyValue( DFF_Prop_fillType );
538 }
539 
541 {
542  switch( rStrm.GetRecId() )
543  {
544  case EXC_ID_CHPICFORMAT:
545  maPicFmt.mnBmpMode = rStrm.ReaduInt16();
546  rStrm.Ignore( 2 );
547  maPicFmt.mnFlags = rStrm.ReaduInt16();
548  maPicFmt.mfScale = rStrm.ReadDouble();
549  break;
550  }
551 }
552 
554  ScfPropertySet& rPropSet, XclChObjectType eObjType, bool bUsePicFmt ) const
555 {
556  const XclChFormatInfo& rFmtInfo = rRoot.GetFormatInfo( eObjType );
557  rRoot.ConvertEscherFormat( rPropSet, maData, bUsePicFmt ? &maPicFmt : nullptr, mnDffFillType, rFmtInfo.mePropMode );
558 }
559 
561 {
562  if( !rFmtInfo.mbCreateDefFrame )
563  return;
564 
565  switch( rFmtInfo.meDefFrameType )
566  {
569  if( rFmtInfo.mbIsFrame )
570  mxAreaFmt = std::make_shared<XclImpChAreaFormat>();
571  break;
573  {
574  XclChLineFormat aLineFmt;
575  ::set_flag( aLineFmt.mnFlags, EXC_CHLINEFORMAT_AUTO, false );
576  aLineFmt.mnPattern = EXC_CHLINEFORMAT_NONE;
577  mxLineFmt = new XclImpChLineFormat( aLineFmt );
578  if( rFmtInfo.mbIsFrame )
579  {
580  XclChAreaFormat aAreaFmt;
581  ::set_flag( aAreaFmt.mnFlags, EXC_CHAREAFORMAT_AUTO, false );
582  aAreaFmt.mnPattern = EXC_PATT_NONE;
583  mxAreaFmt = std::make_shared<XclImpChAreaFormat>( aAreaFmt );
584  }
585  }
586  break;
587  default:
588  OSL_FAIL( "XclImpChFrameBase::XclImpChFrameBase - unknown frame type" );
589  }
590 }
591 
593 {
594  switch( rStrm.GetRecId() )
595  {
596  case EXC_ID_CHLINEFORMAT:
598  mxLineFmt->ReadChLineFormat( rStrm );
599  break;
600  case EXC_ID_CHAREAFORMAT:
601  mxAreaFmt = std::make_shared<XclImpChAreaFormat>();
602  mxAreaFmt->ReadChAreaFormat( rStrm );
603  break;
605  mxEscherFmt = std::make_shared<XclImpChEscherFormat>( rStrm.GetRoot() );
606  mxEscherFmt->ReadRecordGroup( rStrm );
607  break;
608  }
609 }
610 
612  ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx ) const
613 {
614  if( mxLineFmt )
615  mxLineFmt->Convert( rRoot, rPropSet, eObjType, nFormatIdx );
616 }
617 
619  ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx, bool bUsePicFmt ) const
620 {
621  if( rRoot.GetFormatInfo( eObjType ).mbIsFrame )
622  {
623  // CHESCHERFORMAT overrides CHAREAFORMAT (even if it is auto)
624  if( mxEscherFmt )
625  mxEscherFmt->Convert( rRoot, rPropSet, eObjType, bUsePicFmt );
626  else if( mxAreaFmt )
627  mxAreaFmt->Convert( rRoot, rPropSet, eObjType, nFormatIdx );
628  }
629 }
630 
632  ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx, bool bUsePicFmt ) const
633 {
634  ConvertLineBase( rRoot, rPropSet, eObjType, nFormatIdx );
635  ConvertAreaBase( rRoot, rPropSet, eObjType, nFormatIdx, bUsePicFmt );
636 }
637 
639  XclImpChFrameBase( rRoot.GetFormatInfo( eObjType ) ),
640  XclImpChRoot( rRoot ),
641  meObjType( eObjType )
642 {
643 }
644 
646 {
647  maData.mnFormat = rStrm.ReaduInt16();
648  maData.mnFlags = rStrm.ReaduInt16();
649 }
650 
651 void XclImpChFrame::UpdateObjFrame( const XclObjLineData& rLineData, const XclObjFillData& rFillData )
652 {
653  const XclImpPalette& rPal = GetPalette();
654 
655  if( rLineData.IsVisible() && (!mxLineFmt || !mxLineFmt->HasLine()) )
656  {
657  // line formatting
658  XclChLineFormat aLineFmt;
659  aLineFmt.maColor = rPal.GetColor( rLineData.mnColorIdx );
660  switch( rLineData.mnStyle )
661  {
662  case EXC_OBJ_LINE_SOLID: aLineFmt.mnPattern = EXC_CHLINEFORMAT_SOLID; break;
663  case EXC_OBJ_LINE_DASH: aLineFmt.mnPattern = EXC_CHLINEFORMAT_DASH; break;
664  case EXC_OBJ_LINE_DOT: aLineFmt.mnPattern = EXC_CHLINEFORMAT_DOT; break;
670  case EXC_OBJ_LINE_NONE: aLineFmt.mnPattern = EXC_CHLINEFORMAT_NONE; break;
671  default: aLineFmt.mnPattern = EXC_CHLINEFORMAT_SOLID;
672  }
673  switch( rLineData.mnWidth )
674  {
675  case EXC_OBJ_LINE_HAIR: aLineFmt.mnWeight = EXC_CHLINEFORMAT_HAIR; break;
676  case EXC_OBJ_LINE_THIN: aLineFmt.mnWeight = EXC_CHLINEFORMAT_SINGLE; break;
677  case EXC_OBJ_LINE_MEDIUM: aLineFmt.mnWeight = EXC_CHLINEFORMAT_DOUBLE; break;
678  case EXC_OBJ_LINE_THICK: aLineFmt.mnWeight = EXC_CHLINEFORMAT_TRIPLE; break;
679  default: aLineFmt.mnWeight = EXC_CHLINEFORMAT_HAIR;
680  }
681  ::set_flag( aLineFmt.mnFlags, EXC_CHLINEFORMAT_AUTO, rLineData.IsAuto() );
682  mxLineFmt = new XclImpChLineFormat( aLineFmt );
683  }
684 
685  if( rFillData.IsFilled() && (!mxAreaFmt || !mxAreaFmt->HasArea()) && !mxEscherFmt )
686  {
687  // area formatting
688  XclChAreaFormat aAreaFmt;
689  aAreaFmt.maPattColor = rPal.GetColor( rFillData.mnPattColorIdx );
690  aAreaFmt.maBackColor = rPal.GetColor( rFillData.mnBackColorIdx );
691  aAreaFmt.mnPattern = rFillData.mnPattern;
692  ::set_flag( aAreaFmt.mnFlags, EXC_CHAREAFORMAT_AUTO, rFillData.IsAuto() );
693  mxAreaFmt = std::make_shared<XclImpChAreaFormat>( aAreaFmt );
694  }
695 }
696 
697 void XclImpChFrame::Convert( ScfPropertySet& rPropSet, bool bUsePicFmt ) const
698 {
699  ConvertFrameBase( GetChRoot(), rPropSet, meObjType, EXC_CHDATAFORMAT_UNKNOWN, bUsePicFmt );
700 }
701 
702 // Source links ===============================================================
703 
704 namespace {
705 
707 Reference< XLabeledDataSequence > lclCreateLabeledDataSequence(
708  const XclImpChSourceLinkRef& xValueLink, const OUString& rValueRole,
709  const XclImpChSourceLink* pTitleLink = nullptr )
710 {
711  // create data sequence for values and title
712  Reference< XDataSequence > xValueSeq;
713  if( xValueLink )
714  xValueSeq = xValueLink->CreateDataSequence( rValueRole );
715  Reference< XDataSequence > xTitleSeq;
716  if( pTitleLink )
717  xTitleSeq = pTitleLink->CreateDataSequence( EXC_CHPROP_ROLE_LABEL );
718 
719  // create the labeled data sequence, if values or title are present
720  Reference< XLabeledDataSequence > xLabeledSeq;
721  if( xValueSeq.is() || xTitleSeq.is() )
722  xLabeledSeq = LabeledDataSequence::create(comphelper::getProcessComponentContext());
723  if( xLabeledSeq.is() )
724  {
725  if( xValueSeq.is() )
726  xLabeledSeq->setValues( xValueSeq );
727  if( xTitleSeq.is() )
728  xLabeledSeq->setLabel( xTitleSeq );
729  }
730  return xLabeledSeq;
731 }
732 
733 } // namespace
734 
736  XclImpChRoot( rRoot )
737 {
738 }
739 
741 {
742 }
743 
745 {
746  maData.mnDestType = rStrm.ReaduInt8();
747  maData.mnLinkType = rStrm.ReaduInt8();
748  maData.mnFlags = rStrm.ReaduInt16();
749  maData.mnNumFmtIdx = rStrm.ReaduInt16();
750 
751  mxTokenArray.reset();
753  {
754  // read token array
755  XclTokenArray aXclTokArr;
756  rStrm >> aXclTokArr;
757 
758  // convert BIFF formula tokens to Calc token array
759  if( std::unique_ptr<ScTokenArray> pTokens = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CHART, aXclTokArr ) )
760  mxTokenArray = std::move( pTokens );
761  }
762 
763  // try to read a following CHSTRING record
764  if( (rStrm.GetNextRecId() == EXC_ID_CHSTRING) && rStrm.StartNextRecord() )
765  {
766  mxString = std::make_shared<XclImpString>();
767  rStrm.Ignore( 2 );
769  }
770 }
771 
772 void XclImpChSourceLink::SetString( const OUString& rString )
773 {
774  if( !mxString )
775  mxString = std::make_shared<XclImpString>();
776  mxString->SetText( rString );
777 }
778 
780 {
781  if( mxString )
782  mxString->SetFormats( std::move(rFormats) );
783 }
784 
786 {
787  sal_uInt32 nCellCount = 0;
788  if( mxTokenArray )
789  {
790  FormulaTokenArrayPlainIterator aIter(*mxTokenArray);
791  for( const FormulaToken* pToken = aIter.First(); pToken; pToken = aIter.Next() )
792  {
793  switch( pToken->GetType() )
794  {
795  case ::formula::svSingleRef:
796  case ::formula::svExternalSingleRef:
797  // single cell
798  ++nCellCount;
799  break;
800  case ::formula::svDoubleRef:
801  case ::formula::svExternalDoubleRef:
802  {
803  // cell range
804  const ScComplexRefData& rComplexRef = *pToken->GetDoubleRef();
805  ScAddress aAbs1 = rComplexRef.Ref1.toAbs(GetRoot().GetDoc(), ScAddress());
806  ScAddress aAbs2 = rComplexRef.Ref2.toAbs(GetRoot().GetDoc(), ScAddress());
807  sal_uInt32 nTabs = static_cast<sal_uInt32>(aAbs2.Tab() - aAbs1.Tab() + 1);
808  sal_uInt32 nCols = static_cast<sal_uInt32>(aAbs2.Col() - aAbs1.Col() + 1);
809  sal_uInt32 nRows = static_cast<sal_uInt32>(aAbs2.Row() - aAbs1.Row() + 1);
810  nCellCount += nCols * nRows * nTabs;
811  }
812  break;
813  default: ;
814  }
815  }
816  }
817  return limit_cast< sal_uInt16 >( nCellCount );
818 }
819 
820 void XclImpChSourceLink::ConvertNumFmt( ScfPropertySet& rPropSet, bool bPercent ) const
821 {
822  bool bLinkToSource = ::get_flag( maData.mnFlags, EXC_CHSRCLINK_NUMFMT );
823  sal_uInt32 nScNumFmt = bLinkToSource ? GetNumFmtBuffer().GetScFormat( maData.mnNumFmtIdx ) : NUMBERFORMAT_ENTRY_NOT_FOUND;
824  OUString aPropName = bPercent ? OUString( EXC_CHPROP_PERCENTAGENUMFMT ) : OUString( EXC_CHPROP_NUMBERFORMAT );
825  if( nScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND )
826  rPropSet.SetProperty( aPropName, static_cast< sal_Int32 >( nScNumFmt ) );
827  else
828  // restore 'link to source' at data point (series may contain manual number format)
829  rPropSet.SetAnyProperty( aPropName, Any() );
830 }
831 
832 Reference< XDataSequence > XclImpChSourceLink::CreateDataSequence( const OUString& rRole ) const
833 {
834  Reference< XDataSequence > xDataSeq;
835  Reference< XDataProvider > xDataProv = GetDataProvider();
836  if( xDataProv.is() )
837  {
838  if ( mxTokenArray )
839  {
840  ScCompiler aComp( GetDoc(), ScAddress(), *mxTokenArray, GetDoc().GetGrammar() );
841  OUStringBuffer aRangeRep;
842  aComp.CreateStringFromTokenArray( aRangeRep );
843  try
844  {
845  xDataSeq = xDataProv->createDataSequenceByRangeRepresentation( aRangeRep.makeStringAndClear() );
846  // set sequence role
847  ScfPropertySet aSeqProp( xDataSeq );
848  aSeqProp.SetProperty( EXC_CHPROP_ROLE, rRole );
849  }
850  catch( Exception& )
851  {
852  // OSL_FAIL( "XclImpChSourceLink::CreateDataSequence - cannot create data sequence" );
853  }
854  }
855  else if( rRole == EXC_CHPROP_ROLE_LABEL && mxString && !mxString->GetText().isEmpty() )
856  {
857  try
858  {
859  OUString aString("\"");
860  xDataSeq = xDataProv->createDataSequenceByRangeRepresentation( aString + mxString->GetText() + aString );
861  // set sequence role
862  ScfPropertySet aSeqProp( xDataSeq );
863  aSeqProp.SetProperty( EXC_CHPROP_ROLE, rRole );
864  }
865  catch( Exception& ) { }
866  }
867  }
868  return xDataSeq;
869 }
870 
871 Sequence< Reference< XFormattedString > > XclImpChSourceLink::CreateStringSequence(
872  const XclImpChRoot& rRoot, sal_uInt16 nLeadFontIdx, const Color& rLeadFontColor ) const
873 {
874  ::std::vector< Reference< XFormattedString > > aStringVec;
875  if( mxString )
876  {
877  for( XclImpStringIterator aIt( *mxString ); aIt.Is(); ++aIt )
878  {
879  Reference< css::chart2::XFormattedString2 > xFmtStr = css::chart2::FormattedString::create( comphelper::getProcessComponentContext() );
880  // set text data
881  xFmtStr->setString( aIt.GetPortionText() );
882 
883  // set font formatting and font color
884  ScfPropertySet aStringProp( xFmtStr );
885  sal_uInt16 nFontIdx = aIt.GetPortionFont();
886  if( (nFontIdx == EXC_FONT_NOTFOUND) && (aIt.GetPortionIndex() == 0) )
887  // leading unformatted portion - use passed font settings
888  rRoot.ConvertFont( aStringProp, nLeadFontIdx, &rLeadFontColor );
889  else
890  rRoot.ConvertFont( aStringProp, nFontIdx );
891 
892  // add string to vector of strings
893  aStringVec.emplace_back(xFmtStr );
894  }
895  }
896  return ScfApiHelper::VectorToSequence( aStringVec );
897 }
898 
899 void XclImpChSourceLink::FillSourceLink( ::std::vector< ScTokenRef >& rTokens ) const
900 {
901  if( !mxTokenArray )
902  // no links to fill.
903  return;
904 
905  FormulaTokenArrayPlainIterator aIter(*mxTokenArray);
906  for (FormulaToken* p = aIter.First(); p; p = aIter.Next())
907  {
908  ScTokenRef pToken(p->Clone());
909  if (ScRefTokenHelper::isRef(pToken))
910  // This is a reference token. Store it.
911  ScRefTokenHelper::join(&GetRoot().GetDoc(), rTokens, pToken, ScAddress());
912  }
913 }
914 
915 // Text =======================================================================
916 
918 {
919 }
920 
921 void XclImpChFontBase::ConvertFontBase( const XclImpChRoot& rRoot, ScfPropertySet& rPropSet ) const
922 {
923  Color aFontColor = GetFontColor();
924  rRoot.ConvertFont( rPropSet, GetFontIndex(), &aFontColor );
925 }
926 
927 void XclImpChFontBase::ConvertRotationBase( ScfPropertySet& rPropSet, bool bSupportsStacked ) const
928 {
929  XclChPropSetHelper::WriteRotationProperties( rPropSet, GetRotation(), bSupportsStacked );
930 }
931 
933  mnFontIdx( EXC_FONT_NOTFOUND )
934 {
935 }
936 
938 {
939  mnFontIdx = rStrm.ReaduInt16();
940 }
941 
943  XclImpChRoot( rRoot )
944 {
945 }
946 
948 {
949  maData.mnHAlign = rStrm.ReaduInt8();
950  maData.mnVAlign = rStrm.ReaduInt8();
951  maData.mnBackMode = rStrm.ReaduInt16();
952  rStrm >> maData.maTextColor
953  >> maData.maRect;
954  maData.mnFlags = rStrm.ReaduInt16();
955 
956  if( GetBiff() == EXC_BIFF8 )
957  {
958  // BIFF8: index into palette used instead of RGB data
960  // placement and rotation
961  maData.mnFlags2 = rStrm.ReaduInt16();
962  maData.mnRotation = rStrm.ReaduInt16();
963  }
964  else
965  {
966  // BIFF2-BIFF7: get rotation from text orientation
967  sal_uInt8 nOrient = ::extract_value< sal_uInt8 >( maData.mnFlags, 8, 3 );
969  }
970 }
971 
973 {
974  switch( rStrm.GetRecId() )
975  {
976  case EXC_ID_CHFRAMEPOS:
977  mxFramePos = std::make_shared<XclImpChFramePos>();
978  mxFramePos->ReadChFramePos( rStrm );
979  break;
980  case EXC_ID_CHFONT:
981  mxFont = std::make_shared<XclImpChFont>();
982  mxFont->ReadChFont( rStrm );
983  break;
984  case EXC_ID_CHFORMATRUNS:
985  if( GetBiff() == EXC_BIFF8 )
987  break;
988  case EXC_ID_CHSOURCELINK:
989  mxSrcLink = std::make_shared<XclImpChSourceLink>( GetChRoot() );
990  mxSrcLink->ReadChSourceLink( rStrm );
991  break;
992  case EXC_ID_CHFRAME:
993  mxFrame = std::make_shared<XclImpChFrame>( GetChRoot(), EXC_CHOBJTYPE_TEXT );
994  mxFrame->ReadRecordGroup( rStrm );
995  break;
996  case EXC_ID_CHOBJECTLINK:
997  maObjLink.mnTarget = rStrm.ReaduInt16();
1000  break;
1001  case EXC_ID_CHFRLABELPROPS:
1002  ReadChFrLabelProps( rStrm );
1003  break;
1004  case EXC_ID_CHEND:
1005  if( mxSrcLink && !maFormats.empty() )
1006  mxSrcLink->SetTextFormats( std::vector(maFormats) );
1007  break;
1008  }
1009 }
1010 
1011 sal_uInt16 XclImpChText::GetFontIndex() const
1012 {
1013  return mxFont ? mxFont->GetFontIndex() : EXC_FONT_NOTFOUND;
1014 }
1015 
1017 {
1019 }
1020 
1021 sal_uInt16 XclImpChText::GetRotation() const
1022 {
1023  return maData.mnRotation;
1024 }
1025 
1026 void XclImpChText::SetString( const OUString& rString )
1027 {
1028  if( !mxSrcLink )
1029  mxSrcLink = std::make_shared<XclImpChSourceLink>( GetChRoot() );
1030  mxSrcLink->SetString( rString );
1031 }
1032 
1033 void XclImpChText::UpdateText( const XclImpChText* pParentText )
1034 {
1035  if( !pParentText )
1036  return;
1037 
1038  // update missing members
1039  if( !mxFrame )
1040  mxFrame = pParentText->mxFrame;
1041  if( !mxFont )
1042  {
1043  mxFont = pParentText->mxFont;
1044  // text color is taken from CHTEXT record, not from font in CHFONT
1046  maData.maTextColor = pParentText->maData.maTextColor;
1047  }
1048 }
1049 
1050 void XclImpChText::UpdateDataLabel( bool bCateg, bool bValue, bool bPercent )
1051 {
1055  ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWCATEGPERC, bCateg && bPercent );
1056  ::set_flag( maData.mnFlags, EXC_CHTEXT_DELETED, !bCateg && !bValue && !bPercent );
1057 }
1058 
1060 {
1061  ConvertFontBase( GetChRoot(), rPropSet );
1062 }
1063 
1064 void XclImpChText::ConvertRotation( ScfPropertySet& rPropSet, bool bSupportsStacked ) const
1065 {
1066  ConvertRotationBase( rPropSet, bSupportsStacked );
1067 }
1068 
1070 {
1071  if( mxFrame )
1072  mxFrame->Convert( rPropSet );
1073 }
1074 
1075 void XclImpChText::ConvertNumFmt( ScfPropertySet& rPropSet, bool bPercent ) const
1076 {
1077  if( mxSrcLink )
1078  mxSrcLink->ConvertNumFmt( rPropSet, bPercent );
1079 }
1080 
1081 void XclImpChText::ConvertDataLabel( ScfPropertySet& rPropSet, const XclChTypeInfo& rTypeInfo, const ScfPropertySet* pGlobalPropSet ) const
1082 {
1083  // existing CHFRLABELPROPS record wins over flags from CHTEXT
1084  sal_uInt16 nShowFlags = mxLabelProps ? mxLabelProps->mnFlags : maData.mnFlags;
1086  sal_uInt16 SHOWANYVALUE = mxLabelProps ? EXC_CHFRLABELPROPS_SHOWVALUE : EXC_CHTEXT_SHOWVALUE;
1088  sal_uInt16 SHOWANYBUBBLE = mxLabelProps ? EXC_CHFRLABELPROPS_SHOWBUBBLE : EXC_CHTEXT_SHOWBUBBLE;
1089 
1090  // get raw flags for label values
1091  bool bShowNone = IsDeleted();
1092  bool bShowCateg = !bShowNone && ::get_flag( nShowFlags, SHOWANYCATEG );
1093  bool bShowPercent = !bShowNone && ::get_flag( nShowFlags, SHOWANYPERCENT );
1094  bool bShowValue = !bShowNone && ::get_flag( nShowFlags, SHOWANYVALUE );
1095  bool bShowBubble = !bShowNone && ::get_flag( nShowFlags, SHOWANYBUBBLE );
1096 
1097  // adjust to Chart2 behaviour
1098  if( rTypeInfo.meTypeId == EXC_CHTYPEID_BUBBLES )
1099  bShowValue = bShowBubble; // Chart2 bubble charts show bubble size if 'ShowValue' is set
1100 
1101  // other flags
1102  bool bShowAny = bShowValue || bShowPercent || bShowCateg;
1103  bool bShowSymbol = bShowAny && ::get_flag( maData.mnFlags, EXC_CHTEXT_SHOWSYMBOL );
1104 
1105  // create API struct for label values, set API label separator
1106  cssc2::DataPointLabel aPointLabel( bShowValue, bShowPercent, bShowCateg, bShowSymbol, false, false );
1107  rPropSet.SetProperty( EXC_CHPROP_LABEL, aPointLabel );
1108  OUString aSep = mxLabelProps ? mxLabelProps->maSeparator : OUString('\n');
1109  if( aSep.isEmpty() )
1110  aSep = "; ";
1111  rPropSet.SetStringProperty( EXC_CHPROP_LABELSEPARATOR, aSep );
1112 
1113  // text properties of attached label
1114  if( !bShowAny )
1115  return;
1116 
1117  ConvertFont( rPropSet );
1118  ConvertRotation( rPropSet, false );
1119  // label placement
1120  using namespace cssc::DataLabelPlacement;
1121  sal_Int32 nPlacement = rTypeInfo.mnDefaultLabelPos;
1122  switch( ::extract_value< sal_uInt16 >( maData.mnFlags2, 0, 4 ) )
1123  {
1124  case EXC_CHTEXT_POS_DEFAULT: nPlacement = rTypeInfo.mnDefaultLabelPos; break;
1125  case EXC_CHTEXT_POS_OUTSIDE: nPlacement = OUTSIDE; break;
1126  case EXC_CHTEXT_POS_INSIDE: nPlacement = INSIDE; break;
1127  case EXC_CHTEXT_POS_CENTER: nPlacement = CENTER; break;
1128  case EXC_CHTEXT_POS_AXIS: nPlacement = NEAR_ORIGIN; break;
1129  case EXC_CHTEXT_POS_ABOVE: nPlacement = TOP; break;
1130  case EXC_CHTEXT_POS_BELOW: nPlacement = BOTTOM; break;
1131  case EXC_CHTEXT_POS_LEFT: nPlacement = LEFT; break;
1132  case EXC_CHTEXT_POS_RIGHT: nPlacement = RIGHT; break;
1133  case EXC_CHTEXT_POS_AUTO: nPlacement = AVOID_OVERLAP; break;
1134  }
1135  sal_Int32 nGlobalPlacement = 0;
1136  if ( ( nPlacement == rTypeInfo.mnDefaultLabelPos ) && pGlobalPropSet &&
1137  pGlobalPropSet->GetProperty( nGlobalPlacement, EXC_CHPROP_LABELPLACEMENT ) )
1138  nPlacement = nGlobalPlacement;
1139 
1140  rPropSet.SetProperty( EXC_CHPROP_LABELPLACEMENT, nPlacement );
1141  // label number format (percentage format wins over value format)
1142  if( bShowPercent || bShowValue )
1143  ConvertNumFmt( rPropSet, bShowPercent );
1144 }
1145 
1146 Reference< XTitle > XclImpChText::CreateTitle() const
1147 {
1148  Reference< XTitle > xTitle;
1149  if( mxSrcLink && mxSrcLink->HasString() )
1150  {
1151  // create the formatted strings
1152  Sequence< Reference< XFormattedString > > aStringSeq(
1153  mxSrcLink->CreateStringSequence( GetChRoot(), GetFontIndex(), GetFontColor() ) );
1154  if( aStringSeq.hasElements() )
1155  {
1156  // create the title object
1157  xTitle.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_TITLE ), UNO_QUERY );
1158  if( xTitle.is() )
1159  {
1160  // set the formatted strings
1161  xTitle->setText( aStringSeq );
1162  // more title formatting properties
1163  ScfPropertySet aTitleProp( xTitle );
1164  ConvertFrame( aTitleProp );
1165  ConvertRotation( aTitleProp, true );
1166  }
1167  }
1168  }
1169  return xTitle;
1170 }
1171 
1172 void XclImpChText::ConvertTitlePosition( const XclChTextKey& rTitleKey ) const
1173 {
1174  if( !mxFramePos ) return;
1175 
1176  const XclChFramePos& rPosData = mxFramePos->GetFramePosData();
1177  OSL_ENSURE( (rPosData.mnTLMode == EXC_CHFRAMEPOS_PARENT) && (rPosData.mnBRMode == EXC_CHFRAMEPOS_PARENT),
1178  "XclImpChText::ConvertTitlePosition - unexpected frame position mode" );
1179 
1180  /* Check if title is moved manually. To get the actual position of the
1181  title, we do some kind of hack and use the values from the CHTEXT
1182  record, effectively ignoring the contents of the CHFRAMEPOS record
1183  which contains the position relative to the default title position
1184  (according to the spec, the CHFRAMEPOS supersedes the CHTEXT record).
1185  Especially when it comes to axis titles, things would become very
1186  complicated here, because the relative title position is stored in a
1187  measurement unit that is dependent on the size of the inner plot area,
1188  the interpretation of the X and Y coordinate is dependent on the
1189  direction of the axis, and in 3D charts, and the title default
1190  positions are dependent on the 3D view settings (rotation, elevation,
1191  and perspective). Thus, it is easier to assume that the creator has
1192  written out the correct absolute position and size of the title in the
1193  CHTEXT record. This is assured by checking that the shape size stored
1194  in the CHTEXT record is non-zero. */
1195  if( !((rPosData.mnTLMode == EXC_CHFRAMEPOS_PARENT) &&
1196  ((rPosData.maRect.mnX != 0) || (rPosData.maRect.mnY != 0)) &&
1197  (maData.maRect.mnWidth > 0) && (maData.maRect.mnHeight > 0)) )
1198  return;
1199 
1200  try
1201  {
1202  Reference< XShape > xTitleShape( GetTitleShape( rTitleKey ), UNO_SET_THROW );
1203  // the call to XShape.getSize() may recalc the chart view
1204  css::awt::Size aTitleSize = xTitleShape->getSize();
1205  // rotated titles need special handling...
1206  Degree100 nScRot = XclTools::GetScRotation( GetRotation(), 0_deg100 );
1207  double fRad = nScRot.get() * F_PI18000;
1208  double fSin = fabs( sin( fRad ) );
1209  // calculate the title position from the values in the CHTEXT record
1210  css::awt::Point aTitlePos(
1213  // add part of height to X direction, if title is rotated down (clockwise)
1214  if( nScRot > 18000_deg100 )
1215  aTitlePos.X += static_cast< sal_Int32 >( fSin * aTitleSize.Height + 0.5 );
1216  // add part of width to Y direction, if title is rotated up (counterclockwise)
1217  else if( nScRot > 0_deg100 )
1218  aTitlePos.Y += static_cast< sal_Int32 >( fSin * aTitleSize.Width + 0.5 );
1219  // set the resulting position at the title shape
1220  xTitleShape->setPosition( aTitlePos );
1221  }
1222  catch( Exception& )
1223  {
1224  }
1225 }
1226 
1228 {
1229  if( GetBiff() == EXC_BIFF8 )
1230  {
1231  mxLabelProps = std::make_shared<XclChFrLabelProps>();
1232  sal_uInt16 nSepLen;
1233  rStrm.Ignore( 12 );
1234  mxLabelProps->mnFlags = rStrm.ReaduInt16();
1235  nSepLen = rStrm.ReaduInt16();
1236  if( nSepLen > 0 )
1237  mxLabelProps->maSeparator = rStrm.ReadUniString( nSepLen );
1238  }
1239 }
1240 
1241 namespace {
1242 
1243 void lclUpdateText( XclImpChTextRef& rxText, const XclImpChText* xDefText )
1244 {
1245  if (rxText)
1246  rxText->UpdateText( xDefText );
1247  else if (xDefText)
1248  {
1249  rxText = std::make_shared<XclImpChText>(*xDefText);
1250  }
1251 }
1252 
1253 void lclFinalizeTitle( XclImpChTextRef& rxTitle, const XclImpChText* pDefText, const OUString& rAutoTitle )
1254 {
1255  /* Do not update a title, if it is not visible (if rxTitle is null).
1256  Existing reference indicates enabled title. */
1257  if( rxTitle )
1258  {
1259  if( !rxTitle->HasString() )
1260  rxTitle->SetString( rAutoTitle );
1261  if( rxTitle->HasString() )
1262  rxTitle->UpdateText(pDefText);
1263  else
1264  rxTitle.reset();
1265  }
1266 }
1267 
1268 } // namespace
1269 
1270 // Data series ================================================================
1271 
1273 {
1274  rStrm >> maData.maLineColor >> maData.maFillColor;
1275  maData.mnMarkerType = rStrm.ReaduInt16();
1276  maData.mnFlags = rStrm.ReaduInt16();
1277 
1278  const XclImpRoot& rRoot = rStrm.GetRoot();
1279  if( rRoot.GetBiff() == EXC_BIFF8 )
1280  {
1281  // BIFF8: index into palette used instead of RGB data
1282  const XclImpPalette& rPal = rRoot.GetPalette();
1283  maData.maLineColor = rPal.GetColor( rStrm.ReaduInt16() );
1284  maData.maFillColor = rPal.GetColor( rStrm.ReaduInt16() );
1285  // marker size
1286  maData.mnMarkerSize = rStrm.ReaduInt32();
1287  }
1288 }
1289 
1291  ScfPropertySet& rPropSet, sal_uInt16 nFormatIdx, sal_Int16 nLineWeight ) const
1292 {
1293  if( IsAuto() )
1294  {
1295  XclChMarkerFormat aMarkerFmt;
1296  // line and fill color of the symbol are equal to series line color
1297  //TODO: Excel sets no fill color for specific symbols (e.g. cross)
1298  aMarkerFmt.maLineColor = aMarkerFmt.maFillColor = rRoot.GetSeriesLineAutoColor( nFormatIdx );
1299  switch( nLineWeight )
1300  {
1305  default: aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_SINGLESIZE;
1306  }
1307  aMarkerFmt.mnMarkerType = XclChartHelper::GetAutoMarkerType( nFormatIdx );
1308  XclChPropSetHelper::WriteMarkerProperties( rPropSet, aMarkerFmt );
1309  }
1310  else
1311  {
1313  }
1314 }
1315 
1317  ScfPropertySet& rPropSet, sal_uInt16 nFormatIdx ) const
1318 {
1319  Color aLineColor = IsAuto() ? rRoot.GetSeriesLineAutoColor( nFormatIdx ) : maData.maFillColor;
1320  rPropSet.SetColorProperty( EXC_CHPROP_COLOR, aLineColor );
1321 }
1322 
1324  mnPieDist( 0 )
1325 {
1326 }
1327 
1329 {
1330  mnPieDist = rStrm.ReaduInt16();
1331 }
1332 
1334 {
1335  double fApiDist = ::std::min< double >( mnPieDist / 100.0, 1.0 );
1336  rPropSet.SetProperty( EXC_CHPROP_OFFSET, fApiDist );
1337 }
1338 
1340  mnFlags( 0 )
1341 {
1342 }
1343 
1345 {
1346  mnFlags = rStrm.ReaduInt16();
1347 }
1348 
1350 {
1351  maData.mnBase = rStrm.ReaduInt8();
1352  maData.mnTop = rStrm.ReaduInt8();
1353 }
1354 
1356 {
1357  using namespace ::com::sun::star::chart2::DataPointGeometry3D;
1358  sal_Int32 nApiType = (maData.mnBase == EXC_CH3DDATAFORMAT_RECT) ?
1359  ((maData.mnTop == EXC_CH3DDATAFORMAT_STRAIGHT) ? CUBOID : PYRAMID) :
1360  ((maData.mnTop == EXC_CH3DDATAFORMAT_STRAIGHT) ? CYLINDER : CONE);
1361  rPropSet.SetProperty( EXC_CHPROP_GEOMETRY3D, nApiType );
1362 }
1363 
1365  XclImpChRoot( rRoot ),
1366  mnFlags( 0 )
1367 {
1368 }
1369 
1371 {
1372  mnFlags = rStrm.ReaduInt16();
1373 }
1374 
1376 {
1377  const sal_uInt16 EXC_CHATTLABEL_SHOWANYVALUE = EXC_CHATTLABEL_SHOWVALUE;
1378  const sal_uInt16 EXC_CHATTLABEL_SHOWANYPERCENT = EXC_CHATTLABEL_SHOWPERCENT | EXC_CHATTLABEL_SHOWCATEGPERC;
1379  const sal_uInt16 EXC_CHATTLABEL_SHOWANYCATEG = EXC_CHATTLABEL_SHOWCATEG | EXC_CHATTLABEL_SHOWCATEGPERC;
1380 
1381  XclImpChTextRef xLabel;
1382  if ( pParent )
1383  xLabel = std::make_shared<XclImpChText>( *pParent );
1384  else
1385  xLabel = std::make_shared<XclImpChText>( GetChRoot() );
1386  xLabel->UpdateDataLabel(
1387  ::get_flag( mnFlags, EXC_CHATTLABEL_SHOWANYCATEG ),
1388  ::get_flag( mnFlags, EXC_CHATTLABEL_SHOWANYVALUE ),
1389  ::get_flag( mnFlags, EXC_CHATTLABEL_SHOWANYPERCENT ) );
1390  return xLabel;
1391 }
1392 
1394  XclImpChRoot( rRoot )
1395 {
1396 }
1397 
1399 {
1402  maData.mnFormatIdx = rStrm.ReaduInt16();
1403  maData.mnFlags = rStrm.ReaduInt16();
1404 }
1405 
1407 {
1408  switch( rStrm.GetRecId() )
1409  {
1410  case EXC_ID_CHMARKERFORMAT:
1411  mxMarkerFmt = std::make_shared<XclImpChMarkerFormat>();
1412  mxMarkerFmt->ReadChMarkerFormat( rStrm );
1413  break;
1414  case EXC_ID_CHPIEFORMAT:
1415  mxPieFmt = std::make_shared<XclImpChPieFormat>();
1416  mxPieFmt->ReadChPieFormat( rStrm );
1417  break;
1418  case EXC_ID_CHSERIESFORMAT:
1419  mxSeriesFmt = std::make_shared<XclImpChSeriesFormat>();
1420  mxSeriesFmt->ReadChSeriesFormat( rStrm );
1421  break;
1422  case EXC_ID_CH3DDATAFORMAT:
1423  mx3dDataFmt = std::make_shared<XclImpCh3dDataFormat>();
1424  mx3dDataFmt->ReadCh3dDataFormat( rStrm );
1425  break;
1427  mxAttLabel = std::make_shared<XclImpChAttachedLabel>( GetChRoot() );
1428  mxAttLabel->ReadChAttachedLabel( rStrm );
1429  break;
1430  default:
1432  }
1433 }
1434 
1435 void XclImpChDataFormat::SetPointPos( const XclChDataPointPos& rPointPos, sal_uInt16 nFormatIdx )
1436 {
1437  maData.maPointPos = rPointPos;
1438  maData.mnFormatIdx = nFormatIdx;
1439 }
1440 
1442 {
1443  // remove formats not used for the current chart type
1444  RemoveUnusedFormats( rTypeInfo );
1445 }
1446 
1448 {
1449  // update missing formats from passed chart type group format
1450  if( pGroupFmt )
1451  {
1452  if( !mxLineFmt )
1453  mxLineFmt = pGroupFmt->mxLineFmt;
1454  if( !mxAreaFmt && !mxEscherFmt )
1455  {
1456  mxAreaFmt = pGroupFmt->mxAreaFmt;
1457  mxEscherFmt = pGroupFmt->mxEscherFmt;
1458  }
1459  if( !mxMarkerFmt )
1460  mxMarkerFmt = pGroupFmt->mxMarkerFmt;
1461  if( !mxPieFmt )
1462  mxPieFmt = pGroupFmt->mxPieFmt;
1463  if( !mxSeriesFmt )
1464  mxSeriesFmt = pGroupFmt->mxSeriesFmt;
1465  if( !mx3dDataFmt )
1466  mx3dDataFmt = pGroupFmt->mx3dDataFmt;
1467  if( !mxAttLabel )
1468  mxAttLabel = pGroupFmt->mxAttLabel;
1469  }
1470 
1471  /* Create missing but required formats. Existing line, area, and marker
1472  format objects are needed to create automatic series formatting. */
1473  if( !mxLineFmt )
1474  mxLineFmt = new XclImpChLineFormat();
1475  if( !mxAreaFmt && !mxEscherFmt )
1476  mxAreaFmt = std::make_shared<XclImpChAreaFormat>();
1477  if( !mxMarkerFmt )
1478  mxMarkerFmt = std::make_shared<XclImpChMarkerFormat>();
1479 
1480  // remove formats not used for the current chart type
1481  RemoveUnusedFormats( rTypeInfo );
1482  // update data label
1483  UpdateDataLabel( pGroupFmt );
1484 }
1485 
1487 {
1488  // remove formats if they are automatic in this and in the passed series format
1489  if( pSeriesFmt )
1490  {
1491  if( IsAutoLine() && pSeriesFmt->IsAutoLine() )
1492  mxLineFmt.clear();
1493  if( IsAutoArea() && pSeriesFmt->IsAutoArea() )
1494  mxAreaFmt.reset();
1495  if( IsAutoMarker() && pSeriesFmt->IsAutoMarker() )
1496  mxMarkerFmt.reset();
1497  mxSeriesFmt.reset();
1498  }
1499 
1500  // Excel ignores 3D bar format for single data points
1501  mx3dDataFmt.reset();
1502  // remove point line formats for linear chart types, TODO: implement in OOChart
1503  if( !rTypeInfo.IsSeriesFrameFormat() )
1504  mxLineFmt.clear();
1505 
1506  // remove formats not used for the current chart type
1507  RemoveUnusedFormats( rTypeInfo );
1508  // update data label
1509  UpdateDataLabel( pSeriesFmt );
1510 }
1511 
1513 {
1514  if( !mxLineFmt )
1515  mxLineFmt = new XclImpChLineFormat();
1516  mxAreaFmt.reset();
1517  mxEscherFmt.reset();
1518  mxMarkerFmt.reset();
1519  mxPieFmt.reset();
1520  mxSeriesFmt.reset();
1521  mx3dDataFmt.reset();
1522  mxAttLabel.reset();
1523  // update data label
1524  UpdateDataLabel( nullptr );
1525 }
1526 
1527 void XclImpChDataFormat::Convert( ScfPropertySet& rPropSet, const XclChExtTypeInfo& rTypeInfo, const ScfPropertySet* pGlobalPropSet ) const
1528 {
1529  /* Line and area format.
1530  #i71810# If the data points are filled with bitmaps, textures, or
1531  patterns, then only bar charts will use the CHPICFORMAT record to
1532  determine stacking/stretching mode. All other chart types ignore this
1533  record and always use the property 'fill-type' from the DFF property
1534  set (stretched for bitmaps, and stacked for textures and patterns). */
1535  bool bUsePicFmt = rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_BAR;
1536  ConvertFrameBase( GetChRoot(), rPropSet, rTypeInfo.GetSeriesObjectType(), maData.mnFormatIdx, bUsePicFmt );
1537 
1538  // #i83151# only hair lines in 3D charts with filled data points
1539  if( rTypeInfo.mb3dChart && rTypeInfo.IsSeriesFrameFormat() && mxLineFmt && mxLineFmt->HasLine() )
1540  rPropSet.SetProperty< sal_Int32 >( "BorderWidth", 0 );
1541 
1542  // other formatting
1543  if( mxMarkerFmt )
1544  mxMarkerFmt->Convert( GetChRoot(), rPropSet, maData.mnFormatIdx, GetLineWeight() );
1545  if( mxPieFmt )
1546  mxPieFmt->Convert( rPropSet );
1547  if( mx3dDataFmt )
1548  mx3dDataFmt->Convert( rPropSet );
1549  if( mxLabel )
1550  mxLabel->ConvertDataLabel( rPropSet, rTypeInfo, pGlobalPropSet );
1551 
1552  // 3D settings
1553  rPropSet.SetProperty< sal_Int16 >( EXC_CHPROP_PERCENTDIAGONAL, 0 );
1554 
1555  /* Special case: set marker color as line color, if series line is not
1556  visible. This makes the color visible in the marker area.
1557  TODO: remove this if OOChart supports own colors in markers. */
1558  if( !rTypeInfo.IsSeriesFrameFormat() && !HasLine() && mxMarkerFmt )
1559  mxMarkerFmt->ConvertColor( GetChRoot(), rPropSet, maData.mnFormatIdx );
1560 }
1561 
1563 {
1564  ConvertLineBase( GetChRoot(), rPropSet, eObjType );
1565 }
1566 
1567 void XclImpChDataFormat::ConvertArea( ScfPropertySet& rPropSet, sal_uInt16 nFormatIdx ) const
1568 {
1569  ConvertAreaBase( GetChRoot(), rPropSet, EXC_CHOBJTYPE_FILLEDSERIES, nFormatIdx );
1570 }
1571 
1573 {
1574  // data point marker only in linear 2D charts
1575  if( rTypeInfo.IsSeriesFrameFormat() )
1576  mxMarkerFmt.reset();
1577  // pie format only in pie/donut charts
1578  if( rTypeInfo.meTypeCateg != EXC_CHTYPECATEG_PIE )
1579  mxPieFmt.reset();
1580  // 3D format only in 3D bar charts
1581  if( !rTypeInfo.mb3dChart || (rTypeInfo.meTypeCateg != EXC_CHTYPECATEG_BAR) )
1582  mx3dDataFmt.reset();
1583 }
1584 
1586 {
1587  /* CHTEXT groups linked to data labels override existing CHATTACHEDLABEL
1588  records. Only if there is a CHATTACHEDLABEL record without a CHTEXT
1589  group, the contents of the CHATTACHEDLABEL record are used. In this
1590  case a new CHTEXT group is created and filled with the settings from
1591  the CHATTACHEDLABEL record. */
1592  const XclImpChText* pDefText = nullptr;
1593  if (pParentFmt)
1594  pDefText = pParentFmt->GetDataLabel();
1595  if (!pDefText)
1597  if (mxLabel)
1598  mxLabel->UpdateText(pDefText);
1599  else if (mxAttLabel)
1600  mxLabel = mxAttLabel->CreateDataLabel( pDefText );
1601 }
1602 
1604  XclImpChRoot( rRoot )
1605 {
1606 }
1607 
1609 {
1610  maData.mnLineType = rStrm.ReaduInt8();
1611  maData.mnOrder = rStrm.ReaduInt8();
1612  maData.mfIntercept = rStrm.ReadDouble();
1613  maData.mnShowEquation = rStrm.ReaduInt8();
1614  maData.mnShowRSquared = rStrm.ReaduInt8();
1615  maData.mfForecastFor = rStrm.ReadDouble();
1616  maData.mfForecastBack = rStrm.ReadDouble();
1617 }
1618 
1619 Reference< XRegressionCurve > XclImpChSerTrendLine::CreateRegressionCurve() const
1620 {
1621  // trend line type
1622  Reference< XRegressionCurve > xRegCurve;
1623  switch( maData.mnLineType )
1624  {
1626  if( maData.mnOrder == 1 )
1627  {
1628  xRegCurve = LinearRegressionCurve::create( comphelper::getProcessComponentContext() );
1629  } else {
1630  xRegCurve = PolynomialRegressionCurve::create( comphelper::getProcessComponentContext() );
1631  }
1632  break;
1634  xRegCurve = ExponentialRegressionCurve::create( comphelper::getProcessComponentContext() );
1635  break;
1637  xRegCurve = LogarithmicRegressionCurve::create( comphelper::getProcessComponentContext() );
1638  break;
1639  case EXC_CHSERTREND_POWER:
1640  xRegCurve = PotentialRegressionCurve::create( comphelper::getProcessComponentContext() );
1641  break;
1643  xRegCurve = MovingAverageRegressionCurve::create( comphelper::getProcessComponentContext() );
1644  break;
1645  }
1646 
1647  // trend line formatting
1648  if( xRegCurve.is() && mxDataFmt )
1649  {
1650  ScfPropertySet aPropSet( xRegCurve );
1651  mxDataFmt->ConvertLine( aPropSet, EXC_CHOBJTYPE_TRENDLINE );
1652 
1654  aPropSet.SetProperty(EXC_CHPROP_POLYNOMIAL_DEGREE, static_cast<sal_Int32> (maData.mnOrder) );
1655  aPropSet.SetProperty(EXC_CHPROP_MOVING_AVERAGE_PERIOD, static_cast<sal_Int32> (maData.mnOrder) );
1658 
1659  bool bForceIntercept = std::isfinite(maData.mfIntercept);
1660  aPropSet.SetProperty(EXC_CHPROP_FORCE_INTERCEPT, bForceIntercept);
1661  if (bForceIntercept)
1662  {
1664  }
1665 
1666  // #i83100# show equation and correlation coefficient
1667  ScfPropertySet aLabelProp( xRegCurve->getEquationProperties() );
1669  aLabelProp.SetBoolProperty( EXC_CHPROP_SHOWCORRELATION, maData.mnShowRSquared != 0 );
1670 
1671  // #i83100# formatting of the equation text box
1672  if (const XclImpChText* pLabel = mxDataFmt->GetDataLabel())
1673  {
1674  pLabel->ConvertFont( aLabelProp );
1675  pLabel->ConvertFrame( aLabelProp );
1676  pLabel->ConvertNumFmt( aLabelProp, false );
1677  }
1678  }
1679 
1680  return xRegCurve;
1681 }
1682 
1684  XclImpChRoot( rRoot )
1685 {
1686 }
1687 
1689 {
1690  maData.mnBarType = rStrm.ReaduInt8();
1691  maData.mnSourceType = rStrm.ReaduInt8();
1692  maData.mnLineEnd = rStrm.ReaduInt8();
1693  rStrm.Ignore( 1 );
1694  maData.mfValue = rStrm.ReadDouble();
1695  maData.mnValueCount = rStrm.ReaduInt16();
1696 }
1697 
1699 {
1700  mxValueLink = xValueLink;
1701  mxDataFmt = xDataFmt;
1702 }
1703 
1704 Reference< XLabeledDataSequence > XclImpChSerErrorBar::CreateValueSequence() const
1705 {
1706  return lclCreateLabeledDataSequence( mxValueLink, XclChartHelper::GetErrorBarValuesRole( maData.mnBarType ) );
1707 }
1708 
1710 {
1711  Reference< XPropertySet > xErrorBar;
1712 
1713  if( const XclImpChSerErrorBar* pPrimaryBar = pPosBar ? pPosBar : pNegBar )
1714  {
1715  xErrorBar.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_ERRORBAR ), UNO_QUERY );
1716  ScfPropertySet aBarProp( xErrorBar );
1717 
1718  // plus/minus bars visible?
1719  aBarProp.SetBoolProperty( EXC_CHPROP_SHOWPOSITIVEERROR, pPosBar != nullptr );
1720  aBarProp.SetBoolProperty( EXC_CHPROP_SHOWNEGATIVEERROR, pNegBar != nullptr );
1721 
1722  // type of displayed error
1723  switch( pPrimaryBar->maData.mnSourceType )
1724  {
1725  case EXC_CHSERERR_PERCENT:
1726  aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::RELATIVE );
1727  aBarProp.SetProperty( EXC_CHPROP_POSITIVEERROR, pPrimaryBar->maData.mfValue );
1728  aBarProp.SetProperty( EXC_CHPROP_NEGATIVEERROR, pPrimaryBar->maData.mfValue );
1729  break;
1730  case EXC_CHSERERR_FIXED:
1731  aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::ABSOLUTE );
1732  aBarProp.SetProperty( EXC_CHPROP_POSITIVEERROR, pPrimaryBar->maData.mfValue );
1733  aBarProp.SetProperty( EXC_CHPROP_NEGATIVEERROR, pPrimaryBar->maData.mfValue );
1734  break;
1735  case EXC_CHSERERR_STDDEV:
1736  aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::STANDARD_DEVIATION );
1737  aBarProp.SetProperty( EXC_CHPROP_WEIGHT, pPrimaryBar->maData.mfValue );
1738  break;
1739  case EXC_CHSERERR_STDERR:
1740  aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::STANDARD_ERROR );
1741  break;
1742  case EXC_CHSERERR_CUSTOM:
1743  {
1744  aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::FROM_DATA );
1745  // attach data sequences to error bar
1746  Reference< XDataSink > xDataSink( xErrorBar, UNO_QUERY );
1747  if( xDataSink.is() )
1748  {
1749  // create vector of all value sequences
1750  ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
1751  // add positive values
1752  if( pPosBar )
1753  {
1754  Reference< XLabeledDataSequence > xValueSeq = pPosBar->CreateValueSequence();
1755  if( xValueSeq.is() )
1756  aLabeledSeqVec.push_back( xValueSeq );
1757  }
1758  // add negative values
1759  if( pNegBar )
1760  {
1761  Reference< XLabeledDataSequence > xValueSeq = pNegBar->CreateValueSequence();
1762  if( xValueSeq.is() )
1763  aLabeledSeqVec.push_back( xValueSeq );
1764  }
1765  // attach labeled data sequences to series
1766  if( aLabeledSeqVec.empty() )
1767  xErrorBar.clear();
1768  else
1769  xDataSink->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec ) );
1770  }
1771  }
1772  break;
1773  default:
1774  xErrorBar.clear();
1775  }
1776 
1777  // error bar formatting
1778  if( pPrimaryBar->mxDataFmt && xErrorBar.is() )
1779  pPrimaryBar->mxDataFmt->ConvertLine( aBarProp, EXC_CHOBJTYPE_ERRORBAR );
1780  }
1781 
1782  return xErrorBar;
1783 }
1784 
1785 XclImpChSeries::XclImpChSeries( const XclImpChRoot& rRoot, sal_uInt16 nSeriesIdx ) :
1786  XclImpChRoot( rRoot ),
1787  mnGroupIdx( EXC_CHSERGROUP_NONE ),
1788  mnSeriesIdx( nSeriesIdx ),
1789  mnParentIdx( EXC_CHSERIES_INVALID ),
1790  mbLabelDeleted( false )
1791 {
1792 }
1793 
1795 {
1796  maData.mnCategType = rStrm.ReaduInt16();
1797  maData.mnValueType = rStrm.ReaduInt16();
1798  maData.mnCategCount = rStrm.ReaduInt16();
1799  maData.mnValueCount = rStrm.ReaduInt16();
1800  if( GetBiff() == EXC_BIFF8 )
1801  {
1802  maData.mnBubbleType = rStrm.ReaduInt16();
1803  maData.mnBubbleCount = rStrm.ReaduInt16();
1804  }
1805 }
1806 
1808 {
1809  switch( rStrm.GetRecId() )
1810  {
1811  case EXC_ID_CHSOURCELINK:
1812  ReadChSourceLink( rStrm );
1813  break;
1814  case EXC_ID_CHDATAFORMAT:
1815  ReadChDataFormat( rStrm );
1816  break;
1817  case EXC_ID_CHSERGROUP:
1818  mnGroupIdx = rStrm.ReaduInt16();
1819  break;
1820  case EXC_ID_CHSERPARENT:
1821  ReadChSerParent( rStrm );
1822  break;
1823  case EXC_ID_CHSERTRENDLINE:
1824  ReadChSerTrendLine( rStrm );
1825  break;
1826  case EXC_ID_CHSERERRORBAR:
1827  ReadChSerErrorBar( rStrm );
1828  break;
1830  ReadChLegendException( rStrm );
1831  break;
1832  }
1833 }
1834 
1836 {
1837  if (!xDataFmt)
1838  return;
1839 
1840  sal_uInt16 nPointIdx = xDataFmt->GetPointPos().mnPointIdx;
1841  if (nPointIdx == EXC_CHDATAFORMAT_ALLPOINTS)
1842  {
1843  if (mxSeriesFmt)
1844  // Don't overwrite the existing format.
1845  return;
1846 
1847  mxSeriesFmt = xDataFmt;
1848  if (HasParentSeries())
1849  return;
1850 
1852  if (pTypeGroup)
1853  pTypeGroup->SetUsedFormatIndex(xDataFmt->GetFormatIdx());
1854 
1855  return;
1856  }
1857 
1858  if (nPointIdx >= EXC_CHDATAFORMAT_MAXPOINTCOUNT)
1859  // Above the max point count. Bail out.
1860  return;
1861 
1862  XclImpChDataFormatMap::iterator itr = maPointFmts.lower_bound(nPointIdx);
1863  if (itr == maPointFmts.end() || maPointFmts.key_comp()(nPointIdx, itr->first))
1864  {
1865  // No object exists at this point index position. Insert it.
1866  itr = maPointFmts.insert(itr, XclImpChDataFormatMap::value_type(nPointIdx, xDataFmt));
1867  }
1868 }
1869 
1871 {
1872  if (!xLabel)
1873  return;
1874 
1875  sal_uInt16 nPointIdx = xLabel->GetPointPos().mnPointIdx;
1876  if ((nPointIdx != EXC_CHDATAFORMAT_ALLPOINTS) && (nPointIdx >= EXC_CHDATAFORMAT_MAXPOINTCOUNT))
1877  // Above the maximum allowed data points. Bail out.
1878  return;
1879 
1880  XclImpChTextMap::iterator itr = maLabels.lower_bound(nPointIdx);
1881  if (itr == maLabels.end() || maLabels.key_comp()(nPointIdx, itr->first))
1882  {
1883  // No object exists at this point index position. Insert it.
1884  itr = maLabels.insert(itr, XclImpChTextMap::value_type(nPointIdx, xLabel));
1885  }
1886 }
1887 
1889 {
1890  OSL_ENSURE( !HasParentSeries(), "XclImpChSeries::AddChildSeries - not allowed for child series" );
1891  if (&rSeries == this)
1892  {
1893  SAL_WARN("sc.filter", "self add attempt");
1894  return;
1895  }
1896 
1897  /* In Excel, trend lines and error bars are stored as own series. In Calc,
1898  these are properties of the parent series. This function adds the
1899  settings of the passed series to this series. */
1900  maTrendLines.insert( maTrendLines.end(), rSeries.maTrendLines.begin(), rSeries.maTrendLines.end() );
1901  for (auto const& it : rSeries.m_ErrorBars)
1902  {
1903  m_ErrorBars.insert(std::make_pair(it.first, std::make_unique<XclImpChSerErrorBar>(*it.second)));
1904  }
1905 }
1906 
1908 {
1909  if( HasParentSeries() )
1910  {
1911  // *** series is a child series, e.g. trend line or error bar ***
1912 
1913  // create missing series format
1914  if( !mxSeriesFmt )
1916 
1917  if( mxSeriesFmt )
1918  {
1919  // #i83100# set text label format, e.g. for trend line equations
1920  XclImpChTextRef xLabel;
1921  XclImpChTextMap::iterator itr = maLabels.find(EXC_CHDATAFORMAT_ALLPOINTS);
1922  if (itr != maLabels.end())
1923  xLabel = itr->second;
1924  mxSeriesFmt->SetDataLabel(xLabel);
1925  // create missing automatic formats
1926  mxSeriesFmt->UpdateTrendLineFormat();
1927  }
1928 
1929  // copy series formatting to child objects
1930  for (auto const& trendLine : maTrendLines)
1931  {
1932  trendLine->SetDataFormat(mxSeriesFmt);
1933  if (mxTitleLink && mxTitleLink->HasString())
1934  {
1935  trendLine->SetTrendlineName(mxTitleLink->GetString());
1936  }
1937  }
1938  for (auto const& it : m_ErrorBars)
1939  {
1940  it.second->SetSeriesData( mxValueLink, mxSeriesFmt );
1941  }
1942  }
1943  else if( XclImpChTypeGroup* pTypeGroup = GetChartData().GetTypeGroup( mnGroupIdx ).get() )
1944  {
1945  // *** series is a regular data series ***
1946 
1947  // create missing series format
1948  if( !mxSeriesFmt )
1949  {
1950  // #i51639# use a new unused format index to create series default format
1951  sal_uInt16 nFormatIdx = pTypeGroup->PopUnusedFormatIndex();
1953  }
1954 
1955  // set text labels to data formats
1956  for (auto const& label : maLabels)
1957  {
1958  sal_uInt16 nPointIdx = label.first;
1959  if (nPointIdx == EXC_CHDATAFORMAT_ALLPOINTS)
1960  {
1961  if (!mxSeriesFmt)
1963  mxSeriesFmt->SetDataLabel(label.second);
1964  }
1965  else if (nPointIdx < EXC_CHDATAFORMAT_MAXPOINTCOUNT)
1966  {
1968  XclImpChDataFormatMap::iterator itr = maPointFmts.lower_bound(nPointIdx);
1969  if (itr == maPointFmts.end() || maPointFmts.key_comp()(nPointIdx, itr->first))
1970  {
1971  // No object exists at this point index position. Insert
1972  // a new one.
1974  itr = maPointFmts.insert(
1975  itr, XclImpChDataFormatMap::value_type(nPointIdx, p));
1976  }
1977  else
1978  p = itr->second;
1979  p->SetDataLabel(label.second);
1980  }
1981  }
1982 
1983  // update series format (copy missing formatting from group default format)
1984  if( mxSeriesFmt )
1985  mxSeriesFmt->UpdateSeriesFormat( pTypeGroup->GetTypeInfo(), pTypeGroup->GetGroupFormat().get() );
1986 
1987  // update data point formats (removes unchanged automatic formatting)
1988  for (auto const& pointFormat : maPointFmts)
1989  pointFormat.second->UpdatePointFormat( pTypeGroup->GetTypeInfo(), mxSeriesFmt.get() );
1990  }
1991 }
1992 
1993 namespace {
1994 
1996 ScfPropertySet lclGetPointPropSet( Reference< XDataSeries > const & xDataSeries, sal_uInt16 nPointIdx )
1997 {
1998  ScfPropertySet aPropSet;
1999  try
2000  {
2001  aPropSet.Set( xDataSeries->getDataPointByIndex( static_cast< sal_Int32 >( nPointIdx ) ) );
2002  }
2003  catch( Exception& )
2004  {
2005  OSL_FAIL( "lclGetPointPropSet - no data point property set" );
2006  }
2007  return aPropSet;
2008 }
2009 
2010 } // namespace
2011 
2012 Reference< XLabeledDataSequence > XclImpChSeries::CreateValueSequence( const OUString& rValueRole ) const
2013 {
2014  return lclCreateLabeledDataSequence( mxValueLink, rValueRole, mxTitleLink.get() );
2015 }
2016 
2017 Reference< XLabeledDataSequence > XclImpChSeries::CreateCategSequence( const OUString& rCategRole ) const
2018 {
2019  return lclCreateLabeledDataSequence( mxCategLink, rCategRole );
2020 }
2021 
2022 Reference< XDataSeries > XclImpChSeries::CreateDataSeries() const
2023 {
2024  Reference< XDataSeries > xDataSeries;
2025  if( const XclImpChTypeGroup* pTypeGroup = GetChartData().GetTypeGroup( mnGroupIdx ).get() )
2026  {
2027  const XclChExtTypeInfo& rTypeInfo = pTypeGroup->GetTypeInfo();
2028 
2029  // create the data series object
2030  xDataSeries.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_DATASERIES ), UNO_QUERY );
2031 
2032  // attach data and title sequences to series
2033  Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY );
2034  if( xDataSink.is() )
2035  {
2036  // create vector of all value sequences
2037  ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
2038  // add Y values
2039  Reference< XLabeledDataSequence > xYValueSeq =
2041  if( xYValueSeq.is() )
2042  aLabeledSeqVec.push_back( xYValueSeq );
2043  // add X values
2044  if( !rTypeInfo.mbCategoryAxis )
2045  {
2046  Reference< XLabeledDataSequence > xXValueSeq =
2048  if( xXValueSeq.is() )
2049  aLabeledSeqVec.push_back( xXValueSeq );
2050  // add size values of bubble charts
2051  if( rTypeInfo.meTypeId == EXC_CHTYPEID_BUBBLES )
2052  {
2053  Reference< XLabeledDataSequence > xSizeValueSeq =
2054  lclCreateLabeledDataSequence( mxBubbleLink, EXC_CHPROP_ROLE_SIZEVALUES, mxTitleLink.get() );
2055  if( xSizeValueSeq.is() )
2056  aLabeledSeqVec.push_back( xSizeValueSeq );
2057  }
2058  }
2059  // attach labeled data sequences to series
2060  if( !aLabeledSeqVec.empty() )
2061  xDataSink->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec ) );
2062  }
2063 
2064  // series formatting
2065  ScfPropertySet aSeriesProp( xDataSeries );
2066  if( mxSeriesFmt )
2067  mxSeriesFmt->Convert( aSeriesProp, rTypeInfo );
2068 
2069  if (mbLabelDeleted)
2070  aSeriesProp.SetProperty(EXC_CHPROP_SHOWLEGENDENTRY, false);
2071 
2072  // trend lines
2073  ConvertTrendLines( xDataSeries );
2074 
2075  // error bars
2077  if( xErrorBarX.is() )
2078  aSeriesProp.SetProperty( EXC_CHPROP_ERRORBARX, xErrorBarX );
2080  if( xErrorBarY.is() )
2081  aSeriesProp.SetProperty( EXC_CHPROP_ERRORBARY, xErrorBarY );
2082 
2083  // own area formatting for every data point (TODO: varying line color not supported)
2084  bool bVarPointFmt = pTypeGroup->HasVarPointFormat() && rTypeInfo.IsSeriesFrameFormat();
2086  // #i91271# always set area formatting for every point in pie/doughnut charts
2087  if (mxSeriesFmt && mxValueLink && ((bVarPointFmt && mxSeriesFmt->IsAutoArea()) || (rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE)))
2088  {
2089  for( sal_uInt16 nPointIdx = 0, nPointCount = mxValueLink->GetCellCount(); nPointIdx < nPointCount; ++nPointIdx )
2090  {
2091  ScfPropertySet aPointProp = lclGetPointPropSet( xDataSeries, nPointIdx );
2092  mxSeriesFmt->ConvertArea( aPointProp, bVarPointFmt ? nPointIdx : mnSeriesIdx );
2093  }
2094  }
2095 
2096  // data point formatting
2097  for (auto const& pointFormat : maPointFmts)
2098  {
2099  ScfPropertySet aPointProp = lclGetPointPropSet( xDataSeries, pointFormat.first );
2100  pointFormat.second->Convert( aPointProp, rTypeInfo, &aSeriesProp );
2101  }
2102  }
2103  return xDataSeries;
2104 }
2105 
2106 void XclImpChSeries::FillAllSourceLinks( ::std::vector< ScTokenRef >& rTokens ) const
2107 {
2108  if( mxValueLink )
2109  mxValueLink->FillSourceLink( rTokens );
2110  if( mxCategLink )
2111  mxCategLink->FillSourceLink( rTokens );
2112  if( mxTitleLink )
2113  mxTitleLink->FillSourceLink( rTokens );
2114  if( mxBubbleLink )
2115  mxBubbleLink->FillSourceLink( rTokens );
2116 }
2117 
2119 {
2120  XclImpChSourceLinkRef xSrcLink = std::make_shared<XclImpChSourceLink>( GetChRoot() );
2121  xSrcLink->ReadChSourceLink( rStrm );
2122  switch( xSrcLink->GetDestType() )
2123  {
2124  case EXC_CHSRCLINK_TITLE: mxTitleLink = xSrcLink; break;
2125  case EXC_CHSRCLINK_VALUES: mxValueLink = xSrcLink; break;
2126  case EXC_CHSRCLINK_CATEGORY: mxCategLink = xSrcLink; break;
2127  case EXC_CHSRCLINK_BUBBLES: mxBubbleLink = xSrcLink; break;
2128  }
2129 }
2130 
2132 {
2133  // #i51639# chart stores all data formats and assigns them later to the series
2134  GetChartData().ReadChDataFormat( rStrm );
2135 }
2136 
2138 {
2139  mnParentIdx = rStrm.ReaduInt16();
2140  // index to parent series is 1-based, convert it to 0-based
2141  if( mnParentIdx > 0 )
2142  --mnParentIdx;
2143  else
2145 }
2146 
2148 {
2149  XclImpChSerTrendLineRef xTrendLine = std::make_shared<XclImpChSerTrendLine>( GetChRoot() );
2150  xTrendLine->ReadChSerTrendLine( rStrm );
2151  maTrendLines.push_back( xTrendLine );
2152 }
2153 
2155 {
2156  unique_ptr<XclImpChSerErrorBar> pErrorBar(new XclImpChSerErrorBar(GetChRoot()));
2157  pErrorBar->ReadChSerErrorBar(rStrm);
2158  sal_uInt8 nBarType = pErrorBar->GetBarType();
2159  m_ErrorBars.insert(std::make_pair(nBarType, std::move(pErrorBar)));
2160 }
2161 
2162 XclImpChDataFormatRef XclImpChSeries::CreateDataFormat( sal_uInt16 nPointIdx, sal_uInt16 nFormatIdx )
2163 {
2164  XclImpChDataFormatRef xDataFmt = std::make_shared<XclImpChDataFormat>( GetChRoot() );
2165  xDataFmt->SetPointPos( XclChDataPointPos( mnSeriesIdx, nPointIdx ), nFormatIdx );
2166  return xDataFmt;
2167 }
2168 
2169 void XclImpChSeries::ConvertTrendLines( Reference< XDataSeries > const & xDataSeries ) const
2170 {
2171  Reference< XRegressionCurveContainer > xRegCurveCont( xDataSeries, UNO_QUERY );
2172  if( !xRegCurveCont.is() )
2173  return;
2174 
2175  for (auto const& trendLine : maTrendLines)
2176  {
2177  try
2178  {
2179  Reference< XRegressionCurve > xRegCurve = trendLine->CreateRegressionCurve();
2180  if( xRegCurve.is() )
2181  {
2182  xRegCurveCont->addRegressionCurve( xRegCurve );
2183  }
2184  }
2185  catch( Exception& )
2186  {
2187  OSL_FAIL( "XclImpChSeries::ConvertTrendLines - cannot add regression curve" );
2188  }
2189  }
2190 }
2191 
2193 {
2194  XclImpChSerErrorBarMap::const_iterator itrPosBar = m_ErrorBars.find(nPosBarId);
2195  XclImpChSerErrorBarMap::const_iterator itrNegBar = m_ErrorBars.find(nNegBarId);
2196  XclImpChSerErrorBarMap::const_iterator itrEnd = m_ErrorBars.end();
2197  if (itrPosBar == itrEnd || itrNegBar == itrEnd)
2198  return Reference<XPropertySet>();
2199 
2200  return XclImpChSerErrorBar::CreateErrorBar(itrPosBar->second.get(), itrNegBar->second.get());
2201 }
2202 
2204 {
2205  rStrm.Ignore(2);
2206  sal_uInt16 nFlags = rStrm.ReaduInt16();
2208 }
2209 
2210 // Chart type groups ==========================================================
2211 
2213  XclImpChRoot( rRoot ),
2214  mnRecId( EXC_ID_CHUNKNOWN ),
2215  maTypeInfo( rRoot.GetChartTypeInfo( EXC_CHTYPEID_UNKNOWN ) )
2216 {
2217 }
2218 
2220 {
2221  sal_uInt16 nRecId = rStrm.GetRecId();
2222  bool bKnownType = true;
2223 
2224  switch( nRecId )
2225  {
2226  case EXC_ID_CHBAR:
2227  maData.mnOverlap = rStrm.ReadInt16();
2228  maData.mnGap = rStrm.ReadInt16();
2229  maData.mnFlags = rStrm.ReaduInt16();
2230  break;
2231 
2232  case EXC_ID_CHLINE:
2233  case EXC_ID_CHAREA:
2234  case EXC_ID_CHRADARLINE:
2235  case EXC_ID_CHRADARAREA:
2236  maData.mnFlags = rStrm.ReaduInt16();
2237  break;
2238 
2239  case EXC_ID_CHPIE:
2240  maData.mnRotation = rStrm.ReaduInt16();
2241  maData.mnPieHole = rStrm.ReaduInt16();
2242  if( GetBiff() == EXC_BIFF8 )
2243  maData.mnFlags = rStrm.ReaduInt16();
2244  else
2245  maData.mnFlags = 0;
2246  break;
2247 
2248  case EXC_ID_CHPIEEXT:
2249  maData.mnRotation = 0;
2250  maData.mnPieHole = 0;
2251  maData.mnFlags = 0;
2252  break;
2253 
2254  case EXC_ID_CHSCATTER:
2255  if( GetBiff() == EXC_BIFF8 )
2256  {
2257  maData.mnBubbleSize = rStrm.ReaduInt16();
2258  maData.mnBubbleType = rStrm.ReaduInt16();
2259  maData.mnFlags = rStrm.ReaduInt16();
2260  }
2261  else
2262  maData.mnFlags = 0;
2263  break;
2264 
2265  case EXC_ID_CHSURFACE:
2266  maData.mnFlags = rStrm.ReaduInt16();
2267  break;
2268 
2269  default:
2270  bKnownType = false;
2271  }
2272 
2273  if( bKnownType )
2274  mnRecId = nRecId;
2275 }
2276 
2277 void XclImpChType::Finalize( bool bStockChart )
2278 {
2279  switch( mnRecId )
2280  {
2281  case EXC_ID_CHLINE:
2282  maTypeInfo = GetChartTypeInfo( bStockChart ?
2284  break;
2285  case EXC_ID_CHBAR:
2289  break;
2290  case EXC_ID_CHPIE:
2293  break;
2294  case EXC_ID_CHSCATTER:
2298  break;
2299  default:
2301  }
2302 
2303  switch( maTypeInfo.meTypeId )
2304  {
2305  case EXC_CHTYPEID_PIEEXT:
2306  case EXC_CHTYPEID_BUBBLES:
2307  case EXC_CHTYPEID_SURFACE:
2308  case EXC_CHTYPEID_UNKNOWN:
2310  break;
2311  default:;
2312  }
2313 }
2314 
2316 {
2317  bool bStacked = false;
2319  {
2320  case EXC_CHTYPECATEG_LINE:
2321  bStacked =
2324  break;
2325  case EXC_CHTYPECATEG_BAR:
2326  bStacked =
2329  break;
2330  default:;
2331  }
2332  return bStacked;
2333 }
2334 
2336 {
2337  bool bPercent = false;
2339  {
2340  case EXC_CHTYPECATEG_LINE:
2341  bPercent =
2344  break;
2345  case EXC_CHTYPECATEG_BAR:
2346  bPercent =
2349  break;
2350  default:;
2351  }
2352  return bPercent;
2353 }
2354 
2356 {
2357  // radar charts disable category labels in chart type, not in CHTICK of X axis
2359 }
2360 
2361 Reference< XCoordinateSystem > XclImpChType::CreateCoordSystem( bool b3dChart ) const
2362 {
2363  // create the coordinate system object
2364  Reference< css::uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
2365  Reference< XCoordinateSystem > xCoordSystem;
2367  {
2368  if( b3dChart )
2369  xCoordSystem = css::chart2::PolarCoordinateSystem3d::create(xContext);
2370  else
2371  xCoordSystem = css::chart2::PolarCoordinateSystem2d::create(xContext);
2372  }
2373  else
2374  {
2375  if( b3dChart )
2376  xCoordSystem = css::chart2::CartesianCoordinateSystem3d::create(xContext);
2377  else
2378  xCoordSystem = css::chart2::CartesianCoordinateSystem2d::create(xContext);
2379  }
2380 
2381  // swap X and Y axis
2383  {
2384  ScfPropertySet aCoordSysProp( xCoordSystem );
2385  aCoordSysProp.SetBoolProperty( EXC_CHPROP_SWAPXANDYAXIS, true );
2386  }
2387 
2388  return xCoordSystem;
2389 }
2390 
2391 Reference< XChartType > XclImpChType::CreateChartType( Reference< XDiagram > const & xDiagram, bool b3dChart ) const
2392 {
2393  OUString aService = OUString::createFromAscii( maTypeInfo.mpcServiceName );
2394  Reference< XChartType > xChartType( ScfApiHelper::CreateInstance( aService ), UNO_QUERY );
2395 
2396  // additional properties
2397  switch( maTypeInfo.meTypeCateg )
2398  {
2399  case EXC_CHTYPECATEG_BAR:
2400  {
2401  ScfPropertySet aTypeProp( xChartType );
2402  Sequence< sal_Int32 > aInt32Seq( 2 );
2403  aInt32Seq[ 0 ] = aInt32Seq[ 1 ] = -maData.mnOverlap;
2404  aTypeProp.SetProperty( EXC_CHPROP_OVERLAPSEQ, aInt32Seq );
2405  aInt32Seq[ 0 ] = aInt32Seq[ 1 ] = maData.mnGap;
2406  aTypeProp.SetProperty( EXC_CHPROP_GAPWIDTHSEQ, aInt32Seq );
2407  }
2408  break;
2409  case EXC_CHTYPECATEG_PIE:
2410  {
2411  ScfPropertySet aTypeProp( xChartType );
2413  /* #i85166# starting angle of first pie slice. 3D pie charts use Y
2414  rotation setting in view3D element. Of-pie charts do not
2415  support pie rotation. */
2416  if( !b3dChart && (maTypeInfo.meTypeId != EXC_CHTYPEID_PIEEXT) )
2417  {
2418  ScfPropertySet aDiaProp( xDiagram );
2420  }
2421  }
2422  break;
2423  default:;
2424  }
2425 
2426  return xChartType;
2427 }
2428 
2430 {
2431  maData.mnRotation = rStrm.ReaduInt16();
2432  maData.mnElevation = rStrm.ReadInt16();
2433  maData.mnEyeDist = rStrm.ReaduInt16();
2434  maData.mnRelHeight = rStrm.ReaduInt16();
2435  maData.mnRelDepth = rStrm.ReaduInt16();
2436  maData.mnDepthGap = rStrm.ReaduInt16();
2437  maData.mnFlags = rStrm.ReaduInt16();
2438 }
2439 
2440 void XclImpChChart3d::Convert( ScfPropertySet& rPropSet, bool b3dWallChart ) const
2441 {
2442  namespace cssd = ::com::sun::star::drawing;
2443 
2444 // #i104057# do not assert this, written by broken external generators
2445 // OSL_ENSURE( ::get_flag( maData.mnFlags, EXC_CHCHART3D_HASWALLS ) == b3dWallChart, "XclImpChChart3d::Convert - wrong wall flag" );
2446 
2447  sal_Int32 nRotationY = 0;
2448  sal_Int32 nRotationX = 0;
2449  sal_Int32 nPerspective = 15;
2450  bool bRightAngled = false;
2451  cssd::ProjectionMode eProjMode = cssd::ProjectionMode_PERSPECTIVE;
2452  Color aAmbientColor, aLightColor;
2453 
2454  if( b3dWallChart )
2455  {
2456  // Y rotation (Excel [0..359], Chart2 [-179,180])
2457  nRotationY = NormAngle180<sal_Int32>(maData.mnRotation);
2458  // X rotation a.k.a. elevation (Excel [-90..90], Chart2 [-179,180])
2459  nRotationX = limit_cast< sal_Int32, sal_Int32 >( maData.mnElevation, -90, 90 );
2460  // perspective (Excel and Chart2 [0,100])
2461  nPerspective = limit_cast< sal_Int32, sal_Int32 >( maData.mnEyeDist, 0, 100 );
2462  // right-angled axes
2463  bRightAngled = !::get_flag( maData.mnFlags, EXC_CHCHART3D_REAL3D );
2464  // projection mode (parallel axes, if right-angled, #i90360# or if perspective is at 0%)
2465  bool bParallel = bRightAngled || (nPerspective == 0);
2466  eProjMode = bParallel ? cssd::ProjectionMode_PARALLEL : cssd::ProjectionMode_PERSPECTIVE;
2467  // ambient color (Gray 20%)
2468  aAmbientColor = Color( 204, 204, 204 );
2469  // light color (Gray 60%)
2470  aLightColor = Color( 102, 102, 102 );
2471  }
2472  else
2473  {
2474  // Y rotation not used in pie charts, but 'first pie slice angle'
2475  nRotationY = 0;
2477  // X rotation a.k.a. elevation (map Excel [10..80] to Chart2 [-80,-10])
2478  nRotationX = limit_cast< sal_Int32, sal_Int32 >( maData.mnElevation, 10, 80 ) - 90;
2479  // perspective (Excel and Chart2 [0,100])
2480  nPerspective = limit_cast< sal_Int32, sal_Int32 >( maData.mnEyeDist, 0, 100 );
2481  // no right-angled axes in pie charts, but parallel projection
2482  bRightAngled = false;
2483  eProjMode = cssd::ProjectionMode_PARALLEL;
2484  // ambient color (Gray 30%)
2485  aAmbientColor = Color( 179, 179, 179 );
2486  // light color (Gray 70%)
2487  aLightColor = Color( 76, 76, 76 );
2488  }
2489 
2490  // properties
2491  rPropSet.SetProperty( EXC_CHPROP_3DRELATIVEHEIGHT, static_cast<sal_Int32>(maData.mnRelHeight / 2)); // seems to be 200%, change to 100%
2492  rPropSet.SetProperty( EXC_CHPROP_ROTATIONVERTICAL, nRotationY );
2493  rPropSet.SetProperty( EXC_CHPROP_ROTATIONHORIZONTAL, nRotationX );
2494  rPropSet.SetProperty( EXC_CHPROP_PERSPECTIVE, nPerspective );
2495  rPropSet.SetBoolProperty( EXC_CHPROP_RIGHTANGLEDAXES, bRightAngled );
2496  rPropSet.SetProperty( EXC_CHPROP_D3DSCENEPERSPECTIVE, eProjMode );
2497 
2498  // light settings
2499  rPropSet.SetProperty( EXC_CHPROP_D3DSCENESHADEMODE, cssd::ShadeMode_FLAT );
2500  rPropSet.SetColorProperty( EXC_CHPROP_D3DSCENEAMBIENTCOLOR, aAmbientColor );
2501  rPropSet.SetBoolProperty( EXC_CHPROP_D3DSCENELIGHTON1, false );
2502  rPropSet.SetBoolProperty( EXC_CHPROP_D3DSCENELIGHTON2, true );
2503  rPropSet.SetColorProperty( EXC_CHPROP_D3DSCENELIGHTCOLOR2, aLightColor );
2504  rPropSet.SetProperty( EXC_CHPROP_D3DSCENELIGHTDIR2, cssd::Direction3D( 0.2, 0.4, 1.0 ) );
2505 }
2506 
2508  XclImpChRoot( rRoot )
2509 {
2510 }
2511 
2513 {
2514  rStrm >> maData.maRect;
2515  maData.mnDockMode = rStrm.ReaduInt8();
2516  maData.mnSpacing = rStrm.ReaduInt8();
2517  maData.mnFlags = rStrm.ReaduInt16();
2518 
2519  // trace unsupported features
2520  if( GetTracer().IsEnabled() )
2521  {
2526  }
2527 }
2528 
2530 {
2531  switch( rStrm.GetRecId() )
2532  {
2533  case EXC_ID_CHFRAMEPOS:
2534  mxFramePos = std::make_shared<XclImpChFramePos>();
2535  mxFramePos->ReadChFramePos( rStrm );
2536  break;
2537  case EXC_ID_CHTEXT:
2538  mxText = std::make_shared<XclImpChText>( GetChRoot() );
2539  mxText->ReadRecordGroup( rStrm );
2540  break;
2541  case EXC_ID_CHFRAME:
2542  mxFrame = std::make_shared<XclImpChFrame>( GetChRoot(), EXC_CHOBJTYPE_LEGEND );
2543  mxFrame->ReadRecordGroup( rStrm );
2544  break;
2545  }
2546 }
2547 
2549 {
2550  // legend default formatting differs in OOChart and Excel, missing frame means automatic
2551  if( !mxFrame )
2552  mxFrame = std::make_shared<XclImpChFrame>( GetChRoot(), EXC_CHOBJTYPE_LEGEND );
2553  // Update text formatting. If mxText is empty, the passed default text is used.
2554  lclUpdateText( mxText, GetChartData().GetDefaultText( EXC_CHTEXTTYPE_LEGEND ) );
2555 }
2556 
2557 Reference< XLegend > XclImpChLegend::CreateLegend() const
2558 {
2559  Reference< XLegend > xLegend( ScfApiHelper::CreateInstance( SERVICE_CHART2_LEGEND ), UNO_QUERY );
2560  if( xLegend.is() )
2561  {
2562  ScfPropertySet aLegendProp( xLegend );
2563  aLegendProp.SetBoolProperty( EXC_CHPROP_SHOW, true );
2564 
2565  // frame properties
2566  if( mxFrame )
2567  mxFrame->Convert( aLegendProp );
2568  // text properties
2569  if( mxText )
2570  mxText->ConvertFont( aLegendProp );
2571 
2572  /* Legend position and size. Default positions are used only if the
2573  plot area is positioned automatically (Excel sets the plot area to
2574  manual mode, if the legend is moved or resized). With manual plot
2575  areas, Excel ignores the value in maData.mnDockMode completely. */
2576  cssc2::LegendPosition eApiPos = cssc2::LegendPosition_LINE_END;
2577  cssc::ChartLegendExpansion eApiExpand = cssc::ChartLegendExpansion_CUSTOM;
2578  if( !GetChartData().IsManualPlotArea() ) switch( maData.mnDockMode )
2579  {
2580  case EXC_CHLEGEND_LEFT:
2581  eApiPos = cssc2::LegendPosition_LINE_START;
2582  eApiExpand = cssc::ChartLegendExpansion_HIGH;
2583  break;
2584  case EXC_CHLEGEND_RIGHT:
2585  // top-right not supported
2586  case EXC_CHLEGEND_CORNER:
2587  eApiPos = cssc2::LegendPosition_LINE_END;
2588  eApiExpand = cssc::ChartLegendExpansion_HIGH;
2589  break;
2590  case EXC_CHLEGEND_TOP:
2591  eApiPos = cssc2::LegendPosition_PAGE_START;
2592  eApiExpand = cssc::ChartLegendExpansion_WIDE;
2593  break;
2594  case EXC_CHLEGEND_BOTTOM:
2595  eApiPos = cssc2::LegendPosition_PAGE_END;
2596  eApiExpand = cssc::ChartLegendExpansion_WIDE;
2597  break;
2598  }
2599 
2600  // no automatic position/size: try to find the correct position and size
2601  if( GetChartData().IsManualPlotArea() || maData.mnDockMode == EXC_CHLEGEND_NOTDOCKED )
2602  {
2603  const XclChFramePos* pFramePos = mxFramePos ? &mxFramePos->GetFramePosData() : nullptr;
2604 
2605  /* Legend position. Only the settings from the CHFRAMEPOS record
2606  are used by Excel, the position in the CHLEGEND record will be
2607  ignored. */
2608  if( pFramePos )
2609  {
2610  RelativePosition aRelPos(
2611  CalcRelativeFromChartX( pFramePos->maRect.mnX ),
2612  CalcRelativeFromChartY( pFramePos->maRect.mnY ),
2613  css::drawing::Alignment_TOP_LEFT );
2614  aLegendProp.SetProperty( EXC_CHPROP_RELATIVEPOSITION, aRelPos );
2615  }
2616  else
2617  {
2618  // no manual position/size found, just go for the default
2619  eApiPos = cssc2::LegendPosition_LINE_END;
2620  }
2621 
2622  /* Legend size. The member mnBRMode specifies whether size is
2623  automatic or changes manually. Manual size is given in points,
2624  not in chart units. */
2625  if( pFramePos && (pFramePos->mnBRMode == EXC_CHFRAMEPOS_ABSSIZE_POINTS) &&
2626  (pFramePos->maRect.mnWidth > 0) && (pFramePos->maRect.mnHeight > 0) )
2627  {
2628  eApiExpand = cssc::ChartLegendExpansion_CUSTOM;
2629  sal_Int32 nWidthHmm = o3tl::convert(pFramePos->maRect.mnWidth, o3tl::Length::pt, o3tl::Length::mm100);
2630  sal_Int32 nHeightHmm = o3tl::convert(pFramePos->maRect.mnHeight, o3tl::Length::pt, o3tl::Length::mm100);
2631  RelativeSize aRelSize( CalcRelativeFromHmmX( nWidthHmm ), CalcRelativeFromHmmY( nHeightHmm ) );
2632  aLegendProp.SetProperty( EXC_CHPROP_RELATIVESIZE, aRelSize );
2633  }
2634  else
2635  {
2636  // automatic size: determine entry direction from flags
2638  cssc::ChartLegendExpansion_HIGH, cssc::ChartLegendExpansion_WIDE );
2639  }
2640  }
2641  aLegendProp.SetProperty( EXC_CHPROP_ANCHORPOSITION, eApiPos );
2642  aLegendProp.SetProperty( EXC_CHPROP_EXPANSION, eApiExpand );
2643  }
2644  return xLegend;
2645 }
2646 
2647 XclImpChDropBar::XclImpChDropBar( sal_uInt16 nDropBar ) :
2648  mnDropBar( nDropBar ),
2649  mnBarDist( 0 )
2650 {
2651 }
2652 
2654 {
2655  mnBarDist = rStrm.ReaduInt16();
2656 }
2657 
2658 void XclImpChDropBar::Convert( const XclImpChRoot& rRoot, ScfPropertySet& rPropSet ) const
2659 {
2661  switch( mnDropBar )
2662  {
2663  case EXC_CHDROPBAR_UP: eObjType = EXC_CHOBJTYPE_WHITEDROPBAR; break;
2664  case EXC_CHDROPBAR_DOWN: eObjType = EXC_CHOBJTYPE_BLACKDROPBAR; break;
2665  }
2666  ConvertFrameBase( rRoot, rPropSet, eObjType );
2667 }
2668 
2670  XclImpChRoot( rRoot ),
2671  maType( rRoot ),
2672  maTypeInfo( maType.GetTypeInfo() )
2673 {
2674  // Initialize unused format indexes set. At this time, all formats are unused.
2675  for( sal_uInt16 nFormatIdx = 0; nFormatIdx <= EXC_CHSERIES_MAXSERIES; ++nFormatIdx )
2676  maUnusedFormats.insert( maUnusedFormats.end(), nFormatIdx );
2677 }
2678 
2680 {
2681  rStrm.Ignore( 16 );
2682  maData.mnFlags = rStrm.ReaduInt16();
2683  maData.mnGroupIdx = rStrm.ReaduInt16();
2684 }
2685 
2687 {
2688  switch( rStrm.GetRecId() )
2689  {
2690  case EXC_ID_CHCHART3D:
2691  mxChart3d = std::make_shared<XclImpChChart3d>();
2692  mxChart3d->ReadChChart3d( rStrm );
2693  break;
2694  case EXC_ID_CHLEGEND:
2695  mxLegend = std::make_shared<XclImpChLegend>( GetChRoot() );
2696  mxLegend->ReadRecordGroup( rStrm );
2697  break;
2698  case EXC_ID_CHDEFAULTTEXT:
2699  GetChartData().ReadChDefaultText( rStrm );
2700  break;
2701  case EXC_ID_CHDROPBAR:
2702  ReadChDropBar( rStrm );
2703  break;
2704  case EXC_ID_CHCHARTLINE:
2705  ReadChChartLine( rStrm );
2706  break;
2707  case EXC_ID_CHDATAFORMAT:
2708  ReadChDataFormat( rStrm );
2709  break;
2710  default:
2711  maType.ReadChType( rStrm );
2712  }
2713 }
2714 
2716 {
2717  // check and set valid chart type
2718  bool bStockChart =
2719  (maType.GetRecId() == EXC_ID_CHLINE) && // must be a line chart
2720  !mxChart3d && // must be a 2d chart
2721  m_ChartLines.find(EXC_CHCHARTLINE_HILO) != m_ChartLines.end() && // must contain hi-lo lines
2722  (maSeries.size() == static_cast<XclImpChSeriesVec::size_type>(HasDropBars() ? 4 : 3)); // correct series count
2723  maType.Finalize( bStockChart );
2724 
2725  // extended type info
2726  maTypeInfo.Set( maType.GetTypeInfo(), static_cast< bool >(mxChart3d), false );
2727 
2728  // reverse series order for some unstacked 2D chart types
2730  ::std::reverse( maSeries.begin(), maSeries.end() );
2731 
2732  // update chart type group format, may depend on chart type finalized above
2733  if( mxGroupFmt )
2734  mxGroupFmt->UpdateGroupFormat( maTypeInfo );
2735 }
2736 
2738 {
2739  if( xSeries )
2740  maSeries.push_back( xSeries );
2741  // store first inserted series separately, series order may be reversed later
2742  if( !mxFirstSeries )
2743  mxFirstSeries = xSeries;
2744 }
2745 
2746 void XclImpChTypeGroup::SetUsedFormatIndex( sal_uInt16 nFormatIdx )
2747 {
2748  maUnusedFormats.erase( nFormatIdx );
2749 }
2750 
2752 {
2753  OSL_ENSURE( !maUnusedFormats.empty(), "XclImpChTypeGroup::PopUnusedFormatIndex - no more format indexes available" );
2754  sal_uInt16 nFormatIdx = maUnusedFormats.empty() ? 0 : *maUnusedFormats.begin();
2755  SetUsedFormatIndex( nFormatIdx );
2756  return nFormatIdx;
2757 }
2758 
2760 {
2762  ((maTypeInfo.meVarPointMode == EXC_CHVARPOINT_MULTI) || // multiple series allowed
2763  ((maTypeInfo.meVarPointMode == EXC_CHVARPOINT_SINGLE) && // or exactly 1 series?
2764  (maSeries.size() == 1)));
2765 }
2766 
2768 {
2769  // existence of connector lines (only in stacked bar charts)
2771  return false;
2772  XclImpChLineFormatMap::const_iterator aConLine = m_ChartLines.find(EXC_CHCHARTLINE_CONNECT);
2773  return (aConLine != m_ChartLines.end() && aConLine->second.HasLine());
2774 }
2775 
2777 {
2778  // no automatic title for series with trendlines or error bars
2779  // pie charts always show an automatic title, even if more series exist
2780  return (mxFirstSeries && !mxFirstSeries->HasChildSeries() && (maTypeInfo.mbSingleSeriesVis || (maSeries.size() == 1))) ?
2781  mxFirstSeries->GetTitle() : OUString();
2782 }
2783 
2785 {
2786  if( mxChart3d )
2787  mxChart3d->Convert( rPropSet, Is3dWallChart() );
2788 }
2789 
2790 Reference< XCoordinateSystem > XclImpChTypeGroup::CreateCoordSystem() const
2791 {
2792  return maType.CreateCoordSystem( Is3dChart() );
2793 }
2794 
2795 Reference< XChartType > XclImpChTypeGroup::CreateChartType( Reference< XDiagram > const & xDiagram, sal_Int32 nApiAxesSetIdx ) const
2796 {
2797  OSL_ENSURE( IsValidGroup(), "XclImpChTypeGroup::CreateChartType - type group without series" );
2798 
2799  // create the chart type object
2800  Reference< XChartType > xChartType = maType.CreateChartType( xDiagram, Is3dChart() );
2801 
2802  // bar chart connector lines
2803  if( HasConnectorLines() )
2804  {
2805  ScfPropertySet aDiaProp( xDiagram );
2806  aDiaProp.SetBoolProperty( EXC_CHPROP_CONNECTBARS, true );
2807  }
2808 
2809  /* Stock chart needs special processing. Create one 'big' series with
2810  data sequences of different roles. */
2812  CreateStockSeries( xChartType, nApiAxesSetIdx );
2813  else
2814  CreateDataSeries( xChartType, nApiAxesSetIdx );
2815 
2816  return xChartType;
2817 }
2818 
2819 Reference< XLabeledDataSequence > XclImpChTypeGroup::CreateCategSequence() const
2820 {
2821  Reference< XLabeledDataSequence > xLabeledSeq;
2822  // create category sequence from first visible series
2823  if( mxFirstSeries )
2824  xLabeledSeq = mxFirstSeries->CreateCategSequence( EXC_CHPROP_ROLE_CATEG );
2825  return xLabeledSeq;
2826 }
2827 
2829 {
2830  if (m_DropBars.find(EXC_CHDROPBAR_UP) == m_DropBars.end())
2831  {
2832  unique_ptr<XclImpChDropBar> p(new XclImpChDropBar(EXC_CHDROPBAR_UP));
2833  p->ReadRecordGroup(rStrm);
2834  m_DropBars.insert(std::make_pair(EXC_CHDROPBAR_UP, std::move(p)));
2835  }
2836  else if (m_DropBars.find(EXC_CHDROPBAR_DOWN) == m_DropBars.end())
2837  {
2838  unique_ptr<XclImpChDropBar> p(new XclImpChDropBar(EXC_CHDROPBAR_DOWN));
2839  p->ReadRecordGroup(rStrm);
2840  m_DropBars.insert(std::make_pair(EXC_CHDROPBAR_DOWN, std::move(p)));
2841  }
2842 }
2843 
2845 {
2846  sal_uInt16 nLineId = rStrm.ReaduInt16();
2847  if( (rStrm.GetNextRecId() == EXC_ID_CHLINEFORMAT) && rStrm.StartNextRecord() )
2848  {
2849  XclImpChLineFormat aLineFmt;
2850  aLineFmt.ReadChLineFormat( rStrm );
2851  m_ChartLines[ nLineId ] = aLineFmt;
2852  }
2853 }
2854 
2856 {
2857  // global series and data point format
2858  XclImpChDataFormatRef xDataFmt = std::make_shared<XclImpChDataFormat>( GetChRoot() );
2859  xDataFmt->ReadRecordGroup( rStrm );
2860  const XclChDataPointPos& rPos = xDataFmt->GetPointPos();
2861  if( (rPos.mnSeriesIdx == 0) && (rPos.mnPointIdx == 0) &&
2862  (xDataFmt->GetFormatIdx() == EXC_CHDATAFORMAT_DEFAULT) )
2863  mxGroupFmt = xDataFmt;
2864 }
2865 
2866 void XclImpChTypeGroup::InsertDataSeries( Reference< XChartType > const & xChartType,
2867  Reference< XDataSeries > const & xSeries, sal_Int32 nApiAxesSetIdx ) const
2868 {
2869  Reference< XDataSeriesContainer > xSeriesCont( xChartType, UNO_QUERY );
2870  if( !(xSeriesCont.is() && xSeries.is()) )
2871  return;
2872 
2873  // series stacking mode
2874  cssc2::StackingDirection eStacking = cssc2::StackingDirection_NO_STACKING;
2875  // stacked overrides deep-3d
2876  if( maType.IsStacked() || maType.IsPercent() )
2877  eStacking = cssc2::StackingDirection_Y_STACKING;
2878  else if( Is3dDeepChart() )
2879  eStacking = cssc2::StackingDirection_Z_STACKING;
2880 
2881  // additional series properties
2882  ScfPropertySet aSeriesProp( xSeries );
2883  aSeriesProp.SetProperty( EXC_CHPROP_STACKINGDIR, eStacking );
2884  aSeriesProp.SetProperty( EXC_CHPROP_ATTAXISINDEX, nApiAxesSetIdx );
2885 
2886  // insert series into container
2887  try
2888  {
2889  xSeriesCont->addDataSeries( xSeries );
2890  }
2891  catch( Exception& )
2892  {
2893  OSL_FAIL( "XclImpChTypeGroup::InsertDataSeries - cannot add data series" );
2894  }
2895 }
2896 
2897 void XclImpChTypeGroup::CreateDataSeries( Reference< XChartType > const & xChartType, sal_Int32 nApiAxesSetIdx ) const
2898 {
2899  bool bSpline = false;
2900  for (auto const& elem : maSeries)
2901  {
2902  Reference< XDataSeries > xDataSeries = elem->CreateDataSeries();
2903  InsertDataSeries( xChartType, xDataSeries, nApiAxesSetIdx );
2904  bSpline |= elem->HasSpline();
2905  }
2906  // spline - TODO: set at single series (#i66858#)
2908  {
2909  ScfPropertySet aTypeProp( xChartType );
2910  aTypeProp.SetProperty( EXC_CHPROP_CURVESTYLE, css::chart2::CurveStyle_CUBIC_SPLINES );
2911  }
2912 }
2913 
2914 void XclImpChTypeGroup::CreateStockSeries( Reference< XChartType > const & xChartType, sal_Int32 nApiAxesSetIdx ) const
2915 {
2916  // create the data series object
2917  Reference< XDataSeries > xDataSeries( ScfApiHelper::CreateInstance( SERVICE_CHART2_DATASERIES ), UNO_QUERY );
2918  Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY );
2919  if( !xDataSink.is() )
2920  return;
2921 
2922  // create a list of data sequences from all series
2923  ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
2924  OSL_ENSURE( maSeries.size() >= 3, "XclImpChTypeGroup::CreateChartType - missing stock series" );
2925  int nRoleIdx = (maSeries.size() == 3) ? 1 : 0;
2926  for( const auto& rxSeries : maSeries )
2927  {
2928  // create a data sequence with a specific role
2929  OUString aRole;
2930  switch( nRoleIdx )
2931  {
2932  case 0: aRole = EXC_CHPROP_ROLE_OPENVALUES; break;
2933  case 1: aRole = EXC_CHPROP_ROLE_HIGHVALUES; break;
2934  case 2: aRole = EXC_CHPROP_ROLE_LOWVALUES; break;
2935  case 3: aRole = EXC_CHPROP_ROLE_CLOSEVALUES; break;
2936  }
2937  Reference< XLabeledDataSequence > xDataSeq = rxSeries->CreateValueSequence( aRole );
2938  if( xDataSeq.is() )
2939  aLabeledSeqVec.push_back( xDataSeq );
2940  ++nRoleIdx;
2941  if (nRoleIdx >= 4)
2942  break;
2943  }
2944 
2945  // attach labeled data sequences to series and insert series into chart type
2946  xDataSink->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec ) );
2947 
2948  // formatting of special stock chart elements
2949  ScfPropertySet aTypeProp( xChartType );
2952  aTypeProp.SetBoolProperty( EXC_CHPROP_SHOWHIGHLOW, true );
2953  // hi-lo line format
2954  XclImpChLineFormatMap::const_iterator aHiLoLine = m_ChartLines.find( EXC_CHCHARTLINE_HILO );
2955  if (aHiLoLine != m_ChartLines.end())
2956  {
2957  ScfPropertySet aSeriesProp( xDataSeries );
2958  aHiLoLine->second.Convert( GetChRoot(), aSeriesProp, EXC_CHOBJTYPE_HILOLINE );
2959  }
2960  // white dropbar format
2961  XclImpChDropBarMap::const_iterator itr = m_DropBars.find(EXC_CHDROPBAR_UP);
2962  Reference<XPropertySet> xWhitePropSet;
2963  if (itr != m_DropBars.end() && aTypeProp.GetProperty(xWhitePropSet, EXC_CHPROP_WHITEDAY))
2964  {
2965  ScfPropertySet aBarProp( xWhitePropSet );
2966  itr->second->Convert(GetChRoot(), aBarProp);
2967  }
2968  // black dropbar format
2969  itr = m_DropBars.find(EXC_CHDROPBAR_DOWN);
2970  Reference<XPropertySet> xBlackPropSet;
2971  if (itr != m_DropBars.end() && aTypeProp.GetProperty(xBlackPropSet, EXC_CHPROP_BLACKDAY))
2972  {
2973  ScfPropertySet aBarProp( xBlackPropSet );
2974  itr->second->Convert(GetChRoot(), aBarProp);
2975  }
2976 
2977  // insert the series into the chart type object
2978  InsertDataSeries( xChartType, xDataSeries, nApiAxesSetIdx );
2979 }
2980 
2981 // Axes =======================================================================
2982 
2984  XclImpChRoot( rRoot )
2985 {
2986 }
2987 
2989 {
2990  maLabelData.mnCross = rStrm.ReaduInt16();
2992  maLabelData.mnTickFreq = rStrm.ReaduInt16();
2993  maLabelData.mnFlags = rStrm.ReaduInt16();
2994 }
2995 
2997 {
2998  maDateData.mnMinDate = rStrm.ReaduInt16();
2999  maDateData.mnMaxDate = rStrm.ReaduInt16();
3000  maDateData.mnMajorStep = rStrm.ReaduInt16();
3001  maDateData.mnMajorUnit = rStrm.ReaduInt16();
3002  maDateData.mnMinorStep = rStrm.ReaduInt16();
3003  maDateData.mnMinorUnit = rStrm.ReaduInt16();
3004  maDateData.mnBaseUnit = rStrm.ReaduInt16();
3005  maDateData.mnCross = rStrm.ReaduInt16();
3006  maDateData.mnFlags = rStrm.ReaduInt16();
3007 }
3008 
3009 void XclImpChLabelRange::Convert( ScfPropertySet& rPropSet, ScaleData& rScaleData, bool bMirrorOrient ) const
3010 {
3011  // automatic axis type detection
3012  rScaleData.AutoDateAxis = ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTODATE );
3013 
3014  // the flag EXC_CHDATERANGE_DATEAXIS specifies whether this is a date axis
3016  {
3017  /* Chart2 requires axis type CATEGORY for automatic category/date axis
3018  (even if it is a date axis currently). */
3019  rScaleData.AxisType = rScaleData.AutoDateAxis ? cssc2::AxisType::CATEGORY : cssc2::AxisType::DATE;
3020  rScaleData.Scaling = css::chart2::LinearScaling::create( comphelper::getProcessComponentContext() );
3021  /* Min/max values depend on base time unit, they specify the number of
3022  days, months, or years starting from null date. */
3023  lclConvertTimeValue( GetRoot(), rScaleData.Minimum, maDateData.mnMinDate, ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMIN ), maDateData.mnBaseUnit );
3024  lclConvertTimeValue( GetRoot(), rScaleData.Maximum, maDateData.mnMaxDate, ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMAX ), maDateData.mnBaseUnit );
3025  // increment
3026  cssc::TimeIncrement& rTimeIncrement = rScaleData.TimeIncrement;
3027  lclConvertTimeInterval( rTimeIncrement.MajorTimeInterval, maDateData.mnMajorStep, ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMAJOR ), maDateData.mnMajorUnit );
3028  lclConvertTimeInterval( rTimeIncrement.MinorTimeInterval, maDateData.mnMinorStep, ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMINOR ), maDateData.mnMinorUnit );
3029  // base unit
3031  rTimeIncrement.TimeResolution.clear();
3032  else
3033  rTimeIncrement.TimeResolution <<= lclGetApiTimeUnit( maDateData.mnBaseUnit );
3034  }
3035  else
3036  {
3037  // do not overlap text unless all labels are visible
3039  // do not break text into several lines unless all labels are visible
3041  // do not stagger labels in two lines
3042  rPropSet.SetProperty( EXC_CHPROP_ARRANGEORDER, cssc::ChartAxisArrangeOrderType_SIDE_BY_SIDE );
3043  }
3044 
3045  // reverse order
3046  bool bReverse = ::get_flag( maLabelData.mnFlags, EXC_CHLABELRANGE_REVERSE ) != bMirrorOrient;
3047  rScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL;
3048 
3049  //TODO #i58731# show n-th category
3050 }
3051 
3052 void XclImpChLabelRange::ConvertAxisPosition( ScfPropertySet& rPropSet, bool b3dChart ) const
3053 {
3054  /* Crossing mode (max-cross flag overrides other crossing settings). Excel
3055  does not move the Y axis in 3D charts, regardless of actual settings.
3056  But: the Y axis has to be moved to "end", if the X axis is mirrored,
3057  to keep it at the left end of the chart. */
3059  cssc::ChartAxisPosition eAxisPos = bMaxCross ? cssc::ChartAxisPosition_END : cssc::ChartAxisPosition_VALUE;
3060  rPropSet.SetProperty( EXC_CHPROP_CROSSOVERPOSITION, eAxisPos );
3061 
3062  // crossing position (depending on axis type text/date)
3064  {
3066  /* Crossing position value depends on base time unit, it specifies the
3067  number of days, months, or years from null date. Note that Excel
3068  2007/2010 write broken BIFF8 files, they always stores the number
3069  of days regardless of the base time unit (and they are reading it
3070  the same way, thus wrongly displaying files written by Excel
3071  97-2003). This filter sticks to the correct behaviour of Excel
3072  97-2003. */
3073  double fCrossingPos = bAutoCross ? 1.0 : lclGetSerialDay( GetRoot(), maDateData.mnCross, maDateData.mnBaseUnit );
3074  rPropSet.SetProperty( EXC_CHPROP_CROSSOVERVALUE, fCrossingPos );
3075  }
3076  else
3077  {
3078  double fCrossingPos = b3dChart ? 1.0 : maLabelData.mnCross;
3079  rPropSet.SetProperty( EXC_CHPROP_CROSSOVERVALUE, fCrossingPos );
3080  }
3081 }
3082 
3084  XclImpChRoot( rRoot )
3085 {
3086 }
3087 
3089 {
3090  maData.mfMin = rStrm.ReadDouble();
3091  maData.mfMax = rStrm.ReadDouble();
3092  maData.mfMajorStep = rStrm.ReadDouble();
3093  maData.mfMinorStep = rStrm.ReadDouble();
3094  maData.mfCross = rStrm.ReadDouble();
3095  maData.mnFlags = rStrm.ReaduInt16();
3096 }
3097 
3098 void XclImpChValueRange::Convert( ScaleData& rScaleData, bool bMirrorOrient ) const
3099 {
3100  // scaling algorithm
3101  const bool bLogScale = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_LOGSCALE );
3102  if( bLogScale )
3103  rScaleData.Scaling = css::chart2::LogarithmicScaling::create( comphelper::getProcessComponentContext() );
3104  else
3105  rScaleData.Scaling = css::chart2::LinearScaling::create( comphelper::getProcessComponentContext() );
3106 
3107  // min/max
3108  lclSetExpValueOrClearAny( rScaleData.Minimum, maData.mfMin, bLogScale, ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMIN ) );
3109  lclSetExpValueOrClearAny( rScaleData.Maximum, maData.mfMax, bLogScale, ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMAX ) );
3110 
3111  // increment
3112  bool bAutoMajor = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMAJOR );
3113  bool bAutoMinor = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMINOR );
3114  // major increment
3115  IncrementData& rIncrementData = rScaleData.IncrementData;
3116  lclSetValueOrClearAny( rIncrementData.Distance, maData.mfMajorStep, bAutoMajor );
3117  // minor increment
3118  Sequence< SubIncrement >& rSubIncrementSeq = rIncrementData.SubIncrements;
3119  rSubIncrementSeq.realloc( 1 );
3120  Any& rIntervalCount = rSubIncrementSeq[ 0 ].IntervalCount;
3121  rIntervalCount.clear();
3122  if( bLogScale )
3123  {
3124  if( !bAutoMinor )
3125  rIntervalCount <<= sal_Int32( 9 );
3126  }
3127  else if( !bAutoMajor && !bAutoMinor && (0.0 < maData.mfMinorStep) && (maData.mfMinorStep <= maData.mfMajorStep) )
3128  {
3129  double fCount = maData.mfMajorStep / maData.mfMinorStep + 0.5;
3130  if( (1.0 <= fCount) && (fCount < 1001.0) )
3131  rIntervalCount <<= static_cast< sal_Int32 >( fCount );
3132  }
3133  else if( bAutoMinor )
3134  {
3135  // tdf#114168 If minor unit is not set then set interval to 5, as MS Excel do.
3136  rIntervalCount <<= static_cast< sal_Int32 >( 5 );
3137  }
3138 
3139  // reverse order
3140  bool bReverse = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_REVERSE ) != bMirrorOrient;
3141  rScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL;
3142 }
3143 
3145 {
3146  bool bMaxCross = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_MAXCROSS );
3147  bool bAutoCross = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOCROSS );
3148  bool bLogScale = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_LOGSCALE );
3149 
3150  // crossing mode (max-cross flag overrides other crossing settings)
3151  cssc::ChartAxisPosition eAxisPos = bMaxCross ? cssc::ChartAxisPosition_END : cssc::ChartAxisPosition_VALUE;
3152  rPropSet.SetProperty( EXC_CHPROP_CROSSOVERPOSITION, eAxisPos );
3153 
3154  // crossing position
3155  double fCrossingPos = bAutoCross ? 0.0 : maData.mfCross;
3156  if( bLogScale ) fCrossingPos = pow( 10.0, fCrossingPos );
3157  rPropSet.SetProperty( EXC_CHPROP_CROSSOVERVALUE, fCrossingPos );
3158 }
3159 
3160 namespace {
3161 
3162 sal_Int32 lclGetApiTickmarks( sal_uInt8 nXclTickPos )
3163 {
3164  using namespace ::com::sun::star::chart2::TickmarkStyle;
3165  sal_Int32 nApiTickmarks = css::chart2::TickmarkStyle::NONE;
3166  ::set_flag( nApiTickmarks, INNER, ::get_flag( nXclTickPos, EXC_CHTICK_INSIDE ) );
3167  ::set_flag( nApiTickmarks, OUTER, ::get_flag( nXclTickPos, EXC_CHTICK_OUTSIDE ) );
3168  return nApiTickmarks;
3169 }
3170 
3171 cssc::ChartAxisLabelPosition lclGetApiLabelPosition( sal_Int8 nXclLabelPos )
3172 {
3173  using namespace ::com::sun::star::chart;
3174  switch( nXclLabelPos )
3175  {
3176  case EXC_CHTICK_LOW: return ChartAxisLabelPosition_OUTSIDE_START;
3177  case EXC_CHTICK_HIGH: return ChartAxisLabelPosition_OUTSIDE_END;
3178  case EXC_CHTICK_NEXT: return ChartAxisLabelPosition_NEAR_AXIS;
3179  }
3180  return ChartAxisLabelPosition_NEAR_AXIS;
3181 }
3182 
3183 } // namespace
3184 
3186  XclImpChRoot( rRoot )
3187 {
3188 }
3189 
3191 {
3192  maData.mnMajor = rStrm.ReaduInt8();
3193  maData.mnMinor = rStrm.ReaduInt8();
3194  maData.mnLabelPos = rStrm.ReaduInt8();
3195  maData.mnBackMode = rStrm.ReaduInt8();
3196  rStrm.Ignore( 16 );
3197  rStrm >> maData.maTextColor;
3198  maData.mnFlags = rStrm.ReaduInt16();
3199 
3200  if( GetBiff() == EXC_BIFF8 )
3201  {
3202  // BIFF8: index into palette used instead of RGB data
3204  // rotation
3205  maData.mnRotation = rStrm.ReaduInt16();
3206  }
3207  else
3208  {
3209  // BIFF2-BIFF7: get rotation from text orientation
3210  sal_uInt8 nOrient = ::extract_value< sal_uInt8 >( maData.mnFlags, 2, 3 );
3212  }
3213 }
3214 
3216 {
3218 }
3219 
3220 sal_uInt16 XclImpChTick::GetRotation() const
3221 {
3222  /* n#720443: Ignore auto-rotation if there is a suggested rotation.
3223  * Better fix would be to improve our axis auto rotation algorithm.
3224  */
3225  if( maData.mnRotation != EXC_ROT_NONE )
3226  return maData.mnRotation;
3228 }
3229 
3230 void XclImpChTick::Convert( ScfPropertySet& rPropSet ) const
3231 {
3232  rPropSet.SetProperty( EXC_CHPROP_MAJORTICKS, lclGetApiTickmarks( maData.mnMajor ) );
3233  rPropSet.SetProperty( EXC_CHPROP_MINORTICKS, lclGetApiTickmarks( maData.mnMinor ) );
3234  rPropSet.SetProperty( EXC_CHPROP_LABELPOSITION, lclGetApiLabelPosition( maData.mnLabelPos ) );
3235  rPropSet.SetProperty( EXC_CHPROP_MARKPOSITION, cssc::ChartAxisMarkPosition_AT_AXIS );
3236 }
3237 
3238 XclImpChAxis::XclImpChAxis( const XclImpChRoot& rRoot, sal_uInt16 nAxisType ) :
3239  XclImpChRoot( rRoot ),
3240  mnNumFmtIdx( EXC_FORMAT_NOTFOUND )
3241 {
3242  maData.mnType = nAxisType;
3243 }
3244 
3246 {
3247  maData.mnType = rStrm.ReaduInt16();
3248 }
3249 
3251 {
3252  switch( rStrm.GetRecId() )
3253  {
3254  case EXC_ID_CHLABELRANGE:
3255  mxLabelRange = std::make_shared<XclImpChLabelRange>( GetChRoot() );
3256  mxLabelRange->ReadChLabelRange( rStrm );
3257  break;
3258  case EXC_ID_CHDATERANGE:
3259  if( !mxLabelRange )
3260  mxLabelRange = std::make_shared<XclImpChLabelRange>( GetChRoot() );
3261  mxLabelRange->ReadChDateRange( rStrm );
3262  break;
3263  case EXC_ID_CHVALUERANGE:
3264  mxValueRange = std::make_shared<XclImpChValueRange>( GetChRoot() );
3265  mxValueRange->ReadChValueRange( rStrm );
3266  break;
3267  case EXC_ID_CHFORMAT:
3268  mnNumFmtIdx = rStrm.ReaduInt16();
3269  break;
3270  case EXC_ID_CHTICK:
3271  mxTick = std::make_shared<XclImpChTick>( GetChRoot() );
3272  mxTick->ReadChTick( rStrm );
3273  break;
3274  case EXC_ID_CHFONT:
3275  mxFont = std::make_shared<XclImpChFont>();
3276  mxFont->ReadChFont( rStrm );
3277  break;
3278  case EXC_ID_CHAXISLINE:
3279  ReadChAxisLine( rStrm );
3280  break;
3281  }
3282 }
3283 
3285 {
3286  // add default scaling, needed e.g. to adjust rotation direction of pie and radar charts
3287  if( !mxLabelRange )
3288  mxLabelRange = std::make_shared<XclImpChLabelRange>( GetChRoot() );
3289  if( !mxValueRange )
3290  mxValueRange = std::make_shared<XclImpChValueRange>( GetChRoot() );
3291  // remove invisible grid lines completely
3292  if( mxMajorGrid && !mxMajorGrid->HasLine() )
3293  mxMajorGrid.clear();
3294  if( mxMinorGrid && !mxMinorGrid->HasLine() )
3295  mxMinorGrid.clear();
3296  // default tick settings different in OOChart and Excel
3297  if( !mxTick )
3298  mxTick = std::make_shared<XclImpChTick>( GetChRoot() );
3299  // #i4140# different default axis line color
3300  if( !mxAxisLine )
3301  {
3302  XclChLineFormat aLineFmt;
3303  // set "show axis" flag, default if line format record is missing
3305  mxAxisLine = new XclImpChLineFormat( aLineFmt );
3306  }
3307  // add wall/floor frame for 3d charts
3308  if( !mxWallFrame )
3309  CreateWallFrame();
3310 }
3311 
3312 sal_uInt16 XclImpChAxis::GetFontIndex() const
3313 {
3314  return mxFont ? mxFont->GetFontIndex() : EXC_FONT_NOTFOUND;
3315 }
3316 
3318 {
3319  return mxTick ? mxTick->GetFontColor() : GetFontAutoColor();
3320 }
3321 
3322 sal_uInt16 XclImpChAxis::GetRotation() const
3323 {
3324  return mxTick ? mxTick->GetRotation() : EXC_CHART_AUTOROTATION;
3325 }
3326 
3327 Reference< XAxis > XclImpChAxis::CreateAxis( const XclImpChTypeGroup& rTypeGroup, const XclImpChAxis* pCrossingAxis ) const
3328 {
3329  // create the axis object (always)
3330  Reference< XAxis > xAxis( ScfApiHelper::CreateInstance( SERVICE_CHART2_AXIS ), UNO_QUERY );
3331  if( xAxis.is() )
3332  {
3333  ScfPropertySet aAxisProp( xAxis );
3334  // #i58688# axis enabled
3335  aAxisProp.SetBoolProperty( EXC_CHPROP_SHOW, !mxAxisLine || mxAxisLine->IsShowAxis() );
3336 
3337  // axis line properties
3338  if( mxAxisLine )
3339  mxAxisLine->Convert( GetChRoot(), aAxisProp, EXC_CHOBJTYPE_AXISLINE );
3340  // axis ticks properties
3341  if( mxTick )
3342  mxTick->Convert( aAxisProp );
3343 
3344  // axis caption text --------------------------------------------------
3345 
3346  // radar charts disable their category labels via chart type, not via axis
3347  bool bHasLabels = (!mxTick || mxTick->HasLabels()) &&
3348  ((GetAxisType() != EXC_CHAXIS_X) || rTypeGroup.HasCategoryLabels());
3349  aAxisProp.SetBoolProperty( EXC_CHPROP_DISPLAYLABELS, bHasLabels );
3350  if( bHasLabels )
3351  {
3352  // font settings from CHFONT record or from default text
3353  if( mxFont )
3354  ConvertFontBase( GetChRoot(), aAxisProp );
3355  else if( const XclImpChText* pDefText = GetChartData().GetDefaultText( EXC_CHTEXTTYPE_AXISLABEL ) )
3356  pDefText->ConvertFont( aAxisProp );
3357  // label text rotation
3358  ConvertRotationBase( aAxisProp, true );
3359  // number format
3360  bool bLinkNumberFmtToSource = true;
3362  {
3363  sal_uInt32 nScNumFmt = GetNumFmtBuffer().GetScFormat( mnNumFmtIdx );
3364  if( nScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND )
3365  {
3366  aAxisProp.SetProperty( EXC_CHPROP_NUMBERFORMAT, static_cast< sal_Int32 >( nScNumFmt ) );
3367  bLinkNumberFmtToSource = false;
3368  }
3369  }
3370 
3371  aAxisProp.SetProperty( EXC_CHPROP_NUMBERFORMAT_LINKSRC, bLinkNumberFmtToSource );
3372  }
3373 
3374  // axis scaling and increment -----------------------------------------
3375 
3376  const XclChExtTypeInfo& rTypeInfo = rTypeGroup.GetTypeInfo();
3377  ScaleData aScaleData = xAxis->getScaleData();
3378  // set axis type
3379  switch( GetAxisType() )
3380  {
3381  case EXC_CHAXIS_X:
3382  if( rTypeInfo.mbCategoryAxis )
3383  {
3384  aScaleData.AxisType = cssc2::AxisType::CATEGORY;
3385  aScaleData.Categories = rTypeGroup.CreateCategSequence();
3386  }
3387  else
3388  aScaleData.AxisType = cssc2::AxisType::REALNUMBER;
3389  break;
3390  case EXC_CHAXIS_Y:
3391  aScaleData.AxisType = rTypeGroup.IsPercent() ?
3392  cssc2::AxisType::PERCENT : cssc2::AxisType::REALNUMBER;
3393  break;
3394  case EXC_CHAXIS_Z:
3395  aScaleData.AxisType = cssc2::AxisType::SERIES;
3396  break;
3397  }
3398  // axis scaling settings, dependent on axis type
3399  switch( aScaleData.AxisType )
3400  {
3401  case cssc2::AxisType::CATEGORY:
3402  case cssc2::AxisType::SERIES:
3403  // #i71684# radar charts have reversed rotation direction
3404  if (mxLabelRange)
3405  mxLabelRange->Convert( aAxisProp, aScaleData, rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_RADAR );
3406  else
3407  SAL_WARN("sc.filter", "missing LabelRange");
3408  break;
3409  case cssc2::AxisType::REALNUMBER:
3411  // #i85167# pie/donut charts have reversed rotation direction (at Y axis!)
3412  if (mxValueRange)
3413  mxValueRange->Convert( aScaleData, rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE );
3414  else
3415  SAL_WARN("sc.filter", "missing ValueRange");
3416  break;
3417  default:
3418  OSL_FAIL( "XclImpChAxis::CreateAxis - unknown axis type" );
3419  }
3420 
3421  /* Do not set a value to the Origin member anymore (will be done via
3422  new axis properties 'CrossoverPosition' and 'CrossoverValue'). */
3423  aScaleData.Origin.clear();
3424 
3425  // write back
3426  xAxis->setScaleData( aScaleData );
3427 
3428  // grid ---------------------------------------------------------------
3429 
3430  // main grid
3431  ScfPropertySet aGridProp( xAxis->getGridProperties() );
3432  aGridProp.SetBoolProperty( EXC_CHPROP_SHOW, static_cast<bool>(mxMajorGrid) );
3433  if( mxMajorGrid )
3434  mxMajorGrid->Convert( GetChRoot(), aGridProp, EXC_CHOBJTYPE_GRIDLINE );
3435  // sub grid
3436  Sequence< Reference< XPropertySet > > aSubGridPropSeq = xAxis->getSubGridProperties();
3437  if( aSubGridPropSeq.hasElements() )
3438  {
3439  ScfPropertySet aSubGridProp( aSubGridPropSeq[ 0 ] );
3440  aSubGridProp.SetBoolProperty( EXC_CHPROP_SHOW, static_cast<bool>(mxMinorGrid) );
3441  if( mxMinorGrid )
3442  mxMinorGrid->Convert( GetChRoot(), aSubGridProp, EXC_CHOBJTYPE_GRIDLINE );
3443  }
3444 
3445  // position of crossing axis ------------------------------------------
3446 
3447  if( pCrossingAxis )
3448  pCrossingAxis->ConvertAxisPosition( aAxisProp, rTypeGroup );
3449  }
3450  return xAxis;
3451 }
3452 
3454 {
3455  // #i71810# walls and floor in 3D charts use the CHPICFORMAT record for bitmap mode
3456  if( mxWallFrame )
3457  mxWallFrame->Convert( rPropSet, true );
3458 }
3459 
3460 void XclImpChAxis::ConvertAxisPosition( ScfPropertySet& rPropSet, const XclImpChTypeGroup& rTypeGroup ) const
3461 {
3462  if( ((GetAxisType() == EXC_CHAXIS_X) && rTypeGroup.GetTypeInfo().mbCategoryAxis) || (GetAxisType() == EXC_CHAXIS_Z) )
3463  {
3464  if (mxLabelRange)
3465  mxLabelRange->ConvertAxisPosition( rPropSet, rTypeGroup.Is3dChart() );
3466  else
3467  SAL_WARN("sc.filter", "missing LabelRange");
3468  }
3469  else
3470  {
3471  if (mxValueRange)
3472  mxValueRange->ConvertAxisPosition( rPropSet );
3473  else
3474  SAL_WARN("sc.filter", "missing ValueRange");
3475  }
3476 }
3477 
3479 {
3480  XclImpChLineFormatRef* pxLineFmt = nullptr;
3481  bool bWallFrame = false;
3482  switch( rStrm.ReaduInt16() )
3483  {
3484  case EXC_CHAXISLINE_AXISLINE: pxLineFmt = &mxAxisLine; break;
3485  case EXC_CHAXISLINE_MAJORGRID: pxLineFmt = &mxMajorGrid; break;
3486  case EXC_CHAXISLINE_MINORGRID: pxLineFmt = &mxMinorGrid; break;
3487  case EXC_CHAXISLINE_WALLS: bWallFrame = true; break;
3488  }
3489  if( bWallFrame )
3490  CreateWallFrame();
3491 
3492  bool bLoop = pxLineFmt || bWallFrame;
3493  while( bLoop )
3494  {
3495  sal_uInt16 nRecId = rStrm.GetNextRecId();
3496  bLoop = ((nRecId == EXC_ID_CHLINEFORMAT) ||
3497  (nRecId == EXC_ID_CHAREAFORMAT) ||
3498  (nRecId == EXC_ID_CHESCHERFORMAT))
3499  && rStrm.StartNextRecord();
3500  if( bLoop )
3501  {
3502  if( pxLineFmt && (nRecId == EXC_ID_CHLINEFORMAT) )
3503  {
3504  (*pxLineFmt) = new XclImpChLineFormat();
3505  (*pxLineFmt)->ReadChLineFormat( rStrm );
3506  }
3507  else if( bWallFrame && mxWallFrame )
3508  {
3509  mxWallFrame->ReadSubRecord( rStrm );
3510  }
3511  }
3512  }
3513 }
3514 
3516 {
3517  switch( GetAxisType() )
3518  {
3519  case EXC_CHAXIS_X:
3520  mxWallFrame = std::make_shared<XclImpChFrame>( GetChRoot(), EXC_CHOBJTYPE_WALL3D );
3521  break;
3522  case EXC_CHAXIS_Y:
3523  mxWallFrame = std::make_shared<XclImpChFrame>( GetChRoot(), EXC_CHOBJTYPE_FLOOR3D );
3524  break;
3525  default:
3526  mxWallFrame.reset();
3527  }
3528 }
3529 
3530 XclImpChAxesSet::XclImpChAxesSet( const XclImpChRoot& rRoot, sal_uInt16 nAxesSetId ) :
3531  XclImpChRoot( rRoot )
3532 {
3533  maData.mnAxesSetId = nAxesSetId;
3534 }
3535 
3537 {
3538  maData.mnAxesSetId = rStrm.ReaduInt16();
3539  rStrm >> maData.maRect;
3540 }
3541 
3543 {
3544  switch( rStrm.GetRecId() )
3545  {
3546  case EXC_ID_CHFRAMEPOS:
3547  mxFramePos = std::make_shared<XclImpChFramePos>();
3548  mxFramePos->ReadChFramePos( rStrm );
3549  break;
3550  case EXC_ID_CHAXIS:
3551  ReadChAxis( rStrm );
3552  break;
3553  case EXC_ID_CHTEXT:
3554  ReadChText( rStrm );
3555  break;
3556  case EXC_ID_CHPLOTFRAME:
3557  ReadChPlotFrame( rStrm );
3558  break;
3559  case EXC_ID_CHTYPEGROUP:
3560  ReadChTypeGroup( rStrm );
3561  break;
3562  }
3563 }
3564 
3566 {
3567  if( IsValidAxesSet() )
3568  {
3569  // finalize chart type groups, erase empty groups without series
3570  XclImpChTypeGroupMap aValidGroups;
3571  for (auto const& typeGroup : maTypeGroups)
3572  {
3573  XclImpChTypeGroupRef xTypeGroup = typeGroup.second;
3574  xTypeGroup->Finalize();
3575  if( xTypeGroup->IsValidGroup() )
3576  aValidGroups.emplace(typeGroup.first, xTypeGroup);
3577  }
3578  maTypeGroups.swap( aValidGroups );
3579  }
3580 
3581  // invalid chart type groups are deleted now, check again with IsValidAxesSet()
3582  if( !IsValidAxesSet() )
3583  return;
3584 
3585  // always create missing axis objects
3586  if( !mxXAxis )
3587  mxXAxis = std::make_shared<XclImpChAxis>( GetChRoot(), EXC_CHAXIS_X );
3588  if( !mxYAxis )
3589  mxYAxis = std::make_shared<XclImpChAxis>( GetChRoot(), EXC_CHAXIS_Y );
3590  if( !mxZAxis && GetFirstTypeGroup()->Is3dDeepChart() )
3591  mxZAxis = std::make_shared<XclImpChAxis>( GetChRoot(), EXC_CHAXIS_Z );
3592 
3593  // finalize axes
3594  if( mxXAxis ) mxXAxis->Finalize();
3595  if( mxYAxis ) mxYAxis->Finalize();
3596  if( mxZAxis ) mxZAxis->Finalize();
3597 
3598  // finalize axis titles
3600  OUString aAutoTitle(ScResId(STR_AXISTITLE));
3601  lclFinalizeTitle( mxXAxisTitle, pDefText, aAutoTitle );
3602  lclFinalizeTitle( mxYAxisTitle, pDefText, aAutoTitle );
3603  lclFinalizeTitle( mxZAxisTitle, pDefText, aAutoTitle );
3604 
3605  // #i47745# missing plot frame -> invisible border and area
3606  if( !mxPlotFrame )
3607  mxPlotFrame = std::make_shared<XclImpChFrame>( GetChRoot(), EXC_CHOBJTYPE_PLOTFRAME );
3608 }
3609 
3611 {
3612  XclImpChTypeGroupMap::const_iterator itr = maTypeGroups.find(nGroupIdx);
3613  return itr == maTypeGroups.end() ? XclImpChTypeGroupRef() : itr->second;
3614 }
3615 
3617 {
3618  XclImpChTypeGroupRef xTypeGroup;
3619  if( !maTypeGroups.empty() )
3620  xTypeGroup = maTypeGroups.begin()->second;
3621  return xTypeGroup;
3622 }
3623 
3625 {
3626  XclImpChLegendRef xLegend;
3627  for( const auto& rEntry : maTypeGroups )
3628  {
3629  xLegend = rEntry.second->GetLegend();
3630  if (xLegend)
3631  break;
3632  }
3633  return xLegend;
3634 }
3635 
3637 {
3638  return (maTypeGroups.size() == 1) ? maTypeGroups.begin()->second->GetSingleSeriesTitle() : OUString();
3639 }
3640 
3641 void XclImpChAxesSet::Convert( Reference< XDiagram > const & xDiagram ) const
3642 {
3643  if( !(IsValidAxesSet() && xDiagram.is()) )
3644  return;
3645 
3646  // diagram background formatting
3648  ConvertBackground( xDiagram );
3649 
3650  // create the coordinate system, this inserts all chart types and series
3651  Reference< XCoordinateSystem > xCoordSystem = CreateCoordSystem( xDiagram );
3652  if( !xCoordSystem.is() )
3653  return;
3654 
3655  // insert coordinate system, if not already done
3656  try
3657  {
3658  Reference< XCoordinateSystemContainer > xCoordSystemCont( xDiagram, UNO_QUERY_THROW );
3659  Sequence< Reference< XCoordinateSystem > > aCoordSystems = xCoordSystemCont->getCoordinateSystems();
3660  if( !aCoordSystems.hasElements() )
3661  xCoordSystemCont->addCoordinateSystem( xCoordSystem );
3662  }
3663  catch( Exception& )
3664  {
3665  OSL_FAIL( "XclImpChAxesSet::Convert - cannot insert coordinate system" );
3666  }
3667 
3668  // create the axes with grids and axis titles and insert them into the diagram
3669  ConvertAxis( mxXAxis, mxXAxisTitle, xCoordSystem, mxYAxis.get() );
3670  ConvertAxis( mxYAxis, mxYAxisTitle, xCoordSystem, mxXAxis.get() );
3671  ConvertAxis( mxZAxis, mxZAxisTitle, xCoordSystem, nullptr );
3672 }
3673 
3675 {
3676  if( mxXAxisTitle )
3678  if( mxYAxisTitle )
3680  if( mxZAxisTitle )
3682 }
3683 
3685 {
3686  XclImpChAxisRef xAxis = std::make_shared<XclImpChAxis>( GetChRoot() );
3687  xAxis->ReadRecordGroup( rStrm );
3688 
3689  switch( xAxis->GetAxisType() )
3690  {
3691  case EXC_CHAXIS_X: mxXAxis = xAxis; break;
3692  case EXC_CHAXIS_Y: mxYAxis = xAxis; break;
3693  case EXC_CHAXIS_Z: mxZAxis = xAxis; break;
3694  }
3695 }
3696 
3698 {
3699  XclImpChTextRef xText = std::make_shared<XclImpChText>( GetChRoot() );
3700  xText->ReadRecordGroup( rStrm );
3701 
3702  switch( xText->GetLinkTarget() )
3703  {
3704  case EXC_CHOBJLINK_XAXIS: mxXAxisTitle = xText; break;
3705  case EXC_CHOBJLINK_YAXIS: mxYAxisTitle = xText; break;
3706  case EXC_CHOBJLINK_ZAXIS: mxZAxisTitle = xText; break;
3707  }
3708 }
3709 
3711 {
3712  if( (rStrm.GetNextRecId() == EXC_ID_CHFRAME) && rStrm.StartNextRecord() )
3713  {
3714  mxPlotFrame = std::make_shared<XclImpChFrame>( GetChRoot(), EXC_CHOBJTYPE_PLOTFRAME );
3715  mxPlotFrame->ReadRecordGroup( rStrm );
3716  }
3717 }
3718 
3720 {
3721  XclImpChTypeGroupRef xTypeGroup = std::make_shared<XclImpChTypeGroup>( GetChRoot() );
3722  xTypeGroup->ReadRecordGroup( rStrm );
3723  sal_uInt16 nGroupIdx = xTypeGroup->GetGroupIdx();
3724  XclImpChTypeGroupMap::iterator itr = maTypeGroups.lower_bound(nGroupIdx);
3725  if (itr != maTypeGroups.end() && !maTypeGroups.key_comp()(nGroupIdx, itr->first))
3726  // Overwrite the existing element.
3727  itr->second = xTypeGroup;
3728  else
3729  maTypeGroups.insert(
3730  itr, XclImpChTypeGroupMap::value_type(nGroupIdx, xTypeGroup));
3731 }
3732 
3733 Reference< XCoordinateSystem > XclImpChAxesSet::CreateCoordSystem( Reference< XDiagram > const & xDiagram ) const
3734 {
3735  Reference< XCoordinateSystem > xCoordSystem;
3736 
3737  /* Try to get existing coordinate system. For now, all series from primary
3738  and secondary axes sets are inserted into one coordinate system. Later,
3739  this should be changed to use one coordinate system for each axes set. */
3740  Reference< XCoordinateSystemContainer > xCoordSystemCont( xDiagram, UNO_QUERY );
3741  if( xCoordSystemCont.is() )
3742  {
3743  Sequence< Reference< XCoordinateSystem > > aCoordSystems = xCoordSystemCont->getCoordinateSystems();
3744  OSL_ENSURE( aCoordSystems.getLength() <= 1, "XclImpChAxesSet::CreateCoordSystem - too many existing coordinate systems" );
3745  if( aCoordSystems.hasElements() )
3746  xCoordSystem = aCoordSystems[ 0 ];
3747  }
3748 
3749  // create the coordinate system according to the first chart type
3750  if( !xCoordSystem.is() )
3751  {
3752  XclImpChTypeGroupRef xTypeGroup = GetFirstTypeGroup();
3753  if( xTypeGroup )
3754  {
3755  xCoordSystem = xTypeGroup->CreateCoordSystem();
3756  // convert 3d chart settings
3757  ScfPropertySet aDiaProp( xDiagram );
3758  xTypeGroup->ConvertChart3d( aDiaProp );
3759  }
3760  }
3761 
3762  /* Create XChartType objects for all chart type groups. Each group will
3763  add its series to the data provider attached to the chart document. */
3764  Reference< XChartTypeContainer > xChartTypeCont( xCoordSystem, UNO_QUERY );
3765  if( xChartTypeCont.is() )
3766  {
3767  sal_Int32 nApiAxesSetIdx = GetApiAxesSetIndex();
3768  for( const auto& rEntry : maTypeGroups )
3769  {
3770  try
3771  {
3772  Reference< XChartType > xChartType = rEntry.second->CreateChartType( xDiagram, nApiAxesSetIdx );
3773  if( xChartType.is() )
3774  xChartTypeCont->addChartType( xChartType );
3775  }
3776  catch( Exception& )
3777  {
3778  OSL_FAIL( "XclImpChAxesSet::CreateCoordSystem - cannot add chart type" );
3779  }
3780  }
3781  }
3782 
3783  return xCoordSystem;
3784 }
3785 
3787  XclImpChAxisRef const & xChAxis, XclImpChTextRef const & xChAxisTitle,
3788  Reference< XCoordinateSystem > const & xCoordSystem, const XclImpChAxis* pCrossingAxis ) const
3789 {
3790  if( !xChAxis )
3791  return;
3792 
3793  // create and attach the axis object
3794  Reference< XAxis > xAxis = CreateAxis( *xChAxis, pCrossingAxis );
3795  if( !xAxis.is() )
3796  return;
3797 
3798  // create and attach the axis title
3799  if( xChAxisTitle ) try
3800  {
3801  Reference< XTitled > xTitled( xAxis, UNO_QUERY_THROW );
3802  Reference< XTitle > xTitle( xChAxisTitle->CreateTitle(), UNO_SET_THROW );
3803  xTitled->setTitleObject( xTitle );
3804  }
3805  catch( Exception& )
3806  {
3807  OSL_FAIL( "XclImpChAxesSet::ConvertAxis - cannot set axis title" );
3808  }
3809 
3810  // insert axis into coordinate system
3811  try
3812  {
3813  sal_Int32 nApiAxisDim = xChAxis->GetApiAxisDimension();
3814  sal_Int32 nApiAxesSetIdx = GetApiAxesSetIndex();
3815  xCoordSystem->setAxisByDimension( nApiAxisDim, xAxis, nApiAxesSetIdx );
3816  }
3817  catch( Exception& )
3818  {
3819  OSL_FAIL( "XclImpChAxesSet::ConvertAxis - cannot set axis" );
3820  }
3821 }
3822 
3823 Reference< XAxis > XclImpChAxesSet::CreateAxis( const XclImpChAxis& rChAxis, const XclImpChAxis* pCrossingAxis ) const
3824 {
3825  Reference< XAxis > xAxis;
3826  if( const XclImpChTypeGroup* pTypeGroup = GetFirstTypeGroup().get() )
3827  xAxis = rChAxis.CreateAxis( *pTypeGroup, pCrossingAxis );
3828  return xAxis;
3829 }
3830 
3831 void XclImpChAxesSet::ConvertBackground( Reference< XDiagram > const & xDiagram ) const
3832 {
3833  XclImpChTypeGroupRef xTypeGroup = GetFirstTypeGroup();
3834  if( xTypeGroup && xTypeGroup->Is3dWallChart() )
3835  {
3836  // wall/floor formatting (3D charts)
3837  if( mxXAxis )
3838  {
3839  ScfPropertySet aWallProp( xDiagram->getWall() );
3840  mxXAxis->ConvertWall( aWallProp );
3841  }
3842  if( mxYAxis )
3843  {
3844  ScfPropertySet aFloorProp( xDiagram->getFloor() );
3845  mxYAxis->ConvertWall( aFloorProp );
3846  }
3847  }
3848  else if( mxPlotFrame )
3849  {
3850  // diagram background formatting
3851  ScfPropertySet aWallProp( xDiagram->getWall() );
3852  mxPlotFrame->Convert( aWallProp );
3853  }
3854 }
3855 
3856 // The chart object ===========================================================
3857 
3859  XclImpChRoot( rRoot, *this )
3860 {
3861  mxPrimAxesSet = std::make_shared<XclImpChAxesSet>( GetChRoot(), EXC_CHAXESSET_PRIMARY );
3862  mxSecnAxesSet = std::make_shared<XclImpChAxesSet>( GetChRoot(), EXC_CHAXESSET_SECONDARY );
3863 }
3864 
3866 {
3867 }
3868 
3870 {
3871  // coordinates are stored as 16.16 fixed point
3872  rStrm >> maRect;
3873 }
3874 
3876 {
3877  switch( rStrm.GetRecId() )
3878  {
3879  case EXC_ID_CHFRAME:
3880  mxFrame = std::make_shared<XclImpChFrame>( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND );
3881  mxFrame->ReadRecordGroup( rStrm );
3882  break;
3883  case EXC_ID_CHSERIES:
3884  ReadChSeries( rStrm );
3885  break;
3886  case EXC_ID_CHPROPERTIES:
3887  ReadChProperties( rStrm );
3888  break;
3889  case EXC_ID_CHDEFAULTTEXT:
3890  ReadChDefaultText( rStrm );
3891  break;
3892  case EXC_ID_CHAXESSET:
3893  ReadChAxesSet( rStrm );
3894  break;
3895  case EXC_ID_CHTEXT:
3896  ReadChText( rStrm );
3897  break;
3898  case EXC_ID_CHEND:
3899  Finalize(); // finalize the entire chart object
3900  break;
3901  }
3902 }
3903 
3905 {
3906  sal_uInt16 nTextId = rStrm.ReaduInt16();
3907  if( (rStrm.GetNextRecId() == EXC_ID_CHTEXT) && rStrm.StartNextRecord() )
3908  {
3909  unique_ptr<XclImpChText> pText(new XclImpChText(GetChRoot()));
3910  pText->ReadRecordGroup(rStrm);
3911  m_DefTexts.insert(std::make_pair(nTextId, std::move(pText)));
3912  }
3913 }
3914 
3916 {
3917  XclImpChDataFormatRef xDataFmt = std::make_shared<XclImpChDataFormat>( GetChRoot() );
3918  xDataFmt->ReadRecordGroup( rStrm );
3919  if( xDataFmt->GetPointPos().mnSeriesIdx <= EXC_CHSERIES_MAXSERIES )
3920  {
3921  const XclChDataPointPos& rPos = xDataFmt->GetPointPos();
3922  XclImpChDataFormatMap::iterator itr = maDataFmts.lower_bound(rPos);
3923  if (itr == maDataFmts.end() || maDataFmts.key_comp()(rPos, itr->first))
3924  // No element exists for this data point. Insert it.
3925  maDataFmts.insert(
3926  itr, XclImpChDataFormatMap::value_type(rPos, xDataFmt));
3927 
3928  /* Do not overwrite existing data format group, Excel always uses the
3929  first data format group occurring in any CHSERIES group. */
3930  }
3931 }
3932 
3933 void XclImpChChart::UpdateObjFrame( const XclObjLineData& rLineData, const XclObjFillData& rFillData )
3934 {
3935  if( !mxFrame )
3936  mxFrame = std::make_shared<XclImpChFrame>( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND );
3937  mxFrame->UpdateObjFrame( rLineData, rFillData );
3938 }
3939 
3941 {
3942  XclImpChTypeGroupRef xTypeGroup = mxPrimAxesSet->GetTypeGroup( nGroupIdx );
3943  if( !xTypeGroup ) xTypeGroup = mxSecnAxesSet->GetTypeGroup( nGroupIdx );
3944  if( !xTypeGroup ) xTypeGroup = mxPrimAxesSet->GetFirstTypeGroup();
3945  return xTypeGroup;
3946 }
3947 
3949 {
3950  sal_uInt16 nDefTextId = EXC_CHDEFTEXT_GLOBAL;
3951  bool bBiff8 = GetBiff() == EXC_BIFF8;
3952  switch( eTextType )
3953  {
3954  case EXC_CHTEXTTYPE_TITLE: nDefTextId = EXC_CHDEFTEXT_GLOBAL; break;
3955  case EXC_CHTEXTTYPE_LEGEND: nDefTextId = EXC_CHDEFTEXT_GLOBAL; break;
3956  case EXC_CHTEXTTYPE_AXISTITLE: nDefTextId = bBiff8 ? EXC_CHDEFTEXT_AXESSET : EXC_CHDEFTEXT_GLOBAL; break;
3957  case EXC_CHTEXTTYPE_AXISLABEL: nDefTextId = bBiff8 ? EXC_CHDEFTEXT_AXESSET : EXC_CHDEFTEXT_GLOBAL; break;
3958  case EXC_CHTEXTTYPE_DATALABEL: nDefTextId = bBiff8 ? EXC_CHDEFTEXT_AXESSET : EXC_CHDEFTEXT_GLOBAL; break;
3959  }
3960 
3961  XclImpChTextMap::const_iterator const itr = m_DefTexts.find(nDefTextId);
3962  return itr == m_DefTexts.end() ? nullptr : itr->second.get();
3963 }
3964 
3966 {
3967  // there is no real automatic mode in BIFF5 charts
3969 }
3970 
3971 void XclImpChChart::Convert( const Reference<XChartDocument>& xChartDoc,
3972  XclImpDffConverter& rDffConv, const OUString& rObjName, const tools::Rectangle& rChartRect ) const
3973 {
3974  // initialize conversion (locks the model to suppress any internal updates)
3975  InitConversion( xChartDoc, rChartRect );
3976 
3977  // chart frame formatting
3978  if( mxFrame )
3979  {
3980  ScfPropertySet aFrameProp( xChartDoc->getPageBackground() );
3981  mxFrame->Convert( aFrameProp );
3982  }
3983 
3984  // chart title
3985  if( mxTitle ) try
3986  {
3987  Reference< XTitled > xTitled( xChartDoc, UNO_QUERY_THROW );
3988  Reference< XTitle > xTitle( mxTitle->CreateTitle(), UNO_SET_THROW );
3989  xTitled->setTitleObject( xTitle );
3990  }
3991  catch( Exception& )
3992  {
3993  }
3994 
3995  /* Create the diagram object and attach it to the chart document. Currently,
3996  one diagram is used to carry all coordinate systems and data series. */
3997  Reference< XDiagram > xDiagram = CreateDiagram();
3998  xChartDoc->setFirstDiagram( xDiagram );
3999 
4000  // coordinate systems and chart types, convert axis settings
4001  mxPrimAxesSet->Convert( xDiagram );
4002  mxSecnAxesSet->Convert( xDiagram );
4003 
4004  // legend
4005  if( xDiagram.is() && mxLegend )
4006  xDiagram->setLegend( mxLegend->CreateLegend() );
4007 
4008  /* Following all conversions needing the old Chart1 API that involves full
4009  initialization of the chart view. */
4010  Reference< cssc::XChartDocument > xChart1Doc( xChartDoc, UNO_QUERY );
4011  if( xChart1Doc.is() )
4012  {
4013  Reference< cssc::XDiagram > xDiagram1 = xChart1Doc->getDiagram();
4014 
4015  /* Set the 'IncludeHiddenCells' property via the old API as only this
4016  ensures that the data provider and all created sequences get this
4017  flag correctly. */
4018  ScfPropertySet aDiaProp( xDiagram1 );
4019  bool bShowVisCells = ::get_flag( maProps.mnFlags, EXC_CHPROPS_SHOWVISIBLEONLY );
4020  aDiaProp.SetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS, !bShowVisCells );
4021 
4022  // plot area position and size (there is no real automatic mode in BIFF5 charts)
4023  XclImpChFramePosRef xPlotAreaPos = mxPrimAxesSet->GetPlotAreaFramePos();
4024  if( IsManualPlotArea() && xPlotAreaPos ) try
4025  {
4026  const XclChFramePos& rFramePos = xPlotAreaPos->GetFramePosData();
4027  if( (rFramePos.mnTLMode == EXC_CHFRAMEPOS_PARENT) && (rFramePos.mnBRMode == EXC_CHFRAMEPOS_PARENT) )
4028  {
4029  Reference< cssc::XDiagramPositioning > xPositioning( xDiagram1, UNO_QUERY_THROW );
4030  css::awt::Rectangle aDiagramRect = CalcHmmFromChartRect( rFramePos.maRect );
4031  // for pie charts, always set inner plot area size to exclude the data labels as Excel does
4032  const XclImpChTypeGroup* pFirstTypeGroup = mxPrimAxesSet->GetFirstTypeGroup().get();
4033  if( pFirstTypeGroup && (pFirstTypeGroup->GetTypeInfo().meTypeCateg == EXC_CHTYPECATEG_PIE) )
4034  xPositioning->setDiagramPositionExcludingAxes( aDiagramRect );
4035  else if( pFirstTypeGroup && pFirstTypeGroup->Is3dChart() )
4036  xPositioning->setDiagramPositionIncludingAxesAndAxisTitles( aDiagramRect );
4037  else
4038  xPositioning->setDiagramPositionIncludingAxes( aDiagramRect );
4039  }
4040  }
4041  catch( Exception& )
4042  {
4043  }
4044 
4045  // positions of all title objects
4046  if( mxTitle )
4047  mxTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_TITLE ) );
4048  mxPrimAxesSet->ConvertTitlePositions();
4049  mxSecnAxesSet->ConvertTitlePositions();
4050  }
4051 
4052  // unlock the model
4053  FinishConversion( rDffConv );
4054 
4055  // start listening to this chart
4056  ScDocument& rDoc = GetRoot().GetDoc();
4057  ScChartListenerCollection* pChartCollection = rDoc.GetChartListenerCollection();
4058  if(!pChartCollection)
4059  return;
4060 
4061  ::std::unique_ptr< ::std::vector< ScTokenRef > > xRefTokens( new ::std::vector< ScTokenRef > );
4062  for( const auto& rxSeries : maSeries )
4063  rxSeries->FillAllSourceLinks( *xRefTokens );
4064  if( !xRefTokens->empty() )
4065  {
4066  ::std::unique_ptr< ScChartListener > xListener( new ScChartListener( rObjName, rDoc, std::move(xRefTokens) ) );
4067  xListener->SetUsed( true );
4068  xListener->StartListeningTo();
4069  pChartCollection->insert( xListener.release() );
4070  }
4071 }
4072 
4074 {
4075  sal_uInt16 nNewSeriesIdx = static_cast< sal_uInt16 >( maSeries.size() );
4076  XclImpChSeriesRef xSeries = std::make_shared<XclImpChSeries>( GetChRoot(), nNewSeriesIdx );
4077  xSeries->ReadRecordGroup( rStrm );
4078  maSeries.push_back( xSeries );
4079 }
4080 
4082 {
4083  maProps.mnFlags = rStrm.ReaduInt16();
4084  maProps.mnEmptyMode = rStrm.ReaduInt8();
4085 }
4086 
4088 {
4089  XclImpChAxesSetRef xAxesSet = std::make_shared<XclImpChAxesSet>( GetChRoot(), EXC_CHAXESSET_NONE );
4090  xAxesSet->ReadRecordGroup( rStrm );
4091  switch( xAxesSet->GetAxesSetId() )
4092  {
4093  case EXC_CHAXESSET_PRIMARY: mxPrimAxesSet = xAxesSet; break;
4094  case EXC_CHAXESSET_SECONDARY: mxSecnAxesSet = xAxesSet; break;
4095  }
4096 }
4097 
4099 {
4100  XclImpChTextRef xText = std::make_shared<XclImpChText>( GetChRoot() );
4101  xText->ReadRecordGroup( rStrm );
4102  switch( xText->GetLinkTarget() )
4103  {
4104  case EXC_CHOBJLINK_TITLE:
4105  mxTitle = xText;
4106  break;
4107  case EXC_CHOBJLINK_DATA:
4108  {
4109  sal_uInt16 nSeriesIdx = xText->GetPointPos().mnSeriesIdx;
4110  if( nSeriesIdx < maSeries.size() )
4111  maSeries[ nSeriesIdx ]->SetDataLabel( xText );
4112  }
4113  break;
4114  }
4115 }
4116 
4118 {
4119  // finalize series (must be done first)
4120  FinalizeSeries();
4121  // #i49218# legend may be attached to primary or secondary axes set
4122  mxLegend = mxPrimAxesSet->GetLegend();
4123  if( !mxLegend )
4124  mxLegend = mxSecnAxesSet->GetLegend();
4125  if( mxLegend )
4126  mxLegend->Finalize();
4127  // axes sets, updates chart type group default formats -> must be called before FinalizeDataFormats()
4128  mxPrimAxesSet->Finalize();
4129  mxSecnAxesSet->Finalize();
4130  // formatting of all series
4132  // #i47745# missing frame -> invisible border and area
4133  if( !mxFrame )
4134  mxFrame = std::make_shared<XclImpChFrame>( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND );
4135  // chart title
4136  FinalizeTitle();
4137 }
4138 
4140 {
4141  for( const XclImpChSeriesRef& xSeries : maSeries )
4142  {
4143  if( xSeries->HasParentSeries() )
4144  {
4145  /* Process child series (trend lines and error bars). Data of
4146  child series will be set at the connected parent series. */
4147  if( xSeries->GetParentIdx() < maSeries.size() )
4148  maSeries[ xSeries->GetParentIdx() ]->AddChildSeries( *xSeries );
4149  }
4150  else
4151  {
4152  // insert the series into the related chart type group
4153  if( XclImpChTypeGroup* pTypeGroup = GetTypeGroup( xSeries->GetGroupIdx() ).get() )
4154  pTypeGroup->AddSeries( xSeries );
4155  }
4156  }
4157 }
4158 
4160 {
4161  /* #i51639# (part 1): CHDATAFORMAT groups are part of CHSERIES groups.
4162  Each CHDATAFORMAT group specifies the series and data point it is
4163  assigned to. This makes it possible to have a data format that is
4164  related to another series, e.g. a CHDATAFORMAT group for series 2 is
4165  part of a CHSERIES group that describes series 1. Therefore the chart
4166  itself has collected all CHDATAFORMAT groups to be able to store data
4167  format groups for series that have not been imported at that time. This
4168  loop finally assigns these groups to the related series. */
4169  for( const auto& [rPos, rDataFmt] : maDataFmts )
4170  {
4171  sal_uInt16 nSeriesIdx = rPos.mnSeriesIdx;
4172  if( nSeriesIdx < maSeries.size() )
4173  maSeries[ nSeriesIdx ]->SetDataFormat( rDataFmt );
4174  }
4175 
4176  /* #i51639# (part 2): Finalize data formats of all series. This adds for
4177  example missing CHDATAFORMAT groups for entire series that are needed
4178  for automatic colors of lines and areas. */
4179  for( auto& rxSeries : maSeries )
4180  rxSeries->FinalizeDataFormats();
4181 }
4182 
4184 {
4185  // special handling for auto-generated title
4186  OUString aAutoTitle;
4187  if( !mxTitle || (!mxTitle->IsDeleted() && !mxTitle->HasString()) )
4188  {
4189  // automatic title from first series name (if there are no series on secondary axes set)
4190  if( !mxSecnAxesSet->IsValidAxesSet() )
4191  aAutoTitle = mxPrimAxesSet->GetSingleSeriesTitle();
4192  if( mxTitle || (!aAutoTitle.isEmpty()) )
4193  {
4194  if( !mxTitle )
4195  mxTitle = std::make_shared<XclImpChText>( GetChRoot() );
4196  if( aAutoTitle.isEmpty() )
4197  aAutoTitle = ScResId(STR_CHARTTITLE);
4198  }
4199  }
4200 
4201  // will reset mxTitle, if it does not contain a string and no auto title exists
4202  lclFinalizeTitle( mxTitle, GetDefaultText( EXC_CHTEXTTYPE_TITLE ), aAutoTitle );
4203 }
4204 
4205 Reference< XDiagram > XclImpChChart::CreateDiagram() const
4206 {
4207  // create a diagram object
4208  Reference< XDiagram > xDiagram( ScfApiHelper::CreateInstance( SERVICE_CHART2_DIAGRAM ), UNO_QUERY );
4209 
4210  // convert global chart settings
4211  ScfPropertySet aDiaProp( xDiagram );
4212 
4213  // treatment of missing values
4214  using namespace cssc::MissingValueTreatment;
4215  sal_Int32 nMissingValues = LEAVE_GAP;
4216  switch( maProps.mnEmptyMode )
4217  {
4218  case EXC_CHPROPS_EMPTY_SKIP: nMissingValues = LEAVE_GAP; break;
4219  case EXC_CHPROPS_EMPTY_ZERO: nMissingValues = USE_ZERO; break;
4220  case EXC_CHPROPS_EMPTY_INTERPOLATE: nMissingValues = CONTINUE; break;
4221  }
4222  aDiaProp.SetProperty( EXC_CHPROP_MISSINGVALUETREATMENT, nMissingValues );
4223 
4224  return xDiagram;
4225 }
4226 
4228  XclImpDrawing( rRoot, bOwnTab ), // sheet charts may contain OLE objects
4229  mnScTab( rRoot.GetCurrScTab() ),
4230  mbOwnTab( bOwnTab )
4231 {
4232 }
4233 
4235  const Reference< XModel >& rxModel, const tools::Rectangle& rChartRect )
4236 {
4237  maChartRect = rChartRect; // needed in CalcAnchorRect() callback
4238 
4239  SdrModel* pSdrModel = nullptr;
4240  SdrPage* pSdrPage = nullptr;
4241  if( mbOwnTab )
4242  {
4243  // chart sheet: insert all shapes into the sheet, not into the chart object
4244  pSdrModel = GetDoc().GetDrawLayer();
4245  pSdrPage = GetSdrPage( mnScTab );
4246  }
4247  else
4248  {
4249  // embedded chart object: insert all shapes into the chart
4250  try
4251  {
4252  Reference< XDrawPageSupplier > xDrawPageSupp( rxModel, UNO_QUERY_THROW );
4253  Reference< XDrawPage > xDrawPage( xDrawPageSupp->getDrawPage(), UNO_SET_THROW );
4254  pSdrPage = ::GetSdrPageFromXDrawPage( xDrawPage );
4255  pSdrModel = pSdrPage ? &pSdrPage->getSdrModelFromSdrPage() : nullptr;
4256  }
4257  catch( Exception& )
4258  {
4259  }
4260  }
4261 
4262  if( pSdrModel && pSdrPage )
4263  ImplConvertObjects( rDffConv, *pSdrModel, *pSdrPage );
4264 }
4265 
4266 tools::Rectangle XclImpChartDrawing::CalcAnchorRect( const XclObjAnchor& rAnchor, bool bDffAnchor ) const
4267 {
4268  /* In objects with DFF client anchor, the position of the shape is stored
4269  in the cell address components of the client anchor. In old BIFF3-BIFF5
4270  objects, the position is stored in the offset components of the anchor. */
4271  tools::Rectangle aRect(
4272  static_cast< tools::Long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnCol : rAnchor.mnLX ) / EXC_CHART_TOTALUNITS * maChartRect.GetWidth() + 0.5 ),
4273  static_cast< tools::Long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnRow : rAnchor.mnTY ) / EXC_CHART_TOTALUNITS * maChartRect.GetHeight() + 0.5 ),
4274  static_cast< tools::Long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnCol : rAnchor.mnRX ) / EXC_CHART_TOTALUNITS * maChartRect.GetWidth() + 0.5 ),
4275  static_cast< tools::Long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnRow : rAnchor.mnBY ) / EXC_CHART_TOTALUNITS * maChartRect.GetHeight() + 0.5 ) );
4276  aRect.Justify();
4277  // move shapes into chart area for sheet charts
4278  if( mbOwnTab )
4279  aRect.Move( maChartRect.Left(), maChartRect.Top() );
4280  return aRect;
4281 }
4282 
4284 {
4285 }
4286 
4287 XclImpChart::XclImpChart( const XclImpRoot& rRoot, bool bOwnTab ) :
4288  XclImpRoot( rRoot ),
4289  mbOwnTab( bOwnTab ),
4290  mbIsPivotChart( false )
4291 {
4292 }
4293 
4295 {
4296 }
4297 
4299 {
4300  XclImpPageSettings& rPageSett = GetPageSettings();
4301  XclImpTabViewSettings& rTabViewSett = GetTabViewSettings();
4302 
4303  bool bLoop = true;
4304  while( bLoop && rStrm.StartNextRecord() )
4305  {
4306  // page settings - only for charts in entire sheet
4307  if( mbOwnTab ) switch( rStrm.GetRecId() )
4308  {
4309  case EXC_ID_HORPAGEBREAKS:
4310  case EXC_ID_VERPAGEBREAKS: rPageSett.ReadPageBreaks( rStrm ); break;
4311  case EXC_ID_HEADER:
4312  case EXC_ID_FOOTER: rPageSett.ReadHeaderFooter( rStrm ); break;
4313  case EXC_ID_LEFTMARGIN:
4314  case EXC_ID_RIGHTMARGIN:
4315  case EXC_ID_TOPMARGIN:
4316  case EXC_ID_BOTTOMMARGIN: rPageSett.ReadMargin( rStrm ); break;
4317  case EXC_ID_PRINTHEADERS: rPageSett.ReadPrintHeaders( rStrm ); break;
4318  case EXC_ID_PRINTGRIDLINES: rPageSett.ReadPrintGridLines( rStrm ); break;
4319  case EXC_ID_HCENTER:
4320  case EXC_ID_VCENTER: rPageSett.ReadCenter( rStrm ); break;
4321  case EXC_ID_SETUP: rPageSett.ReadSetup( rStrm ); break;
4322  case EXC_ID8_IMGDATA: rPageSett.ReadImgData( rStrm ); break;
4323 
4324  case EXC_ID_WINDOW2: rTabViewSett.ReadWindow2( rStrm, true );break;
4325  case EXC_ID_SCL: rTabViewSett.ReadScl( rStrm ); break;
4326 
4327  case EXC_ID_SHEETEXT: //0x0862
4328  {
4329  // FIXME: do not need to pass palette, XclImpTabVieSettings is derived from root
4330  XclImpPalette& rPal = GetPalette();
4331  rTabViewSett.ReadTabBgColor( rStrm, rPal);
4332  }
4333  break;
4334 
4335  case EXC_ID_CODENAME: ReadCodeName( rStrm, false ); break;
4336  }
4337 
4338  // common records
4339  switch( rStrm.GetRecId() )
4340  {
4341  case EXC_ID_EOF: bLoop = false; break;
4342 
4343  // #i31882# ignore embedded chart objects
4344  case EXC_ID2_BOF:
4345  case EXC_ID3_BOF:
4346  case EXC_ID4_BOF:
4347  case EXC_ID5_BOF: XclTools::SkipSubStream( rStrm ); break;
4348 
4349  case EXC_ID_CHCHART: ReadChChart( rStrm ); break;
4350 
4351  case EXC_ID8_CHPIVOTREF:
4353  mbIsPivotChart = true;
4354  break;
4355 
4356  // BIFF specific records
4357  default: switch( GetBiff() )
4358  {
4359  case EXC_BIFF5: switch( rStrm.GetRecId() )
4360  {
4361  case EXC_ID_OBJ: GetChartDrawing().ReadObj( rStrm ); break;
4362  }
4363  break;
4364  case EXC_BIFF8: switch( rStrm.GetRecId() )
4365  {
4366  case EXC_ID_MSODRAWING: GetChartDrawing().ReadMsoDrawing( rStrm ); break;
4367  // #i61786# weird documents: OBJ without MSODRAWING -> read in BIFF5 format
4368  case EXC_ID_OBJ: GetChartDrawing().ReadObj( rStrm ); break;
4369  }
4370  break;
4371  default:;
4372  }
4373  }
4374  }
4375 }
4376 
4377 void XclImpChart::UpdateObjFrame( const XclObjLineData& rLineData, const XclObjFillData& rFillData )
4378 {
4379  if( !mxChartData )
4380  mxChartData = std::make_shared<XclImpChChart>( GetRoot() );
4381  mxChartData->UpdateObjFrame( rLineData, rFillData );
4382 }
4383 
4384 std::size_t XclImpChart::GetProgressSize() const
4385 {
4386  return
4388  (mxChartDrawing ? mxChartDrawing->GetProgressSize() : 0);
4389 }
4390 
4391 void XclImpChart::Convert( Reference< XModel > const & xModel, XclImpDffConverter& rDffConv, const OUString& rObjName, const tools::Rectangle& rChartRect ) const
4392 {
4393  Reference< XChartDocument > xChartDoc( xModel, UNO_QUERY );
4394  if( xChartDoc.is() )
4395  {
4396  if( mxChartData )
4397  mxChartData->Convert( xChartDoc, rDffConv, rObjName, rChartRect );
4398  if( mxChartDrawing )
4399  mxChartDrawing->ConvertObjects( rDffConv, xModel, rChartRect );
4400  }
4401 }
4402 
4404 {
4405  if( !mxChartDrawing )
4406  mxChartDrawing = std::make_shared<XclImpChartDrawing>( GetRoot(), mbOwnTab );
4407  return *mxChartDrawing;
4408 }
4409 
4411 {
4412  mxChartData = std::make_shared<XclImpChChart>( GetRoot() );
4413  mxChartData->ReadRecordGroup( rStrm );
4414 }
4415 
4416 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual void ReadSubRecord(XclImpStream &rStrm) override
Reads a record from the CHTYPEGROUP group (called by base class).
Definition: xichart.cxx:2686
void UpdateDataLabel(bool bCateg, bool bValue, bool bPercent)
Updates display type of this data point label text object.
Definition: xichart.cxx:1050
XclChPropertyMode
Specifies the type of a formatting.
Definition: xlchart.hxx:1080
Color maTextColor
Definition: xlchart.hxx:1045
const sal_uInt16 EXC_CHSERGROUP_NONE
Definition: xlchart.hxx:611
ObjectType meObjType
const sal_uInt8 EXC_CHPROPS_EMPTY_SKIP
Manual plot area layout in CHFRAMEPOS record.
Definition: xlchart.hxx:603
Color maPattColor
Definition: xlchart.hxx:800
XclImpChLegendRef mxLegend
3D settings (CHCHART3D record).
Definition: xichart.hxx:1073
virtual void ReadHeaderRecord(XclImpStream &rStrm) override
Reads the CHCHART record (called by base class).
Definition: xichart.cxx:3869
XclImpChType(const XclImpChRoot &rRoot)
Definition: xichart.cxx:2212
XclImpChSourceLinkRef mxSrcLink
Relative text frame position (CHFRAMEPOS record).
Definition: xichart.hxx:553
void ConvertAxisPosition(ScfPropertySet &rPropSet) const
Converts position settings of this axis at a crossing axis.
Definition: xichart.cxx:3144
const sal_uInt16 EXC_CHDATERANGE_AUTOMAJOR
Definition: xlchart.hxx:713
sal_uInt16 mnValueCount
Number of category entries.
Definition: xlchart.hxx:944
void AddChildSeries(const XclImpChSeries &rSeries)
Adds error bar settings from the passed series to the own series.
Definition: xichart.cxx:1888
void ReadCodeName(XclImpStream &rStrm, bool bGlobals)
Reads the CODENAME record and inserts the codename into the document.
Definition: xiroot.cxx:271
void ReadChLegendException(XclImpStream &rStrm)
Definition: xichart.cxx:2203
const sal_uInt16 EXC_ID_CHPICFORMAT
true = 2d wall/gridlines, no floor.
Definition: xlchart.hxx:544
const sal_uInt16 EXC_CHLINEFORMAT_DASHDOT
Definition: xlchart.hxx:252
const sal_uInt16 EXC_ID_CHLINE
Definition: xlchart.hxx:356
const sal_uInt16 EXC_CHTEXT_POS_DEFAULT
Data point caption is category name.
Definition: xlchart.hxx:484
OUString maType
XclChSeries maData
Definition: xichart.hxx:850
void ConvertRotation(ScfPropertySet &rPropSet, bool bSupportsStacked) const
Converts and writes the contained rotation settings to the passed property set.
Definition: xichart.cxx:1064
void Convert(ScfPropertySet &rPropSet) const
Converts and writes the contained data to the passed property set.
Definition: xichart.cxx:3230
double CalcRelativeFromChartY(sal_Int32 nPosY) const
Converts the passed vertical coordinate from Excel chart units into a relative position.
Definition: xichart.cxx:351
const sal_Int32 EXC_CHART_TOTALUNITS
API secondary axes set index.
Definition: xlchart.hxx:162
virtual Color GetFontColor() const override
Returns the leading font color for the text object.
Definition: xichart.cxx:1016
#define EXC_CHPROP_ATTAXISINDEX
Definition: xlchart.hxx:57
void ConvertAxis(XclImpChAxisRef const &xChAxis, XclImpChTextRef const &xChAxisTitle, css::uno::Reference< css::chart2::XCoordinateSystem > const &xCoordSystem, const XclImpChAxis *pCrossingAxis) const
Creates and inserts an axis into the container and registers the coordinate system.
Definition: xichart.cxx:3786
void ReadWindow2(XclImpStream &rStrm, bool bChart)
Reads a WINDOW2 record.
Definition: xiview.cxx:117
virtual void ReadHeaderRecord(XclImpStream &rStrm) override
Reads the CHESCHERFORMAT record (complex fill data) (called by base class).
Definition: xichart.cxx:528
void ReadChSerParent(XclImpStream &rStrm)
Reads a CHSERPARENT record specifying the parent series of this series.
Definition: xichart.cxx:2137
virtual sal_uInt16 GetRotation() const override
Returns the rotation value for the text object.
Definition: xichart.cxx:1021
const sal_uInt8 EXC_CHTICK_OUTSIDE
Definition: xlchart.hxx:403
#define EXC_CHPROP_ROTATIONVERTICAL
Definition: xlchart.hxx:112
const sal_uInt16 EXC_ID_CHBAR
Definition: xlchart.hxx:347
Text boxes (titles, data point labels).
Definition: xlchart.hxx:1117
void ReadPageBreaks(XclImpStream &rStrm)
Reads a HORIZONTALPAGEBREAKS or VERTICALPAGEBREAKS record.
Definition: xipage.cxx:141
const sal_uInt8 EXC_CH3DDATAFORMAT_STRAIGHT
Circular base.
Definition: xlchart.hxx:699
sal_uInt16 GetNextRecId()
Returns the record ID of the following record.
Definition: xistream.cxx:587
void UpdateTrendLineFormat()
Updates default data format for trend lines.
Definition: xichart.cxx:1512
const XclImpChText * GetDataLabel() const
Returns the data label text object.
Definition: xichart.hxx:688
bool Is3dChart() const
Returns true, if the chart is three-dimensional.
Definition: xichart.hxx:1009
css::uno::Reference< css::beans::XPropertySet > CreateErrorBar(sal_uInt8 nPosBarId, sal_uInt8 nNegBarId) const
Tries to create an error bar API object from the specified Excel error bars.
Definition: xichart.cxx:2192
No varied colors supported.
Definition: xlchart.hxx:1201
void InsertDataSeries(css::uno::Reference< css::chart2::XChartType > const &xChartType, css::uno::Reference< css::chart2::XDataSeries > const &xSeries, sal_Int32 nApiAxesSetIdx) const
Inserts the passed series into the chart type.
Definition: xichart.cxx:2866
XclImpChFramePosRef mxFramePos
Formatting runs (CHFORMATRUNS record).
Definition: xichart.hxx:552
const sal_uInt8 EXC_OBJ_LINE_MEDTRANS
Definition: xlescher.hxx:86
const sal_uInt16 EXC_CHAXESSET_PRIMARY
Definition: xlchart.hxx:582
void ReadCenter(XclImpStream &rStrm)
Reads a HCENTER or VCENTER record.
Definition: xipage.cxx:101
sal_uInt8 mnEmptyMode
Additional flags.
Definition: xlchart.hxx:999
double mfScale
Additional flags.
Definition: xlchart.hxx:827
void ReadFormats(XclImpStream &rStrm)
Reads and appends the formatting information (run count and runs) from stream.
Definition: xistring.hxx:46
sal_Int32 ReadInt32()
Definition: xistream.cxx:667
Chart axis labels.
Definition: xlchart.hxx:1273
#define SERVICE_CHART2_DATASERIES
Definition: xlchart.hxx:47
void WriteLineProperties(ScfPropertySet &rPropSet, XclChObjectTable &rDashTable, const XclChLineFormat &rLineFmt, XclChPropertyMode ePropMode)
Writes all line properties to the passed property set.
Definition: xlchart.cxx:905
XclImpChAttachedLabel(const XclImpChRoot &rRoot)
Definition: xichart.cxx:1364
std::shared_ptr< XclImpChSeries > XclImpChSeriesRef
Definition: xichart.hxx:866
const sal_uInt16 EXC_ID_CHAREAFORMAT
Definition: xlchart.hxx:293
void ReadChMarkerFormat(XclImpStream &rStrm)
Reads the CHMARKERFORMAT record (data point marker properties).
Definition: xichart.cxx:1272
#define EXC_CHPROP_SHOWPOSITIVEERROR
Definition: xlchart.hxx:120
const sal_uInt16 EXC_CHAXESSET_NONE
Definition: xlchart.hxx:584
sal_uInt8 mnBackMode
Position of labels relative to axis.
Definition: xlchart.hxx:1049
XclImpChLabelRangeRef mxLabelRange
Contents of the CHAXIS record.
Definition: xichart.hxx:1191
XclChAxesSet maData
Definition: xichart.hxx:1271
#define EXC_CHPROP_MOVING_AVERAGE_PERIOD
Definition: xlchart.hxx:96
sal_uInt16 GetAxesSetId() const
Returns the index of the axes set (primary/secondary).
Definition: xichart.hxx:1225
const sal_uInt16 EXC_ID_CHSERIES
Definition: xlchart.hxx:224
XclCh3dDataFormat maData
Definition: xichart.hxx:628
Contains all view settings for a single sheet.
Definition: xiview.hxx:58
bool IsValidGroup() const
Returns true, if this chart type group contains at least one valid series.
Definition: xichart.hxx:1005
virtual void ReadHeaderRecord(XclImpStream &rStrm) override
Reads the CHLEGEND record (called by base class).
Definition: xichart.cxx:2512
bool HasVarPointFormat() const
Returns true, if points of a series show varying automatic area format.
Definition: xichart.cxx:2759
#define EXC_CHPROP_EXTRAPOLATE_BACKWARD
Definition: xlchart.hxx:80
XclImpTabViewSettings & GetTabViewSettings() const
Returns the view settings of the current sheet.
Definition: xiroot.cxx:258
void ConvertWall(ScfPropertySet &rPropSet) const
Converts and writes 3D wall/floor properties to the passed property set.
Definition: xichart.cxx:3453
const sal_uInt16 EXC_ID_CHFRAMEPOS
Definition: xlchart.hxx:638
void ConvertFrame(ScfPropertySet &rPropSet) const
Converts and writes the contained frame data to the passed property set.
Definition: xichart.cxx:1069
XclImpNumFmtBuffer & GetNumFmtBuffer() const
Returns the number format buffer.
Definition: xiroot.cxx:151
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:89
#define EXC_CHPROP_EXPANSION
Definition: xlchart.hxx:77
XclImpChEscherFormatRef mxEscherFmt
Area format (CHAREAFORMAT record).
Definition: xichart.hxx:359
ReturnType get_flagvalue(Type nBitField, Type nMask, ReturnType nSet, ReturnType nUnset)
Returns nSet, if at least one bit of nMask is set in nBitField, otherwise nUnset. ...
Definition: ftools.hxx:80
#define EXC_CHPROP_ARRANGEORDER
Definition: xlchart.hxx:56
virtual ~XclImpChChart() override
Definition: xichart.cxx:3865
std::shared_ptr< XclImpChSerTrendLine > XclImpChSerTrendLineRef
Definition: xichart.hxx:738
const sal_uInt8 EXC_CHSERERR_YPLUS
Definition: xlchart.hxx:672
void ConvertChart3d(ScfPropertySet &rPropSet) const
Converts and writes all 3D settings to the passed diagram.
Definition: xichart.cxx:2784
XclImpChTextRef mxText
Legend frame position (CHFRAMEPOS record).
Definition: xichart.hxx:945
const sal_uInt16 EXC_CHTEXT_POS_AUTO
Definition: xlchart.hxx:493
XclImpChAreaFormatRef mxAreaFmt
Line format (CHLINEFORMAT record).
Definition: xichart.hxx:358
const XclChFormatInfo & GetFormatInfo(XclChObjectType eObjType) const
Returns an info struct about auto formatting for the passed object type.
Definition: xichart.cxx:241
sal_uInt16 GetRecId() const
Returns the current record ID.
Definition: xistream.hxx:353
void ReadChPieFormat(XclImpStream &rStrm)
Reads the CHPIEFORMAT record (pie segment properties).
Definition: xichart.cxx:1328
const sal_uInt8 EXC_CHSERERR_CUSTOM
Definition: xlchart.hxx:678
const sal_uInt16 EXC_CHLEGENDEXCEPTION_DELETED
Definition: xlchart.hxx:590
const sal_uInt8 EXC_CHSERERR_STDERR
Definition: xlchart.hxx:679
Contains information for a chart type.
Definition: xlchart.hxx:1206
SCROW Row() const
Definition: address.hxx:261
Color GetFontAutoColor() const
Returns the default text color for charts.
Definition: xichart.cxx:246
#define EXC_CHPROP_TEXTBREAK
Definition: xlchart.hxx:126
XclChText maData
Definition: xichart.hxx:549
const sal_uInt8 EXC_CHSRCLINK_WORKSHEET
Definition: xlchart.hxx:661
sal_Int32 mnX
Definition: xlchart.hxx:744
void UpdateDataLabel(const XclImpChDataFormat *pParentFmt)
Updates or creates the data point label.
Definition: xichart.cxx:1585
bool HasCategoryLabels() const
Returns true, if chart type has category labels enabled (may be disabled in radar charts)...
Definition: xichart.cxx:2355
#define EXC_CHPROP_ROLE_CLOSEVALUES
Definition: xlchart.hxx:144
const sal_uInt16 EXC_CHLEGEND_STACKED
Definition: xlchart.hxx:342
void SetSeriesData(XclImpChSourceLinkRef const &xValueLink, XclImpChDataFormatRef const &xDataFmt)
Sets link and formatting information for the error bars.
Definition: xichart.cxx:1698
sal_uInt8 mnPattern
Definition: xlescher.hxx:369
sal_Int32 mnDefaultLabelPos
Mode for varying point colors.
Definition: xlchart.hxx:1213
bool HasLine() const
Returns true, if the line style is set to something visible.
Definition: xichart.hxx:335
const sal_uInt16 EXC_CHDATERANGE_DAYS
Recognize date/text automatically.
Definition: xlchart.hxx:720
const sal_uInt16 EXC_ID_CHPLOTFRAME
Definition: xlchart.hxx:530
sal_uInt16 mnBackMode
Vertical alignment.
Definition: xlchart.hxx:876
void ReadChTypeGroup(XclImpStream &rStrm)
Reads a CHTYPEGROUP record group containing chart type and chart settings.
Definition: xichart.cxx:3719
XclChTypeInfo maTypeInfo
Record identifier for chart type.
Definition: xichart.hxx:901
void Convert(css::uno::Reference< css::frame::XModel > const &xModel, XclImpDffConverter &rDffConv, const OUString &rObjName, const tools::Rectangle &rChartRect) const
Creates the chart object in the passed component.
Definition: xichart.cxx:4391
sal_uInt16 mnRX
Y offset in top row (1/256 of row height).
Definition: xlescher.hxx:287
#define EXC_CHPROP_ERRORBARSTYLE
Definition: xlchart.hxx:74
void Convert(ScfPropertySet &rPropSet, const XclChExtTypeInfo &rTypeInfo, const ScfPropertySet *pGlobalPropSet=nullptr) const
Converts and writes the contained data to the passed property set.
Definition: xichart.cxx:1527
XclImpChDataFormatRef CreateDataFormat(sal_uInt16 nPointIdx, sal_uInt16 nFormatIdx)
Creates a new CHDATAFORMAT group with the specified point index.
Definition: xichart.cxx:2162
void ConvertAxisPosition(ScfPropertySet &rPropSet, bool b3dChart) const
Converts position settings of this axis at a crossing axis.
Definition: xichart.cxx:3052
sal_uInt16 mnRelHeight
Eye distance to chart (0...100).
Definition: xlchart.hxx:970
const sal_uInt16 EXC_ID_CHFORMAT
Definition: xlchart.hxx:634
const sal_uInt16 EXC_CHSERIES_MAXSERIES
Definition: xlchart.hxx:231
const sal_uInt16 EXC_CHOBJLINK_YAXIS
Chart title.
Definition: xlchart.hxx:507
sal_uInt16 mnBubbleSize
Hole size in donut chart (CHPIE).
Definition: xlchart.hxx:958
signed char sal_Int8
#define EXC_CHPROP_SHOWFIRST
Definition: xlchart.hxx:117
constexpr tools::Long Left() const
#define EXC_CHPROP_NEGATIVEERROR
Definition: xlchart.hxx:97
void ConvertLine(ScfPropertySet &rPropSet, XclChObjectType eObjType) const
Writes the line format only, e.g.
Definition: xichart.cxx:1562
Represents the CHDATAFORMAT record group containing data point properties.
Definition: xichart.hxx:655
virtual void ReadSubRecord(XclImpStream &rStrm) override
Reads a record from the CHDATAFORMAT group (called by base class).
Definition: xichart.cxx:1406
void Convert(const XclImpChRoot &rRoot, ScfPropertySet &rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx) const
Converts and writes the contained data to the passed property set.
Definition: xichart.cxx:502
XclFormatRunVec maFormats
Link target for this text object.
Definition: xichart.hxx:551
void Convert(const XclImpChRoot &rRoot, ScfPropertySet &rPropSet, XclChObjectType eObjType, bool bUsePicFmt) const
Converts and writes the contained data to the passed property set.
Definition: xichart.cxx:553
void ConvertArea(ScfPropertySet &rPropSet, sal_uInt16 nFormatIdx) const
Writes the area format only for the series or a data point.
Definition: xichart.cxx:1567
bool insert(ScChartListener *pListener)
Definition: chartlis.cxx:386
bool IsManualPlotArea() const
Returns true, if the plot area has benn moved and/or resized manually.
Definition: xichart.cxx:3965
void ReadChSeriesFormat(XclImpStream &rStrm)
Reads the CHSERIESFORMAT record (additional settings for a series).
Definition: xichart.cxx:1344
const sal_uInt8 EXC_CHTICK_INSIDE
Definition: xlchart.hxx:402
XclImpChAttLabelRef mxAttLabel
3D bar format (CH3DDATAFORMAT record).
Definition: xichart.hxx:709
const sal_uInt16 EXC_ID_CHFORMATRUNS
Definition: xlchart.hxx:648
Series trend line.
Definition: xlchart.hxx:1123
ScAddress toAbs(const ScSheetLimits &rLimits, const ScAddress &rPos) const
Definition: refdata.cxx:193
const sal_uInt16 EXC_CHTEXT_POS_RIGHT
Definition: xlchart.hxx:492
Series formatting in a chart supporting line formatting only.
Definition: xlchart.hxx:1119
bool IsAutoArea() const
Returns true, if the area format is set to automatic.
Definition: xichart.hxx:340
XclImpChDataFormatRef mxSeriesFmt
Link data for series bubble sizes.
Definition: xichart.hxx:855
#define EXC_CHPROP_MARKPOSITION
Definition: xlchart.hxx:93
static void ConvertPieRotation(ScfPropertySet &rPropSet, sal_uInt16 nAngle)
Writes the pie rotation property for the passed angle.
Definition: xichart.cxx:384
virtual sal_uInt16 GetFontIndex() const override
Returns the leading font index for the text object.
Definition: xichart.cxx:1011
void Convert(css::uno::Reference< css::chart2::XDiagram > const &xDiagram) const
Creates a coordinate system and converts all series and axis settings.
Definition: xichart.cxx:3641
XclImpChDataFormatMap maPointFmts
CHDATAFORMAT group for series format.
Definition: xichart.hxx:856
Bar charts (horizontal or vertical).
Definition: xlchart.hxx:1190
void WriteEscherProperties(ScfPropertySet &rPropSet, XclChObjectTable &rGradientTable, XclChObjectTable &rBitmapTable, const XclChEscherFormat &rEscherFmt, const XclChPicFormat *pPicFmt, sal_uInt32 nDffFillType, XclChPropertyMode ePropMode)
Writes gradient or bitmap area properties to the passed property set.
Definition: xlchart.cxx:991
XclImpChAxesSetRef mxSecnAxesSet
Primary axes set (CHAXESSET group).
Definition: xichart.hxx:1362
#define EXC_CHPROP_EXTRAPOLATE_FORWARD
Definition: xlchart.hxx:79
const sal_uInt16 EXC_CHATTLABEL_SHOWPERCENT
Definition: xlchart.hxx:307
bool mbOwnTab
Drawing container for embedded shapes.
Definition: xichart.hxx:1429
bool mbIsPivotChart
true = own sheet; false = embedded object.
Definition: xichart.hxx:1430
const sal_uInt8 EXC_CHSRCLINK_TITLE
Definition: xlchart.hxx:654
sal_uInt16 mnBarDist
Drop bar identifier, needed for auto format.
Definition: xichart.hxx:969
long Long
const sal_uInt16 EXC_ID_CHTEXT
No default text available.
Definition: xlchart.hxx:460
void ConvertAxisPosition(ScfPropertySet &rPropSet, const XclImpChTypeGroup &rTypeGroup) const
Converts position settings of this axis at a crossing axis.
Definition: xichart.cxx:3460
XclImpChValueRangeRef mxValueRange
Category scaling (CHLABELRANGE record).
Definition: xichart.hxx:1192
#define SERVICE_CHART2_AXIS
Definition: xlchart.hxx:45
double mfForecastBack
Counter to forecast forward.
Definition: xlchart.hxx:918
const sal_uInt16 EXC_CHAXISLINE_AXISLINE
Definition: xlchart.hxx:443
void SetDataLabel(const XclImpChTextRef &xLabel)
Sets a label text (CHTEXT group) attached to a series or data point.
Definition: xichart.cxx:1870
const sal_uInt16 EXC_CHVALUERANGE_MAXCROSS
Axis direction reversed.
Definition: xlchart.hxx:428
High/low lines in stock charts.
Definition: xlchart.hxx:1126
void ReadChDataFormat(XclImpStream &rStrm)
Reads a CHDATAFORMAT group containing series and point formatting.
Definition: xichart.cxx:2131
XclChObjectType meObjType
Contents of the CHFRAME record.
Definition: xichart.hxx:386
XclImpChSeriesFormatRef mxSeriesFmt
Pie segment format (CHPIEFORMAT record).
Definition: xichart.hxx:707
XclChTypeGroup maData
Definition: xichart.hxx:1067
bool mbCreateDefFrame
Default format type for missing frame objects.
Definition: xlchart.hxx:1146
const sal_uInt16 EXC_CHOBJLINK_TITLE
No link target.
Definition: xlchart.hxx:506
XclImpChLineFormatRef mxAxisLine
Index into font buffer (CHFONT record).
Definition: xichart.hxx:1195
const sal_uInt8 EXC_CHSERTREND_EXPONENTIAL
If order is 1, trend line is linear.
Definition: xlchart.hxx:627
const sal_uInt16 EXC_CHBAR_HORIZONTAL
Definition: xlchart.hxx:349
const sal_uInt16 EXC_CHTEXT_POS_AXIS
Definition: xlchart.hxx:488
#define EXC_CHPROP_CURVENAME
Definition: xlchart.hxx:65
const sal_uInt16 EXC_ID_CHCHART
Definition: xlchart.hxx:220
css::uno::Reference< css::chart2::data::XLabeledDataSequence > CreateValueSequence() const
Creates a labeled data sequence object from value data link.
Definition: xichart.cxx:1704
constexpr Point convert(const Point &rPoint, o3tl::Length eFrom, o3tl::Length eTo)
sal_uInt16 mnNumFmtIdx
Wall/floor format (sub records of CHFRAME group).
Definition: xichart.hxx:1199
XclImpChSerTrendLine(const XclImpChRoot &rRoot)
Definition: xichart.cxx:1603
bool IsAuto() const
Definition: xlescher.hxx:359
constexpr OUStringLiteral PERCENT(u"Percent")
const sal_uInt16 EXC_CHDATAFORMAT_DEFAULT
Maximum number of data points.
Definition: xlchart.hxx:239
css::uno::Reference< css::frame::XModel3 > GetModel() const
XclImpChPieFormatRef mxPieFmt
Data point marker (CHMARKERFORMAT record).
Definition: xichart.hxx:706
sal_uInt16 mnFlags
Crossing position of other axis.
Definition: xlchart.hxx:1038
const sal_uInt16 EXC_CHCHARTLINE_CONNECT
Hi-lo lines.
Definition: xlchart.hxx:387
sal_uInt8 mnColorIdx
Definition: xlescher.hxx:352
void ConvertRotationBase(ScfPropertySet &rPropSet, bool bSupportsStacked) const
Converts and writes the contained rotation settings to the passed property set.
Definition: xichart.cxx:927
const sal_uInt16 EXC_CHATTLABEL_SHOWVALUE
Definition: xlchart.hxx:306
Contains information about auto formatting of a specific chart object type.
Definition: xlchart.hxx:1138
#define EXC_CHPROP_D3DSCENESHADEMODE
Definition: xlchart.hxx:72
sal_uInt16 mnRotation
Additional flags.
Definition: xlchart.hxx:1051
#define EXC_CHPROP_CROSSOVERVALUE
Definition: xlchart.hxx:63
std::shared_ptr< XclImpChLegend > XclImpChLegendRef
Definition: xichart.hxx:949
XclImpChChart & GetChartData() const
Returns a reference to the parent chart data object.
Definition: xichart.cxx:226
sal_uInt8 mnShowEquation
Polynomial order or moving average counter.
Definition: xlchart.hxx:921
#define EXC_CHPROP_LABELSEPARATOR
Definition: xlchart.hxx:90
const sal_uInt16 EXC_ID_CHRADARLINE
Definition: xlchart.hxx:565
Chart title.
Definition: xlchart.hxx:1270
XclImpChSeriesVec maSeries
Extended chart type info.
Definition: xichart.hxx:1070
const sal_uInt16 EXC_CHRADAR_AXISLABELS
Definition: xlchart.hxx:568
void ReadChDropBar(XclImpStream &rStrm)
Reads a CHDROPBAR record group.
Definition: xichart.cxx:2828
const std::size_t EXC_CHART_PROGRESS_SIZE
Definition: xlchart.hxx:151
void SC_DLLPUBLIC join(const ScDocument *pDoc,::std::vector< ScTokenRef > &rTokens, const ScTokenRef &pToken, const ScAddress &rPos)
const sal_uInt16 EXC_CHTEXT_POS_ABOVE
Definition: xlchart.hxx:489
XclImpChFrameRef mxPlotFrame
The Z axis title (CHTEXT group).
Definition: xichart.hxx:1279
void Finalize(bool bStockChart)
Final processing after reading the entire chart.
Definition: xichart.cxx:2277
XclImpChChart3dRef mxChart3d
First series in this chart type group (CHSERIES groups).
Definition: xichart.hxx:1072
const sal_uInt16 EXC_ID_CHMARKERFORMAT
Definition: xlchart.hxx:269
void Convert(ScfPropertySet &rPropSet, bool b3dWallChart) const
Converts and writes the contained data to the passed property set.
Definition: xichart.cxx:2440
sal_uInt8 mnLabelPos
Type of tick marks of minor grid.
Definition: xlchart.hxx:1048
static void SkipBlock(XclImpStream &rStrm)
Helper to skip a CHBEGIN/CHEND block, includes nested blocks.
Definition: xichart.cxx:424
const sal_uInt8 EXC_CHPROPS_EMPTY_INTERPOLATE
Plot empty values as zero.
Definition: xlchart.hxx:605
bool IsAutoMarker() const
Returns true, if markers are set to automatic format.
Definition: xichart.hxx:684
void Finalize()
Final processing after reading the entire chart.
Definition: xichart.cxx:2715
const sal_uInt16 EXC_ID_CH3DDATAFORMAT
Definition: xlchart.hxx:694
#define DFF_Prop_fillType
XclImpChAxesSet(const XclImpChRoot &rRoot, sal_uInt16 nAxesSetId)
Definition: xichart.cxx:3530
Data point connector line.
Definition: xlchart.hxx:1125
std::shared_ptr< XclImpChAxis > XclImpChAxisRef
Definition: xichart.hxx:1202
void set_flag(Type &rnBitField, Type nMask, bool bSet=true)
Sets or clears (according to bSet) all set bits of nMask in rnBitField.
Definition: ftools.hxx:95
XclAddress maLast
Definition: xladdress.hxx:61
void TraceChartLegendPosition()
Definition: xltracer.cxx:114
sal_uInt32 mnRow
Definition: xladdress.hxx:32
XclChExtTypeInfo maTypeInfo
Chart type (e.g. CHBAR, CHLINE, ...).
Definition: xichart.hxx:1069
static void WriteRotationProperties(ScfPropertySet &rPropSet, sal_uInt16 nRotation, bool bSupportsStacked)
Writes rotation properties to the passed property set.
Definition: xlchart.cxx:1094
const sal_uInt16 EXC_ID8_IMGDATA
Definition: xlescher.hxx:242
XclChAreaFormat maData
Definition: xichart.hxx:287
Color GetFontColor() const
Returns the leading font color for the axis labels.
Definition: xichart.cxx:3215
bool mbIsFrame
true = Delete default frame formatting on export.
Definition: xlchart.hxx:1148
void ImplConvertObjects(XclImpDffConverter &rDffConv, SdrModel &rSdrModel, SdrPage &rSdrPage)
Converts all objects and inserts them into the current drawing page.
Definition: xiescher.cxx:4084
XclImpChType maType
Contents of the CHTYPEGROUP record.
Definition: xichart.hxx:1068
static sal_uInt8 GetXclRotFromOrient(sal_uInt8 nXclOrient)
Calculates BIFF8 rotation angle from BIFF2-BIFF5 text orientation.
Definition: xltools.cxx:176
void ReadChLineFormat(XclImpStream &rStrm)
Reads the CHLINEFORMAT record (basic line properties).
Definition: xichart.cxx:453
void ReadChSourceLink(XclImpStream &rStrm)
Reads a CHSOURCELINK record.
Definition: xichart.cxx:2118
ReturnType limit_cast(Type nValue, ReturnType nMin, ReturnType nMax)
Returns the value, if it is not less than nMin and not greater than nMax, otherwise one of the limits...
Definition: ftools.hxx:63
void Progress(std::size_t nDelta=1)
Increase the progress bar by the passed value.
Definition: xiescher.cxx:3372
#define EXC_CHPROP_INCLUDEHIDDENCELLS
Definition: xlchart.hxx:84