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