| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_xmloff.hxx" |
| |
| #include <xmloff/xmlprmap.hxx> |
| |
| #include "SchXMLExport.hxx" |
| #include "XMLChartPropertySetMapper.hxx" |
| #include "SchXMLSeriesHelper.hxx" |
| #include "ColorPropertySet.hxx" |
| #include "SchXMLTools.hxx" |
| #include "SchXMLEnumConverter.hxx" |
| |
| #include <tools/debug.hxx> |
| #include <rtl/logfile.hxx> |
| #include <comphelper/processfactory.hxx> |
| #include <tools/globname.hxx> |
| #include <sot/clsids.hxx> |
| |
| #include <xmloff/nmspmap.hxx> |
| #include "xmloff/xmlnmspe.hxx" |
| #include <xmloff/xmltoken.hxx> |
| #include <xmloff/families.hxx> |
| #include <xmloff/xmlaustp.hxx> |
| #include <xmloff/xmluconv.hxx> |
| #include <xmloff/xmlmetae.hxx> |
| #include "xexptran.hxx" |
| #include <rtl/math.hxx> |
| // header for any2enum |
| #include <comphelper/extract.hxx> |
| |
| #include <list> |
| #include <typeinfo> |
| #include <algorithm> |
| |
| #include <com/sun/star/task/XStatusIndicatorSupplier.hpp> |
| #include <com/sun/star/lang/XServiceInfo.hpp> |
| #include <com/sun/star/lang/XServiceName.hpp> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include <com/sun/star/uno/XComponentContext.hpp> |
| #include <com/sun/star/util/XRefreshable.hpp> |
| |
| #include <com/sun/star/chart/XAxis.hpp> |
| #include <com/sun/star/chart/XAxisSupplier.hpp> |
| #include <com/sun/star/chart/XChartDocument.hpp> |
| #include <com/sun/star/chart/ChartLegendPosition.hpp> |
| #include <com/sun/star/chart/ChartLegendExpansion.hpp> |
| #include <com/sun/star/chart/ChartDataRowSource.hpp> |
| #include <com/sun/star/chart/ChartAxisAssign.hpp> |
| #include <com/sun/star/chart/ChartAxisType.hpp> |
| #include <com/sun/star/chart/TimeIncrement.hpp> |
| #include <com/sun/star/chart/TimeInterval.hpp> |
| #include <com/sun/star/chart/TimeUnit.hpp> |
| #include <com/sun/star/chart/ChartSeriesAddress.hpp> |
| #include <com/sun/star/chart/X3DDisplay.hpp> |
| #include <com/sun/star/chart/XStatisticDisplay.hpp> |
| #include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp> |
| #include <com/sun/star/chart/XDiagramPositioning.hpp> |
| |
| #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp> |
| #include <com/sun/star/chart2/AxisType.hpp> |
| #include <com/sun/star/chart2/XChartDocument.hpp> |
| #include <com/sun/star/chart2/XDiagram.hpp> |
| #include <com/sun/star/chart2/RelativePosition.hpp> |
| #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> |
| #include <com/sun/star/chart2/XRegressionCurveContainer.hpp> |
| #include <com/sun/star/chart2/XChartTypeContainer.hpp> |
| #include <com/sun/star/chart2/XDataSeriesContainer.hpp> |
| #include <com/sun/star/chart2/data/XDataSource.hpp> |
| #include <com/sun/star/chart2/data/XDataSink.hpp> |
| #include <com/sun/star/chart2/data/XDataReceiver.hpp> |
| #include <com/sun/star/chart2/data/XDataProvider.hpp> |
| #include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp> |
| #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp> |
| #include <com/sun/star/chart2/data/XTextualDataSequence.hpp> |
| #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp> |
| |
| #include <com/sun/star/util/XStringMapping.hpp> |
| #include <com/sun/star/drawing/HomogenMatrix.hpp> |
| #include <com/sun/star/drawing/XDrawPageSupplier.hpp> |
| #include <com/sun/star/drawing/XShapes.hpp> |
| #include <com/sun/star/embed/Aspects.hpp> |
| #include <com/sun/star/embed/XVisualObject.hpp> |
| #include <com/sun/star/container/XChild.hpp> |
| |
| |
| #include "MultiPropertySetHandler.hxx" |
| #include "PropertyMap.hxx" |
| |
| using namespace com::sun::star; |
| using namespace ::xmloff::token; |
| |
| using ::rtl::OUString; |
| using ::rtl::OUStringBuffer; |
| using ::rtl::OUStringToOString; |
| using ::com::sun::star::uno::Sequence; |
| using ::com::sun::star::uno::Reference; |
| using ::com::sun::star::uno::Any; |
| using ::std::vector; |
| |
| // ======================================== |
| // class SchXMLExportHelper_Impl |
| // ======================================== |
| |
| class SchXMLExportHelper_Impl |
| { |
| public: |
| // first: data sequence for label, second: data sequence for values. |
| typedef ::std::pair< ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence >, |
| ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence > > tLabelValuesDataPair; |
| typedef ::std::vector< tLabelValuesDataPair > tDataSequenceCont; |
| |
| public: |
| SchXMLExportHelper_Impl( SvXMLExport& rExport, |
| SvXMLAutoStylePoolP& rASPool ); |
| |
| virtual ~SchXMLExportHelper_Impl(); |
| |
| // auto-styles |
| /// parse chart and collect all auto-styles used in current pool |
| void collectAutoStyles( com::sun::star::uno::Reference< |
| com::sun::star::chart::XChartDocument > rChartDoc ); |
| |
| /// write the styles collected into the current pool as <style:style> elements |
| void exportAutoStyles(); |
| |
| /** export the <chart:chart> element corresponding to rChartDoc |
| if bIncludeTable is true, the chart data is exported as <table:table> |
| element (inside the chart element). |
| |
| Otherwise the external references stored in the chart document are used |
| for writing the corresponding attributes at series |
| |
| All attributes contained in xAttrList are written at the chart element, |
| which ist the outer element of a chart. So these attributes can easily |
| be parsed again by the container |
| */ |
| void exportChart( com::sun::star::uno::Reference< |
| com::sun::star::chart::XChartDocument > rChartDoc, |
| sal_Bool bIncludeTable ); |
| |
| UniReference< XMLPropertySetMapper > GetPropertySetMapper() const; |
| |
| void SetChartRangeAddress( const ::rtl::OUString& rAddress ) |
| { msChartAddress = rAddress; } |
| void SetTableNumberList( const ::rtl::OUString& rList ) |
| { msTableNumberList = rList; } |
| |
| void InitRangeSegmentationProperties( |
| const ::com::sun::star::uno::Reference< |
| ::com::sun::star::chart2::XChartDocument > & xChartDoc ); |
| |
| ::com::sun::star::awt::Size getPageSize( |
| const ::com::sun::star::uno::Reference< |
| ::com::sun::star::chart2::XChartDocument > & xChartDoc ) const; |
| |
| /** first parseDocument: collect autostyles and store names in this queue |
| second parseDocument: export content and use names from this queue |
| */ |
| ::std::queue< ::rtl::OUString > maAutoStyleNameQueue; |
| void CollectAutoStyle( |
| const std::vector< XMLPropertyState >& aStates ); |
| void AddAutoStyleAttribute( |
| const std::vector< XMLPropertyState >& aStates ); |
| |
| SvXMLAutoStylePoolP& GetAutoStylePoolP() |
| { return mrAutoStylePool; } |
| |
| /// if bExportContent is false the auto-styles are collected |
| void parseDocument( com::sun::star::uno::Reference< |
| com::sun::star::chart::XChartDocument >& rChartDoc, |
| sal_Bool bExportContent, |
| sal_Bool bIncludeTable = sal_False ); |
| void exportTable(); |
| void exportPlotArea( |
| com::sun::star::uno::Reference< com::sun::star::chart::XDiagram > xDiagram, |
| com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > xNewDiagram, |
| const ::com::sun::star::awt::Size & rPageSize, |
| sal_Bool bExportContent, |
| sal_Bool bIncludeTable ); |
| void exportCoordinateRegion( const com::sun::star::uno::Reference< com::sun::star::chart::XDiagram >& xDiagram ); |
| void exportAxes( const com::sun::star::uno::Reference< com::sun::star::chart::XDiagram > & xDiagram, |
| const com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > & xNewDiagram, |
| sal_Bool bExportContent ); |
| void exportAxis( enum XMLTokenEnum eDimension, enum XMLTokenEnum eAxisName, |
| const Reference< beans::XPropertySet > xAxisProps, const Reference< chart2::XAxis >& xChart2Axis, |
| const OUString& rCategoriesRanges, |
| bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid, bool bExportContent ); |
| void exportGrid( const Reference< beans::XPropertySet > xGridProperties, bool bMajor, bool bExportContent ); |
| void exportDateScale( const Reference< beans::XPropertySet > xAxisProps ); |
| void exportAxisTitle( const Reference< beans::XPropertySet > xTitleProps, bool bExportContent ); |
| |
| void exportSeries( |
| const com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > & xNewDiagram, |
| const ::com::sun::star::awt::Size & rPageSize, |
| sal_Bool bExportContent, |
| sal_Bool bHasTwoYAxes ); |
| void exportCandleStickSeries( |
| const ::com::sun::star::uno::Sequence< |
| ::com::sun::star::uno::Reference< |
| ::com::sun::star::chart2::XDataSeries > > & aSeriesSeq, |
| const ::com::sun::star::uno::Reference< |
| ::com::sun::star::chart2::XDiagram > & xDiagram, |
| sal_Bool bJapaneseCandleSticks, |
| sal_Bool bExportContent ); |
| void exportDataPoints( |
| const ::com::sun::star::uno::Reference< |
| ::com::sun::star::beans::XPropertySet > & xSeriesProperties, |
| sal_Int32 nSeriesLength, |
| const ::com::sun::star::uno::Reference< |
| ::com::sun::star::chart2::XDiagram > & xDiagram, |
| sal_Bool bExportContent ); |
| void exportRegressionCurve( |
| const ::com::sun::star::uno::Reference< |
| ::com::sun::star::chart2::XDataSeries > & xSeries, |
| const ::com::sun::star::uno::Reference< |
| ::com::sun::star::beans::XPropertySet > & xSeriesProp, |
| const ::com::sun::star::awt::Size & rPageSize, |
| sal_Bool bExportContent ); |
| |
| /// add svg position as attribute for current element |
| void addPosition( const ::com::sun::star::awt::Point & rPosition ); |
| void addPosition( com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape ); |
| /// add svg size as attribute for current element |
| void addSize( const ::com::sun::star::awt::Size & rSize, bool bIsOOoNamespace = false ); |
| void addSize( com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape, bool bIsOOoNamespace = false ); |
| /// fills the member msString with the appropriate String (i.e. "A3") |
| void getCellAddress( sal_Int32 nCol, sal_Int32 nRow ); |
| /// exports a string as a paragraph element |
| void exportText( const ::rtl::OUString& rText, bool bConvertTabsLFs = false ); |
| void exportErrorBarRanges(); |
| |
| SchXMLExportHelper_Impl(SchXMLExportHelper_Impl &); // not defined |
| void operator =(SchXMLExportHelper_Impl &); // not defined |
| |
| public: |
| SvXMLExport& mrExport; |
| SvXMLAutoStylePoolP& mrAutoStylePool; |
| UniReference< XMLPropertyHandlerFactory > mxPropertyHandlerFactory; |
| UniReference< XMLPropertySetMapper > mxPropertySetMapper; |
| UniReference< XMLChartExportPropertyMapper > mxExpPropMapper; |
| |
| rtl::OUString msTableName; |
| rtl::OUStringBuffer msStringBuffer; |
| rtl::OUString msString; |
| |
| // members filled by InitRangeSegmentationProperties (retrieved from DataProvider) |
| sal_Bool mbHasSeriesLabels; |
| sal_Bool mbHasCategoryLabels; //if the categories are only automatically generated this will be false |
| sal_Bool mbRowSourceColumns; |
| rtl::OUString msChartAddress; |
| rtl::OUString msTableNumberList; |
| ::com::sun::star::uno::Sequence< sal_Int32 > maSequenceMapping; |
| |
| rtl::OUString msCLSID; |
| |
| ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > mxAdditionalShapes; |
| |
| tDataSequenceCont m_aDataSequencesToExport; |
| rtl::OUString maCategoriesRange; |
| }; |
| |
| namespace |
| { |
| Reference< uno::XComponentContext > lcl_getComponentContext() |
| { |
| Reference< uno::XComponentContext > xContext; |
| try |
| { |
| Reference< beans::XPropertySet > xFactProp( comphelper::getProcessServiceFactory(), uno::UNO_QUERY ); |
| if( xFactProp.is()) |
| xFactProp->getPropertyValue(OUString::createFromAscii("DefaultContext")) >>= xContext; |
| } |
| catch( uno::Exception& ) |
| {} |
| |
| return xContext; |
| } |
| |
| class lcl_MatchesRole : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool > |
| { |
| public: |
| explicit lcl_MatchesRole( const OUString & aRole ) : |
| m_aRole( aRole ) |
| {} |
| |
| bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const |
| { |
| if( !xSeq.is() ) |
| return false; |
| Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY ); |
| OUString aRole; |
| |
| return ( xProp.is() && |
| (xProp->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )) ) >>= aRole ) && |
| m_aRole.equals( aRole )); |
| } |
| |
| private: |
| OUString m_aRole; |
| }; |
| |
| template< typename T > |
| void lcl_SequenceToVectorAppend( const Sequence< T > & rSource, ::std::vector< T > & rDestination ) |
| { |
| rDestination.reserve( rDestination.size() + rSource.getLength()); |
| ::std::copy( rSource.getConstArray(), rSource.getConstArray() + rSource.getLength(), |
| ::std::back_inserter( rDestination )); |
| } |
| |
| template< typename T > |
| void lcl_SequenceToVector( const Sequence< T > & rSource, ::std::vector< T > & rDestination ) |
| { |
| rDestination.clear(); |
| lcl_SequenceToVectorAppend( rSource, rDestination ); |
| } |
| |
| Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( const Reference< chart2::XDiagram > & xDiagram ) |
| { |
| Reference< chart2::data::XLabeledDataSequence > xResult; |
| try |
| { |
| Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( |
| xDiagram, uno::UNO_QUERY_THROW ); |
| Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( |
| xCooSysCnt->getCoordinateSystems()); |
| for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i ) |
| { |
| Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[i] ); |
| OSL_ASSERT( xCooSys.is()); |
| for( sal_Int32 nN = xCooSys->getDimension(); nN--; ) |
| { |
| const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nN); |
| for(sal_Int32 nI=0; nI<=nMaxAxisIndex; ++nI) |
| { |
| Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( nN, nI ); |
| OSL_ASSERT( xAxis.is()); |
| if( xAxis.is()) |
| { |
| chart2::ScaleData aScaleData = xAxis->getScaleData(); |
| if( aScaleData.Categories.is()) |
| { |
| xResult.set( aScaleData.Categories ); |
| break; |
| } |
| } |
| } |
| } |
| } |
| } |
| catch( uno::Exception & ex ) |
| { |
| (void)ex; // avoid warning for pro build |
| OSL_ENSURE( false, OUStringToOString( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "Exception caught. Type: " )) + |
| OUString::createFromAscii( typeid( ex ).name()) + |
| OUString( RTL_CONSTASCII_USTRINGPARAM( ", Message: " )) + |
| ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr()); |
| } |
| |
| return xResult; |
| } |
| |
| Reference< chart2::data::XDataSource > lcl_createDataSource( |
| const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aData ) |
| { |
| Reference< chart2::data::XDataSink > xSink; |
| Reference< uno::XComponentContext > xContext( lcl_getComponentContext()); |
| if( xContext.is() ) |
| xSink.set( |
| xContext->getServiceManager()->createInstanceWithContext( |
| OUString::createFromAscii("com.sun.star.chart2.data.DataSource"), |
| xContext ), uno::UNO_QUERY_THROW ); |
| if( xSink.is()) |
| xSink->setData( aData ); |
| |
| return Reference< chart2::data::XDataSource >( xSink, uno::UNO_QUERY ); |
| } |
| |
| Sequence< Reference< chart2::data::XLabeledDataSequence > > lcl_getAllSeriesSequences( const Reference< chart2::XChartDocument >& xChartDoc ) |
| { |
| ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aContainer; |
| if( xChartDoc.is() ) |
| { |
| Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram()); |
| ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( SchXMLSeriesHelper::getDataSeriesFromDiagram( xDiagram )); |
| for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aSeriesIt( aSeriesVector.begin() ) |
| ; aSeriesIt != aSeriesVector.end(); ++aSeriesIt ) |
| { |
| Reference< chart2::data::XDataSource > xDataSource( *aSeriesIt, uno::UNO_QUERY ); |
| if( !xDataSource.is() ) |
| continue; |
| uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() ); |
| lcl_SequenceToVectorAppend( aDataSequences, aContainer ); |
| } |
| } |
| |
| Sequence< Reference< chart2::data::XLabeledDataSequence > > aRet( aContainer.size()); |
| ::std::copy( aContainer.begin(), aContainer.end(), aRet.getArray()); |
| |
| return aRet; |
| } |
| |
| Reference< chart2::data::XLabeledDataSequence > |
| lcl_getDataSequenceByRole( |
| const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aLabeledSeq, |
| const OUString & rRole ) |
| { |
| Reference< chart2::data::XLabeledDataSequence > aNoResult; |
| |
| const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray(); |
| const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength(); |
| const Reference< chart2::data::XLabeledDataSequence > * pMatch = |
| ::std::find_if( pBegin, pEnd, lcl_MatchesRole( rRole )); |
| |
| if( pMatch != pEnd ) |
| return *pMatch; |
| |
| return aNoResult; |
| } |
| |
| Reference< chart2::data::XDataSource > lcl_pressUsedDataIntoRectangularFormat( const Reference< chart2::XChartDocument >& xChartDoc, sal_Bool& rOutSourceHasCategoryLabels ) |
| { |
| ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeqVector; |
| |
| //categories are always the first sequence |
| Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram()); |
| Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xDiagram ) ); |
| if( xCategories.is() ) |
| aLabeledSeqVector.push_back( xCategories ); |
| rOutSourceHasCategoryLabels = sal_Bool(xCategories.is()); |
| |
| Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeriesSeqVector( |
| lcl_getAllSeriesSequences( xChartDoc ) ); |
| |
| //the first x-values is always the next sequence //todo ... other x-values get lost for old format |
| Reference< chart2::data::XLabeledDataSequence > xXValues( |
| lcl_getDataSequenceByRole( aSeriesSeqVector, OUString::createFromAscii("values-x" ) ) ); |
| if( xXValues.is() ) |
| aLabeledSeqVector.push_back( xXValues ); |
| |
| //add all other sequences now without x-values |
| lcl_MatchesRole aHasXValues( OUString::createFromAscii("values-x" ) ); |
| for( sal_Int32 nN=0; nN<aSeriesSeqVector.getLength(); nN++ ) |
| { |
| if( !aHasXValues( aSeriesSeqVector[nN] ) ) |
| aLabeledSeqVector.push_back( aSeriesSeqVector[nN] ); |
| } |
| |
| Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( aLabeledSeqVector.size() ); |
| ::std::copy( aLabeledSeqVector.begin(), aLabeledSeqVector.end(), aSeq.getArray() ); |
| |
| return lcl_createDataSource( aSeq ); |
| } |
| |
| bool lcl_isSeriesAttachedToFirstAxis( |
| const Reference< chart2::XDataSeries > & xDataSeries ) |
| { |
| bool bResult=true; |
| |
| try |
| { |
| sal_Int32 nAxisIndex = 0; |
| Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW ); |
| if( xProp.is() ) |
| xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("AttachedAxisIndex") ) ) >>= nAxisIndex; |
| bResult = (0==nAxisIndex); |
| } |
| catch( uno::Exception & ex ) |
| { |
| (void)ex; // avoid warning for pro build |
| OSL_ENSURE( false, OUStringToOString( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "Exception caught. Type: " )) + |
| OUString::createFromAscii( typeid( ex ).name()) + |
| OUString( RTL_CONSTASCII_USTRINGPARAM( ", Message: " )) + |
| ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr()); |
| } |
| |
| return bResult; |
| } |
| |
| OUString lcl_ConvertRange( const ::rtl::OUString & rRange, const Reference< chart2::XChartDocument > & xDoc ) |
| { |
| OUString aResult = rRange; |
| if( !xDoc.is() ) |
| return aResult; |
| Reference< chart2::data::XRangeXMLConversion > xConversion( |
| xDoc->getDataProvider(), uno::UNO_QUERY ); |
| if( xConversion.is()) |
| aResult = xConversion->convertRangeToXML( rRange ); |
| return aResult; |
| } |
| |
| typedef ::std::pair< OUString, OUString > tLabelAndValueRange; |
| |
| tLabelAndValueRange lcl_getLabelAndValueRangeByRole( |
| const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt, |
| const OUString & rRole, |
| const Reference< chart2::XChartDocument > & xDoc, |
| SchXMLExportHelper_Impl::tDataSequenceCont & rOutSequencesToExport ) |
| { |
| tLabelAndValueRange aResult; |
| |
| Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( |
| lcl_getDataSequenceByRole( aSeqCnt, rRole )); |
| if( xLabeledSeq.is()) |
| { |
| Reference< chart2::data::XDataSequence > xLabelSeq( xLabeledSeq->getLabel()); |
| if( xLabelSeq.is()) |
| aResult.first = lcl_ConvertRange( xLabelSeq->getSourceRangeRepresentation(), xDoc ); |
| |
| Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues()); |
| if( xValueSeq.is()) |
| aResult.second = lcl_ConvertRange( xValueSeq->getSourceRangeRepresentation(), xDoc ); |
| |
| if( xLabelSeq.is() || xValueSeq.is()) |
| rOutSequencesToExport.push_back( SchXMLExportHelper_Impl::tLabelValuesDataPair( xLabelSeq, xValueSeq )); |
| } |
| |
| return aResult; |
| } |
| |
| sal_Int32 lcl_getSequenceLengthByRole( |
| const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt, |
| const OUString & rRole ) |
| { |
| Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( |
| lcl_getDataSequenceByRole( aSeqCnt, rRole )); |
| if( xLabeledSeq.is()) |
| { |
| Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getValues()); |
| return xSeq->getData().getLength(); |
| } |
| return 0; |
| } |
| |
| bool lcl_hasChartType( const Reference< chart2::XDiagram > & xDiagram, const OUString & rChartType ) |
| { |
| try |
| { |
| Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW ); |
| Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems()); |
| for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx ) |
| { |
| Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW ); |
| Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes()); |
| for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx ) |
| { |
| if( aChartTypes[nCTIdx]->getChartType().equals( rChartType )) |
| return true; |
| } |
| } |
| } |
| catch( uno::Exception & ) |
| { |
| DBG_ERROR( "Exception while searching for chart type in diagram" ); |
| } |
| return false; |
| } |
| |
| OUString lcl_flattenStringSequence( const Sequence< OUString > & rSequence ) |
| { |
| OUStringBuffer aResult; |
| bool bPrecedeWithSpace = false; |
| for( sal_Int32 nIndex=0; nIndex<rSequence.getLength(); ++nIndex ) |
| { |
| if( rSequence[nIndex].getLength()) |
| { |
| if( bPrecedeWithSpace ) |
| aResult.append( static_cast< sal_Unicode >( ' ' )); |
| aResult.append( rSequence[nIndex] ); |
| bPrecedeWithSpace = true; |
| } |
| } |
| return aResult.makeStringAndClear(); |
| } |
| |
| void lcl_getLabelStringSequence( Sequence< OUString >& rOutLabels, const Reference< chart2::data::XDataSequence > & xLabelSeq ) |
| { |
| uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xLabelSeq, uno::UNO_QUERY ); |
| if( xTextualDataSequence.is()) |
| { |
| rOutLabels = xTextualDataSequence->getTextualData(); |
| } |
| else if( xLabelSeq.is()) |
| { |
| Sequence< uno::Any > aAnies( xLabelSeq->getData()); |
| rOutLabels.realloc( aAnies.getLength()); |
| for( sal_Int32 i=0; i<aAnies.getLength(); ++i ) |
| aAnies[i] >>= rOutLabels[i]; |
| } |
| } |
| |
| sal_Int32 lcl_getMaxSequenceLength( |
| const SchXMLExportHelper_Impl::tDataSequenceCont & rContainer ) |
| { |
| sal_Int32 nResult = 0; |
| for( SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aIt( rContainer.begin()); |
| aIt != rContainer.end(); ++aIt ) |
| { |
| if( aIt->second.is()) |
| { |
| sal_Int32 nSeqLength = aIt->second->getData().getLength(); |
| if( nSeqLength > nResult ) |
| nResult = nSeqLength; |
| } |
| } |
| return nResult; |
| } |
| |
| uno::Sequence< rtl::OUString > lcl_DataSequenceToStringSequence( |
| const uno::Reference< chart2::data::XDataSequence >& xDataSequence ) |
| { |
| uno::Sequence< rtl::OUString > aResult; |
| if(!xDataSequence.is()) |
| return aResult; |
| |
| uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY ); |
| if( xTextualDataSequence.is() ) |
| { |
| aResult = xTextualDataSequence->getTextualData(); |
| } |
| else |
| { |
| uno::Sequence< uno::Any > aValues = xDataSequence->getData(); |
| aResult.realloc(aValues.getLength()); |
| |
| for(sal_Int32 nN=aValues.getLength();nN--;) |
| aValues[nN] >>= aResult[nN]; |
| } |
| |
| return aResult; |
| } |
| ::std::vector< double > lcl_getAllValuesFromSequence( const Reference< chart2::data::XDataSequence > & xSeq ) |
| { |
| double fNan = 0.0; |
| ::rtl::math::setNan( &fNan ); |
| ::std::vector< double > aResult; |
| if(!xSeq.is()) |
| return aResult; |
| |
| uno::Sequence< double > aValuesSequence; |
| Reference< chart2::data::XNumericalDataSequence > xNumSeq( xSeq, uno::UNO_QUERY ); |
| if( xNumSeq.is() ) |
| { |
| aValuesSequence = xNumSeq->getNumericalData(); |
| } |
| else |
| { |
| Sequence< uno::Any > aAnies( xSeq->getData() ); |
| aValuesSequence.realloc( aAnies.getLength() ); |
| for( sal_Int32 i=0; i<aAnies.getLength(); ++i ) |
| aAnies[i] >>= aValuesSequence[i]; |
| } |
| |
| //special handling for x-values (if x-values do point to categories, indices are used instead ) |
| Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY ); |
| if( xProp.is() ) |
| { |
| OUString aRole; |
| xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Role") ) ) >>= aRole; |
| if( aRole.match( OUString( RTL_CONSTASCII_USTRINGPARAM( "values-x") ) ) ) |
| { |
| //lcl_clearIfNoValuesButTextIsContained - replace by indices if the values are not appropriate |
| bool bHasValue=false; |
| bool bHasText=false; |
| sal_Int32 nCount = aValuesSequence.getLength(); |
| for( sal_Int32 j = 0; j < nCount; ++j ) |
| { |
| if( !::rtl::math::isNan( aValuesSequence[j] ) ) |
| { |
| bHasValue=true; |
| break; |
| } |
| } |
| if(!bHasValue) |
| { |
| //no double value is countained |
| //is there any text? |
| uno::Sequence< rtl::OUString > aStrings( lcl_DataSequenceToStringSequence( xSeq ) ); |
| sal_Int32 nTextCount = aStrings.getLength(); |
| for( sal_Int32 j = 0; j < nTextCount; ++j ) |
| { |
| if( aStrings[j].getLength() ) |
| { |
| bHasText=true; |
| break; |
| } |
| } |
| } |
| if( !bHasValue && bHasText ) |
| { |
| for( sal_Int32 j = 0; j < nCount; ++j ) |
| aValuesSequence[j] = j+1; |
| } |
| } |
| } |
| |
| ::std::copy( aValuesSequence.getConstArray(), aValuesSequence.getConstArray() + aValuesSequence.getLength(), |
| ::std::back_inserter( aResult )); |
| return aResult; |
| } |
| |
| bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence ) |
| { |
| if( !xDataSequence.is() ) |
| return false; |
| uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY ); |
| if( xProp.is() ) |
| { |
| uno::Sequence< sal_Int32 > aHiddenValues; |
| try |
| { |
| xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "HiddenValues" ) ) ) >>= aHiddenValues; |
| if( !aHiddenValues.getLength() ) |
| return true; |
| } |
| catch( uno::Exception& e ) |
| { |
| (void)e; // avoid warning |
| return true; |
| } |
| } |
| if( xDataSequence->getData().getLength() ) |
| return true; |
| return false; |
| } |
| |
| typedef vector< OUString > tStringVector; |
| typedef vector< double > tDoubleVector; |
| typedef vector< vector< OUString > > t2DStringVector; |
| typedef vector< vector< double > > t2DNumberContainer; |
| |
| struct lcl_TableData |
| { |
| t2DNumberContainer aDataInRows; |
| tStringVector aDataRangeRepresentations; |
| |
| tStringVector aColumnDescriptions; |
| tStringVector aColumnDescriptions_Ranges; |
| |
| tStringVector aRowDescriptions; |
| tStringVector aRowDescriptions_Ranges; |
| |
| Sequence< Sequence< uno::Any > > aComplexColumnDescriptions;//outer index is columns - inner index is level |
| Sequence< Sequence< uno::Any > > aComplexRowDescriptions;//outer index is rows - inner index is level |
| |
| ::std::vector< sal_Int32 > aHiddenColumns; |
| }; |
| |
| // ::std::bind2nd( ::std::mem_fun_ref( &T::resize ), nSize ) does not work |
| template< class T > |
| struct lcl_resize |
| { |
| lcl_resize( typename T::size_type nSize, typename T::value_type fDefaultValue ) : m_nSize( nSize ), m_fDefaultValue( fDefaultValue ) {} |
| void operator()( T & t ) |
| { t.resize( m_nSize, m_fDefaultValue ); } |
| private: |
| typename T::size_type m_nSize; |
| typename T::value_type m_fDefaultValue; |
| }; |
| |
| |
| typedef ::std::map< sal_Int32, SchXMLExportHelper_Impl::tLabelValuesDataPair > |
| lcl_DataSequenceMap; |
| |
| struct lcl_SequenceToMapElement : |
| public ::std::unary_function< lcl_DataSequenceMap::mapped_type, lcl_DataSequenceMap::value_type > |
| { |
| lcl_SequenceToMapElement() |
| {} |
| result_type operator() ( const argument_type & rContent ) |
| { |
| sal_Int32 nIndex = -1; |
| if( rContent.second.is()) //has values |
| { |
| OUString aRangeRep( rContent.second->getSourceRangeRepresentation()); |
| nIndex = aRangeRep.toInt32(); |
| } |
| else if( rContent.first.is()) //has labels |
| nIndex = rContent.first->getSourceRangeRepresentation().copy( sizeof("label ")).toInt32(); |
| return result_type( nIndex, rContent ); |
| } |
| }; |
| |
| void lcl_ReorderInternalSequencesAccordingToTheirRangeName( |
| SchXMLExportHelper_Impl::tDataSequenceCont & rInOutSequences ) |
| { |
| lcl_DataSequenceMap aIndexSequenceMap; |
| ::std::transform( rInOutSequences.begin(), rInOutSequences.end(), |
| ::std::inserter( aIndexSequenceMap, aIndexSequenceMap.begin()), |
| lcl_SequenceToMapElement()); |
| |
| rInOutSequences.clear(); |
| sal_Int32 nIndex = 0; |
| for( lcl_DataSequenceMap::const_iterator aIt = aIndexSequenceMap.begin(); |
| aIt != aIndexSequenceMap.end(); ++aIt, ++nIndex ) |
| { |
| if( aIt->first < 0 ) |
| continue; |
| // fill empty columns |
| for( ; nIndex < aIt->first; ++nIndex ) |
| rInOutSequences.push_back( |
| SchXMLExportHelper_Impl::tDataSequenceCont::value_type( 0, 0 )); |
| OSL_ASSERT( nIndex == aIt->first ); |
| rInOutSequences.push_back( aIt->second ); |
| } |
| } |
| |
| |
| lcl_TableData lcl_getDataForLocalTable( |
| const SchXMLExportHelper_Impl::tDataSequenceCont & aSequencesToExport, |
| const Reference< chart2::XAnyDescriptionAccess >& xAnyDescriptionAccess, |
| const OUString& rCategoriesRange, |
| bool bSeriesFromColumns, |
| const Reference< chart2::data::XRangeXMLConversion > & xRangeConversion ) |
| { |
| lcl_TableData aResult; |
| |
| try |
| { |
| Sequence< OUString > aSimpleCategories; |
| if( xAnyDescriptionAccess.is() ) |
| { |
| //categories |
| if( bSeriesFromColumns ) |
| { |
| aSimpleCategories = xAnyDescriptionAccess->getRowDescriptions(); |
| aResult.aComplexRowDescriptions = xAnyDescriptionAccess->getAnyRowDescriptions(); |
| } |
| else |
| { |
| aSimpleCategories = xAnyDescriptionAccess->getColumnDescriptions(); |
| aResult.aComplexColumnDescriptions = xAnyDescriptionAccess->getAnyColumnDescriptions(); |
| } |
| } |
| |
| //series values and series labels |
| SchXMLExportHelper_Impl::tDataSequenceCont::size_type nNumSequences = aSequencesToExport.size(); |
| SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aBegin( aSequencesToExport.begin()); |
| SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aEnd( aSequencesToExport.end()); |
| SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aIt( aBegin ); |
| |
| size_t nMaxSequenceLength( lcl_getMaxSequenceLength( aSequencesToExport )); |
| size_t nCategoriesLength( aSimpleCategories.getLength() ); |
| if( nCategoriesLength > nMaxSequenceLength ) |
| { |
| aSimpleCategories.realloc(nMaxSequenceLength);//#i110617# |
| nCategoriesLength = nMaxSequenceLength; |
| } |
| size_t nNumColumns( bSeriesFromColumns ? nNumSequences : nMaxSequenceLength ); |
| size_t nNumRows( bSeriesFromColumns ? nMaxSequenceLength : nNumSequences ); |
| |
| // resize data |
| aResult.aDataInRows.resize( nNumRows ); |
| double fNan = 0.0; |
| ::rtl::math::setNan( &fNan ); |
| ::std::for_each( aResult.aDataInRows.begin(), aResult.aDataInRows.end(), |
| lcl_resize< t2DNumberContainer::value_type >( nNumColumns, fNan )); |
| aResult.aColumnDescriptions.resize( nNumColumns ); |
| aResult.aComplexColumnDescriptions.realloc( nNumColumns ); |
| aResult.aRowDescriptions.resize( nNumRows ); |
| aResult.aComplexRowDescriptions.realloc( nNumRows ); |
| |
| tStringVector& rCategories = bSeriesFromColumns ? aResult.aRowDescriptions : aResult.aColumnDescriptions; |
| tStringVector& rLabels = bSeriesFromColumns ? aResult.aColumnDescriptions : aResult.aRowDescriptions; |
| |
| //categories |
| lcl_SequenceToVector( aSimpleCategories, rCategories ); |
| if( rCategoriesRange.getLength() ) |
| { |
| OUString aRange(rCategoriesRange); |
| if( xRangeConversion.is()) |
| aRange = xRangeConversion->convertRangeToXML( aRange ); |
| if( bSeriesFromColumns ) |
| aResult.aRowDescriptions_Ranges.push_back( aRange ); |
| else |
| aResult.aColumnDescriptions_Ranges.push_back( aRange ); |
| } |
| |
| // iterate over all sequences |
| size_t nSeqIdx = 0; |
| Sequence< Sequence< OUString > > aComplexLabels(nNumSequences); |
| for( ; aIt != aEnd; ++aIt, ++nSeqIdx ) |
| { |
| OUString aRange; |
| Sequence< OUString >& rCurrentComplexLabel = aComplexLabels[nSeqIdx]; |
| if( aIt->first.is()) |
| { |
| lcl_getLabelStringSequence( rCurrentComplexLabel, aIt->first ); |
| rLabels[nSeqIdx] = lcl_flattenStringSequence( rCurrentComplexLabel ); |
| aRange = aIt->first->getSourceRangeRepresentation(); |
| if( xRangeConversion.is()) |
| aRange = xRangeConversion->convertRangeToXML( aRange ); |
| } |
| else if( aIt->second.is()) |
| { |
| rCurrentComplexLabel.realloc(1); |
| rLabels[nSeqIdx] = rCurrentComplexLabel[0] = lcl_flattenStringSequence( |
| aIt->second->generateLabel( chart2::data::LabelOrigin_SHORT_SIDE )); |
| } |
| if( bSeriesFromColumns ) |
| aResult.aColumnDescriptions_Ranges.push_back( aRange ); |
| else |
| aResult.aRowDescriptions_Ranges.push_back( aRange ); |
| |
| ::std::vector< double > aNumbers( lcl_getAllValuesFromSequence( aIt->second )); |
| if( bSeriesFromColumns ) |
| { |
| const sal_Int32 nSize( static_cast< sal_Int32 >( aNumbers.size())); |
| for( sal_Int32 nIdx=0; nIdx<nSize; ++nIdx ) |
| aResult.aDataInRows[nIdx][nSeqIdx] = aNumbers[nIdx]; |
| } |
| else |
| aResult.aDataInRows[nSeqIdx] = aNumbers; |
| |
| if( aIt->second.is()) |
| { |
| aRange = aIt->second->getSourceRangeRepresentation(); |
| if( xRangeConversion.is()) |
| aRange = xRangeConversion->convertRangeToXML( aRange ); |
| } |
| aResult.aDataRangeRepresentations.push_back( aRange ); |
| |
| //is column hidden? |
| if( !lcl_SequenceHasUnhiddenData(aIt->first) && !lcl_SequenceHasUnhiddenData(aIt->second) ) |
| aResult.aHiddenColumns.push_back(nSeqIdx); |
| } |
| Sequence< Sequence< Any > >& rComplexAnyLabels = bSeriesFromColumns ? aResult.aComplexColumnDescriptions : aResult.aComplexRowDescriptions;//#i116544# |
| rComplexAnyLabels.realloc(aComplexLabels.getLength()); |
| for( sal_Int32 nN=0; nN<aComplexLabels.getLength();nN++ ) |
| { |
| Sequence< OUString >& rSource = aComplexLabels[nN]; |
| Sequence< Any >& rTarget = rComplexAnyLabels[nN]; |
| rTarget.realloc( rSource.getLength() ); |
| for( sal_Int32 i=0; i<rSource.getLength(); i++ ) |
| rTarget[i] = uno::makeAny( rSource[i] ); |
| } |
| } |
| catch( uno::Exception & rEx ) |
| { |
| (void)rEx; // avoid warning for pro build |
| OSL_TRACE( OUStringToOString( OUString( RTL_CONSTASCII_USTRINGPARAM( |
| "something went wrong during table data collection: " )) + rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr()); |
| } |
| |
| return aResult; |
| } |
| |
| void lcl_exportNumberFormat( const OUString& rPropertyName, const Reference< beans::XPropertySet >& xPropSet, |
| SvXMLExport& rExport ) |
| { |
| if( xPropSet.is()) |
| { |
| sal_Int32 nNumberFormat = 0; |
| Any aNumAny = xPropSet->getPropertyValue( rPropertyName ); |
| if( (aNumAny >>= nNumberFormat) && (nNumberFormat != -1) ) |
| rExport.addDataStyle( nNumberFormat ); |
| } |
| } |
| |
| ::std::vector< Reference< chart2::data::XDataSequence > > |
| lcl_getErrorBarSequences( const Reference< beans::XPropertySet > & xErrorBarProp ) |
| { |
| ::std::vector< Reference< chart2::data::XDataSequence > > aResult; |
| Reference< chart2::data::XDataSource > xErrorBarDataSource( xErrorBarProp, uno::UNO_QUERY ); |
| if( !xErrorBarDataSource.is()) |
| return aResult; |
| |
| const OUString aRolePrefix( RTL_CONSTASCII_USTRINGPARAM( "error-bars-" )); |
| // const OUString aXRolePrefix( aRolePrefix + OUString( RTL_CONSTASCII_USTRINGPARAM( "x-" ))); |
| // const OUString aYRolePrefix( aRolePrefix + OUString( RTL_CONSTASCII_USTRINGPARAM( "y-" ))); |
| // const OUString aPositivePostfix( RTL_CONSTASCII_USTRINGPARAM( "positive" )); |
| // const OUString aNegativePostfix( RTL_CONSTASCII_USTRINGPARAM( "negative" )); |
| |
| Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( |
| xErrorBarDataSource->getDataSequences()); |
| for( sal_Int32 nI=0; nI< aSequences.getLength(); ++nI ) |
| { |
| try |
| { |
| if( aSequences[nI].is()) |
| { |
| Reference< chart2::data::XDataSequence > xSequence( aSequences[nI]->getValues()); |
| Reference< beans::XPropertySet > xSeqProp( xSequence, uno::UNO_QUERY_THROW ); |
| OUString aRole; |
| if( ( xSeqProp->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" ))) >>= aRole ) && |
| aRole.match( aRolePrefix )) |
| { |
| aResult.push_back( xSequence ); |
| } |
| } |
| } |
| catch( uno::Exception & rEx ) |
| { |
| #ifdef DBG_UTIL |
| String aStr( rEx.Message ); |
| ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US ); |
| DBG_ERROR1( "chart:exporting error bar ranges: %s", aBStr.GetBuffer()); |
| #else |
| (void)rEx; // avoid warning |
| #endif |
| } |
| } |
| |
| return aResult; |
| } |
| |
| bool lcl_exportDomainForThisSequence( const Reference< chart2::data::XDataSequence > xValues, rtl::OUString& rFirstRangeForThisDomainIndex, SvXMLExport& rExport ) |
| { |
| bool bDomainExported = false; |
| if( xValues.is()) |
| { |
| Reference< chart2::XChartDocument > xNewDoc( rExport.GetModel(), uno::UNO_QUERY ); |
| OUString aRange( lcl_ConvertRange( xValues->getSourceRangeRepresentation(), xNewDoc ) ); |
| |
| //work around error in OOo 2.0 (problems with multiple series having a domain element) |
| if( !rFirstRangeForThisDomainIndex.getLength() || !aRange.equals(rFirstRangeForThisDomainIndex) ) |
| { |
| rExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, aRange); |
| SvXMLElementExport aDomain( rExport, XML_NAMESPACE_CHART, XML_DOMAIN, sal_True, sal_True ); |
| bDomainExported = true; |
| } |
| |
| if( !rFirstRangeForThisDomainIndex.getLength() ) |
| rFirstRangeForThisDomainIndex = aRange; |
| } |
| return bDomainExported; |
| } |
| |
| } // anonymous namespace |
| |
| struct SchXMLDataPointStruct |
| { |
| OUString maStyleName; |
| sal_Int32 mnRepeat; |
| |
| SchXMLDataPointStruct() : mnRepeat( 1 ) {} |
| }; |
| |
| // ======================================== |
| // class SchXMLExportHelper |
| // ======================================== |
| |
| SchXMLExportHelper::SchXMLExportHelper( SvXMLExport& rExport, SvXMLAutoStylePoolP& rASPool ) |
| : m_pImpl( new SchXMLExportHelper_Impl( rExport, rASPool ) ) |
| { |
| } |
| |
| SchXMLExportHelper::~SchXMLExportHelper() |
| { |
| delete m_pImpl; |
| } |
| |
| const OUString& SchXMLExportHelper::getChartCLSID() |
| { |
| return m_pImpl->msCLSID; |
| } |
| |
| UniReference< XMLPropertySetMapper > SchXMLExportHelper_Impl::GetPropertySetMapper() const |
| { |
| return mxPropertySetMapper; |
| } |
| |
| void SchXMLExportHelper_Impl::exportAutoStyles() |
| { |
| if( mxExpPropMapper.is()) |
| { |
| //ToDo: when embedded in calc/writer this is not necessary because the |
| // numberformatter is shared between both documents |
| mrExport.exportAutoDataStyles(); |
| |
| // export chart auto styles |
| mrAutoStylePool.exportXML( |
| XML_STYLE_FAMILY_SCH_CHART_ID |
| , mrExport.GetDocHandler(), |
| mrExport.GetMM100UnitConverter(), |
| mrExport.GetNamespaceMap() |
| ); |
| |
| // export auto styles for additional shapes |
| mrExport.GetShapeExport()->exportAutoStyles(); |
| // and for text in additional shapes |
| mrExport.GetTextParagraphExport()->exportTextAutoStyles(); |
| } |
| } |
| |
| // private methods |
| // --------------- |
| |
| SchXMLExportHelper_Impl::SchXMLExportHelper_Impl( |
| SvXMLExport& rExport, |
| SvXMLAutoStylePoolP& rASPool ) : |
| mrExport( rExport ), |
| mrAutoStylePool( rASPool ), |
| mbHasSeriesLabels( sal_False ), |
| mbHasCategoryLabels( sal_False ), |
| mbRowSourceColumns( sal_True ) |
| // #110680# |
| // this id depends on the ServiceManager used due to the binary filter stripping. |
| // ,msCLSID( rtl::OUString( SvGlobalName( SO3_SCH_CLASSID ).GetHexName())) |
| { |
| // #110680# |
| // changed initialisation for msCLSID. Compare the ServiceInfo name with |
| // the known name of the LegacyServiceManager. |
| Reference<lang::XServiceInfo> xServiceInfo( mrExport.getServiceFactory(), uno::UNO_QUERY ); |
| DBG_ASSERT( xServiceInfo.is(), "XMultiServiceFactory without xServiceInfo (!)" ); |
| OUString rdbURL = xServiceInfo->getImplementationName(); |
| OUString implLegacyServiceManagerName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.office.LegacyServiceManager" ) ); |
| |
| if( rdbURL.equals( implLegacyServiceManagerName )) |
| { |
| msCLSID = OUString( SvGlobalName( BF_SO3_SCH_CLASSID ).GetHexName()); |
| } |
| else |
| { |
| msCLSID = OUString( SvGlobalName( SO3_SCH_CLASSID ).GetHexName()); |
| } |
| |
| msTableName = OUString::createFromAscii( "local-table" ); |
| |
| // create factory |
| mxPropertyHandlerFactory = new XMLChartPropHdlFactory; |
| |
| if( mxPropertyHandlerFactory.is() ) |
| { |
| // create property set mapper |
| mxPropertySetMapper = new XMLChartPropertySetMapper; |
| } |
| |
| mxExpPropMapper = new XMLChartExportPropertyMapper( mxPropertySetMapper, rExport ); |
| |
| // register chart auto-style family |
| mrAutoStylePool.AddFamily( |
| XML_STYLE_FAMILY_SCH_CHART_ID, |
| OUString::createFromAscii( XML_STYLE_FAMILY_SCH_CHART_NAME ), |
| mxExpPropMapper.get(), |
| OUString::createFromAscii( XML_STYLE_FAMILY_SCH_CHART_PREFIX )); |
| |
| // register shape family |
| mrAutoStylePool.AddFamily( |
| XML_STYLE_FAMILY_SD_GRAPHICS_ID, |
| OUString::createFromAscii( XML_STYLE_FAMILY_SD_GRAPHICS_NAME ), |
| mxExpPropMapper.get(), |
| OUString::createFromAscii( XML_STYLE_FAMILY_SD_GRAPHICS_PREFIX )); |
| // register paragraph family also for shapes |
| mrAutoStylePool.AddFamily( |
| XML_STYLE_FAMILY_TEXT_PARAGRAPH, |
| GetXMLToken( XML_PARAGRAPH ), |
| mxExpPropMapper.get(), |
| String( 'P' )); |
| // register text family also for shapes |
| mrAutoStylePool.AddFamily( |
| XML_STYLE_FAMILY_TEXT_TEXT, |
| GetXMLToken( XML_TEXT ), |
| mxExpPropMapper.get(), |
| String( 'T' )); |
| } |
| |
| SchXMLExportHelper_Impl::~SchXMLExportHelper_Impl() |
| { |
| } |
| |
| void SchXMLExportHelper_Impl::collectAutoStyles( Reference< chart::XChartDocument > rChartDoc ) |
| { |
| parseDocument( rChartDoc, sal_False ); |
| } |
| |
| void SchXMLExportHelper_Impl::exportChart( Reference< chart::XChartDocument > rChartDoc, |
| sal_Bool bIncludeTable ) |
| { |
| parseDocument( rChartDoc, sal_True, bIncludeTable ); |
| DBG_ASSERT( maAutoStyleNameQueue.empty(), "There are still remaining autostyle names in the queue" ); |
| } |
| |
| ::rtl::OUString lcl_GetStringFromNumberSequence( const ::com::sun::star::uno::Sequence< sal_Int32 >& rSequenceMapping, bool bRemoveOneFromEachIndex /*should be true if having categories*/ ) |
| { |
| const sal_Int32* pArray = rSequenceMapping.getConstArray(); |
| const sal_Int32 nSize = rSequenceMapping.getLength(); |
| sal_Int32 i = 0; |
| OUStringBuffer aBuf; |
| bool bHasPredecessor = false; |
| for( i = 0; i < nSize; ++i ) |
| { |
| sal_Int32 nIndex = pArray[ i ]; |
| if( bRemoveOneFromEachIndex ) |
| --nIndex; |
| if(nIndex>=0) |
| { |
| if(bHasPredecessor) |
| aBuf.append( static_cast< sal_Unicode >( ' ' )); |
| aBuf.append( nIndex, 10 ); |
| bHasPredecessor = true; |
| } |
| } |
| return aBuf.makeStringAndClear(); |
| } |
| |
| /// if bExportContent is false the auto-styles are collected |
| void SchXMLExportHelper_Impl::parseDocument( Reference< chart::XChartDocument >& rChartDoc, |
| sal_Bool bExportContent, |
| sal_Bool bIncludeTable ) |
| { |
| Reference< chart2::XChartDocument > xNewDoc( rChartDoc, uno::UNO_QUERY ); |
| if( !rChartDoc.is() || !xNewDoc.is() ) |
| { |
| DBG_ERROR( "No XChartDocument was given for export." ); |
| return; |
| } |
| |
| awt::Size aPageSize( getPageSize( xNewDoc )); |
| if( bExportContent ) |
| addSize( aPageSize ); |
| Reference< chart::XDiagram > xDiagram = rChartDoc->getDiagram(); |
| Reference< chart2::XDiagram > xNewDiagram; |
| if( xNewDoc.is()) |
| xNewDiagram.set( xNewDoc->getFirstDiagram()); |
| |
| //todo remove if model changes are notified and view is updated automatically |
| if( bExportContent ) |
| { |
| Reference< util::XRefreshable > xRefreshable( xNewDoc, uno::UNO_QUERY ); |
| if( xRefreshable.is() ) |
| xRefreshable->refresh(); |
| } |
| |
| // get Properties of ChartDocument |
| sal_Bool bHasMainTitle = sal_False; |
| sal_Bool bHasSubTitle = sal_False; |
| sal_Bool bHasLegend = sal_False; |
| util::DateTime aNullDate(0,0,0,0,30,12,1899); |
| |
| std::vector< XMLPropertyState > aPropertyStates; |
| |
| Reference< beans::XPropertySet > xDocPropSet( rChartDoc, uno::UNO_QUERY ); |
| if( xDocPropSet.is()) |
| { |
| try |
| { |
| Any aAny( xDocPropSet->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "HasMainTitle" )))); |
| aAny >>= bHasMainTitle; |
| aAny = xDocPropSet->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "HasSubTitle" ))); |
| aAny >>= bHasSubTitle; |
| aAny = xDocPropSet->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "HasLegend" ))); |
| aAny >>= bHasLegend; |
| if ( bIncludeTable ) |
| { |
| OUString sNullDate( RTL_CONSTASCII_USTRINGPARAM( "NullDate" )); |
| aAny = xDocPropSet->getPropertyValue(sNullDate); |
| if ( !aAny.hasValue() ) |
| { |
| Reference<container::XChild> xChild(rChartDoc, uno::UNO_QUERY ); |
| if ( xChild.is() ) |
| { |
| Reference< beans::XPropertySet > xParentDoc( xChild->getParent(),uno::UNO_QUERY); |
| if ( xParentDoc.is() && xParentDoc->getPropertySetInfo()->hasPropertyByName(sNullDate) ) |
| aAny = xParentDoc->getPropertyValue(sNullDate); |
| } |
| } |
| |
| aAny >>= aNullDate; |
| } |
| } |
| catch( beans::UnknownPropertyException & ) |
| { |
| DBG_WARNING( "Required property not found in ChartDocument" ); |
| } |
| } // if( xDocPropSet.is()) |
| |
| if ( bIncludeTable && (aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899 ) ) |
| { |
| SvXMLElementExport aSet( mrExport, XML_NAMESPACE_TABLE, XML_CALCULATION_SETTINGS, sal_True, sal_True ); |
| { |
| ::rtl::OUStringBuffer sBuffer; |
| SvXMLUnitConverter::convertDateTime(sBuffer,aNullDate); |
| mrExport.AddAttribute( XML_NAMESPACE_TABLE,XML_DATE_VALUE,sBuffer.makeStringAndClear()); |
| SvXMLElementExport aNull( mrExport, XML_NAMESPACE_TABLE, XML_NULL_DATE, sal_True, sal_True ); |
| } |
| } |
| |
| // chart element |
| // ------------- |
| |
| SvXMLElementExport* pElChart = 0; |
| // get property states for autostyles |
| if( mxExpPropMapper.is()) |
| { |
| Reference< beans::XPropertySet > xPropSet( rChartDoc->getArea(), uno::UNO_QUERY ); |
| if( xPropSet.is()) |
| aPropertyStates = mxExpPropMapper->Filter( xPropSet ); |
| } |
| |
| if( bExportContent ) |
| { |
| //export data provider in xlink:href attribute |
| const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() ); |
| if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 ) |
| { |
| OUString aDataProviderURL( RTL_CONSTASCII_USTRINGPARAM( ".." ) ); |
| if( xNewDoc->hasInternalDataProvider() ) |
| aDataProviderURL = OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) ); |
| else //special handling for data base data provider necessary |
| { |
| Reference< chart2::data::XDatabaseDataProvider > xDBDataProvider( xNewDoc->getDataProvider(), uno::UNO_QUERY ); |
| if( xDBDataProvider.is() ) |
| aDataProviderURL = OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) ); |
| } |
| mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, aDataProviderURL ); |
| mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE ); |
| } |
| |
| OUString sChartType( xDiagram->getDiagramType() ); |
| |
| // attributes |
| // determine class |
| if( sChartType.getLength()) |
| { |
| enum XMLTokenEnum eXMLChartType = SchXMLTools::getTokenByChartType( sChartType, true /* bUseOldNames */ ); |
| |
| DBG_ASSERT( eXMLChartType != XML_TOKEN_INVALID, "invalid chart class" ); |
| if( eXMLChartType == XML_TOKEN_INVALID ) |
| eXMLChartType = XML_BAR; |
| |
| if( eXMLChartType == XML_ADD_IN ) |
| { |
| // sChartType is the servie-name of the add-in |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS, |
| mrExport.GetNamespaceMap().GetQNameByKey( |
| XML_NAMESPACE_OOO, sChartType) ); |
| } |
| else if( eXMLChartType != XML_TOKEN_INVALID ) |
| { |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS, |
| mrExport.GetNamespaceMap().GetQNameByKey( |
| XML_NAMESPACE_CHART, GetXMLToken(eXMLChartType )) ); |
| } |
| |
| //column-mapping or row-mapping |
| if( maSequenceMapping.getLength() ) |
| { |
| enum XMLTokenEnum eTransToken = ::xmloff::token::XML_ROW_MAPPING; |
| if( mbRowSourceColumns ) |
| eTransToken = ::xmloff::token::XML_COLUMN_MAPPING; |
| ::rtl::OUString aSequenceMappingStr( lcl_GetStringFromNumberSequence( |
| maSequenceMapping, mbHasCategoryLabels && !xNewDoc->hasInternalDataProvider() ) ); |
| |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, |
| ::xmloff::token::GetXMLToken( eTransToken ), |
| aSequenceMappingStr ); |
| } |
| } |
| // write style name |
| AddAutoStyleAttribute( aPropertyStates ); |
| |
| //element |
| pElChart = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_CHART, sal_True, sal_True ); |
| } |
| else // autostyles |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| // remove property states for autostyles |
| aPropertyStates.clear(); |
| |
| // title element |
| // ------------- |
| |
| if( bHasMainTitle ) |
| { |
| // get property states for autostyles |
| if( mxExpPropMapper.is()) |
| { |
| Reference< beans::XPropertySet > xPropSet( rChartDoc->getTitle(), uno::UNO_QUERY ); |
| if( xPropSet.is()) |
| aPropertyStates = mxExpPropMapper->Filter( xPropSet ); |
| } |
| if( bExportContent ) |
| { |
| Reference< drawing::XShape > xShape = rChartDoc->getTitle(); |
| if( xShape.is()) // && "hasTitleBeenMoved" |
| addPosition( xShape ); |
| |
| // write style name |
| AddAutoStyleAttribute( aPropertyStates ); |
| |
| // element |
| SvXMLElementExport aElTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, sal_True, sal_True ); |
| |
| // content (text:p) |
| Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY ); |
| if( xPropSet.is()) |
| { |
| Any aAny( xPropSet->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "String" )))); |
| OUString aText; |
| aAny >>= aText; |
| exportText( aText ); |
| } |
| } |
| else // autostyles |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| // remove property states for autostyles |
| aPropertyStates.clear(); |
| } |
| |
| // subtitle element |
| // ---------------- |
| |
| if( bHasSubTitle ) |
| { |
| // get property states for autostyles |
| if( mxExpPropMapper.is()) |
| { |
| Reference< beans::XPropertySet > xPropSet( rChartDoc->getSubTitle(), uno::UNO_QUERY ); |
| if( xPropSet.is()) |
| aPropertyStates = mxExpPropMapper->Filter( xPropSet ); |
| } |
| |
| if( bExportContent ) |
| { |
| Reference< drawing::XShape > xShape = rChartDoc->getSubTitle(); |
| if( xShape.is()) |
| addPosition( xShape ); |
| |
| // write style name |
| AddAutoStyleAttribute( aPropertyStates ); |
| |
| // element (has no subelements) |
| SvXMLElementExport aElSubTitle( mrExport, XML_NAMESPACE_CHART, XML_SUBTITLE, sal_True, sal_True ); |
| |
| // content (text:p) |
| Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY ); |
| if( xPropSet.is()) |
| { |
| Any aAny( xPropSet->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "String" )))); |
| OUString aText; |
| aAny >>= aText; |
| exportText( aText ); |
| } |
| } |
| else // autostyles |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| // remove property states for autostyles |
| aPropertyStates.clear(); |
| } |
| |
| // legend element |
| // -------------- |
| if( bHasLegend ) |
| { |
| // get property states for autostyles |
| if( mxExpPropMapper.is()) |
| { |
| Reference< beans::XPropertySet > xPropSet( rChartDoc->getLegend(), uno::UNO_QUERY ); |
| if( xPropSet.is()) |
| aPropertyStates = mxExpPropMapper->Filter( xPropSet ); |
| } |
| |
| if( bExportContent ) |
| { |
| Reference< beans::XPropertySet > xProp( rChartDoc->getLegend(), uno::UNO_QUERY ); |
| if( xProp.is()) |
| { |
| // export legend anchor position |
| try |
| { |
| Any aAny( xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Alignment" )))); |
| if( SchXMLEnumConverter::getLegendPositionConverter().exportXML( msString, aAny, mrExport.GetMM100UnitConverter() ) ) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LEGEND_POSITION, msString ); |
| } |
| catch( beans::UnknownPropertyException & ) |
| { |
| DBG_WARNING( "Property Align not found in ChartLegend" ); |
| } |
| |
| // export absolute legend position |
| Reference< drawing::XShape > xLegendShape( xProp, uno::UNO_QUERY ); |
| addPosition( xLegendShape ); |
| |
| // export legend size |
| const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() ); |
| if( xLegendShape.is() && nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 && nCurrentODFVersion == SvtSaveOptions::ODFVER_LATEST )//do not export legend-expansion to ODF 1.0 and export size only if extensions are enabled //#i28670# todo: change this dependent on fileformat evolution |
| { |
| try |
| { |
| chart::ChartLegendExpansion nLegendExpansion = chart::ChartLegendExpansion_HIGH; |
| OUString aExpansionString; |
| Any aAny( xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Expansion" )))); |
| bool bHasExpansion = (aAny >>= nLegendExpansion); |
| if( bHasExpansion && SchXMLEnumConverter::getLegendExpansionConverter().exportXML( aExpansionString, aAny, mrExport.GetMM100UnitConverter() ) ) |
| { |
| mrExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEGEND_EXPANSION, aExpansionString ); |
| if( nLegendExpansion == chart::ChartLegendExpansion_CUSTOM) |
| { |
| awt::Size aSize( xLegendShape->getSize() ); |
| addSize( aSize, true ); |
| rtl::OUStringBuffer aAspectRatioString; |
| SvXMLUnitConverter::convertDouble(aAspectRatioString, double(aSize.Width)/double(aSize.Height)); |
| mrExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEGEND_EXPANSION_ASPECT_RATIO, aAspectRatioString.makeStringAndClear() ); |
| } |
| } |
| } |
| catch( beans::UnknownPropertyException & ) |
| { |
| DBG_WARNING( "Property Expansion not found in ChartLegend" ); |
| } |
| } |
| } |
| |
| // write style name |
| AddAutoStyleAttribute( aPropertyStates ); |
| |
| // element |
| SvXMLElementExport aLegend( mrExport, XML_NAMESPACE_CHART, XML_LEGEND, sal_True, sal_True ); |
| } |
| else // autostyles |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| // remove property states for autostyles |
| aPropertyStates.clear(); |
| } |
| |
| // plot-area element |
| // ----------------- |
| if( xDiagram.is()) |
| exportPlotArea( xDiagram, xNewDiagram, aPageSize, bExportContent, bIncludeTable ); |
| |
| // export additional shapes |
| // ------------------------ |
| if( xDocPropSet.is() ) |
| { |
| if( bExportContent ) |
| { |
| if( mxAdditionalShapes.is()) |
| { |
| // can't call exportShapes with all shapes because the |
| // initialisation happend with the complete draw page and not |
| // the XShapes object used here. Thus the shapes have to be |
| // exported one by one |
| UniReference< XMLShapeExport > rShapeExport = mrExport.GetShapeExport(); |
| Reference< drawing::XShape > xShape; |
| const sal_Int32 nShapeCount( mxAdditionalShapes->getCount()); |
| for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ ) |
| { |
| mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape; |
| DBG_ASSERT( xShape.is(), "Shape without an XShape?" ); |
| if( ! xShape.is()) |
| continue; |
| |
| rShapeExport->exportShape( xShape ); |
| } |
| // this would be the easier way if it worked: |
| //mrExport.GetShapeExport()->exportShapes( mxAdditionalShapes ); |
| } |
| } |
| else |
| { |
| // get a sequence of non-chart shapes (inserted via clipboard) |
| try |
| { |
| Any aShapesAny = xDocPropSet->getPropertyValue( OUString::createFromAscii( "AdditionalShapes" )); |
| aShapesAny >>= mxAdditionalShapes; |
| } |
| catch( uno::Exception & rEx ) |
| { |
| (void)rEx; // avoid warning for pro build |
| OSL_TRACE( |
| OUStringToOString( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( |
| "AdditionalShapes not found: " )) + |
| rEx.Message, |
| RTL_TEXTENCODING_ASCII_US ).getStr()); |
| } |
| |
| if( mxAdditionalShapes.is()) |
| { |
| // seek shapes has to be called for the whole page because in |
| // the shape export the vector of shapes is accessed via the |
| // ZOrder which might be (actually is) larger than the number of |
| // shapes in mxAdditionalShapes |
| Reference< drawing::XDrawPageSupplier > xSupplier( rChartDoc, uno::UNO_QUERY ); |
| DBG_ASSERT( xSupplier.is(), "Cannot retrieve draw page to initialize shape export" ); |
| if( xSupplier.is() ) |
| { |
| Reference< drawing::XShapes > xDrawPage( xSupplier->getDrawPage(), uno::UNO_QUERY ); |
| DBG_ASSERT( xDrawPage.is(), "Invalid draw page for initializing shape export" ); |
| if( xDrawPage.is()) |
| mrExport.GetShapeExport()->seekShapes( xDrawPage ); |
| } |
| |
| // can't call collectShapesAutoStyles with all shapes because |
| // the initialisation happend with the complete draw page and |
| // not the XShapes object used here. Thus the shapes have to be |
| // exported one by one |
| UniReference< XMLShapeExport > rShapeExport = mrExport.GetShapeExport(); |
| Reference< drawing::XShape > xShape; |
| const sal_Int32 nShapeCount( mxAdditionalShapes->getCount()); |
| for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ ) |
| { |
| mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape; |
| DBG_ASSERT( xShape.is(), "Shape without an XShape?" ); |
| if( ! xShape.is()) |
| continue; |
| |
| rShapeExport->collectShapeAutoStyles( xShape ); |
| } |
| // this would be the easier way if it worked: |
| // mrExport.GetShapeExport()->collectShapesAutoStyles( mxAdditionalShapes ); |
| } |
| } |
| } |
| |
| // table element |
| // (is included as subelement of chart) |
| // ------------------------------------ |
| if( bExportContent ) |
| { |
| // #85929# always export table, otherwise clipboard may loose data |
| exportTable(); |
| } |
| |
| // close <chart:chart> element |
| if( pElChart ) |
| delete pElChart; |
| } |
| |
| void lcl_exportComplexLabel( const Sequence< uno::Any >& rComplexLabel, SvXMLExport& rExport ) |
| { |
| sal_Int32 nLength = rComplexLabel.getLength(); |
| if( nLength<=1 ) |
| return; |
| SvXMLElementExport aTextList( rExport, XML_NAMESPACE_TEXT, XML_LIST, sal_True, sal_True ); |
| for(sal_Int32 nN=0; nN<nLength; nN++) |
| { |
| SvXMLElementExport aListItem( rExport, XML_NAMESPACE_TEXT, XML_LIST_ITEM, sal_True, sal_True ); |
| OUString aString; |
| if( !(rComplexLabel[nN]>>=aString) ) |
| { |
| //todo? |
| } |
| SchXMLTools::exportText( rExport, aString, false /*bConvertTabsLFs*/ ); |
| } |
| } |
| |
| void SchXMLExportHelper_Impl::exportTable() |
| { |
| // table element |
| // ------------- |
| mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, msTableName ); |
| |
| try |
| { |
| bool bProtected = false; |
| Reference< beans::XPropertySet > xProps( mrExport.GetModel(), uno::UNO_QUERY_THROW ); |
| if ( ( xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableDataTableDialog" ) ) ) >>= bProtected ) && |
| bProtected ) |
| { |
| mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE ); |
| } |
| } |
| catch ( uno::Exception& ) |
| { |
| } |
| |
| SvXMLElementExport aTable( mrExport, XML_NAMESPACE_TABLE, XML_TABLE, sal_True, sal_True ); |
| |
| bool bHasOwnData = false; |
| Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY ); |
| Reference< chart2::data::XRangeXMLConversion > xRangeConversion; |
| if( xNewDoc.is()) |
| { |
| bHasOwnData = xNewDoc->hasInternalDataProvider(); |
| xRangeConversion.set( xNewDoc->getDataProvider(), uno::UNO_QUERY ); |
| } |
| |
| Reference< chart2::XAnyDescriptionAccess > xAnyDescriptionAccess; |
| { |
| Reference< chart::XChartDocument > xChartDoc( mrExport.GetModel(), uno::UNO_QUERY ); |
| if( xChartDoc.is() ) |
| xAnyDescriptionAccess = Reference< chart2::XAnyDescriptionAccess >( xChartDoc->getData(), uno::UNO_QUERY ); |
| } |
| |
| if( bHasOwnData ) |
| lcl_ReorderInternalSequencesAccordingToTheirRangeName( m_aDataSequencesToExport ); |
| lcl_TableData aData( lcl_getDataForLocalTable( m_aDataSequencesToExport |
| , xAnyDescriptionAccess, maCategoriesRange |
| , mbRowSourceColumns, xRangeConversion )); |
| |
| tStringVector::const_iterator aDataRangeIter( aData.aDataRangeRepresentations.begin()); |
| const tStringVector::const_iterator aDataRangeEndIter( aData.aDataRangeRepresentations.end()); |
| |
| tStringVector::const_iterator aRowDescriptions_RangeIter( aData.aRowDescriptions_Ranges.begin()); |
| const tStringVector::const_iterator aRowDescriptions_RangeEnd( aData.aRowDescriptions_Ranges.end()); |
| |
| // declare columns |
| { |
| SvXMLElementExport aHeaderColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS, sal_True, sal_True ); |
| SvXMLElementExport aHeaderColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True ); |
| } |
| { |
| SvXMLElementExport aColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMNS, sal_True, sal_True ); |
| |
| sal_Int32 nNextIndex = 0; |
| for( size_t nN=0; nN< aData.aHiddenColumns.size(); nN++ ) |
| { |
| //i91578 display of hidden values (copy paste scenario; export hidden flag thus it can be used during migration to locale table upon paste ) |
| sal_Int32 nHiddenIndex = aData.aHiddenColumns[nN]; |
| if( nHiddenIndex > nNextIndex ) |
| { |
| sal_Int64 nRepeat = static_cast< sal_Int64 >( nHiddenIndex - nNextIndex ); |
| if(nRepeat>1) |
| mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, |
| OUString::valueOf( nRepeat )); |
| SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True ); |
| } |
| mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_VISIBILITY, GetXMLToken( XML_COLLAPSE ) ); |
| SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True ); |
| nNextIndex = nHiddenIndex+1; |
| } |
| |
| sal_Int32 nEndIndex = aData.aColumnDescriptions.size()-1; |
| if( nEndIndex >= nNextIndex ) |
| { |
| sal_Int64 nRepeat = static_cast< sal_Int64 >( nEndIndex - nNextIndex + 1 ); |
| if(nRepeat>1) |
| mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, |
| OUString::valueOf( nRepeat )); |
| SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True ); |
| } |
| } |
| |
| // export rows with content |
| //export header row |
| { |
| SvXMLElementExport aHeaderRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, sal_True, sal_True ); |
| SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True ); |
| |
| //first one empty cell for the row descriptions |
| { |
| SvXMLElementExport aEmptyCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True ); |
| SvXMLElementExport aEmptyParagraph( mrExport, XML_NAMESPACE_TEXT, XML_P, sal_True, sal_True ); |
| } |
| |
| //export column descriptions |
| tStringVector::const_iterator aColumnDescriptions_RangeIter( aData.aColumnDescriptions_Ranges.begin()); |
| const tStringVector::const_iterator aColumnDescriptions_RangeEnd( aData.aColumnDescriptions_Ranges.end()); |
| const Sequence< Sequence< uno::Any > >& rComplexColumnDescriptions = aData.aComplexColumnDescriptions; |
| sal_Int32 nComplexCount = rComplexColumnDescriptions.getLength(); |
| sal_Int32 nC = 0; |
| for( tStringVector::const_iterator aIt( aData.aColumnDescriptions.begin()) |
| ; (aIt != aData.aColumnDescriptions.end()) |
| ; aIt++, nC++ ) |
| { |
| bool bExportString = true; |
| if( nC < nComplexCount ) |
| { |
| const Sequence< uno::Any >& rComplexLabel = rComplexColumnDescriptions[nC]; |
| if( rComplexLabel.getLength()>0 ) |
| { |
| double fValue=0.0; |
| if( rComplexLabel[0] >>=fValue ) |
| { |
| bExportString = false; |
| |
| SvXMLUnitConverter::convertDouble( msStringBuffer, fValue ); |
| msString = msStringBuffer.makeStringAndClear(); |
| mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT ); |
| mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString ); |
| } |
| } |
| } |
| if( bExportString ) |
| { |
| mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING ); |
| } |
| |
| SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True ); |
| exportText( *aIt ); |
| if( nC < nComplexCount ) |
| lcl_exportComplexLabel( rComplexColumnDescriptions[nC], mrExport ); |
| if( !bHasOwnData && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd ) |
| { |
| // remind the original range to allow a correct re-association when copying via clipboard |
| if ((*aColumnDescriptions_RangeIter).getLength()) |
| SchXMLTools::exportRangeToSomewhere( mrExport, *aColumnDescriptions_RangeIter ); |
| ++aColumnDescriptions_RangeIter; |
| } |
| } |
| OSL_ASSERT( bHasOwnData || aColumnDescriptions_RangeIter == aColumnDescriptions_RangeEnd ); |
| } // closing row and header-rows elements |
| |
| // export value rows |
| { |
| SvXMLElementExport aRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROWS, sal_True, sal_True ); |
| tStringVector::const_iterator aRowDescriptionsIter( aData.aRowDescriptions.begin()); |
| const Sequence< Sequence< uno::Any > >& rComplexRowDescriptions = aData.aComplexRowDescriptions; |
| sal_Int32 nComplexCount = rComplexRowDescriptions.getLength(); |
| sal_Int32 nC = 0; |
| |
| for( t2DNumberContainer::const_iterator aRowIt( aData.aDataInRows.begin()) |
| ; aRowIt != aData.aDataInRows.end() |
| ; ++aRowIt, ++nC ) |
| { |
| SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True ); |
| |
| //export row descriptions |
| { |
| bool bExportString = true; |
| if( nC < nComplexCount ) |
| { |
| const Sequence< uno::Any >& rComplexLabel = rComplexRowDescriptions[nC]; |
| if( rComplexLabel.getLength()>0 ) |
| { |
| double fValue=0.0; |
| if( rComplexLabel[0] >>=fValue ) |
| { |
| bExportString = false; |
| |
| SvXMLUnitConverter::convertDouble( msStringBuffer, fValue ); |
| msString = msStringBuffer.makeStringAndClear(); |
| mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT ); |
| mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString ); |
| } |
| } |
| } |
| if( bExportString ) |
| { |
| mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING ); |
| } |
| |
| SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True ); |
| if( aRowDescriptionsIter != aData.aRowDescriptions.end()) |
| { |
| exportText( *aRowDescriptionsIter ); |
| if( nC < nComplexCount ) |
| lcl_exportComplexLabel( rComplexRowDescriptions[nC], mrExport ); |
| if( !bHasOwnData && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd ) |
| { |
| // remind the original range to allow a correct re-association when copying via clipboard |
| SchXMLTools::exportRangeToSomewhere( mrExport, *aRowDescriptions_RangeIter ); |
| ++aRowDescriptions_RangeIter; |
| } |
| ++aRowDescriptionsIter; |
| } |
| } |
| |
| //export row values |
| for( t2DNumberContainer::value_type::const_iterator aColIt( aRowIt->begin()); |
| aColIt != aRowIt->end(); ++aColIt ) |
| { |
| SvXMLUnitConverter::convertDouble( msStringBuffer, *aColIt ); |
| msString = msStringBuffer.makeStringAndClear(); |
| mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT ); |
| mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString ); |
| SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True ); |
| exportText( msString, false ); // do not convert tabs and lfs |
| if( ( !bHasOwnData && aDataRangeIter != aDataRangeEndIter ) && |
| ( mbRowSourceColumns || (aColIt == aRowIt->begin()) ) ) |
| { |
| // remind the original range to allow a correct re-association when copying via clipboard |
| if ((*aDataRangeIter).getLength()) |
| SchXMLTools::exportRangeToSomewhere( mrExport, *aDataRangeIter ); |
| ++aDataRangeIter; |
| } |
| } |
| } |
| } |
| |
| // if range iterator was used it should have reached its end |
| OSL_ASSERT( bHasOwnData || (aDataRangeIter == aDataRangeEndIter) ); |
| OSL_ASSERT( bHasOwnData || (aRowDescriptions_RangeIter == aRowDescriptions_RangeEnd) ); |
| } |
| |
| namespace |
| { |
| |
| Reference< chart2::XCoordinateSystem > lcl_getCooSys( const Reference< chart2::XDiagram > & xNewDiagram ) |
| { |
| Reference< chart2::XCoordinateSystem > xCooSys; |
| Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDiagram, uno::UNO_QUERY ); |
| if(xCooSysCnt.is()) |
| { |
| Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() ); |
| if(aCooSysSeq.getLength()>0) |
| xCooSys = aCooSysSeq[0]; |
| } |
| return xCooSys; |
| } |
| |
| Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem >& xCooSys, |
| enum XMLTokenEnum eDimension, bool bPrimary=true ) |
| { |
| Reference< chart2::XAxis > xNewAxis; |
| try |
| { |
| if( xCooSys.is() ) |
| { |
| sal_Int32 nDimensionIndex=0; |
| switch( eDimension ) |
| { |
| case XML_X: |
| nDimensionIndex=0; |
| break; |
| case XML_Y: |
| nDimensionIndex=1; |
| break; |
| case XML_Z: |
| nDimensionIndex=2; |
| break; |
| default: |
| break; |
| } |
| |
| xNewAxis = xCooSys->getAxisByDimension( nDimensionIndex, bPrimary ? 0 : 1 ); |
| } |
| } |
| catch( const uno::Exception & ) |
| { |
| } |
| return xNewAxis; |
| } |
| |
| } |
| |
| void SchXMLExportHelper_Impl::exportPlotArea( |
| Reference< chart::XDiagram > xDiagram, |
| Reference< chart2::XDiagram > xNewDiagram, |
| const awt::Size & rPageSize, |
| sal_Bool bExportContent, |
| sal_Bool bIncludeTable ) |
| { |
| DBG_ASSERT( xDiagram.is(), "Invalid XDiagram as parameter" ); |
| if( ! xDiagram.is()) |
| return; |
| |
| // variables for autostyles |
| Reference< beans::XPropertySet > xPropSet; |
| std::vector< XMLPropertyState > aPropertyStates; |
| |
| sal_Bool bIs3DChart = sal_False; |
| drawing::HomogenMatrix aTransMatrix; |
| |
| msStringBuffer.setLength( 0 ); |
| |
| // plot-area element |
| // ----------------- |
| |
| SvXMLElementExport* pElPlotArea = 0; |
| // get property states for autostyles |
| xPropSet = Reference< beans::XPropertySet >( xDiagram, uno::UNO_QUERY ); |
| if( xPropSet.is()) |
| { |
| if( mxExpPropMapper.is()) |
| aPropertyStates = mxExpPropMapper->Filter( xPropSet ); |
| } |
| if( bExportContent ) |
| { |
| UniReference< XMLShapeExport > rShapeExport; |
| |
| // write style name |
| AddAutoStyleAttribute( aPropertyStates ); |
| |
| if( msChartAddress.getLength() ) |
| { |
| if( !bIncludeTable ) |
| mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, msChartAddress ); |
| |
| Reference< chart::XChartDocument > xDoc( mrExport.GetModel(), uno::UNO_QUERY ); |
| if( xDoc.is() ) |
| { |
| Reference< beans::XPropertySet > xDocProp( xDoc, uno::UNO_QUERY ); |
| if( xDocProp.is()) |
| { |
| Any aAny; |
| sal_Bool bFirstCol = false, bFirstRow = false; |
| |
| try |
| { |
| aAny = xDocProp->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "DataSourceLabelsInFirstColumn" ))); |
| aAny >>= bFirstCol; |
| aAny = xDocProp->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "DataSourceLabelsInFirstRow" ))); |
| aAny >>= bFirstRow; |
| |
| if( bFirstCol || bFirstRow ) |
| { |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, |
| ::xmloff::token::GetXMLToken( ::xmloff::token::XML_DATA_SOURCE_HAS_LABELS ), |
| ( bFirstCol |
| ? ( bFirstRow |
| ? ::xmloff::token::GetXMLToken( ::xmloff::token::XML_BOTH ) |
| : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_COLUMN )) |
| : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_ROW ))); |
| } |
| } |
| catch( beans::UnknownPropertyException & ) |
| { |
| DBG_ERRORFILE( "Properties missing" ); |
| } |
| } |
| } |
| } |
| |
| // #i72973#, #144135# only export table-number-list in OOo format (also for binary) |
| Reference< beans::XPropertySet > xExportInfo( mrExport.getExportInfo()); |
| if( msTableNumberList.getLength() && |
| xExportInfo.is()) |
| { |
| try |
| { |
| OUString sExportTableNumListPropName( RTL_CONSTASCII_USTRINGPARAM("ExportTableNumberList")); |
| Reference< beans::XPropertySetInfo > xInfo( xExportInfo->getPropertySetInfo()); |
| bool bExportTableNumberList = false; |
| if( xInfo.is() && xInfo->hasPropertyByName( sExportTableNumListPropName ) && |
| (xExportInfo->getPropertyValue( sExportTableNumListPropName ) >>= bExportTableNumberList) && |
| bExportTableNumberList ) |
| { |
| // this attribute is for charts embedded in calc documents only. |
| // With this you are able to store a file again in 5.0 binary format |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_TABLE_NUMBER_LIST, msTableNumberList ); |
| } |
| } |
| catch( uno::Exception & rEx ) |
| { |
| #ifdef DBG_UTIL |
| String aStr( rEx.Message ); |
| ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US ); |
| DBG_ERROR1( "chart:TableNumberList property caught: %s", aBStr.GetBuffer()); |
| #else |
| (void)rEx; // avoid warning |
| #endif |
| } |
| } |
| |
| // attributes |
| Reference< drawing::XShape > xShape ( xDiagram, uno::UNO_QUERY ); |
| if( xShape.is()) |
| { |
| addPosition( xShape ); |
| addSize( xShape ); |
| } |
| |
| if( xPropSet.is()) |
| { |
| Any aAny; |
| |
| // 3d attributes |
| try |
| { |
| aAny = xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Dim3D" ))); |
| aAny >>= bIs3DChart; |
| |
| if( bIs3DChart ) |
| { |
| rShapeExport = mrExport.GetShapeExport(); |
| if( rShapeExport.is()) |
| rShapeExport->export3DSceneAttributes( xPropSet ); |
| } |
| } |
| catch( uno::Exception & rEx ) |
| { |
| #ifdef DBG_UTIL |
| String aStr( rEx.Message ); |
| ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US ); |
| DBG_ERROR1( "chart:exportPlotAreaException caught: %s", aBStr.GetBuffer()); |
| #else |
| (void)rEx; // avoid warning |
| #endif |
| } |
| } |
| |
| // plot-area element |
| pElPlotArea = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_PLOT_AREA, sal_True, sal_True ); |
| |
| //inner position rectangle element |
| exportCoordinateRegion( xDiagram ); |
| |
| // light sources (inside plot area element) |
| if( bIs3DChart && |
| rShapeExport.is()) |
| rShapeExport->export3DLamps( xPropSet ); |
| } |
| else // autostyles |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| // remove property states for autostyles |
| aPropertyStates.clear(); |
| |
| // axis elements |
| // ------------- |
| exportAxes( xDiagram, xNewDiagram, bExportContent ); |
| |
| // series elements |
| // --------------- |
| Reference< chart2::XAxis > xSecondYAxis = lcl_getAxis( lcl_getCooSys( xNewDiagram ), XML_Y, false ); |
| exportSeries( xNewDiagram, rPageSize, bExportContent, xSecondYAxis.is() ); |
| |
| // stock-chart elements |
| OUString sChartType ( xDiagram->getDiagramType()); |
| if( 0 == sChartType.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart.StockDiagram" ))) |
| { |
| Reference< chart::XStatisticDisplay > xStockPropProvider( xDiagram, uno::UNO_QUERY ); |
| if( xStockPropProvider.is()) |
| { |
| // stock-gain-marker |
| Reference< beans::XPropertySet > xStockPropSet = xStockPropProvider->getUpBar(); |
| if( xStockPropSet.is()) |
| { |
| aPropertyStates.clear(); |
| aPropertyStates = mxExpPropMapper->Filter( xStockPropSet ); |
| |
| if( !aPropertyStates.empty() ) |
| { |
| if( bExportContent ) |
| { |
| AddAutoStyleAttribute( aPropertyStates ); |
| |
| SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_GAIN_MARKER, sal_True, sal_True ); |
| } |
| else |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| } |
| } |
| |
| // stock-loss-marker |
| xStockPropSet = xStockPropProvider->getDownBar(); |
| if( xStockPropSet.is()) |
| { |
| aPropertyStates.clear(); |
| aPropertyStates = mxExpPropMapper->Filter( xStockPropSet ); |
| |
| if( !aPropertyStates.empty() ) |
| { |
| if( bExportContent ) |
| { |
| AddAutoStyleAttribute( aPropertyStates ); |
| |
| SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_LOSS_MARKER, sal_True, sal_True ); |
| } |
| else |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| } |
| } |
| |
| // stock-range-line |
| xStockPropSet = xStockPropProvider->getMinMaxLine(); |
| if( xStockPropSet.is()) |
| { |
| aPropertyStates.clear(); |
| aPropertyStates = mxExpPropMapper->Filter( xStockPropSet ); |
| |
| if( !aPropertyStates.empty() ) |
| { |
| if( bExportContent ) |
| { |
| AddAutoStyleAttribute( aPropertyStates ); |
| |
| SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_RANGE_LINE, sal_True, sal_True ); |
| } |
| else |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| } |
| } |
| } |
| } |
| |
| // wall and floor element |
| // ---------------------- |
| |
| Reference< chart::X3DDisplay > xWallFloorSupplier( xDiagram, uno::UNO_QUERY ); |
| if( mxExpPropMapper.is() && |
| xWallFloorSupplier.is()) |
| { |
| // remove property states for autostyles |
| aPropertyStates.clear(); |
| |
| Reference< beans::XPropertySet > xWallPropSet( xWallFloorSupplier->getWall(), uno::UNO_QUERY ); |
| if( xWallPropSet.is()) |
| { |
| aPropertyStates = mxExpPropMapper->Filter( xWallPropSet ); |
| |
| if( !aPropertyStates.empty() ) |
| { |
| // write element |
| if( bExportContent ) |
| { |
| // add style name attribute |
| AddAutoStyleAttribute( aPropertyStates ); |
| |
| SvXMLElementExport aWall( mrExport, XML_NAMESPACE_CHART, XML_WALL, sal_True, sal_True ); |
| } |
| else // autostyles |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| } |
| } |
| |
| // floor element |
| // ------------- |
| |
| // remove property states for autostyles |
| aPropertyStates.clear(); |
| |
| Reference< beans::XPropertySet > xFloorPropSet( xWallFloorSupplier->getFloor(), uno::UNO_QUERY ); |
| if( xFloorPropSet.is()) |
| { |
| aPropertyStates = mxExpPropMapper->Filter( xFloorPropSet ); |
| |
| if( !aPropertyStates.empty() ) |
| { |
| // write element |
| if( bExportContent ) |
| { |
| // add style name attribute |
| AddAutoStyleAttribute( aPropertyStates ); |
| |
| SvXMLElementExport aFloor( mrExport, XML_NAMESPACE_CHART, XML_FLOOR, sal_True, sal_True ); |
| } |
| else // autostyles |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| } |
| } |
| } |
| |
| if( pElPlotArea ) |
| delete pElPlotArea; |
| } |
| |
| void SchXMLExportHelper_Impl::exportCoordinateRegion( const uno::Reference< chart::XDiagram >& xDiagram ) |
| { |
| const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() ); |
| if( nCurrentODFVersion <= SvtSaveOptions::ODFVER_012 )//do not export to ODF 1.2 or older |
| return; |
| if( nCurrentODFVersion != SvtSaveOptions::ODFVER_LATEST )//export only if extensions are enabled //#i100778# todo: change this dependent on fileformat evolution |
| return; |
| |
| Reference< chart::XDiagramPositioning > xDiaPos( xDiagram, uno::UNO_QUERY ); |
| DBG_ASSERT( xDiaPos.is(), "Invalid xDiaPos as parameter" ); |
| if( !xDiaPos.is() ) |
| return; |
| |
| awt::Rectangle aRect( xDiaPos->calculateDiagramPositionExcludingAxes() ); |
| addPosition( awt::Point(aRect.X,aRect.Y) ); |
| addSize( awt::Size(aRect.Width,aRect.Height) ); |
| |
| SvXMLElementExport aCoordinateRegion( mrExport, XML_NAMESPACE_CHART_EXT, XML_COORDINATE_REGION, sal_True, sal_True );//#i100778# todo: change to chart namespace in future - dependent on fileformat |
| } |
| |
| namespace |
| { |
| XMLTokenEnum lcl_getTimeUnitToken( sal_Int32 nTimeUnit ) |
| { |
| XMLTokenEnum eToken = XML_DAYS; |
| switch( nTimeUnit ) |
| { |
| case ::com::sun::star::chart::TimeUnit::YEAR: |
| eToken = XML_YEARS; |
| break; |
| case ::com::sun::star::chart::TimeUnit::MONTH: |
| eToken = XML_MONTHS; |
| break; |
| default://days |
| break; |
| } |
| return eToken; |
| } |
| } |
| |
| void SchXMLExportHelper_Impl::exportDateScale( const Reference< beans::XPropertySet > xAxisProps ) |
| { |
| if( !xAxisProps.is() ) |
| return; |
| |
| chart::TimeIncrement aIncrement; |
| if( (xAxisProps->getPropertyValue( OUString::createFromAscii( "TimeIncrement" )) >>= aIncrement) ) |
| { |
| sal_Int32 nTimeResolution = ::com::sun::star::chart::TimeUnit::DAY; |
| if( aIncrement.TimeResolution >>= nTimeResolution ) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_BASE_TIME_UNIT, lcl_getTimeUnitToken( nTimeResolution ) ); |
| |
| OUStringBuffer aValue; |
| chart::TimeInterval aInterval; |
| if( aIncrement.MajorTimeInterval >>= aInterval ) |
| { |
| SvXMLUnitConverter::convertNumber( aValue, aInterval.Number ); |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_VALUE, aValue.makeStringAndClear() ); |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) ); |
| } |
| if( aIncrement.MinorTimeInterval >>= aInterval ) |
| { |
| SvXMLUnitConverter::convertNumber( aValue, aInterval.Number ); |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_VALUE, aValue.makeStringAndClear() ); |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) ); |
| } |
| |
| SvXMLElementExport aDateScale( mrExport, XML_NAMESPACE_CHART_EXT, XML_DATE_SCALE, sal_True, sal_True );//#i25706#todo: change namespace for next ODF version |
| } |
| } |
| |
| void SchXMLExportHelper_Impl::exportAxisTitle( const Reference< beans::XPropertySet > xTitleProps, bool bExportContent ) |
| { |
| if( !xTitleProps.is() ) |
| return; |
| std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xTitleProps ); |
| if( bExportContent ) |
| { |
| OUString aText; |
| Any aAny( xTitleProps->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "String" )))); |
| aAny >>= aText; |
| |
| Reference< drawing::XShape > xShape( xTitleProps, uno::UNO_QUERY ); |
| if( xShape.is()) |
| addPosition( xShape ); |
| |
| AddAutoStyleAttribute( aPropertyStates ); |
| SvXMLElementExport aTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, sal_True, sal_True ); |
| |
| // paragraph containing title |
| exportText( aText ); |
| } |
| else |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| aPropertyStates.clear(); |
| } |
| |
| void SchXMLExportHelper_Impl::exportGrid( const Reference< beans::XPropertySet > xGridProperties, bool bMajor, bool bExportContent ) |
| { |
| if( !xGridProperties.is() ) |
| return; |
| std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xGridProperties ); |
| if( bExportContent ) |
| { |
| AddAutoStyleAttribute( aPropertyStates ); |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS, bMajor ? XML_MAJOR : XML_MINOR ); |
| SvXMLElementExport aGrid( mrExport, XML_NAMESPACE_CHART, XML_GRID, sal_True, sal_True ); |
| } |
| else |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| aPropertyStates.clear(); |
| } |
| |
| namespace |
| { |
| |
| //returns true if a date scale needs to be exported |
| bool lcl_exportAxisType( const Reference< chart2::XAxis > xChart2Axis, SvXMLExport& rExport) |
| { |
| bool bExportDateScale = false; |
| if( !xChart2Axis.is() ) |
| return bExportDateScale; |
| |
| const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() ); |
| if( nCurrentODFVersion != SvtSaveOptions::ODFVER_LATEST ) //#i25706#todo: change version for next ODF version |
| return bExportDateScale; |
| |
| chart2::ScaleData aScale( xChart2Axis->getScaleData() ); |
| //#i25706#todo: change namespace for next ODF version |
| sal_uInt16 nNameSpace = XML_NAMESPACE_CHART_EXT; |
| |
| switch(aScale.AxisType) |
| { |
| case chart2::AxisType::CATEGORY: |
| if( aScale.AutoDateAxis ) |
| { |
| rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO ); |
| bExportDateScale = true; |
| } |
| else |
| rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_TEXT ); |
| break; |
| case chart2::AxisType::DATE: |
| rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_DATE ); |
| bExportDateScale = true; |
| break; |
| default: //AUTOMATIC |
| rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO ); |
| break; |
| } |
| |
| return bExportDateScale; |
| } |
| |
| } |
| |
| void SchXMLExportHelper_Impl::exportAxis( |
| enum XMLTokenEnum eDimension, |
| enum XMLTokenEnum eAxisName, |
| const Reference< beans::XPropertySet > xAxisProps, |
| const Reference< chart2::XAxis >& xChart2Axis, |
| const OUString& rCategoriesRange, |
| bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid, |
| bool bExportContent ) |
| { |
| static const OUString sNumFormat( OUString::createFromAscii( "NumberFormat" )); |
| std::vector< XMLPropertyState > aPropertyStates; |
| SvXMLElementExport* pAxis = NULL; |
| |
| // get property states for autostyles |
| if( xAxisProps.is() && mxExpPropMapper.is() ) |
| { |
| lcl_exportNumberFormat( sNumFormat, xAxisProps, mrExport ); |
| aPropertyStates = mxExpPropMapper->Filter( xAxisProps ); |
| } |
| |
| bool bExportDateScale = false; |
| if( bExportContent ) |
| { |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, eDimension ); |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_NAME, eAxisName ); |
| AddAutoStyleAttribute( aPropertyStates ); // write style name |
| if( rCategoriesRange.getLength() ) |
| bExportDateScale = lcl_exportAxisType( xChart2Axis, mrExport ); |
| |
| // open axis element |
| pAxis = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_AXIS, sal_True, sal_True ); |
| } |
| else |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| aPropertyStates.clear(); |
| |
| //date scale |
| if( bExportDateScale ) |
| exportDateScale( xAxisProps ); |
| |
| Reference< beans::XPropertySet > xTitleProps; |
| Reference< beans::XPropertySet > xMajorGridProps; |
| Reference< beans::XPropertySet > xMinorGridProps; |
| Reference< chart::XAxis > xAxis( xAxisProps, uno::UNO_QUERY ); |
| if( xAxis.is() ) |
| { |
| xTitleProps = bHasTitle ? xAxis->getAxisTitle() : 0; |
| xMajorGridProps = bHasMajorGrid ? xAxis->getMajorGrid() : 0; |
| xMinorGridProps = bHasMinorGrid ? xAxis->getMinorGrid() : 0; |
| } |
| |
| // axis-title |
| exportAxisTitle( xTitleProps , bExportContent ); |
| |
| // categories if we have a categories chart |
| if( bExportContent && rCategoriesRange.getLength() ) |
| { |
| mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, rCategoriesRange ); |
| SvXMLElementExport aCategories( mrExport, XML_NAMESPACE_CHART, XML_CATEGORIES, sal_True, sal_True ); |
| } |
| |
| // grid |
| exportGrid( xMajorGridProps, true, bExportContent ); |
| exportGrid( xMinorGridProps, false, bExportContent ); |
| |
| if( pAxis ) |
| { |
| //close axis element |
| delete pAxis; |
| pAxis = NULL; |
| } |
| } |
| |
| void SchXMLExportHelper_Impl::exportAxes( |
| const Reference< chart::XDiagram > & xDiagram, |
| const Reference< chart2::XDiagram > & xNewDiagram, |
| sal_Bool bExportContent ) |
| { |
| DBG_ASSERT( xDiagram.is(), "Invalid XDiagram as parameter" ); |
| if( ! xDiagram.is()) |
| return; |
| |
| // get some properties from document first |
| sal_Bool bHasXAxis = sal_False, |
| bHasYAxis = sal_False, |
| bHasZAxis = sal_False, |
| bHasSecondaryXAxis = sal_False, |
| bHasSecondaryYAxis = sal_False; |
| sal_Bool bHasXAxisTitle = sal_False, |
| bHasYAxisTitle = sal_False, |
| bHasZAxisTitle = sal_False, |
| bHasSecondaryXAxisTitle = sal_False, |
| bHasSecondaryYAxisTitle = sal_False; |
| sal_Bool bHasXAxisMajorGrid = sal_False, |
| bHasXAxisMinorGrid = sal_False, |
| bHasYAxisMajorGrid = sal_False, |
| bHasYAxisMinorGrid = sal_False, |
| bHasZAxisMajorGrid = sal_False, |
| bHasZAxisMinorGrid = sal_False; |
| |
| // get multiple properties using XMultiPropertySet |
| MultiPropertySetHandler aDiagramProperties (xDiagram); |
| |
| aDiagramProperties.Add ( |
| OUString(RTL_CONSTASCII_USTRINGPARAM("HasXAxis")), bHasXAxis); |
| aDiagramProperties.Add ( |
| OUString(RTL_CONSTASCII_USTRINGPARAM("HasYAxis")), bHasYAxis); |
| aDiagramProperties.Add ( |
| OUString(RTL_CONSTASCII_USTRINGPARAM("HasZAxis")), bHasZAxis); |
| aDiagramProperties.Add ( |
| OUString(RTL_CONSTASCII_USTRINGPARAM("HasSecondaryXAxis")), bHasSecondaryXAxis); |
| aDiagramProperties.Add ( |
| OUString(RTL_CONSTASCII_USTRINGPARAM("HasSecondaryYAxis")), bHasSecondaryYAxis); |
| |
| aDiagramProperties.Add ( |
| OUString (RTL_CONSTASCII_USTRINGPARAM ("HasXAxisTitle")), bHasXAxisTitle); |
| aDiagramProperties.Add ( |
| OUString (RTL_CONSTASCII_USTRINGPARAM ("HasYAxisTitle")), bHasYAxisTitle); |
| aDiagramProperties.Add ( |
| OUString (RTL_CONSTASCII_USTRINGPARAM ("HasZAxisTitle")), bHasZAxisTitle); |
| aDiagramProperties.Add ( |
| OUString (RTL_CONSTASCII_USTRINGPARAM ("HasSecondaryXAxisTitle")), bHasSecondaryXAxisTitle); |
| aDiagramProperties.Add ( |
| OUString (RTL_CONSTASCII_USTRINGPARAM ("HasSecondaryYAxisTitle")), bHasSecondaryYAxisTitle); |
| |
| aDiagramProperties.Add ( |
| OUString (RTL_CONSTASCII_USTRINGPARAM ("HasXAxisGrid")), bHasXAxisMajorGrid); |
| aDiagramProperties.Add ( |
| OUString (RTL_CONSTASCII_USTRINGPARAM ("HasYAxisGrid")), bHasYAxisMajorGrid); |
| aDiagramProperties.Add ( |
| OUString (RTL_CONSTASCII_USTRINGPARAM ("HasZAxisGrid")), bHasZAxisMajorGrid); |
| |
| aDiagramProperties.Add ( |
| OUString (RTL_CONSTASCII_USTRINGPARAM ("HasXAxisHelpGrid")), bHasXAxisMinorGrid); |
| aDiagramProperties.Add ( |
| OUString (RTL_CONSTASCII_USTRINGPARAM ("HasYAxisHelpGrid")), bHasYAxisMinorGrid); |
| aDiagramProperties.Add ( |
| OUString (RTL_CONSTASCII_USTRINGPARAM ("HasZAxisHelpGrid")), bHasZAxisMinorGrid); |
| |
| if ( ! aDiagramProperties.GetProperties ()) |
| { |
| DBG_WARNING ("Required properties not found in Chart diagram"); |
| } |
| |
| Reference< chart2::XCoordinateSystem > xCooSys( lcl_getCooSys(xNewDiagram) ); |
| |
| // write an axis element also if the axis itself is not visible, but a grid or a title |
| |
| OUString aCategoriesRange; |
| Reference< chart::XAxisSupplier > xAxisSupp( xDiagram, uno::UNO_QUERY ); |
| |
| // x axis |
| // ------- |
| Reference< ::com::sun::star::chart2::XAxis > xNewAxis = lcl_getAxis( xCooSys, XML_X ); |
| if( xNewAxis.is() ) |
| { |
| Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(0) : 0, uno::UNO_QUERY ); |
| if( mbHasCategoryLabels && bExportContent ) |
| { |
| Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) ); |
| if( xCategories.is() ) |
| { |
| Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() ); |
| if( xValues.is() ) |
| { |
| Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY ); |
| maCategoriesRange = xValues->getSourceRangeRepresentation(); |
| aCategoriesRange = lcl_ConvertRange( maCategoriesRange, xNewDoc ); |
| } |
| } |
| } |
| exportAxis( XML_X, XML_PRIMARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasXAxisTitle, bHasXAxisMajorGrid, bHasXAxisMinorGrid, bExportContent ); |
| aCategoriesRange = OUString(); |
| } |
| |
| // secondary x axis |
| // ------- |
| Reference< chart::XSecondAxisTitleSupplier > xSecondTitleSupp( xDiagram, uno::UNO_QUERY ); |
| xNewAxis = lcl_getAxis( xCooSys, XML_X, false ); |
| if( xNewAxis.is() ) |
| { |
| Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(0) : 0, uno::UNO_QUERY ); |
| exportAxis( XML_X, XML_SECONDARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryXAxisTitle, false, false, bExportContent ); |
| } |
| |
| // y axis |
| // ------- |
| xNewAxis = lcl_getAxis( xCooSys, XML_Y ); |
| if( xNewAxis.is() ) |
| { |
| Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(1) : 0, uno::UNO_QUERY ); |
| exportAxis( XML_Y, XML_PRIMARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasYAxisTitle, bHasYAxisMajorGrid, bHasYAxisMinorGrid, bExportContent ); |
| } |
| |
| // secondary y axis |
| // ------- |
| xNewAxis = lcl_getAxis( xCooSys, XML_Y, false ); |
| if( xNewAxis.is() ) |
| { |
| Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(1) : 0, uno::UNO_QUERY ); |
| exportAxis( XML_Y, XML_SECONDARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryYAxisTitle, false, false, bExportContent ); |
| } |
| |
| // z axis |
| // ------- |
| xNewAxis = lcl_getAxis( xCooSys, XML_Z ); |
| if( xNewAxis.is() ) |
| { |
| Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(2) : 0, uno::UNO_QUERY ); |
| exportAxis( XML_Z, XML_PRIMARY_Z, xAxisProps, xNewAxis, aCategoriesRange, bHasZAxisTitle, bHasZAxisMajorGrid, bHasZAxisMinorGrid, bExportContent ); |
| } |
| } |
| |
| namespace |
| { |
| bool lcl_hasNoValuesButText( const uno::Reference< chart2::data::XDataSequence >& xDataSequence ) |
| { |
| if( !xDataSequence.is() ) |
| return false;//have no data |
| |
| Sequence< uno::Any > aData; |
| Reference< chart2::data::XNumericalDataSequence > xNumericalDataSequence( xDataSequence, uno::UNO_QUERY ); |
| if( xNumericalDataSequence.is() ) |
| { |
| Sequence< double > aDoubles( xNumericalDataSequence->getNumericalData() ); |
| sal_Int32 nCount = aDoubles.getLength(); |
| for( sal_Int32 i = 0; i < nCount; ++i ) |
| { |
| if( !::rtl::math::isNan( aDoubles[i] ) ) |
| return false;//have double value |
| } |
| } |
| else |
| { |
| aData = xDataSequence->getData(); |
| double fDouble = 0.0; |
| sal_Int32 nCount = aData.getLength(); |
| for( sal_Int32 i = 0; i < nCount; ++i ) |
| { |
| if( (aData[i] >>= fDouble) && !::rtl::math::isNan( fDouble ) ) |
| return false;//have double value |
| } |
| |
| } |
| //no values found |
| |
| Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY ); |
| if( xTextualDataSequence.is() ) |
| { |
| uno::Sequence< rtl::OUString > aStrings( xTextualDataSequence->getTextualData() ); |
| sal_Int32 nCount = aStrings.getLength(); |
| for( sal_Int32 i = 0; i < nCount; ++i ) |
| { |
| if( aStrings[i].getLength() ) |
| return true;//have text |
| } |
| } |
| else |
| { |
| if( !aData.getLength() ) |
| aData = xDataSequence->getData(); |
| uno::Any aAny; |
| OUString aString; |
| sal_Int32 nCount = aData.getLength(); |
| for( sal_Int32 i = 0; i < nCount; ++i ) |
| { |
| if( (aData[i]>>=aString) && aString.getLength() ) |
| return true;//have text |
| } |
| } |
| //no doubles and no texts |
| return false; |
| } |
| } |
| |
| void SchXMLExportHelper_Impl::exportSeries( |
| const Reference< chart2::XDiagram > & xNewDiagram, |
| const awt::Size & rPageSize, |
| sal_Bool bExportContent, |
| sal_Bool bHasTwoYAxes ) |
| { |
| Reference< chart2::XCoordinateSystemContainer > xBCooSysCnt( xNewDiagram, uno::UNO_QUERY ); |
| if( ! xBCooSysCnt.is()) |
| return; |
| Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY ); |
| |
| OUString aFirstXDomainRange; |
| OUString aFirstYDomainRange; |
| |
| std::vector< XMLPropertyState > aPropertyStates; |
| |
| const OUString sNumFormat( OUString::createFromAscii( "NumberFormat" )); |
| const OUString sPercentageNumFormat( OUString::createFromAscii( "PercentageNumberFormat" )); |
| |
| Sequence< Reference< chart2::XCoordinateSystem > > |
| aCooSysSeq( xBCooSysCnt->getCoordinateSystems()); |
| for( sal_Int32 nCSIdx=0; nCSIdx<aCooSysSeq.getLength(); ++nCSIdx ) |
| { |
| Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCSIdx], uno::UNO_QUERY ); |
| if( ! xCTCnt.is()) |
| continue; |
| Sequence< Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes()); |
| for( sal_Int32 nCTIdx=0; nCTIdx<aCTSeq.getLength(); ++nCTIdx ) |
| { |
| Reference< chart2::XDataSeriesContainer > xDSCnt( aCTSeq[nCTIdx], uno::UNO_QUERY ); |
| if( ! xDSCnt.is()) |
| continue; |
| // note: if xDSCnt.is() then also aCTSeq[nCTIdx] |
| OUString aChartType( aCTSeq[nCTIdx]->getChartType()); |
| OUString aLabelRole = aCTSeq[nCTIdx]->getRoleOfSequenceForSeriesLabel(); |
| |
| // special export for stock charts |
| if( aChartType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.CandleStickChartType"))) |
| { |
| sal_Bool bJapaneseCandleSticks = sal_False; |
| Reference< beans::XPropertySet > xCTProp( aCTSeq[nCTIdx], uno::UNO_QUERY ); |
| if( xCTProp.is()) |
| xCTProp->getPropertyValue( OUString::createFromAscii("Japanese")) >>= bJapaneseCandleSticks; |
| exportCandleStickSeries( |
| xDSCnt->getDataSeries(), xNewDiagram, bJapaneseCandleSticks, bExportContent ); |
| continue; |
| } |
| |
| // export dataseries for current chart-type |
| Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries()); |
| for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx ) |
| { |
| // export series |
| Reference< chart2::data::XDataSource > xSource( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY ); |
| if( xSource.is()) |
| { |
| SvXMLElementExport* pSeries = NULL; |
| Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt( |
| xSource->getDataSequences()); |
| sal_Int32 nMainSequenceIndex = -1; |
| sal_Int32 nSeriesLength = 0; |
| sal_Int32 nAttachedAxis = chart::ChartAxisAssign::PRIMARY_Y; |
| sal_Bool bHasMeanValueLine = false; |
| chart::ChartRegressionCurveType eRegressionType( chart::ChartRegressionCurveType_NONE ); |
| chart::ChartErrorIndicatorType eErrorType( chart::ChartErrorIndicatorType_NONE ); |
| sal_Int32 nErrorBarStyle( chart::ErrorBarStyle::NONE ); |
| Reference< beans::XPropertySet > xPropSet; |
| tLabelValuesDataPair aSeriesLabelValuesPair; |
| |
| // search for main sequence and create a series element |
| { |
| Reference< chart2::data::XDataSequence > xValuesSeq; |
| Reference< chart2::data::XDataSequence > xLabelSeq; |
| sal_Int32 nSeqIdx=0; |
| for( ; nSeqIdx<aSeqCnt.getLength(); ++nSeqIdx ) |
| { |
| OUString aRole; |
| Reference< chart2::data::XDataSequence > xTempValueSeq( aSeqCnt[nSeqIdx]->getValues() ); |
| if( nMainSequenceIndex==-1 ) |
| { |
| Reference< beans::XPropertySet > xSeqProp( xTempValueSeq, uno::UNO_QUERY ); |
| if( xSeqProp.is()) |
| xSeqProp->getPropertyValue(OUString::createFromAscii("Role")) >>= aRole; |
| // "main" sequence |
| if( aRole.equals( aLabelRole )) |
| { |
| xValuesSeq.set( xTempValueSeq ); |
| xLabelSeq.set( aSeqCnt[nSeqIdx]->getLabel()); |
| nMainSequenceIndex = nSeqIdx; |
| } |
| } |
| sal_Int32 nSequenceLength = (xTempValueSeq.is()? xTempValueSeq->getData().getLength() : sal_Int32(0)); |
| if( nSeriesLength < nSequenceLength ) |
| nSeriesLength = nSequenceLength; |
| } |
| |
| // have found the main sequence, then xValuesSeq and |
| // xLabelSeq contain those. Otherwise both are empty |
| { |
| // get property states for autostyles |
| try |
| { |
| xPropSet = SchXMLSeriesHelper::createOldAPISeriesPropertySet( |
| aSeriesSeq[nSeriesIdx], mrExport.GetModel() ); |
| } |
| catch( uno::Exception & rEx ) |
| { |
| (void)rEx; // avoid warning for pro build |
| OSL_TRACE( |
| OUStringToOString( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( |
| "Series not found or no XPropertySet: " )) + |
| rEx.Message, |
| RTL_TEXTENCODING_ASCII_US ).getStr()); |
| continue; |
| } |
| if( xPropSet.is()) |
| { |
| // determine attached axis |
| try |
| { |
| Any aAny( xPropSet->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "Axis" )))); |
| aAny >>= nAttachedAxis; |
| |
| aAny = xPropSet->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM ( "MeanValue" ))); |
| aAny >>= bHasMeanValueLine; |
| |
| aAny = xPropSet->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "RegressionCurves" ))); |
| aAny >>= eRegressionType; |
| |
| aAny = xPropSet->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "ErrorIndicator" ))); |
| aAny >>= eErrorType; |
| |
| aAny = xPropSet->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "ErrorBarStyle" ))); |
| aAny >>= nErrorBarStyle; |
| } |
| catch( beans::UnknownPropertyException & rEx ) |
| { |
| (void)rEx; // avoid warning for pro build |
| OSL_TRACE( |
| OUStringToOString( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( |
| "Required property not found in DataRowProperties: " )) + |
| rEx.Message, |
| RTL_TEXTENCODING_ASCII_US ).getStr()); |
| } |
| |
| const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() ); |
| if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 ) |
| { |
| lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport ); |
| lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport ); |
| } |
| |
| if( mxExpPropMapper.is()) |
| aPropertyStates = mxExpPropMapper->Filter( xPropSet ); |
| } |
| |
| if( bExportContent ) |
| { |
| if( bHasTwoYAxes ) |
| { |
| if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y ) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y ); |
| else |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y ); |
| } |
| |
| // write style name |
| AddAutoStyleAttribute( aPropertyStates ); |
| |
| if( xValuesSeq.is()) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, |
| lcl_ConvertRange( |
| xValuesSeq->getSourceRangeRepresentation(), |
| xNewDoc )); |
| else |
| // #i75297# allow empty series, export empty range to have all ranges on import |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, OUString()); |
| |
| if( xLabelSeq.is()) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, |
| lcl_ConvertRange( |
| xLabelSeq->getSourceRangeRepresentation(), |
| xNewDoc )); |
| if( xLabelSeq.is() || xValuesSeq.is() ) |
| aSeriesLabelValuesPair = tLabelValuesDataPair( xLabelSeq, xValuesSeq ); |
| |
| // chart-type for mixed types |
| enum XMLTokenEnum eCTToken( |
| SchXMLTools::getTokenByChartType( aChartType, false /* bUseOldNames */ )); |
| //@todo: get token for current charttype |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS, |
| mrExport.GetNamespaceMap().GetQNameByKey( |
| XML_NAMESPACE_CHART, GetXMLToken( eCTToken ))); |
| |
| // open series element until end of for loop |
| pSeries = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True ); |
| } |
| else // autostyles |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| // remove property states for autostyles |
| aPropertyStates.clear(); |
| } |
| } |
| |
| // export domain elements if we have a series parent element |
| if( pSeries ) |
| { |
| // domain elements |
| if( bExportContent ) |
| { |
| bool bIsScatterChart = aChartType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.ScatterChartType")); |
| bool bIsBubbleChart = aChartType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.BubbleChartType")); |
| Reference< chart2::data::XDataSequence > xYValuesForBubbleChart; |
| if( bIsBubbleChart ) |
| { |
| Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString::createFromAscii("values-y" ) ) ); |
| if( xSequence.is() ) |
| { |
| xYValuesForBubbleChart = xSequence->getValues(); |
| if( !lcl_exportDomainForThisSequence( xYValuesForBubbleChart, aFirstYDomainRange, mrExport ) ) |
| xYValuesForBubbleChart = 0; |
| } |
| } |
| if( bIsScatterChart || bIsBubbleChart ) |
| { |
| Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString::createFromAscii("values-x" ) ) ); |
| if( xSequence.is() ) |
| { |
| Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() ); |
| if( lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport ) ) |
| m_aDataSequencesToExport.push_back( tLabelValuesDataPair( 0, xValues )); |
| } |
| else if( nSeriesIdx==0 ) |
| { |
| //might be that the categories are used as x-values (e.g. for date axis) -> export them accordingly |
| Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) ); |
| if( xCategories.is() ) |
| { |
| Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() ); |
| if( !lcl_hasNoValuesButText( xValues ) ) |
| lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport ); |
| } |
| } |
| } |
| if( xYValuesForBubbleChart.is() ) |
| m_aDataSequencesToExport.push_back( tLabelValuesDataPair( 0, xYValuesForBubbleChart )); |
| } |
| } |
| |
| // add sequences for main sequence after domain sequences, |
| // so that the export of the local table has the correct order |
| if( bExportContent && |
| (aSeriesLabelValuesPair.first.is() || aSeriesLabelValuesPair.second.is())) |
| m_aDataSequencesToExport.push_back( aSeriesLabelValuesPair ); |
| |
| // statistical objects: |
| // regression curves and mean value lines |
| if( bHasMeanValueLine && |
| xPropSet.is() && |
| mxExpPropMapper.is() ) |
| { |
| Reference< beans::XPropertySet > xStatProp; |
| try |
| { |
| Any aPropAny( xPropSet->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "DataMeanValueProperties" )))); |
| aPropAny >>= xStatProp; |
| } |
| catch( uno::Exception & rEx ) |
| { |
| (void)rEx; // avoid warning for pro build |
| DBG_ERROR1( "Exception caught during Export of series - optional DataMeanValueProperties not available: %s", |
| OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); |
| } |
| |
| if( xStatProp.is() ) |
| { |
| aPropertyStates = mxExpPropMapper->Filter( xStatProp ); |
| |
| if( !aPropertyStates.empty() ) |
| { |
| // write element |
| if( bExportContent ) |
| { |
| // add style name attribute |
| AddAutoStyleAttribute( aPropertyStates ); |
| |
| SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_MEAN_VALUE, sal_True, sal_True ); |
| } |
| else // autostyles |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| } |
| } |
| } |
| |
| if( eRegressionType != chart::ChartRegressionCurveType_NONE && |
| xPropSet.is() && |
| mxExpPropMapper.is() ) |
| { |
| exportRegressionCurve( aSeriesSeq[nSeriesIdx], xPropSet, rPageSize, bExportContent ); |
| } |
| |
| if( nErrorBarStyle != chart::ErrorBarStyle::NONE && |
| eErrorType != chart::ChartErrorIndicatorType_NONE && |
| xPropSet.is() && |
| mxExpPropMapper.is() ) |
| { |
| Reference< beans::XPropertySet > xStatProp; |
| try |
| { |
| Any aPropAny( xPropSet->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "DataErrorProperties" )))); |
| aPropAny >>= xStatProp; |
| } |
| catch( uno::Exception & rEx ) |
| { |
| (void)rEx; // avoid warning for pro build |
| DBG_ERROR1( "Exception caught during Export of series - optional DataErrorProperties not available: %s", |
| OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); |
| } |
| |
| if( xStatProp.is() ) |
| { |
| if( bExportContent && |
| nErrorBarStyle == chart::ErrorBarStyle::FROM_DATA ) |
| { |
| // register data ranges for error bars for export in local table |
| ::std::vector< Reference< chart2::data::XDataSequence > > aErrorBarSequences( |
| lcl_getErrorBarSequences( xStatProp )); |
| for( ::std::vector< Reference< chart2::data::XDataSequence > >::const_iterator aIt( |
| aErrorBarSequences.begin()); aIt != aErrorBarSequences.end(); ++aIt ) |
| { |
| m_aDataSequencesToExport.push_back( tLabelValuesDataPair( 0, *aIt )); |
| } |
| } |
| |
| aPropertyStates = mxExpPropMapper->Filter( xStatProp ); |
| |
| if( !aPropertyStates.empty() ) |
| { |
| // write element |
| if( bExportContent ) |
| { |
| // add style name attribute |
| AddAutoStyleAttribute( aPropertyStates ); |
| |
| const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() ); |
| if( nCurrentVersion >= SvtSaveOptions::ODFVER_012 ) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, XML_Y );//#i114149# |
| SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_ERROR_INDICATOR, sal_True, sal_True ); |
| } |
| else // autostyles |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| } |
| } |
| } |
| |
| exportDataPoints( |
| uno::Reference< beans::XPropertySet >( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY ), |
| nSeriesLength, xNewDiagram, bExportContent ); |
| |
| // close series element |
| if( pSeries ) |
| delete pSeries; |
| } |
| } |
| aPropertyStates.clear(); |
| } |
| } |
| } |
| |
| void SchXMLExportHelper_Impl::exportRegressionCurve( |
| const Reference< chart2::XDataSeries > & xSeries, |
| const Reference< beans::XPropertySet > & xSeriesProp, |
| const awt::Size & rPageSize, |
| sal_Bool bExportContent ) |
| { |
| OSL_ASSERT( mxExpPropMapper.is()); |
| |
| std::vector< XMLPropertyState > aPropertyStates; |
| std::vector< XMLPropertyState > aEquationPropertyStates; |
| Reference< beans::XPropertySet > xStatProp; |
| try |
| { |
| Any aPropAny( xSeriesProp->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "DataRegressionProperties" )))); |
| aPropAny >>= xStatProp; |
| } |
| catch( uno::Exception & rEx ) |
| { |
| (void)rEx; // avoid warning for pro build |
| DBG_ERROR1( "Exception caught during Export of series - optional DataRegressionProperties not available: %s", |
| OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); |
| } |
| |
| if( xStatProp.is() ) |
| { |
| Reference< chart2::XRegressionCurve > xRegCurve( SchXMLTools::getRegressionCurve( xSeries )); |
| Reference< beans::XPropertySet > xEquationProperties; |
| if( xRegCurve.is()) |
| xEquationProperties.set( xRegCurve->getEquationProperties()); |
| |
| bool bShowEquation = false; |
| bool bShowRSquared = false; |
| bool bExportEquation = false; |
| aPropertyStates = mxExpPropMapper->Filter( xStatProp ); |
| if( xEquationProperties.is()) |
| { |
| xEquationProperties->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ShowEquation" ))) |
| >>= bShowEquation; |
| xEquationProperties->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ShowCorrelationCoefficient" ))) |
| >>= bShowRSquared; |
| bExportEquation = ( bShowEquation || bShowRSquared ); |
| const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() ); |
| if( nCurrentVersion < SvtSaveOptions::ODFVER_012 ) |
| bExportEquation=false; |
| if( bExportEquation ) |
| { |
| // number format |
| sal_Int32 nNumberFormat = 0; |
| if( ( xEquationProperties->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "NumberFormat" ))) >>= nNumberFormat ) && |
| nNumberFormat != -1 ) |
| { |
| mrExport.addDataStyle( nNumberFormat ); |
| } |
| aEquationPropertyStates = mxExpPropMapper->Filter( xEquationProperties ); |
| } |
| } |
| |
| if( !aPropertyStates.empty() || bExportEquation ) |
| { |
| // write element |
| if( bExportContent ) |
| { |
| // add style name attribute |
| if( !aPropertyStates.empty()) |
| AddAutoStyleAttribute( aPropertyStates ); |
| SvXMLElementExport aRegressionExport( mrExport, XML_NAMESPACE_CHART, XML_REGRESSION_CURVE, sal_True, sal_True ); |
| if( bExportEquation ) |
| { |
| // default is true |
| if( !bShowEquation ) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_EQUATION, XML_FALSE ); |
| // default is false |
| if( bShowRSquared ) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_R_SQUARE, XML_TRUE ); |
| |
| // export position |
| chart2::RelativePosition aRelativePosition; |
| if( xEquationProperties->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("RelativePosition"))) >>= aRelativePosition ) |
| { |
| double fX = aRelativePosition.Primary * rPageSize.Width; |
| double fY = aRelativePosition.Secondary * rPageSize.Height; |
| awt::Point aPos; |
| aPos.X = static_cast< sal_Int32 >( ::rtl::math::round( fX )); |
| aPos.Y = static_cast< sal_Int32 >( ::rtl::math::round( fY )); |
| addPosition( aPos ); |
| } |
| |
| if( !aEquationPropertyStates.empty()) |
| AddAutoStyleAttribute( aEquationPropertyStates ); |
| |
| SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_EQUATION, sal_True, sal_True ); |
| } |
| } |
| else // autostyles |
| { |
| if( !aPropertyStates.empty()) |
| CollectAutoStyle( aPropertyStates ); |
| if( bExportEquation && !aEquationPropertyStates.empty()) |
| CollectAutoStyle( aEquationPropertyStates ); |
| } |
| } |
| } |
| } |
| |
| void SchXMLExportHelper_Impl::exportCandleStickSeries( |
| const Sequence< Reference< chart2::XDataSeries > > & aSeriesSeq, |
| const Reference< chart2::XDiagram > & xDiagram, |
| sal_Bool bJapaneseCandleSticks, |
| sal_Bool bExportContent ) |
| { |
| // std::vector< XMLPropertyState > aPropertyStates; |
| |
| for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx ) |
| { |
| Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nSeriesIdx] ); |
| sal_Int32 nAttachedAxis = lcl_isSeriesAttachedToFirstAxis( xSeries ) |
| ? chart::ChartAxisAssign::PRIMARY_Y |
| : chart::ChartAxisAssign::SECONDARY_Y; |
| |
| Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); |
| if( xSource.is()) |
| { |
| // export series in correct order (as we don't store roles) |
| // with japanese candlesticks: open, low, high, close |
| // otherwise: low, high, close |
| Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt( |
| xSource->getDataSequences()); |
| |
| sal_Int32 nSeriesLength = |
| lcl_getSequenceLengthByRole( aSeqCnt, OUString::createFromAscii("values-last")); |
| |
| if( bExportContent ) |
| { |
| Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY ); |
| //@todo: export data points |
| |
| // open |
| if( bJapaneseCandleSticks ) |
| { |
| tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole( |
| aSeqCnt, OUString::createFromAscii("values-first"), xNewDoc, m_aDataSequencesToExport )); |
| if( aRanges.second.getLength()) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second ); |
| if( aRanges.first.getLength()) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first ); |
| if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y ) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y ); |
| else |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y ); |
| SvXMLElementExport aOpenSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True ); |
| // export empty data points |
| exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent ); |
| } |
| |
| // low |
| { |
| tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole( |
| aSeqCnt, OUString::createFromAscii("values-min"), xNewDoc, m_aDataSequencesToExport )); |
| if( aRanges.second.getLength()) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second ); |
| if( aRanges.first.getLength()) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first ); |
| if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y ) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y ); |
| else |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y ); |
| SvXMLElementExport aLowSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True ); |
| // export empty data points |
| exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent ); |
| } |
| |
| // high |
| { |
| tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole( |
| aSeqCnt, OUString::createFromAscii("values-max"), xNewDoc, m_aDataSequencesToExport )); |
| if( aRanges.second.getLength()) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second ); |
| if( aRanges.first.getLength()) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first ); |
| if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y ) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y ); |
| else |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y ); |
| SvXMLElementExport aHighSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True ); |
| // export empty data points |
| exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent ); |
| } |
| |
| // close |
| { |
| tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole( |
| aSeqCnt, OUString::createFromAscii("values-last"), xNewDoc, m_aDataSequencesToExport )); |
| if( aRanges.second.getLength()) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second ); |
| if( aRanges.first.getLength()) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first ); |
| if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y ) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y ); |
| else |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y ); |
| // write style name |
| // AddAutoStyleAttribute( aPropertyStates ); |
| // chart type |
| // mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS, |
| // mrExport.GetNamespaceMap().GetQNameByKey( |
| // XML_NAMESPACE_CHART, GetXMLToken( XML_STOCK ))); |
| SvXMLElementExport aCloseSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True ); |
| // export empty data points |
| exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent ); |
| } |
| } |
| else // autostyles |
| { |
| // for close series |
| // CollectAutoStyle( aPropertyStates ); |
| } |
| // remove property states for autostyles |
| // aPropertyStates.clear(); |
| } |
| } |
| } |
| |
| void SchXMLExportHelper_Impl::exportDataPoints( |
| const uno::Reference< beans::XPropertySet > & xSeriesProperties, |
| sal_Int32 nSeriesLength, |
| const uno::Reference< chart2::XDiagram > & xDiagram, |
| sal_Bool bExportContent ) |
| { |
| // data-points |
| // ----------- |
| // write data-points only if they contain autostyles |
| // objects with equal autostyles are grouped using the attribute |
| // repeat="number" |
| |
| // Note: if only the nth data-point has autostyles there is an element |
| // without style and repeat="n-1" attribute written in advance. |
| |
| // the sequence aDataPointSeq contains indices of data-points that |
| // do have own attributes. This increases the performance substantially. |
| |
| // more performant version for #93600# |
| if( mxExpPropMapper.is()) |
| { |
| uno::Reference< chart2::XDataSeries > xSeries( xSeriesProperties, uno::UNO_QUERY ); |
| |
| std::vector< XMLPropertyState > aPropertyStates; |
| |
| const OUString sNumFormat( OUString::createFromAscii( "NumberFormat" )); |
| const OUString sPercentageNumFormat( OUString::createFromAscii( "PercentageNumberFormat" )); |
| |
| bool bVaryColorsByPoint = false; |
| Sequence< sal_Int32 > aDataPointSeq; |
| if( xSeriesProperties.is()) |
| { |
| Any aAny = xSeriesProperties->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "AttributedDataPoints" ))); |
| aAny >>= aDataPointSeq; |
| xSeriesProperties->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "VaryColorsByPoint" ))) >>= bVaryColorsByPoint; |
| } |
| |
| |
| sal_Int32 nSize = aDataPointSeq.getLength(); |
| DBG_ASSERT( nSize <= nSeriesLength, "Too many point attributes" ); |
| |
| const sal_Int32 * pPoints = aDataPointSeq.getConstArray(); |
| sal_Int32 nElement; |
| sal_Int32 nRepeat; |
| Reference< chart2::XColorScheme > xColorScheme; |
| if( xDiagram.is()) |
| xColorScheme.set( xDiagram->getDefaultColorScheme()); |
| |
| ::std::list< SchXMLDataPointStruct > aDataPointList; |
| |
| sal_Int32 nLastIndex = -1; |
| sal_Int32 nCurrIndex = 0; |
| |
| // collect elements |
| if( bVaryColorsByPoint && xColorScheme.is() ) |
| { |
| ::std::set< sal_Int32 > aAttrPointSet; |
| ::std::copy( pPoints, pPoints + aDataPointSeq.getLength(), |
| ::std::inserter( aAttrPointSet, aAttrPointSet.begin())); |
| const ::std::set< sal_Int32 >::const_iterator aEndIt( aAttrPointSet.end()); |
| for( nElement = 0; nElement < nSeriesLength; ++nElement ) |
| { |
| aPropertyStates.clear(); |
| uno::Reference< beans::XPropertySet > xPropSet; |
| bool bExportNumFmt = false; |
| if( aAttrPointSet.find( nElement ) != aEndIt ) |
| { |
| try |
| { |
| xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet( |
| xSeries, nElement, mrExport.GetModel() ); |
| bExportNumFmt = true; |
| } |
| catch( uno::Exception & rEx ) |
| { |
| (void)rEx; // avoid warning for pro build |
| DBG_ERROR1( "Exception caught during Export of data point: %s", |
| OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); |
| } |
| } |
| else |
| { |
| // property set only containing the color |
| xPropSet.set( new ::xmloff::chart::ColorPropertySet( |
| xColorScheme->getColorByIndex( nElement ))); |
| } |
| DBG_ASSERT( xPropSet.is(), "Pie Segments should have properties" ); |
| if( xPropSet.is()) |
| { |
| const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() ); |
| if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 && bExportNumFmt ) |
| { |
| lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport ); |
| lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport ); |
| } |
| |
| aPropertyStates = mxExpPropMapper->Filter( xPropSet ); |
| if( !aPropertyStates.empty() ) |
| { |
| if( bExportContent ) |
| { |
| // write data-point with style |
| DBG_ASSERT( ! maAutoStyleNameQueue.empty(), "Autostyle queue empty!" ); |
| |
| SchXMLDataPointStruct aPoint; |
| aPoint.maStyleName = maAutoStyleNameQueue.front(); |
| maAutoStyleNameQueue.pop(); |
| aDataPointList.push_back( aPoint ); |
| } |
| else |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| } |
| } |
| } |
| DBG_ASSERT( !bExportContent || (static_cast<sal_Int32>(aDataPointList.size()) == nSeriesLength), |
| "not enough data points on content export" ); |
| } |
| else |
| { |
| for( nElement = 0; nElement < nSize; ++nElement ) |
| { |
| aPropertyStates.clear(); |
| nCurrIndex = pPoints[ nElement ]; |
| //assuming sorted indices in pPoints |
| |
| if( nCurrIndex<0 || nCurrIndex>=nSeriesLength ) |
| break; |
| |
| // write leading empty data points |
| if( nCurrIndex - nLastIndex > 1 ) |
| { |
| SchXMLDataPointStruct aPoint; |
| aPoint.mnRepeat = nCurrIndex - nLastIndex - 1; |
| aDataPointList.push_back( aPoint ); |
| } |
| |
| uno::Reference< beans::XPropertySet > xPropSet; |
| // get property states |
| try |
| { |
| xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet( |
| xSeries, nCurrIndex, mrExport.GetModel() ); |
| } |
| catch( uno::Exception & rEx ) |
| { |
| (void)rEx; // avoid warning for pro build |
| DBG_ERROR1( "Exception caught during Export of data point: %s", |
| OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); |
| } |
| if( xPropSet.is()) |
| { |
| const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() ); |
| if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 ) |
| { |
| lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport ); |
| lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport ); |
| } |
| |
| aPropertyStates = mxExpPropMapper->Filter( xPropSet ); |
| if( !aPropertyStates.empty() ) |
| { |
| if( bExportContent ) |
| { |
| // write data-point with style |
| DBG_ASSERT( ! maAutoStyleNameQueue.empty(), "Autostyle queue empty!" ); |
| SchXMLDataPointStruct aPoint; |
| aPoint.maStyleName = maAutoStyleNameQueue.front(); |
| maAutoStyleNameQueue.pop(); |
| |
| aDataPointList.push_back( aPoint ); |
| nLastIndex = nCurrIndex; |
| } |
| else |
| { |
| CollectAutoStyle( aPropertyStates ); |
| } |
| continue; |
| } |
| } |
| |
| // if we get here the property states are empty |
| SchXMLDataPointStruct aPoint; |
| aDataPointList.push_back( aPoint ); |
| |
| nLastIndex = nCurrIndex; |
| } |
| // final empty elements |
| nRepeat = nSeriesLength - nLastIndex - 1; |
| if( nRepeat > 0 ) |
| { |
| SchXMLDataPointStruct aPoint; |
| aPoint.mnRepeat = nRepeat; |
| aDataPointList.push_back( aPoint ); |
| } |
| } |
| |
| if( bExportContent ) |
| { |
| // write elements (merge equal ones) |
| ::std::list< SchXMLDataPointStruct >::iterator aIter = aDataPointList.begin(); |
| SchXMLDataPointStruct aPoint; |
| SchXMLDataPointStruct aLastPoint; |
| |
| // initialize so that it doesn't matter if |
| // the element is counted in the first iteration |
| aLastPoint.mnRepeat = 0; |
| |
| for( ; aIter != aDataPointList.end(); ++aIter ) |
| { |
| aPoint = (*aIter); |
| |
| if( aPoint.maStyleName == aLastPoint.maStyleName ) |
| aPoint.mnRepeat += aLastPoint.mnRepeat; |
| else if( aLastPoint.mnRepeat > 0 ) |
| { |
| // write last element |
| if( aLastPoint.maStyleName.getLength() ) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName ); |
| |
| if( aLastPoint.mnRepeat > 1 ) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED, |
| OUString::valueOf( (sal_Int64)( aLastPoint.mnRepeat ) )); |
| |
| SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, sal_True, sal_True ); |
| } |
| aLastPoint = aPoint; |
| } |
| // write last element if it hasn't been written in last iteration |
| if( aPoint.maStyleName == aLastPoint.maStyleName ) |
| { |
| if( aLastPoint.maStyleName.getLength() ) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName ); |
| |
| if( aLastPoint.mnRepeat > 1 ) |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED, |
| OUString::valueOf( (sal_Int64)( aLastPoint.mnRepeat ) )); |
| |
| SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, sal_True, sal_True ); |
| } |
| } |
| } |
| } |
| |
| |
| void SchXMLExportHelper_Impl::getCellAddress( sal_Int32 nCol, sal_Int32 nRow ) |
| { |
| msStringBuffer.append( (sal_Unicode)'.' ); |
| if( nCol < 26 ) |
| msStringBuffer.append( (sal_Unicode)('A' + nCol) ); |
| else if( nCol < 702 ) |
| { |
| msStringBuffer.append( (sal_Unicode)('A' + nCol / 26 - 1 )); |
| msStringBuffer.append( (sal_Unicode)('A' + nCol % 26) ); |
| } |
| else |
| { |
| msStringBuffer.append( (sal_Unicode)('A' + nCol / 702 - 1 )); |
| msStringBuffer.append( (sal_Unicode)('A' + (nCol % 702) / 26 )); |
| msStringBuffer.append( (sal_Unicode)('A' + nCol % 26) ); |
| } |
| |
| msStringBuffer.append( nRow + (sal_Int32)1 ); |
| } |
| |
| void SchXMLExportHelper_Impl::addPosition( const awt::Point & rPosition ) |
| { |
| mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rPosition.X ); |
| msString = msStringBuffer.makeStringAndClear(); |
| mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_X, msString ); |
| |
| mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rPosition.Y ); |
| msString = msStringBuffer.makeStringAndClear(); |
| mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_Y, msString ); |
| } |
| |
| void SchXMLExportHelper_Impl::addPosition( Reference< drawing::XShape > xShape ) |
| { |
| if( xShape.is()) |
| addPosition( xShape->getPosition()); |
| } |
| |
| void SchXMLExportHelper_Impl::addSize( const awt::Size & rSize, bool bIsOOoNamespace) |
| { |
| mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rSize.Width ); |
| msString = msStringBuffer.makeStringAndClear(); |
| mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG , XML_WIDTH, msString ); |
| |
| |
| mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rSize.Height); |
| msString = msStringBuffer.makeStringAndClear(); |
| mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG, XML_HEIGHT, msString ); |
| } |
| |
| void SchXMLExportHelper_Impl::addSize( Reference< drawing::XShape > xShape, bool bIsOOoNamespace ) |
| { |
| if( xShape.is()) |
| addSize( xShape->getSize(), bIsOOoNamespace ); |
| } |
| |
| awt::Size SchXMLExportHelper_Impl::getPageSize( const Reference< chart2::XChartDocument > & xChartDoc ) const |
| { |
| awt::Size aSize( 8000, 7000 ); |
| uno::Reference< embed::XVisualObject > xVisualObject( xChartDoc, uno::UNO_QUERY ); |
| DBG_ASSERT( xVisualObject.is(),"need XVisualObject for page size" ); |
| if( xVisualObject.is() ) |
| aSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); |
| |
| return aSize; |
| } |
| |
| void SchXMLExportHelper_Impl::CollectAutoStyle( const std::vector< XMLPropertyState >& aStates ) |
| { |
| if( !aStates.empty() ) |
| maAutoStyleNameQueue.push( GetAutoStylePoolP().Add( XML_STYLE_FAMILY_SCH_CHART_ID, aStates )); |
| } |
| |
| void SchXMLExportHelper_Impl::AddAutoStyleAttribute( const std::vector< XMLPropertyState >& aStates ) |
| { |
| if( !aStates.empty() ) |
| { |
| DBG_ASSERT( ! maAutoStyleNameQueue.empty(), "Autostyle queue empty!" ); |
| |
| mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, maAutoStyleNameQueue.front() ); |
| maAutoStyleNameQueue.pop(); |
| } |
| } |
| |
| void SchXMLExportHelper_Impl::exportText( const OUString& rText, bool bConvertTabsLFs ) |
| { |
| SchXMLTools::exportText( mrExport, rText, bConvertTabsLFs ); |
| } |
| |
| // ======================================== |
| // class SchXMLExport |
| // ======================================== |
| |
| // #110680# |
| SchXMLExport::SchXMLExport( |
| const Reference< lang::XMultiServiceFactory >& xServiceFactory, |
| sal_uInt16 nExportFlags ) |
| : SvXMLExport( xServiceFactory, MAP_CM, ::xmloff::token::XML_CHART, nExportFlags ), |
| maAutoStylePool( *this ), |
| maExportHelper( *this, maAutoStylePool ) |
| { |
| if( getDefaultVersion() == SvtSaveOptions::ODFVER_LATEST ) |
| _GetNamespaceMap().Add( GetXMLToken(XML_NP_CHART_EXT), GetXMLToken(XML_N_CHART_EXT), XML_NAMESPACE_CHART_EXT); |
| } |
| |
| |
| SchXMLExport::~SchXMLExport() |
| { |
| // stop progress view |
| if( mxStatusIndicator.is()) |
| { |
| mxStatusIndicator->end(); |
| mxStatusIndicator->reset(); |
| } |
| } |
| |
| sal_uInt32 SchXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum eClass ) |
| { |
| Reference< chart2::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY ); |
| maExportHelper.m_pImpl->InitRangeSegmentationProperties( xChartDoc ); |
| return SvXMLExport::exportDoc( eClass ); |
| } |
| |
| void SchXMLExport::_ExportStyles( sal_Bool bUsed ) |
| { |
| SvXMLExport::_ExportStyles( bUsed ); |
| } |
| |
| void SchXMLExport::_ExportMasterStyles() |
| { |
| // not available in chart |
| DBG_WARNING( "Master Style Export requested. Not available for Chart" ); |
| } |
| |
| void SchXMLExport::_ExportAutoStyles() |
| { |
| // there are no styles that require their own autostyles |
| if( getExportFlags() & EXPORT_CONTENT ) |
| { |
| Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY ); |
| if( xChartDoc.is()) |
| { |
| maExportHelper.m_pImpl->collectAutoStyles( xChartDoc ); |
| maExportHelper.m_pImpl->exportAutoStyles(); |
| } |
| else |
| { |
| DBG_ERROR( "Couldn't export chart due to wrong XModel (must be XChartDocument)" ); |
| } |
| } |
| } |
| |
| void SchXMLExport::_ExportContent() |
| { |
| Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY ); |
| if( xChartDoc.is()) |
| { |
| // determine if data comes from the outside |
| sal_Bool bIncludeTable = sal_True; |
| |
| Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY ); |
| if( xNewDoc.is()) |
| { |
| // check if we have own data. If so we must not export the complete |
| // range string, as this is our only indicator for having own or |
| // external data. @todo: fix this in the file format! |
| Reference< lang::XServiceInfo > xDPServiceInfo( xNewDoc->getDataProvider(), uno::UNO_QUERY ); |
| if( ! (xDPServiceInfo.is() && |
| xDPServiceInfo->getImplementationName().equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "com.sun.star.comp.chart.InternalDataProvider" )))) |
| { |
| bIncludeTable = sal_False; |
| } |
| } |
| else |
| { |
| Reference< lang::XServiceInfo > xServ( xChartDoc, uno::UNO_QUERY ); |
| if( xServ.is()) |
| { |
| if( xServ->supportsService( |
| OUString::createFromAscii( "com.sun.star.chart.ChartTableAddressSupplier" ))) |
| { |
| Reference< beans::XPropertySet > xProp( xServ, uno::UNO_QUERY ); |
| if( xProp.is()) |
| { |
| Any aAny; |
| try |
| { |
| OUString sChartAddress; |
| aAny = xProp->getPropertyValue( |
| OUString::createFromAscii( "ChartRangeAddress" )); |
| aAny >>= sChartAddress; |
| maExportHelper.m_pImpl->SetChartRangeAddress( sChartAddress ); |
| |
| OUString sTableNumberList; |
| aAny = xProp->getPropertyValue( |
| OUString::createFromAscii( "TableNumberList" )); |
| aAny >>= sTableNumberList; |
| maExportHelper.m_pImpl->SetTableNumberList( sTableNumberList ); |
| |
| // do not include own table if there are external addresses |
| bIncludeTable = (sChartAddress.getLength() == 0); |
| } |
| catch( beans::UnknownPropertyException & ) |
| { |
| DBG_ERROR( "Property ChartRangeAddress not supported by ChartDocument" ); |
| } |
| } |
| } |
| } |
| } |
| maExportHelper.m_pImpl->exportChart( xChartDoc, bIncludeTable ); |
| } |
| else |
| { |
| DBG_ERROR( "Couldn't export chart due to wrong XModel" ); |
| } |
| } |
| |
| void SchXMLExport::SetProgress( sal_Int32 nPercentage ) |
| { |
| // set progress view |
| if( mxStatusIndicator.is()) |
| mxStatusIndicator->setValue( nPercentage ); |
| } |
| |
| UniReference< XMLPropertySetMapper > SchXMLExport::GetPropertySetMapper() const |
| { |
| return maExportHelper.m_pImpl->GetPropertySetMapper(); |
| } |
| |
| void SchXMLExportHelper_Impl::InitRangeSegmentationProperties( const Reference< chart2::XChartDocument > & xChartDoc ) |
| { |
| if( xChartDoc.is()) |
| try |
| { |
| Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() ); |
| OSL_ENSURE( xDataProvider.is(), "No DataProvider" ); |
| if( xDataProvider.is()) |
| { |
| Reference< chart2::data::XDataSource > xDataSource( lcl_pressUsedDataIntoRectangularFormat( xChartDoc, mbHasCategoryLabels )); |
| Sequence< beans::PropertyValue > aArgs( xDataProvider->detectArguments( xDataSource )); |
| ::rtl::OUString sCellRange, sBrokenRange; |
| bool bBrokenRangeAvailable = false; |
| for( sal_Int32 i=0; i<aArgs.getLength(); ++i ) |
| { |
| if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation"))) |
| aArgs[i].Value >>= sCellRange; |
| else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("BrokenCellRangeForExport"))) |
| { |
| if( aArgs[i].Value >>= sBrokenRange ) |
| bBrokenRangeAvailable = true; |
| } |
| else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DataRowSource"))) |
| { |
| chart::ChartDataRowSource eRowSource; |
| aArgs[i].Value >>= eRowSource; |
| mbRowSourceColumns = ( eRowSource == chart::ChartDataRowSource_COLUMNS ); |
| } |
| else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("FirstCellAsLabel"))) |
| aArgs[i].Value >>= mbHasSeriesLabels; |
| else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("SequenceMapping"))) |
| aArgs[i].Value >>= maSequenceMapping; |
| else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("TableNumberList"))) |
| aArgs[i].Value >>= msTableNumberList; |
| } |
| |
| // #i79009# For Writer we have to export a broken version of the |
| // range, where every row number is noe too large, so that older |
| // version can correctly read those files. |
| msChartAddress = (bBrokenRangeAvailable ? sBrokenRange : sCellRange); |
| if( msChartAddress.getLength() > 0 ) |
| { |
| // convert format to XML-conform one |
| Reference< chart2::data::XRangeXMLConversion > xConversion( xDataProvider, uno::UNO_QUERY ); |
| if( xConversion.is()) |
| msChartAddress = xConversion->convertRangeToXML( msChartAddress ); |
| } |
| } |
| } |
| catch( uno::Exception & ex ) |
| { |
| (void)ex; // avoid warning for pro build |
| OSL_ENSURE( false, OUStringToOString( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "Exception caught. Type: " )) + |
| OUString::createFromAscii( typeid( ex ).name()) + |
| OUString( RTL_CONSTASCII_USTRINGPARAM( ", Message: " )) + |
| ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr()); |
| } |
| } |
| |
| // export components ======================================== |
| |
| // first version: everything goes in one storage |
| |
| Sequence< OUString > SAL_CALL SchXMLExport_getSupportedServiceNames() throw() |
| { |
| const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLExporter" ) ); |
| const Sequence< OUString > aSeq( &aServiceName, 1 ); |
| return aSeq; |
| } |
| |
| OUString SAL_CALL SchXMLExport_getImplementationName() throw() |
| { |
| return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Compact" ) ); |
| } |
| |
| Reference< uno::XInterface > SAL_CALL SchXMLExport_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception ) |
| { |
| // #110680# |
| // #103997# removed some flags from EXPORT_ALL |
| // return (cppu::OWeakObject*)new SchXMLExport( EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS )); |
| return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS )); |
| } |
| |
| // Oasis format |
| Sequence< OUString > SAL_CALL SchXMLExport_Oasis_getSupportedServiceNames() throw() |
| { |
| const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisExporter" ) ); |
| const Sequence< OUString > aSeq( &aServiceName, 1 ); |
| return aSeq; |
| } |
| |
| OUString SAL_CALL SchXMLExport_Oasis_getImplementationName() throw() |
| { |
| return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Compact" ) ); |
| } |
| |
| Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception ) |
| { |
| // #103997# removed some flags from EXPORT_ALL |
| return (cppu::OWeakObject*)new SchXMLExport( rSMgr, |
| (EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS )) | EXPORT_OASIS ); |
| } |
| |
| // ============================================================ |
| |
| // multiple storage version: one for content / styles / meta |
| |
| Sequence< OUString > SAL_CALL SchXMLExport_Styles_getSupportedServiceNames() throw() |
| { |
| const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLStylesExporter" )); |
| const Sequence< OUString > aSeq( &aServiceName, 1 ); |
| return aSeq; |
| } |
| |
| OUString SAL_CALL SchXMLExport_Styles_getImplementationName() throw() |
| { |
| return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Styles" )); |
| } |
| |
| Reference< uno::XInterface > SAL_CALL SchXMLExport_Styles_createInstance(const Reference< lang::XMultiServiceFactory >& rSMgr) throw( uno::Exception ) |
| { |
| // #110680# |
| // return (cppu::OWeakObject*)new SchXMLExport( EXPORT_STYLES ); |
| return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_STYLES ); |
| } |
| |
| // Oasis format |
| Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Styles_getSupportedServiceNames() throw() |
| { |
| const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisStylesExporter" )); |
| const Sequence< OUString > aSeq( &aServiceName, 1 ); |
| return aSeq; |
| } |
| |
| OUString SAL_CALL SchXMLExport_Oasis_Styles_getImplementationName() throw() |
| { |
| return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Styles" )); |
| } |
| |
| Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Styles_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception ) |
| { |
| return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_STYLES | EXPORT_OASIS ); |
| } |
| |
| // ------------------------------------------------------------ |
| |
| Sequence< OUString > SAL_CALL SchXMLExport_Content_getSupportedServiceNames() throw() |
| { |
| const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLContentExporter" )); |
| const Sequence< OUString > aSeq( &aServiceName, 1 ); |
| return aSeq; |
| } |
| |
| OUString SAL_CALL SchXMLExport_Content_getImplementationName() throw() |
| { |
| return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Content" )); |
| } |
| |
| Reference< uno::XInterface > SAL_CALL SchXMLExport_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception ) |
| { |
| // #110680# |
| // return (cppu::OWeakObject*)new SchXMLExport( EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS ); |
| return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS ); |
| } |
| |
| // Oasis format |
| Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Content_getSupportedServiceNames() throw() |
| { |
| const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisContentExporter" )); |
| const Sequence< OUString > aSeq( &aServiceName, 1 ); |
| return aSeq; |
| } |
| |
| OUString SAL_CALL SchXMLExport_Oasis_Content_getImplementationName() throw() |
| { |
| return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Content" )); |
| } |
| |
| Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception ) |
| { |
| return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS | EXPORT_OASIS ); |
| } |
| |
| // ------------------------------------------------------------ |
| |
| // Sequence< OUString > SAL_CALL SchXMLExport_Meta_getSupportedServiceNames() throw() |
| // { |
| // const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLMetaExporter" )); |
| // const Sequence< OUString > aSeq( &aServiceName, 1 ); |
| // return aSeq; |
| // } |
| |
| // OUString SAL_CALL SchXMLExport_Meta_getImplementationName() throw() |
| // { |
| // return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Meta" )); |
| // } |
| |
| // Reference< uno::XInterface > SAL_CALL SchXMLExport_Meta_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception ) |
| // { |
| // return (cppu::OWeakObject*)new SchXMLExport( EXPORT_META ); |
| // } |
| |
| // Oasis format |
| Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Meta_getSupportedServiceNames() throw() |
| { |
| const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisMetaExporter" )); |
| const Sequence< OUString > aSeq( &aServiceName, 1 ); |
| return aSeq; |
| } |
| |
| OUString SAL_CALL SchXMLExport_Oasis_Meta_getImplementationName() throw() |
| { |
| return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Meta" )); |
| } |
| |
| Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Meta_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception ) |
| { |
| return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_META | EXPORT_OASIS ); |
| } |
| |
| |
| // XServiceInfo |
| OUString SAL_CALL SchXMLExport::getImplementationName() throw( uno::RuntimeException ) |
| { |
| switch( getExportFlags()) |
| { |
| case EXPORT_ALL: |
| return SchXMLExport_getImplementationName(); |
| case EXPORT_STYLES: |
| return SchXMLExport_Styles_getImplementationName(); |
| case ( EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS ): |
| return SchXMLExport_Content_getImplementationName(); |
| // case EXPORT_META: |
| // return SchXMLExport_Meta_getImplementationName(); |
| |
| // Oasis format |
| case ( EXPORT_ALL | EXPORT_OASIS ): |
| return SchXMLExport_Oasis_getImplementationName(); |
| case ( EXPORT_STYLES | EXPORT_OASIS ): |
| return SchXMLExport_Oasis_Styles_getImplementationName(); |
| case ( EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS | EXPORT_OASIS ): |
| return SchXMLExport_Oasis_Content_getImplementationName(); |
| case ( EXPORT_META | EXPORT_OASIS ): |
| return SchXMLExport_Oasis_Meta_getImplementationName(); |
| |
| case EXPORT_SETTINGS: |
| // there is no settings component in chart |
| default: |
| return OUString::createFromAscii( "SchXMLExport" ); |
| } |
| } |