diff --git sc/source/filter/excel/xechart.cxx sc/source/filter/excel/xechart.cxx index 7fff80d..96bcaa6 100644 --- sc/source/filter/excel/xechart.cxx +++ sc/source/filter/excel/xechart.cxx @@ -124,16 +124,27 @@ void lclSaveRecord( XclExpStream& rStrm, XclExpRecordRef xRec, sal_uInt16 nRecId } template< typename Type > -inline bool lclIsAutoAnyOrGetValue( Type& rValue, const Any& rAny ) +inline bool lclIsAutoAnyOrGetValue( Type& rValue, const Any& rAny, bool bPercent ) { - return !rAny.hasValue() || !(rAny >>= rValue); + if (!rAny.hasValue()) + return true; + + if (rAny >>= rValue) + { + if (bPercent) + rValue *= 100.0; + return false; + } + else + return true; } -bool lclIsAutoAnyOrGetScaledValue( double& rfValue, const Any& rAny, Reference< XScaling > xScaling ) +bool lclIsAutoAnyOrGetScaledValue( double& rfValue, const Any& rAny, Reference< XScaling > xScaling, bool bPercent ) { - bool bIsAuto = lclIsAutoAnyOrGetValue( rfValue, rAny ); + bool bIsAuto = lclIsAutoAnyOrGetValue( rfValue, rAny, bPercent ); if( !bIsAuto && xScaling.is() ) rfValue = xScaling->doScaling( rfValue ); + return bIsAuto; } @@ -2147,7 +2158,7 @@ void XclExpChLabelRange::Convert( const ScaleData& rScaleData, bool bMirrorOrien { // origin double fOrigin = 0.0; - if( !lclIsAutoAnyOrGetValue( fOrigin, rScaleData.Origin ) ) + if( !lclIsAutoAnyOrGetValue( fOrigin, rScaleData.Origin, false ) ) maData.mnCross = limit_cast< sal_uInt16 >( fOrigin, 1, 32767 ); // reverse order @@ -2171,7 +2182,7 @@ XclExpChValueRange::XclExpChValueRange( const XclExpChRoot& rRoot ) : { } -void XclExpChValueRange::Convert( const ScaleData& rScaleData ) +void XclExpChValueRange::Convert( const ScaleData& rScaleData, bool bPercent ) { // scaling algorithm bool bLogScale = ScfApiHelper::GetServiceName( rScaleData.Scaling ) == SERVICE_CHART2_LOGSCALING; @@ -2181,24 +2192,24 @@ void XclExpChValueRange::Convert( const ScaleData& rScaleData ) xLogScaling = rScaleData.Scaling; // min/max - bool bAutoMin = lclIsAutoAnyOrGetScaledValue( maData.mfMin, rScaleData.Minimum, xLogScaling ); + bool bAutoMin = lclIsAutoAnyOrGetScaledValue( maData.mfMin, rScaleData.Minimum, xLogScaling, bPercent ); ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMIN, bAutoMin ); - bool bAutoMax = lclIsAutoAnyOrGetScaledValue( maData.mfMax, rScaleData.Maximum, xLogScaling ); + bool bAutoMax = lclIsAutoAnyOrGetScaledValue( maData.mfMax, rScaleData.Maximum, xLogScaling, bPercent ); ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMAX, bAutoMax ); // origin - bool bAutoCross = lclIsAutoAnyOrGetScaledValue( maData.mfCross, rScaleData.Origin, xLogScaling ); + bool bAutoCross = lclIsAutoAnyOrGetScaledValue( maData.mfCross, rScaleData.Origin, xLogScaling, bPercent ); ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOCROSS, bAutoCross ); // major increment const IncrementData& rIncrementData = rScaleData.IncrementData; - bool bAutoMajor = lclIsAutoAnyOrGetValue( maData.mfMajorStep, rIncrementData.Distance ) || (maData.mfMajorStep <= 0.0); + bool bAutoMajor = lclIsAutoAnyOrGetValue( maData.mfMajorStep, rIncrementData.Distance, bPercent ) || (maData.mfMajorStep <= 0.0); ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMAJOR, bAutoMajor ); // minor increment const Sequence< SubIncrement >& rSubIncrementSeq = rIncrementData.SubIncrements; sal_Int32 nCount = 0; bool bAutoMinor = bAutoMajor || (rSubIncrementSeq.getLength() < 1) || - lclIsAutoAnyOrGetValue( nCount, rSubIncrementSeq[ 0 ].IntervalCount ) || (nCount < 1); + lclIsAutoAnyOrGetValue( nCount, rSubIncrementSeq[ 0 ].IntervalCount, false ) || (nCount < 1); if( !bAutoMinor ) maData.mfMinorStep = maData.mfMajorStep / nCount; ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMINOR, bAutoMinor ); @@ -2320,7 +2331,8 @@ void XclExpChAxis::SetRotation( sal_uInt16 nRotation ) mxTick->SetRotation( nRotation ); } -void XclExpChAxis::Convert( Reference< XAxis > xAxis, const XclChExtTypeInfo& rTypeInfo, sal_Int32 nApiAxesSetIdx ) +void XclExpChAxis::Convert( Reference< XAxis > xAxis, const XclChExtTypeInfo& rTypeInfo, sal_Int32 nApiAxesSetIdx, + bool bPercent ) { ScfPropertySet aAxisProp( xAxis ); bool bCategoryAxis = ((GetAxisType() == EXC_CHAXIS_X) && rTypeInfo.mbCategoryAxis) || (GetAxisType() == EXC_CHAXIS_Z); @@ -2349,7 +2361,7 @@ void XclExpChAxis::Convert( Reference< XAxis > xAxis, const XclChExtTypeInfo& rT { mxValueRange.reset( new XclExpChValueRange( GetChRoot() ) ); if( xAxis.is() ) - mxValueRange->Convert( xAxis->getScaleData() ); + mxValueRange->Convert( xAxis->getScaleData(), bPercent ); } // axis caption text ------------------------------------------------------ @@ -2523,10 +2535,10 @@ sal_uInt16 XclExpChAxesSet::Convert( Reference< XDiagram > xDiagram, sal_uInt16 // create axes according to chart type (no axes for pie and donut charts) if( rTypeInfo.meTypeCateg != EXC_CHTYPECATEG_PIE ) { - ConvertAxis( mxXAxis, EXC_CHAXIS_X, mxXAxisTitle, EXC_CHOBJLINK_XAXIS, xCoordSystem, rTypeInfo ); - ConvertAxis( mxYAxis, EXC_CHAXIS_Y, mxYAxisTitle, EXC_CHOBJLINK_YAXIS, xCoordSystem, rTypeInfo ); + ConvertAxis( mxXAxis, EXC_CHAXIS_X, mxXAxisTitle, EXC_CHOBJLINK_XAXIS, xCoordSystem, rTypeInfo, bPercent ); + ConvertAxis( mxYAxis, EXC_CHAXIS_Y, mxYAxisTitle, EXC_CHOBJLINK_YAXIS, xCoordSystem, rTypeInfo, bPercent ); if( pGroup->Is3dDeepChart() ) - ConvertAxis( mxZAxis, EXC_CHAXIS_Z, mxZAxisTitle, EXC_CHOBJLINK_ZAXIS, xCoordSystem, rTypeInfo ); + ConvertAxis( mxZAxis, EXC_CHAXIS_Z, mxZAxisTitle, EXC_CHOBJLINK_ZAXIS, xCoordSystem, rTypeInfo, bPercent ); } // X axis category ranges @@ -2610,14 +2622,15 @@ XclExpChTypeGroupRef XclExpChAxesSet::GetLastTypeGroup() const void XclExpChAxesSet::ConvertAxis( XclExpChAxisRef& rxChAxis, sal_uInt16 nAxisType, XclExpChTextRef& rxChAxisTitle, sal_uInt16 nTitleTarget, - Reference< XCoordinateSystem > xCoordSystem, const XclChExtTypeInfo& rTypeInfo ) + Reference< XCoordinateSystem > xCoordSystem, const XclChExtTypeInfo& rTypeInfo, + bool bPercent ) { // create and convert axis object rxChAxis.reset( new XclExpChAxis( GetChRoot(), nAxisType ) ); sal_Int32 nApiAxisDim = rxChAxis->GetApiAxisDimension(); sal_Int32 nApiAxesSetIdx = GetApiAxesSetIndex(); Reference< XAxis > xAxis = lclGetApiAxis( xCoordSystem, nApiAxisDim, nApiAxesSetIdx ); - rxChAxis->Convert( xAxis, rTypeInfo, nApiAxesSetIdx ); + rxChAxis->Convert( xAxis, rTypeInfo, nApiAxesSetIdx, bPercent ); // create and convert axis title Reference< XTitled > xTitled( xAxis, UNO_QUERY ); diff --git sc/source/filter/excel/xichart.cxx sc/source/filter/excel/xichart.cxx index 441f699..1bddb08 100644 --- sc/source/filter/excel/xichart.cxx +++ sc/source/filter/excel/xichart.cxx @@ -1988,6 +1988,15 @@ Reference< XChartType > XclImpChType::CreateChartType( Reference< XDiagram > xDi // additional properties switch( maTypeInfo.meTypeCateg ) { + case EXC_CHTYPECATEG_LINE: + { + ScfPropertySet aTypeProp(xChartType); + bool bStacked = (maData.mnFlags & EXC_CHLINE_STACKED); + bool bPercent = (maData.mnFlags & EXC_CHLINE_PERCENT); + aTypeProp.SetBoolProperty(EXC_CHPROP_STACKED, bStacked); + aTypeProp.SetBoolProperty(EXC_CHPROP_PERCENT, bPercent); + } + break; case EXC_CHTYPECATEG_BAR: { ScfPropertySet aTypeProp( xChartType ); @@ -1996,6 +2005,10 @@ Reference< XChartType > XclImpChType::CreateChartType( Reference< XDiagram > xDi aTypeProp.SetProperty( EXC_CHPROP_OVERLAPSEQ, aInt32Seq ); aInt32Seq[ 0 ] = aInt32Seq[ 1 ] = maData.mnGap; aTypeProp.SetProperty( EXC_CHPROP_GAPWIDTHSEQ, aInt32Seq ); + bool bStacked = (maData.mnFlags & EXC_CHBAR_STACKED); + bool bPercent = (maData.mnFlags & EXC_CHBAR_PERCENT); + aTypeProp.SetBoolProperty(EXC_CHPROP_STACKED, bStacked); + aTypeProp.SetBoolProperty(EXC_CHPROP_PERCENT, bPercent); } break; case EXC_CHTYPECATEG_PIE: @@ -2542,7 +2555,7 @@ void XclImpChValueRange::ReadChValueRange( XclImpStream& rStrm ) >> maData.mnFlags; } -void XclImpChValueRange::Convert( ScaleData& rScaleData, bool bMirrorOrient ) const +void XclImpChValueRange::Convert( ScaleData& rScaleData, bool bMirrorOrient, bool bPercent ) const { // scaling algorithm bool bLogScale = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_LOGSCALE ); @@ -2557,19 +2570,23 @@ void XclImpChValueRange::Convert( ScaleData& rScaleData, bool bMirrorOrient ) co } // min/max - lclSetScaledValueOrClearAny( rScaleData.Minimum, maData.mfMin, xLogScaling, ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMIN ) ); - lclSetScaledValueOrClearAny( rScaleData.Maximum, maData.mfMax, xLogScaling, ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMAX ) ); + double fMinVal = bPercent ? maData.mfMin/100.0 : maData.mfMin; + double fMaxVal = bPercent ? maData.mfMax/100.0 : maData.mfMax; + lclSetScaledValueOrClearAny( rScaleData.Minimum, fMinVal, xLogScaling, ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMIN ) ); + lclSetScaledValueOrClearAny( rScaleData.Maximum, fMaxVal, xLogScaling, ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMAX ) ); // origin (max-cross overrides crossing settings, fall back to auto-cross) const sal_uInt16 nAutoCrossFlags = EXC_CHVALUERANGE_AUTOCROSS | EXC_CHVALUERANGE_MAXCROSS; - lclSetScaledValueOrClearAny( rScaleData.Origin, maData.mfCross, xLogScaling, ::get_flag( maData.mnFlags, nAutoCrossFlags ) ); + double fCross = bPercent ? maData.mfCross/100.0 : maData.mfCross; + lclSetScaledValueOrClearAny( rScaleData.Origin, fCross, xLogScaling, ::get_flag( maData.mnFlags, nAutoCrossFlags ) ); // increment bool bAutoMajor = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMAJOR ); bool bAutoMinor = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMINOR ); // major increment IncrementData& rIncrementData = rScaleData.IncrementData; - lclSetValueOrClearAny( rIncrementData.Distance, maData.mfMajorStep, bAutoMajor ); + double fMajorStep = bPercent ? maData.mfMajorStep/100.0 : maData.mfMajorStep; + lclSetValueOrClearAny( rIncrementData.Distance, fMajorStep, bAutoMajor ); // minor increment Sequence< SubIncrement >& rSubIncrementSeq = rIncrementData.SubIncrements; rSubIncrementSeq.realloc( 1 ); @@ -2809,8 +2826,11 @@ Reference< XAxis > XclImpChAxis::CreateAxis( const XclImpChTypeGroup& rTypeGroup break; case ApiAxisType::REALNUMBER: case ApiAxisType::PERCENT: + { + bool bPercent = aScaleData.AxisType == ApiAxisType::PERCENT; // #i85167# pie/donut charts have reversed rotation direction (at Y axis!) - mxValueRange->Convert( aScaleData, rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE ); + mxValueRange->Convert( aScaleData, rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE, bPercent ); + } break; default: DBG_ERRORFILE( "XclImpChAxis::CreateAxis - unknown axis type" ); diff --git sc/source/filter/inc/xechart.hxx sc/source/filter/inc/xechart.hxx index 6ad5595..4fa788e 100644 --- sc/source/filter/inc/xechart.hxx +++ sc/source/filter/inc/xechart.hxx @@ -944,7 +944,7 @@ public: explicit XclExpChValueRange( const XclExpChRoot& rRoot ); /** Converts value axis scaling settings. */ - void Convert( const ScaleData& rScaleData ); + void Convert( const ScaleData& rScaleData, bool bPercent ); private: virtual void WriteBody( XclExpStream& rStrm ); @@ -1004,7 +1004,8 @@ public: virtual void SetRotation( sal_uInt16 nRotation ); /** Converts formatting and scaling settings from the passed axis. */ - void Convert( XAxisRef xAxis, const XclChExtTypeInfo& rTypeInfo, sal_Int32 nApiAxesSetIdx ); + void Convert( XAxisRef xAxis, const XclChExtTypeInfo& rTypeInfo, sal_Int32 nApiAxesSetIdx, + bool bPercent ); /** Converts and writes 3D wall/floor properties from the passed diagram. */ void ConvertWall( XDiagramRef xDiagram ); @@ -1076,7 +1077,8 @@ private: /** Converts a complete axis object including axis title. */ void ConvertAxis( XclExpChAxisRef& rxChAxis, sal_uInt16 nAxisType, XclExpChTextRef& rxChAxisTitle, sal_uInt16 nTitleTarget, - XCoordSystemRef xCoordSystem, const XclChExtTypeInfo& rTypeInfo ); + XCoordSystemRef xCoordSystem, const XclChExtTypeInfo& rTypeInfo, + bool bPercent ); virtual void WriteBody( XclExpStream& rStrm ); diff --git sc/source/filter/inc/xichart.hxx sc/source/filter/inc/xichart.hxx index 2e79767..da91cd5 100644 --- sc/source/filter/inc/xichart.hxx +++ sc/source/filter/inc/xichart.hxx @@ -1109,7 +1109,7 @@ public: /** Reads the CHVALUERANGE record (numeric axis scaling properties). */ void ReadChValueRange( XclImpStream& rStrm ); /** Converts value axis scaling settings. */ - void Convert( ScaleData& rScaleData, bool bMirrorOrient ) const; + void Convert( ScaleData& rScaleData, bool bMirrorOrient, bool bPercent ) const; private: XclChValueRange maData; /// Contents of the CHVALUERANGE record. diff --git sc/source/filter/inc/xlchart.hxx sc/source/filter/inc/xlchart.hxx index 5e3b3f5..1a580ed 100644 --- sc/source/filter/inc/xlchart.hxx +++ sc/source/filter/inc/xlchart.hxx @@ -107,6 +107,7 @@ namespace com { namespace sun { namespace star { #define EXC_CHPROP_OFFSET CREATE_OUSTRING( "Offset" ) #define EXC_CHPROP_OVERLAPSEQ CREATE_OUSTRING( "OverlapSequence" ) #define EXC_CHPROP_PERCENTAGENUMFMT CREATE_OUSTRING( "PercentageNumberFormat" ) +#define EXC_CHPROP_PERCENT CREATE_OUSTRING( "Percent" ) #define EXC_CHPROP_PERCENTDIAGONAL CREATE_OUSTRING( "PercentDiagonal" ) #define EXC_CHPROP_PERSPECTIVE CREATE_OUSTRING( "Perspective" ) #define EXC_CHPROP_POSITIVEERROR CREATE_OUSTRING( "PositiveError" ) @@ -121,6 +122,7 @@ namespace com { namespace sun { namespace star { #define EXC_CHPROP_SHOWHIGHLOW CREATE_OUSTRING( "ShowHighLow" ) #define EXC_CHPROP_SHOWNEGATIVEERROR CREATE_OUSTRING( "ShowNegativeError" ) #define EXC_CHPROP_SHOWPOSITIVEERROR CREATE_OUSTRING( "ShowPositiveError" ) +#define EXC_CHPROP_STACKED CREATE_OUSTRING( "Stacked" ) #define EXC_CHPROP_STACKINGDIR CREATE_OUSTRING( "StackingDirection" ) #define EXC_CHPROP_STARTINGANGLE CREATE_OUSTRING( "StartingAngle" ) #define EXC_CHPROP_SWAPXANDYAXIS CREATE_OUSTRING( "SwapXAndYAxis" )