1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: SchXMLTableContext.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmloff.hxx"
34 #include "SchXMLTableContext.hxx"
35 #include "SchXMLParagraphContext.hxx"
36 #include "SchXMLImport.hxx"
37 #include "SchXMLTools.hxx"
38 #include "transporttypes.hxx"
39 #include <tools/debug.hxx>
40 #include <rtl/math.hxx>
41 #include "xmlnmspe.hxx"
42 #include <xmloff/xmltoken.hxx>
43 #include <xmloff/nmspmap.hxx>
44 #include <xmloff/xmluconv.hxx>
45 #include <com/sun/star/frame/XModel.hpp>
46 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
47 #include <com/sun/star/chart2/XChartDocument.hpp>
48 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
49 #include <com/sun/star/chart2/XInternalDataProvider.hpp>
50 #include <com/sun/star/chart/XChartDataArray.hpp>
51 #include <com/sun/star/chart/ChartSeriesAddress.hpp>
52 #include <com/sun/star/beans/XPropertySet.hpp>
53 #include <com/sun/star/beans/XPropertySetInfo.hpp>
54 #include <com/sun/star/beans/PropertyAttribute.hpp>
56 #include <com/sun/star/chart2/XDiagram.hpp>
57 #include <com/sun/star/chart2/XAxis.hpp>
58 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
59 #include <com/sun/star/chart2/AxisType.hpp>
64 using namespace com::sun::star
;
65 using namespace ::xmloff::token
;
66 using ::com::sun::star::uno::Sequence
;
67 using ::com::sun::star::uno::Reference
;
68 using ::rtl::OUString
;
73 const OUString
lcl_aLabelPrefix( RTL_CONSTASCII_USTRINGPARAM("label "));
74 const OUString
lcl_aCategoriesRange( RTL_CONSTASCII_USTRINGPARAM("categories"));
76 typedef ::std::multimap
< ::rtl::OUString
, ::rtl::OUString
>
77 lcl_tOriginalRangeToInternalRangeMap
;
79 Sequence
< OUString
> lcl_getCategoriesFromTable( const SchXMLTable
& rTable
, bool bHasLabels
)
81 sal_Int32
nNumRows( static_cast< sal_Int32
>( rTable
.aData
.size()));
82 OSL_ENSURE( static_cast< size_t >( nNumRows
) == rTable
.aData
.size(), "Table too big" );
84 sal_Int32
nOffset(bHasLabels
? 1 : 0);
85 Sequence
< OUString
> aResult( nNumRows
- nOffset
);
87 for( ; i
<nNumRows
; ++i
)
89 if( !rTable
.aData
[i
].empty() && (rTable
.aData
[i
].front().eType
== SCH_CELL_TYPE_STRING
))
90 aResult
[i
- nOffset
] = rTable
.aData
[i
].front().aString
;
95 std::vector
< Reference
< chart2::XAxis
> > lcl_getAxesHoldingCategoriesFromDiagram(
96 const Reference
< chart2::XDiagram
> & xDiagram
)
98 std::vector
< Reference
< chart2::XAxis
> > aRet
;
100 Reference
< chart2::XAxis
> xResult
;
101 // return first x-axis as fall-back
102 Reference
< chart2::XAxis
> xFallBack
;
105 Reference
< chart2::XCoordinateSystemContainer
> xCooSysCnt(
106 xDiagram
, uno::UNO_QUERY_THROW
);
107 Sequence
< Reference
< chart2::XCoordinateSystem
> > aCooSysSeq(
108 xCooSysCnt
->getCoordinateSystems());
109 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
111 Reference
< chart2::XCoordinateSystem
> xCooSys( aCooSysSeq
[i
] );
112 OSL_ASSERT( xCooSys
.is());
113 for( sal_Int32 nN
= xCooSys
->getDimension(); nN
--; )
115 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(nN
);
116 for(sal_Int32 nI
=0; nI
<=nMaximumScaleIndex
; ++nI
)
118 Reference
< chart2::XAxis
> xAxis
= xCooSys
->getAxisByDimension( nN
,nI
);
119 OSL_ASSERT( xAxis
.is());
122 chart2::ScaleData aScaleData
= xAxis
->getScaleData();
123 if( aScaleData
.Categories
.is() || (aScaleData
.AxisType
== chart2::AxisType::CATEGORY
) )
125 aRet
.push_back(xAxis
);
127 if( (nN
== 0) && !xFallBack
.is())
128 xFallBack
.set( xAxis
);
134 catch( uno::Exception
& )
139 aRet
.push_back(xFallBack
);
144 void lcl_ApplyColumnLabels(
145 const ::std::vector
< SchXMLCell
> & rFirstRow
,
146 Sequence
< OUString
> & rOutColumnLabels
,
149 const sal_Int32 nColumnLabelsSize
= rOutColumnLabels
.getLength();
150 const sal_Int32 nMax
= ::std::min
< sal_Int32
>( nColumnLabelsSize
,
151 static_cast< sal_Int32
>( rFirstRow
.size()) - nOffset
);
152 OSL_ASSERT( nMax
== nColumnLabelsSize
);
153 for( sal_Int32 i
=0; i
<nMax
; ++i
)
154 if( rFirstRow
[i
+nOffset
].eType
== SCH_CELL_TYPE_STRING
)
155 rOutColumnLabels
[i
] = rFirstRow
[i
+nOffset
].aString
;
158 struct lcl_ApplyCellToData
: public ::std::unary_function
< SchXMLCell
, void >
160 lcl_ApplyCellToData( Sequence
< double > & rOutData
,
161 Sequence
< OUString
> & rOutRowLabels
) :
163 m_rRowLabels( rOutRowLabels
),
165 m_nSize( rOutData
.getLength())
167 ::rtl::math::setNan( &m_fNaN
);
170 void operator() ( const SchXMLCell
& rCell
)
172 if( m_nIndex
< m_nSize
)
174 if( rCell
.eType
== SCH_CELL_TYPE_FLOAT
)
175 m_rData
[m_nIndex
] = rCell
.fValue
;
177 m_rData
[m_nIndex
] = m_fNaN
;
183 Sequence
< double > & m_rData
;
184 Sequence
< OUString
> & m_rRowLabels
;
190 struct lcl_ApplyRowsToData
: public ::std::unary_function
< ::std::vector
< SchXMLCell
>, void >
192 lcl_ApplyRowsToData( Sequence
< Sequence
< double > > & rOutData
,
193 Sequence
< OUString
> & rOutRowLabels
,
197 m_rRowLabels( rOutRowLabels
),
199 m_nOuterSize( rOutData
.getLength()),
200 m_nOffset( nOffset
),
201 m_bHasHeader( bHasHeader
)
203 void operator() ( const ::std::vector
< SchXMLCell
> & rRow
)
208 if( m_bHasHeader
&& m_nIndex
< m_rRowLabels
.getLength() && rRow
.front().eType
== SCH_CELL_TYPE_STRING
)
209 m_rRowLabels
[m_nIndex
] = rRow
.front().aString
;
212 if( m_nIndex
< m_nOuterSize
)
213 ::std::for_each( rRow
.begin() + m_nOffset
, rRow
.end(), lcl_ApplyCellToData( m_rData
[m_nIndex
], m_rRowLabels
));
219 Sequence
< Sequence
< double > > & m_rData
;
220 Sequence
< OUString
> & m_rRowLabels
;
222 sal_Int32 m_nOuterSize
;
227 Sequence
< Sequence
< double > > lcl_getSwappedArray( const Sequence
< Sequence
< double > > & rData
)
229 sal_Int32 nOldOuterSize
= rData
.getLength();
230 sal_Int32 nOldInnerSize
= (nOldOuterSize
== 0 ? 0 : rData
[0].getLength());
231 Sequence
< Sequence
< double > > aResult( nOldInnerSize
);
233 for( sal_Int32 i
=0; i
<nOldInnerSize
; ++i
)
234 aResult
[i
].realloc( nOldOuterSize
);
236 for( sal_Int32 nOuter
=0; nOuter
<nOldOuterSize
; ++nOuter
)
237 for( sal_Int32 nInner
=0; nInner
<nOldInnerSize
; ++nInner
)
238 aResult
[nInner
][nOuter
] = rData
[nOuter
][nInner
];
243 void lcl_applyXMLTableToInternalDataprovider(
244 const SchXMLTable
& rTable
,
245 const Reference
< chart::XChartDataArray
> & xDataArray
)
247 sal_Int32
nNumRows( static_cast< sal_Int32
>( rTable
.aData
.size()));
248 sal_Int32 nRowOffset
= 0;
249 if( rTable
.bHasHeaderRow
)
254 sal_Int32
nNumColumns( rTable
.nMaxColumnIndex
+ 1 );
255 sal_Int32 nColOffset
= 0;
256 if( rTable
.bHasHeaderColumn
)
262 Sequence
< Sequence
< double > > aData( nNumRows
);
263 Sequence
< OUString
> aRowLabels( nNumRows
);
264 Sequence
< OUString
> aColumnLabels( nNumColumns
);
265 for( sal_Int32 i
=0; i
<nNumRows
; ++i
)
266 aData
[i
].realloc( nNumColumns
);
268 if( rTable
.aData
.begin() != rTable
.aData
.end())
270 if( rTable
.bHasHeaderRow
)
271 lcl_ApplyColumnLabels( rTable
.aData
.front(), aColumnLabels
, nColOffset
);
272 ::std::for_each( rTable
.aData
.begin() + nRowOffset
, rTable
.aData
.end(),
273 lcl_ApplyRowsToData( aData
, aRowLabels
, nColOffset
, rTable
.bHasHeaderColumn
));
276 xDataArray
->setData( aData
);
278 if( rTable
.bHasHeaderColumn
)
279 xDataArray
->setRowDescriptions( aRowLabels
);
280 if( rTable
.bHasHeaderRow
)
281 xDataArray
->setColumnDescriptions( aColumnLabels
);
284 void lcl_fillRangeMapping(
285 const SchXMLTable
& rTable
,
286 lcl_tOriginalRangeToInternalRangeMap
& rOutRangeMap
,
287 chart::ChartDataRowSource eDataRowSource
)
289 sal_Int32 nRowOffset
= ( rTable
.bHasHeaderRow
? 1 : 0 );
290 sal_Int32 nColOffset
= ( rTable
.bHasHeaderColumn
? 1 : 0 );
292 // Fill range mapping
293 const size_t nTableRowCount( rTable
.aData
.size());
294 for( size_t nRow
= 0; nRow
< nTableRowCount
; ++nRow
)
296 const ::std::vector
< SchXMLCell
> & rRow( rTable
.aData
[nRow
] );
297 const size_t nTableColCount( rRow
.size());
298 for( size_t nCol
= 0; nCol
< nTableColCount
; ++nCol
)
300 OUString
aRangeId( rRow
[nCol
].aRangeId
);
301 if( aRangeId
.getLength())
303 if( eDataRowSource
== chart::ChartDataRowSource_COLUMNS
)
305 if( nCol
== 0 && rTable
.bHasHeaderColumn
)
307 OSL_ASSERT( static_cast< sal_Int32
>( nRow
) == nRowOffset
);
308 rOutRangeMap
.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
309 aRangeId
, lcl_aCategoriesRange
));
313 OUString aColNumStr
= OUString::valueOf( static_cast< sal_Int32
>( nCol
- nColOffset
));
314 if( nRow
== 0 && rTable
.bHasHeaderRow
)
315 rOutRangeMap
.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
316 aRangeId
, lcl_aLabelPrefix
+ aColNumStr
));
318 rOutRangeMap
.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
319 aRangeId
, aColNumStr
));
322 else // eDataRowSource == chart::ChartDataRowSource_ROWS
324 if( nRow
== 0 && rTable
.bHasHeaderRow
)
326 OSL_ASSERT( static_cast< sal_Int32
>( nCol
) == nColOffset
);
327 rOutRangeMap
.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
328 aRangeId
, lcl_aCategoriesRange
));
332 OUString aRowNumStr
= OUString::valueOf( static_cast< sal_Int32
>( nRow
- nRowOffset
));
333 if( nCol
== 0 && rTable
.bHasHeaderColumn
)
334 rOutRangeMap
.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
335 aRangeId
, lcl_aLabelPrefix
+ aRowNumStr
));
337 rOutRangeMap
.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
338 aRangeId
, aRowNumStr
));
346 Reference
< chart2::data::XDataSequence
>
347 lcl_reassignDataSequence(
348 const Reference
< chart2::data::XDataSequence
> & xSequence
,
349 const Reference
< chart2::data::XDataProvider
> & xDataProvider
,
350 lcl_tOriginalRangeToInternalRangeMap
& rRangeMap
,
351 const OUString
& rRange
)
353 Reference
< chart2::data::XDataSequence
> xResult( xSequence
);
354 lcl_tOriginalRangeToInternalRangeMap::iterator
aIt( rRangeMap
.find( rRange
));
355 if( aIt
!= rRangeMap
.end())
357 // set sequence with correct data
358 xResult
.set( xDataProvider
->createDataSequenceByRangeRepresentation( aIt
->second
));
359 // remove translation, because it was used
360 rRangeMap
.erase( aIt
);
366 bool lcl_mapContainsRange(
367 lcl_tOriginalRangeToInternalRangeMap
& rRangeMap
,
368 const OUString
& rRange
)
370 lcl_tOriginalRangeToInternalRangeMap::iterator
aIt( rRangeMap
.find( rRange
));
371 return ( aIt
!= rRangeMap
.end());
374 bool lcl_tableOfRangeMatches(
375 const ::rtl::OUString
& rRange
,
376 const ::rtl::OUString
& rTableName
)
378 // both strings are non-empty and the table name is part of the range
379 return ( (rRange
.getLength() > 0) &&
380 (rTableName
.getLength() > 0) &&
381 (rRange
.indexOf( rTableName
) != -1 ));
384 template< typename T
>
385 ::std::vector
< T
> lcl_SequenceToVector( const uno::Sequence
< T
> & rSequence
)
387 ::std::vector
< T
> aResult( rSequence
.getLength());
388 ::std::copy( rSequence
.getConstArray(), rSequence
.getConstArray() + rSequence
.getLength(),
393 } // anonymous namespace
396 // ----------------------------------------
397 // class SchXMLTableContext
398 // ----------------------------------------
400 SchXMLTableContext::SchXMLTableContext( SchXMLImportHelper
& rImpHelper
,
401 SvXMLImport
& rImport
,
402 const rtl::OUString
& rLName
,
403 SchXMLTable
& aTable
) :
404 SvXMLImportContext( rImport
, XML_NAMESPACE_TABLE
, rLName
),
405 mrImportHelper( rImpHelper
),
407 mbHasRowPermutation( false ),
408 mbHasColumnPermutation( false )
410 mrTable
.nColumnIndex
= -1;
411 mrTable
.nMaxColumnIndex
= -1;
412 mrTable
.nRowIndex
= -1;
413 mrTable
.aData
.clear();
416 SchXMLTableContext::~SchXMLTableContext()
420 SvXMLImportContext
*SchXMLTableContext::CreateChildContext(
422 const rtl::OUString
& rLocalName
,
423 const uno::Reference
< xml::sax::XAttributeList
>& )
425 SvXMLImportContext
* pContext
= 0;
426 const SvXMLTokenMap
& rTokenMap
= mrImportHelper
.GetTableElemTokenMap();
428 switch( rTokenMap
.Get( nPrefix
, rLocalName
))
430 case XML_TOK_TABLE_HEADER_COLS
:
431 mrTable
.bHasHeaderColumn
= true;
432 // fall through intended
433 case XML_TOK_TABLE_COLUMNS
:
434 pContext
= new SchXMLTableColumnsContext( mrImportHelper
, GetImport(), rLocalName
, mrTable
);
437 case XML_TOK_TABLE_COLUMN
:
438 pContext
= new SchXMLTableColumnContext( mrImportHelper
, GetImport(), rLocalName
, mrTable
);
441 case XML_TOK_TABLE_HEADER_ROWS
:
442 mrTable
.bHasHeaderRow
= true;
443 // fall through intended
444 case XML_TOK_TABLE_ROWS
:
445 pContext
= new SchXMLTableRowsContext( mrImportHelper
, GetImport(), rLocalName
, mrTable
);
448 case XML_TOK_TABLE_ROW
:
449 pContext
= new SchXMLTableRowContext( mrImportHelper
, GetImport(), rLocalName
, mrTable
);
453 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
459 void SchXMLTableContext::StartElement( const uno::Reference
< xml::sax::XAttributeList
>& xAttrList
)
462 sal_Int16 nAttrCount
= xAttrList
.is()? xAttrList
->getLength(): 0;
464 for( sal_Int16 i
= 0; i
< nAttrCount
; i
++ )
466 rtl::OUString sAttrName
= xAttrList
->getNameByIndex( i
);
467 rtl::OUString aLocalName
;
468 USHORT nPrefix
= GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
470 if( nPrefix
== XML_NAMESPACE_TABLE
&&
471 IsXMLToken( aLocalName
, XML_NAME
) )
473 mrTable
.aTableNameOfFile
= xAttrList
->getValueByIndex( i
);
474 break; // we only need this attribute
479 void SchXMLTableContext::EndElement()
481 if( mbHasColumnPermutation
)
483 OSL_ASSERT( !mbHasRowPermutation
);
484 ::std::vector
< sal_Int32
> aPermutation( lcl_SequenceToVector( maColumnPermutation
));
485 OSL_ASSERT( !aPermutation
.empty());
486 if( aPermutation
.empty())
489 // permute the values of all rows according to aPermutation
490 for( ::std::vector
< ::std::vector
< SchXMLCell
> >::iterator
aRowIt( mrTable
.aData
.begin());
491 aRowIt
!= mrTable
.aData
.end(); ++aRowIt
)
493 bool bModified
= false;
494 ::std::vector
< SchXMLCell
> aModifiedRow
;
495 const size_t nPermSize
= aPermutation
.size();
496 OSL_ASSERT( static_cast< sal_Int32
>( nPermSize
) - 1 == *(::std::max_element( aPermutation
.begin(), aPermutation
.end())));
497 const size_t nRowSize
= aRowIt
->size();
498 const size_t nDestSize
= ::std::min( nPermSize
, nRowSize
);
499 for( size_t nDestinationIndex
= 0; nDestinationIndex
< nDestSize
; ++nDestinationIndex
)
501 const size_t nSourceIndex
= static_cast< size_t >( aPermutation
[ nDestinationIndex
] );
502 if( nSourceIndex
!= nDestinationIndex
&&
503 nSourceIndex
< nRowSize
)
505 // copy original on first real permutation
508 OSL_ASSERT( aModifiedRow
.empty());
509 aModifiedRow
.reserve( aRowIt
->size());
510 ::std::copy( aRowIt
->begin(), aRowIt
->end(), ::std::back_inserter( aModifiedRow
));
511 OSL_ASSERT( !aModifiedRow
.empty());
513 OSL_ASSERT( nDestinationIndex
< aModifiedRow
.size());
514 aModifiedRow
[ nDestinationIndex
] = (*aRowIt
)[ nSourceIndex
];
520 ::std::copy( aModifiedRow
.begin(), aModifiedRow
.end(), aRowIt
->begin());
523 else if( mbHasRowPermutation
)
525 ::std::vector
< sal_Int32
> aPermutation( lcl_SequenceToVector( maRowPermutation
));
526 OSL_ASSERT( !aPermutation
.empty());
527 if( aPermutation
.empty())
530 bool bModified
= false;
531 const size_t nPermSize
= aPermutation
.size();
532 OSL_ASSERT( static_cast< sal_Int32
>( nPermSize
) - 1 == *(::std::max_element( aPermutation
.begin(), aPermutation
.end())));
533 const size_t nTableRowCount
= mrTable
.aData
.size();
534 const size_t nDestSize
= ::std::min( nPermSize
, nTableRowCount
);
535 ::std::vector
< ::std::vector
< SchXMLCell
> > aDestination
;
536 for( size_t nDestinationIndex
= 0; nDestinationIndex
< nDestSize
; ++nDestinationIndex
)
538 const size_t nSourceIndex
= static_cast< size_t >( aPermutation
[ nDestinationIndex
] );
539 if( nSourceIndex
!= nDestinationIndex
&&
540 nSourceIndex
< nTableRowCount
)
542 // copy original on first real permutation
545 OSL_ASSERT( aDestination
.empty());
546 aDestination
.reserve( mrTable
.aData
.size());
547 ::std::copy( mrTable
.aData
.begin(), mrTable
.aData
.end(), ::std::back_inserter( aDestination
));
548 OSL_ASSERT( !aDestination
.empty());
550 OSL_ASSERT( nDestinationIndex
< aDestination
.size());
551 aDestination
[ nDestinationIndex
] = mrTable
.aData
[ nSourceIndex
];
558 ::std::copy( aDestination
.begin(), aDestination
.end(), mrTable
.aData
.begin());
563 void SchXMLTableContext::setRowPermutation( const uno::Sequence
< sal_Int32
> & rPermutation
)
565 maRowPermutation
= rPermutation
;
566 mbHasRowPermutation
= ( rPermutation
.getLength() > 0 );
568 if( mbHasRowPermutation
&& mbHasColumnPermutation
)
570 mbHasColumnPermutation
= false;
571 maColumnPermutation
.realloc( 0 );
575 void SchXMLTableContext::setColumnPermutation( const uno::Sequence
< sal_Int32
> & rPermutation
)
577 maColumnPermutation
= rPermutation
;
578 mbHasColumnPermutation
= ( rPermutation
.getLength() > 0 );
580 if( mbHasColumnPermutation
&& mbHasRowPermutation
)
582 mbHasRowPermutation
= false;
583 maRowPermutation
.realloc( 0 );
587 // ========================================
588 // classes for columns
589 // ========================================
591 // ----------------------------------------
592 // class SchXMLTableColumnsContext
593 // ----------------------------------------
595 SchXMLTableColumnsContext::SchXMLTableColumnsContext(
596 SchXMLImportHelper
& rImpHelper
,
597 SvXMLImport
& rImport
,
598 const rtl::OUString
& rLocalName
,
599 SchXMLTable
& aTable
) :
600 SvXMLImportContext( rImport
, XML_NAMESPACE_TABLE
, rLocalName
),
601 mrImportHelper( rImpHelper
),
606 SchXMLTableColumnsContext::~SchXMLTableColumnsContext()
610 SvXMLImportContext
* SchXMLTableColumnsContext::CreateChildContext(
612 const rtl::OUString
& rLocalName
,
613 const uno::Reference
< xml::sax::XAttributeList
>& )
615 SvXMLImportContext
* pContext
= 0;
617 if( nPrefix
== XML_NAMESPACE_TABLE
&&
618 IsXMLToken( rLocalName
, XML_TABLE_COLUMN
) )
620 pContext
= new SchXMLTableColumnContext( mrImportHelper
, GetImport(), rLocalName
, mrTable
);
623 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
628 // ----------------------------------------
629 // class SchXMLTableColumnContext
630 // ----------------------------------------
632 SchXMLTableColumnContext::SchXMLTableColumnContext(
633 SchXMLImportHelper
& rImpHelper
,
634 SvXMLImport
& rImport
,
635 const rtl::OUString
& rLocalName
,
636 SchXMLTable
& aTable
) :
637 SvXMLImportContext( rImport
, XML_NAMESPACE_TABLE
, rLocalName
),
638 mrImportHelper( rImpHelper
),
643 void SchXMLTableColumnContext::StartElement( const uno::Reference
< xml::sax::XAttributeList
>& xAttrList
)
645 // get number-columns-repeated attribute
646 sal_Int16 nAttrCount
= xAttrList
.is()? xAttrList
->getLength(): 0;
647 sal_Int32 nRepeated
= 1;
648 bool bHidden
= false;
650 for( sal_Int16 i
= 0; i
< nAttrCount
; i
++ )
652 rtl::OUString sAttrName
= xAttrList
->getNameByIndex( i
);
653 rtl::OUString aLocalName
;
654 USHORT nPrefix
= GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
656 if( nPrefix
== XML_NAMESPACE_TABLE
&&
657 IsXMLToken( aLocalName
, XML_NUMBER_COLUMNS_REPEATED
) )
659 rtl::OUString aValue
= xAttrList
->getValueByIndex( i
);
660 if( aValue
.getLength())
661 nRepeated
= aValue
.toInt32();
663 else if( nPrefix
== XML_NAMESPACE_TABLE
&&
664 IsXMLToken( aLocalName
, XML_VISIBILITY
) )
666 rtl::OUString aVisibility
= xAttrList
->getValueByIndex( i
);
667 bHidden
= aVisibility
.equals( GetXMLToken( XML_COLLAPSE
) );
671 sal_Int32 nOldCount
= mrTable
.nNumberOfColsEstimate
;
672 sal_Int32 nNewCount
= nOldCount
+ nRepeated
;
673 mrTable
.nNumberOfColsEstimate
= nNewCount
;
677 //i91578 display of hidden values (copy paste scenario; use hidden flag during migration to locale table upon paste )
678 sal_Int32 nColOffset
= ( mrTable
.bHasHeaderColumn
? 1 : 0 );
679 for( sal_Int32 nN
= nOldCount
; nN
<nNewCount
; nN
++ )
681 sal_Int32 nHiddenColumnIndex
= nN
-nColOffset
;
682 if( nHiddenColumnIndex
>=0 )
683 mrTable
.aHiddenColumns
.push_back(nHiddenColumnIndex
);
688 SchXMLTableColumnContext::~SchXMLTableColumnContext()
692 // ========================================
694 // ========================================
696 // ----------------------------------------
697 // class SchXMLTableRowsContext
698 // ----------------------------------------
700 SchXMLTableRowsContext::SchXMLTableRowsContext(
701 SchXMLImportHelper
& rImpHelper
,
702 SvXMLImport
& rImport
,
703 const rtl::OUString
& rLocalName
,
704 SchXMLTable
& aTable
) :
705 SvXMLImportContext( rImport
, XML_NAMESPACE_TABLE
, rLocalName
),
706 mrImportHelper( rImpHelper
),
711 SchXMLTableRowsContext::~SchXMLTableRowsContext()
715 SvXMLImportContext
* SchXMLTableRowsContext::CreateChildContext(
717 const rtl::OUString
& rLocalName
,
718 const uno::Reference
< xml::sax::XAttributeList
>& )
720 SvXMLImportContext
* pContext
= 0;
722 if( nPrefix
== XML_NAMESPACE_TABLE
&&
723 IsXMLToken( rLocalName
, XML_TABLE_ROW
) )
725 pContext
= new SchXMLTableRowContext( mrImportHelper
, GetImport(), rLocalName
, mrTable
);
729 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
735 // ----------------------------------------
736 // class SchXMLTableRowContext
737 // ----------------------------------------
739 SchXMLTableRowContext::SchXMLTableRowContext(
740 SchXMLImportHelper
& rImpHelper
,
741 SvXMLImport
& rImport
,
742 const rtl::OUString
& rLocalName
,
743 SchXMLTable
& aTable
) :
744 SvXMLImportContext( rImport
, XML_NAMESPACE_TABLE
, rLocalName
),
745 mrImportHelper( rImpHelper
),
748 mrTable
.nColumnIndex
= -1;
751 std::vector
< SchXMLCell
> aNewRow
;
752 aNewRow
.reserve( mrTable
.nNumberOfColsEstimate
);
753 while( mrTable
.aData
.size() <= (unsigned long)mrTable
.nRowIndex
)
754 mrTable
.aData
.push_back( aNewRow
);
757 SchXMLTableRowContext::~SchXMLTableRowContext()
761 SvXMLImportContext
* SchXMLTableRowContext::CreateChildContext(
763 const rtl::OUString
& rLocalName
,
764 const uno::Reference
< xml::sax::XAttributeList
>& )
766 SvXMLImportContext
* pContext
= 0;
768 // <table:table-cell> element
769 if( nPrefix
== XML_NAMESPACE_TABLE
&&
770 IsXMLToken(rLocalName
, XML_TABLE_CELL
) )
772 pContext
= new SchXMLTableCellContext( mrImportHelper
, GetImport(), rLocalName
, mrTable
);
776 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
783 // ========================================
784 // classes for cells and their content
785 // ========================================
787 // ----------------------------------------
788 // class SchXMLTableCellContext
789 // ----------------------------------------
791 SchXMLTableCellContext::SchXMLTableCellContext(
792 SchXMLImportHelper
& rImpHelper
,
793 SvXMLImport
& rImport
,
794 const rtl::OUString
& rLocalName
,
795 SchXMLTable
& aTable
) :
796 SvXMLImportContext( rImport
, XML_NAMESPACE_TABLE
, rLocalName
),
797 mrImportHelper( rImpHelper
),
802 SchXMLTableCellContext::~SchXMLTableCellContext()
806 void SchXMLTableCellContext::StartElement( const uno::Reference
< xml::sax::XAttributeList
>& xAttrList
)
808 sal_Int16 nAttrCount
= xAttrList
.is()? xAttrList
->getLength(): 0;
809 rtl::OUString aValue
;
810 rtl::OUString aLocalName
;
811 rtl::OUString aCellContent
;
812 SchXMLCellType eValueType
= SCH_CELL_TYPE_UNKNOWN
;
813 const SvXMLTokenMap
& rAttrTokenMap
= mrImportHelper
.GetCellAttrTokenMap();
815 for( sal_Int16 i
= 0; i
< nAttrCount
; i
++ )
817 rtl::OUString sAttrName
= xAttrList
->getNameByIndex( i
);
818 USHORT nPrefix
= GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
820 switch( rAttrTokenMap
.Get( nPrefix
, aLocalName
))
822 case XML_TOK_CELL_VAL_TYPE
:
823 aValue
= xAttrList
->getValueByIndex( i
);
824 if( IsXMLToken( aValue
, XML_FLOAT
) )
825 eValueType
= SCH_CELL_TYPE_FLOAT
;
826 else if( IsXMLToken( aValue
, XML_STRING
) )
827 eValueType
= SCH_CELL_TYPE_STRING
;
830 case XML_TOK_CELL_VALUE
:
831 aCellContent
= xAttrList
->getValueByIndex( i
);
836 mbReadPara
= sal_True
;
838 aCell
.eType
= eValueType
;
840 if( eValueType
== SCH_CELL_TYPE_FLOAT
)
843 // the result may be false if a NaN is read, but that's ok
844 SvXMLUnitConverter::convertDouble( fData
, aCellContent
);
846 aCell
.fValue
= fData
;
847 // dont read following <text:p> element
848 mbReadPara
= sal_False
;
851 mrTable
.aData
[ mrTable
.nRowIndex
].push_back( aCell
);
852 mrTable
.nColumnIndex
++;
853 if( mrTable
.nMaxColumnIndex
< mrTable
.nColumnIndex
)
854 mrTable
.nMaxColumnIndex
= mrTable
.nColumnIndex
;
857 SvXMLImportContext
* SchXMLTableCellContext::CreateChildContext(
859 const rtl::OUString
& rLocalName
,
860 const uno::Reference
< xml::sax::XAttributeList
>& )
862 SvXMLImportContext
* pContext
= 0;
865 if( nPrefix
== XML_NAMESPACE_TEXT
&&
866 IsXMLToken( rLocalName
, XML_P
) )
868 pContext
= new SchXMLParagraphContext( GetImport(), rLocalName
, maCellContent
, &maRangeId
);
872 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
878 void SchXMLTableCellContext::EndElement()
880 if( mbReadPara
&& maCellContent
.getLength())
881 mrTable
.aData
[ mrTable
.nRowIndex
][ mrTable
.nColumnIndex
].aString
= maCellContent
;
882 if( maRangeId
.getLength())
883 mrTable
.aData
[ mrTable
.nRowIndex
][ mrTable
.nColumnIndex
].aRangeId
= maRangeId
;
886 // ========================================
888 // just interpret the table in a linear way with no references used
889 // (this is just a workaround for clipboard handling in EA2)
890 void SchXMLTableHelper::applyTableSimple(
891 const SchXMLTable
& rTable
,
892 const uno::Reference
< chart::XChartDataArray
> & xData
)
894 // interpret table like this:
907 // Standard Role-interpretation:
909 // Column 1 contains the Categories
911 // Chart Type/Class | Col 2 Col 3 Col 4 Col 5 Col 6 | Series | Domain
912 // -----------------+-----------------------------------+--------+-------
913 // Category Charts | Y 1 Y 2 Y 3 Y 4 ... | Y | -
914 // XY Chart | X all Y 1 Y 2 Y 3 ... | Y | X
915 // Stock Chart 1 | Min Max Close - - | Close | -
916 // Stock Chart 2 | Open Min Max Close - | Close | -
917 // Stock Chart 3 | Volume Min Max Close - | Close | -
918 // Stock Chart 4 | Volume Open Min Max Close | Close | -
924 ::rtl::math::setNan( &fSolarNaN
);
925 double fNaN
= fSolarNaN
;
926 sal_Bool bConvertNaN
= sal_False
;
928 uno::Reference
< chart::XChartData
> xChartData( xData
, uno::UNO_QUERY
);
931 fNaN
= xChartData
->getNotANumber();
932 bConvertNaN
= ( ! ::rtl::math::isNan( fNaN
));
935 sal_Int32 nRowCount
= rTable
.aData
.size();
936 sal_Int32 nColumnCount
= 0;
937 sal_Int32 nCol
= 0, nRow
= 0;
940 nColumnCount
= rTable
.aData
[ 0 ].size();
941 ::std::vector
< ::std::vector
< SchXMLCell
> >::const_iterator iRow
= rTable
.aData
.begin();
942 while( iRow
!= rTable
.aData
.end() )
944 nColumnCount
= ::std::max( nColumnCount
, static_cast<sal_Int32
>(iRow
->size()) );
949 // #i27909# avoid illegal index access for empty tables
950 if( nColumnCount
== 0 || nRowCount
== 0 )
953 uno::Sequence
< ::rtl::OUString
> aCategories( nRowCount
- 1 );
954 uno::Sequence
< ::rtl::OUString
> aLabels( nColumnCount
- 1 );
955 uno::Sequence
< uno::Sequence
< double > > aData( nRowCount
- 1 );
956 for( nRow
= 0; nRow
< nRowCount
- 1; nRow
++ )
957 aData
[ nRow
].realloc( nColumnCount
- 1 );
960 ::std::vector
< ::std::vector
< SchXMLCell
> >::const_iterator iRow
= rTable
.aData
.begin();
961 sal_Int32 nColumnCountOnFirstRow
= iRow
->size();
962 for( nCol
= 1; nCol
< nColumnCountOnFirstRow
; nCol
++ )
964 aLabels
[ nCol
- 1 ] = (*iRow
)[ nCol
].aString
;
966 xData
->setColumnDescriptions( aLabels
);
969 const sal_Bool bConstConvertNan
= bConvertNaN
;
970 for( ++iRow
, nRow
= 0; iRow
!= rTable
.aData
.end(); iRow
++, nRow
++ )
972 aCategories
[ nRow
] = (*iRow
)[ 0 ].aString
;
973 sal_Int32
nTableColCount( static_cast< sal_Int32
>((*iRow
).size()));
974 for( nCol
= 1; nCol
< nTableColCount
; nCol
++ )
976 fVal
= (*iRow
)[ nCol
].fValue
;
977 if( bConstConvertNan
&&
978 ::rtl::math::isNan( fVal
))
979 aData
[ nRow
][ nCol
- 1 ] = fNaN
;
981 aData
[ nRow
][ nCol
- 1 ] = fVal
;
983 // set remaining cells to NaN
984 for( ; nCol
< nColumnCount
; ++nCol
)
985 if( bConstConvertNan
)
986 aData
[ nRow
][nCol
- 1 ] = fNaN
;
988 ::rtl::math::setNan( &(aData
[ nRow
][nCol
- 1 ]));
990 xData
->setRowDescriptions( aCategories
);
991 xData
->setData( aData
);
995 // ----------------------------------------
997 void SchXMLTableHelper::applyTableToInternalDataProvider(
998 const SchXMLTable
& rTable
,
999 uno::Reference
< chart2::XChartDocument
> xChartDoc
)
1001 if( ! (xChartDoc
.is() && xChartDoc
->hasInternalDataProvider()))
1003 Reference
< chart2::data::XDataProvider
> xDataProv( xChartDoc
->getDataProvider());
1004 Reference
< chart::XChartDataArray
> xDataArray( xDataProv
, uno::UNO_QUERY
);
1005 if( ! xDataArray
.is())
1007 OSL_ASSERT( xDataProv
.is());
1009 // prerequisite for this method: all objects (data series, domains, etc.)
1010 // need their own range string.
1012 // apply all data read in the table to the chart data-array of the internal
1014 lcl_applyXMLTableToInternalDataprovider( rTable
, xDataArray
);
1017 void SchXMLTableHelper::switchRangesFromOuterToInternalIfNecessary(
1018 const SchXMLTable
& rTable
,
1019 const tSchXMLLSequencesPerIndex
& rLSequencesPerIndex
,
1020 uno::Reference
< chart2::XChartDocument
> xChartDoc
,
1021 chart::ChartDataRowSource eDataRowSource
)
1023 if( ! (xChartDoc
.is() && xChartDoc
->hasInternalDataProvider()))
1026 // If the range-strings are valid (starting with "local-table") they should
1027 // be interpreted like given, otherwise (when the ranges refer to Calc- or
1028 // Writer-ranges, but the container is not available like when pasting a
1029 // chart from Calc to Impress) the range is ignored, and every object gets
1030 // one table column in the order of appearance, which is: 1. categories,
1031 // 2. data series: 2.a) domains, 2.b) values (main-role, usually y-values)
1033 Reference
< chart2::data::XDataProvider
> xDataProv( xChartDoc
->getDataProvider());
1035 // create a mapping from original ranges to new ranges
1036 lcl_tOriginalRangeToInternalRangeMap aRangeMap
;
1038 lcl_fillRangeMapping( rTable
, aRangeMap
, eDataRowSource
);
1040 bool bCategoriesApplied
= false;
1041 // translate ranges (using the map created before)
1042 for( tSchXMLLSequencesPerIndex::const_iterator
aLSeqIt( rLSequencesPerIndex
.begin());
1043 aLSeqIt
!= rLSequencesPerIndex
.end(); ++aLSeqIt
)
1045 if( aLSeqIt
->second
.is())
1047 // values/error bars/categories
1048 if( aLSeqIt
->first
.second
== SCH_XML_PART_VALUES
||
1049 aLSeqIt
->first
.second
== SCH_XML_PART_ERROR_BARS
)
1051 Reference
< chart2::data::XDataSequence
> xSeq( aLSeqIt
->second
->getValues());
1054 SchXMLTools::getXMLRangePropertyFromDataSequence( xSeq
, aRange
, /* bClearProp = */ true ) &&
1055 lcl_mapContainsRange( aRangeMap
, aRange
))
1057 Reference
< chart2::data::XDataSequence
> xNewSeq(
1058 lcl_reassignDataSequence( xSeq
, xDataProv
, aRangeMap
, aRange
));
1059 if( xNewSeq
!= xSeq
)
1061 SchXMLTools::copyProperties( Reference
< beans::XPropertySet
>( xSeq
, uno::UNO_QUERY
),
1062 Reference
< beans::XPropertySet
>( xNewSeq
, uno::UNO_QUERY
));
1063 aLSeqIt
->second
->setValues( xNewSeq
);
1068 if( lcl_tableOfRangeMatches( aRange
, rTable
.aTableNameOfFile
))
1070 if( aLSeqIt
->first
.first
== SCH_XML_CATEGORIES_INDEX
)
1071 bCategoriesApplied
= true;
1075 if( aLSeqIt
->first
.first
== SCH_XML_CATEGORIES_INDEX
)
1077 Reference
< beans::XPropertySet
> xOldSequenceProp( aLSeqIt
->second
->getValues(), uno::UNO_QUERY
);
1078 Reference
< chart2::data::XDataSequence
> xNewSequence(
1079 xDataProv
->createDataSequenceByRangeRepresentation(
1080 OUString(RTL_CONSTASCII_USTRINGPARAM("categories"))));
1081 SchXMLTools::copyProperties(
1082 xOldSequenceProp
, Reference
< beans::XPropertySet
>( xNewSequence
, uno::UNO_QUERY
));
1083 aLSeqIt
->second
->setValues( xNewSequence
);
1084 bCategoriesApplied
= true;
1088 Reference
< beans::XPropertySet
> xOldSequenceProp( aLSeqIt
->second
->getValues(), uno::UNO_QUERY
);
1089 OUString
aRep( OUString::valueOf( aLSeqIt
->first
.first
));
1090 Reference
< chart2::data::XDataSequence
> xNewSequence(
1091 xDataProv
->createDataSequenceByRangeRepresentation( aRep
));
1092 SchXMLTools::copyProperties(
1093 xOldSequenceProp
, Reference
< beans::XPropertySet
>( xNewSequence
, uno::UNO_QUERY
));
1094 aLSeqIt
->second
->setValues( xNewSequence
);
1101 OSL_ASSERT( aLSeqIt
->first
.second
== SCH_XML_PART_LABEL
);
1103 Reference
< chart2::data::XDataSequence
> xSeq( aLSeqIt
->second
->getLabel());
1106 SchXMLTools::getXMLRangePropertyFromDataSequence( xSeq
, aRange
, /* bClearProp = */ true ) &&
1107 lcl_mapContainsRange( aRangeMap
, aRange
))
1109 Reference
< chart2::data::XDataSequence
> xNewSeq(
1110 lcl_reassignDataSequence( xSeq
, xDataProv
, aRangeMap
, aRange
));
1111 if( xNewSeq
!= xSeq
)
1113 SchXMLTools::copyProperties( Reference
< beans::XPropertySet
>( xSeq
, uno::UNO_QUERY
),
1114 Reference
< beans::XPropertySet
>( xNewSeq
, uno::UNO_QUERY
));
1115 aLSeqIt
->second
->setLabel( xNewSeq
);
1118 else if( ! lcl_tableOfRangeMatches( aRange
, rTable
.aTableNameOfFile
))
1120 OUString
aRep( RTL_CONSTASCII_USTRINGPARAM("label "));
1121 aRep
+= OUString::valueOf( aLSeqIt
->first
.first
);
1123 Reference
< chart2::data::XDataSequence
> xNewSeq(
1124 xDataProv
->createDataSequenceByRangeRepresentation( aRep
));
1125 SchXMLTools::copyProperties( Reference
< beans::XPropertySet
>( xSeq
, uno::UNO_QUERY
),
1126 Reference
< beans::XPropertySet
>( xNewSeq
, uno::UNO_QUERY
));
1127 aLSeqIt
->second
->setLabel( xNewSeq
);
1133 // there exist files with own data without a categories element but with row
1134 // descriptions. The row descriptions were used as categories even without
1135 // the categories element
1136 if( ! bCategoriesApplied
)
1138 SchXMLTools::CreateCategories(
1139 xDataProv
, xChartDoc
, OUString(RTL_CONSTASCII_USTRINGPARAM("categories")),
1140 0 /* nCooSysIndex */, 0 /* nDimension */ );
1143 //i91578 display of hidden values (copy paste scenario; use hidden flag during migration to locale table upon paste )
1144 //remove series that consist only of hidden columns
1145 Reference
< chart2::XInternalDataProvider
> xInternalDataProvider( xDataProv
, uno::UNO_QUERY
);
1146 if( xInternalDataProvider
.is() && !rTable
.aHiddenColumns
.empty() )
1150 Reference
< chart2::XCoordinateSystemContainer
> xCooSysCnt( xChartDoc
->getFirstDiagram(), uno::UNO_QUERY_THROW
);
1151 Sequence
< Reference
< chart2::XCoordinateSystem
> > aCooSysSeq( xCooSysCnt
->getCoordinateSystems() );
1152 for( sal_Int32 nC
=0; nC
<aCooSysSeq
.getLength(); ++nC
)
1154 Reference
< chart2::XChartTypeContainer
> xCooSysContainer( aCooSysSeq
[nC
], uno::UNO_QUERY_THROW
);
1155 Sequence
< Reference
< chart2::XChartType
> > aChartTypeSeq( xCooSysContainer
->getChartTypes());
1156 for( sal_Int32 nT
=0; nT
<aChartTypeSeq
.getLength(); ++nT
)
1158 Reference
< chart2::XDataSeriesContainer
> xSeriesContainer( aChartTypeSeq
[nT
], uno::UNO_QUERY
);
1159 if(!xSeriesContainer
.is())
1161 Sequence
< Reference
< chart2::XDataSeries
> > aSeriesSeq( xSeriesContainer
->getDataSeries() );
1162 std::vector
< Reference
< chart2::XDataSeries
> > aRemainingSeries
;
1164 for( sal_Int32 nS
= 0; nS
< aSeriesSeq
.getLength(); nS
++ )
1166 Reference
< chart2::data::XDataSource
> xDataSource( aSeriesSeq
[nS
], uno::UNO_QUERY
);
1167 if( xDataSource
.is() )
1169 bool bHasUnhiddenColumns
= false;
1170 rtl::OUString aRange
;
1171 uno::Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSequences( xDataSource
->getDataSequences() );
1172 for( sal_Int32 nN
=0; nN
< aSequences
.getLength(); ++nN
)
1174 Reference
< chart2::data::XLabeledDataSequence
> xLabeledSequence( aSequences
[nN
] );
1175 if(!xLabeledSequence
.is())
1177 Reference
< chart2::data::XDataSequence
> xValues( xLabeledSequence
->getValues() );
1180 aRange
= xValues
->getSourceRangeRepresentation();
1181 if( ::std::find( rTable
.aHiddenColumns
.begin(), rTable
.aHiddenColumns
.end(), aRange
.toInt32() ) == rTable
.aHiddenColumns
.end() )
1182 bHasUnhiddenColumns
= true;
1184 if( !bHasUnhiddenColumns
)
1186 Reference
< chart2::data::XDataSequence
> xLabel( xLabeledSequence
->getLabel() );
1189 aRange
= xLabel
->getSourceRangeRepresentation();
1190 sal_Int32 nSearchIndex
= 0;
1191 OUString aSecondToken
= aRange
.getToken( 1, ' ', nSearchIndex
);
1192 if( ::std::find( rTable
.aHiddenColumns
.begin(), rTable
.aHiddenColumns
.end(), aSecondToken
.toInt32() ) == rTable
.aHiddenColumns
.end() )
1193 bHasUnhiddenColumns
= true;
1197 if( bHasUnhiddenColumns
)
1198 aRemainingSeries
.push_back( aSeriesSeq
[nS
] );
1202 if( static_cast<sal_Int32
>(aRemainingSeries
.size()) != aSeriesSeq
.getLength() )
1204 //remove the series that have only hidden data
1205 Sequence
< Reference
< chart2::XDataSeries
> > aRemainingSeriesSeq( aRemainingSeries
.size());
1206 ::std::copy( aRemainingSeries
.begin(), aRemainingSeries
.end(), aRemainingSeriesSeq
.getArray());
1207 xSeriesContainer
->setDataSeries( aRemainingSeriesSeq
);
1209 //remove unused sequences
1210 Reference
< chart2::data::XDataSource
> xDataSource( xChartDoc
, uno::UNO_QUERY
);
1211 if( xDataSource
.is() )
1213 //first detect which collumns are really used
1214 std::map
< sal_Int32
, bool > aUsageMap
;
1215 rtl::OUString aRange
;
1216 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aUsedSequences( xDataSource
->getDataSequences() );
1217 for( sal_Int32 nN
=0; nN
< aUsedSequences
.getLength(); ++nN
)
1219 Reference
< chart2::data::XLabeledDataSequence
> xLabeledSequence( aUsedSequences
[nN
] );
1220 if(!xLabeledSequence
.is())
1222 Reference
< chart2::data::XDataSequence
> xValues( xLabeledSequence
->getValues() );
1225 aRange
= xValues
->getSourceRangeRepresentation();
1226 sal_Int32 nIndex
= aRange
.toInt32();
1227 if( nIndex
!=0 || !aRange
.equals(lcl_aCategoriesRange
) )
1228 aUsageMap
[nIndex
] = true;
1230 Reference
< chart2::data::XDataSequence
> xLabel( xLabeledSequence
->getLabel() );
1233 aRange
= xLabel
->getSourceRangeRepresentation();
1234 sal_Int32 nSearchIndex
= 0;
1235 OUString aSecondToken
= aRange
.getToken( 1, ' ', nSearchIndex
);
1236 if( aSecondToken
.getLength() )
1237 aUsageMap
[aSecondToken
.toInt32()] = true;
1241 ::std::vector
< sal_Int32
> aSequenceIndexesToDelete
;
1242 for( ::std::vector
< sal_Int32
>::const_iterator
aIt(
1243 rTable
.aHiddenColumns
.begin()); aIt
!= rTable
.aHiddenColumns
.end(); ++aIt
)
1245 sal_Int32 nSequenceIndex
= *aIt
;
1246 if( aUsageMap
.find(nSequenceIndex
) != aUsageMap
.end() )
1248 aSequenceIndexesToDelete
.push_back(nSequenceIndex
);
1251 // delete unnecessary sequences of the internal data
1252 // iterate using greatest index first, so that deletion does not
1253 // shift other sequences that will be deleted later
1254 ::std::sort( aSequenceIndexesToDelete
.begin(), aSequenceIndexesToDelete
.end());
1255 for( ::std::vector
< sal_Int32
>::reverse_iterator
aIt(
1256 aSequenceIndexesToDelete
.rbegin()); aIt
!= aSequenceIndexesToDelete
.rend(); ++aIt
)
1259 xInternalDataProvider
->deleteSequence( *aIt
);
1266 catch( uno::Exception
& ex
)
1268 (void)ex
; // avoid warning for pro build