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