xref: /AOO41X/main/xmloff/source/chart/SchXMLTableContext.cxx (revision 63bba73cc51e0afb45f8a8d578158724bb5afee8)
1*63bba73cSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*63bba73cSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*63bba73cSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*63bba73cSAndrew Rist  * distributed with this work for additional information
6*63bba73cSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*63bba73cSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*63bba73cSAndrew Rist  * "License"); you may not use this file except in compliance
9*63bba73cSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*63bba73cSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*63bba73cSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*63bba73cSAndrew Rist  * software distributed under the License is distributed on an
15*63bba73cSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*63bba73cSAndrew Rist  * KIND, either express or implied.  See the License for the
17*63bba73cSAndrew Rist  * specific language governing permissions and limitations
18*63bba73cSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*63bba73cSAndrew Rist  *************************************************************/
21*63bba73cSAndrew Rist 
22*63bba73cSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_xmloff.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "SchXMLTableContext.hxx"
28cdf0e10cSrcweir #include "SchXMLParagraphContext.hxx"
29cdf0e10cSrcweir #include "SchXMLTextListContext.hxx"
30cdf0e10cSrcweir #include "SchXMLImport.hxx"
31cdf0e10cSrcweir #include "SchXMLTools.hxx"
32cdf0e10cSrcweir #include "transporttypes.hxx"
33cdf0e10cSrcweir #include "XMLStringBufferImportContext.hxx"
34cdf0e10cSrcweir #include <tools/debug.hxx>
35cdf0e10cSrcweir #include <rtl/math.hxx>
36cdf0e10cSrcweir #include "xmloff/xmlnmspe.hxx"
37cdf0e10cSrcweir #include <xmloff/xmltoken.hxx>
38cdf0e10cSrcweir #include <xmloff/nmspmap.hxx>
39cdf0e10cSrcweir #include <xmloff/xmluconv.hxx>
40cdf0e10cSrcweir #include <com/sun/star/frame/XModel.hpp>
41cdf0e10cSrcweir #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
42cdf0e10cSrcweir #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
43cdf0e10cSrcweir #include <com/sun/star/chart2/XChartDocument.hpp>
44cdf0e10cSrcweir #include <com/sun/star/chart2/XChartTypeContainer.hpp>
45cdf0e10cSrcweir #include <com/sun/star/chart2/XInternalDataProvider.hpp>
46cdf0e10cSrcweir #include <com/sun/star/chart/ChartSeriesAddress.hpp>
47cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
48cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySetInfo.hpp>
49cdf0e10cSrcweir #include <com/sun/star/beans/PropertyAttribute.hpp>
50cdf0e10cSrcweir 
51cdf0e10cSrcweir #include <com/sun/star/chart2/XDiagram.hpp>
52cdf0e10cSrcweir #include <com/sun/star/chart2/XAxis.hpp>
53cdf0e10cSrcweir #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
54cdf0e10cSrcweir #include <com/sun/star/chart2/AxisType.hpp>
55cdf0e10cSrcweir 
56cdf0e10cSrcweir #include <vector>
57cdf0e10cSrcweir #include <algorithm>
58cdf0e10cSrcweir 
59cdf0e10cSrcweir using namespace com::sun::star;
60cdf0e10cSrcweir using namespace ::xmloff::token;
61cdf0e10cSrcweir using ::com::sun::star::uno::Sequence;
62cdf0e10cSrcweir using ::com::sun::star::uno::Reference;
63cdf0e10cSrcweir using ::rtl::OUString;
64cdf0e10cSrcweir 
65cdf0e10cSrcweir namespace
66cdf0e10cSrcweir {
67cdf0e10cSrcweir 
68cdf0e10cSrcweir const OUString lcl_aLabelPrefix( RTL_CONSTASCII_USTRINGPARAM("label "));
69cdf0e10cSrcweir const OUString lcl_aCategoriesRange( RTL_CONSTASCII_USTRINGPARAM("categories"));
70cdf0e10cSrcweir 
71cdf0e10cSrcweir typedef ::std::multimap< ::rtl::OUString, ::rtl::OUString >
72cdf0e10cSrcweir     lcl_tOriginalRangeToInternalRangeMap;
73cdf0e10cSrcweir 
74cdf0e10cSrcweir Sequence< OUString > lcl_getCategoriesFromTable( const SchXMLTable & rTable, bool bHasLabels )
75cdf0e10cSrcweir {
76cdf0e10cSrcweir     sal_Int32 nNumRows( static_cast< sal_Int32 >( rTable.aData.size()));
77cdf0e10cSrcweir     OSL_ENSURE( static_cast< size_t >( nNumRows ) == rTable.aData.size(), "Table too big" );
78cdf0e10cSrcweir 
79cdf0e10cSrcweir     sal_Int32 nOffset(bHasLabels ? 1 : 0);
80cdf0e10cSrcweir     Sequence< OUString > aResult( nNumRows - nOffset );
81cdf0e10cSrcweir     sal_Int32 i=nOffset;
82cdf0e10cSrcweir     for( ; i<nNumRows; ++i )
83cdf0e10cSrcweir     {
84cdf0e10cSrcweir         if( !rTable.aData[i].empty() && (rTable.aData[i].front().eType == SCH_CELL_TYPE_STRING ))
85cdf0e10cSrcweir             aResult[i - nOffset] = rTable.aData[i].front().aString;
86cdf0e10cSrcweir     }
87cdf0e10cSrcweir     return aResult;
88cdf0e10cSrcweir }
89cdf0e10cSrcweir 
90cdf0e10cSrcweir std::vector< Reference< chart2::XAxis > > lcl_getAxesHoldingCategoriesFromDiagram(
91cdf0e10cSrcweir     const Reference< chart2::XDiagram > & xDiagram )
92cdf0e10cSrcweir {
93cdf0e10cSrcweir     std::vector< Reference< chart2::XAxis > > aRet;
94cdf0e10cSrcweir 
95cdf0e10cSrcweir     Reference< chart2::XAxis > xResult;
96cdf0e10cSrcweir     // return first x-axis as fall-back
97cdf0e10cSrcweir     Reference< chart2::XAxis > xFallBack;
98cdf0e10cSrcweir     try
99cdf0e10cSrcweir     {
100cdf0e10cSrcweir         Reference< chart2::XCoordinateSystemContainer > xCooSysCnt(
101cdf0e10cSrcweir             xDiagram, uno::UNO_QUERY_THROW );
102cdf0e10cSrcweir         Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq(
103cdf0e10cSrcweir             xCooSysCnt->getCoordinateSystems());
104cdf0e10cSrcweir         for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
105cdf0e10cSrcweir         {
106cdf0e10cSrcweir             Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[i] );
107cdf0e10cSrcweir             OSL_ASSERT( xCooSys.is());
108cdf0e10cSrcweir             for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
109cdf0e10cSrcweir             {
110cdf0e10cSrcweir                 const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
111cdf0e10cSrcweir                 for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
112cdf0e10cSrcweir                 {
113cdf0e10cSrcweir                     Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( nN,nI );
114cdf0e10cSrcweir                     OSL_ASSERT( xAxis.is());
115cdf0e10cSrcweir                     if( xAxis.is())
116cdf0e10cSrcweir                     {
117cdf0e10cSrcweir                         chart2::ScaleData aScaleData = xAxis->getScaleData();
118cdf0e10cSrcweir                         if( aScaleData.Categories.is() || (aScaleData.AxisType == chart2::AxisType::CATEGORY) )
119cdf0e10cSrcweir                         {
120cdf0e10cSrcweir                             aRet.push_back(xAxis);
121cdf0e10cSrcweir                         }
122cdf0e10cSrcweir                         if( (nN == 0) && !xFallBack.is())
123cdf0e10cSrcweir                             xFallBack.set( xAxis );
124cdf0e10cSrcweir                     }
125cdf0e10cSrcweir                 }
126cdf0e10cSrcweir             }
127cdf0e10cSrcweir         }
128cdf0e10cSrcweir     }
129cdf0e10cSrcweir     catch( uno::Exception & )
130cdf0e10cSrcweir     {
131cdf0e10cSrcweir     }
132cdf0e10cSrcweir 
133cdf0e10cSrcweir     if( aRet.empty())
134cdf0e10cSrcweir         aRet.push_back(xFallBack);
135cdf0e10cSrcweir 
136cdf0e10cSrcweir     return aRet;
137cdf0e10cSrcweir }
138cdf0e10cSrcweir 
139cdf0e10cSrcweir struct lcl_ApplyCellToData : public ::std::unary_function< SchXMLCell, void >
140cdf0e10cSrcweir {
141cdf0e10cSrcweir     lcl_ApplyCellToData( Sequence< double > & rOutData ) :
142cdf0e10cSrcweir             m_rData( rOutData ),
143cdf0e10cSrcweir             m_nIndex( 0 ),
144cdf0e10cSrcweir             m_nSize( rOutData.getLength())
145cdf0e10cSrcweir     {
146cdf0e10cSrcweir         ::rtl::math::setNan( &m_fNaN );
147cdf0e10cSrcweir     }
148cdf0e10cSrcweir 
149cdf0e10cSrcweir     void operator() ( const SchXMLCell & rCell )
150cdf0e10cSrcweir     {
151cdf0e10cSrcweir         if( m_nIndex < m_nSize )
152cdf0e10cSrcweir         {
153cdf0e10cSrcweir             if( rCell.eType == SCH_CELL_TYPE_FLOAT )
154cdf0e10cSrcweir                 m_rData[m_nIndex] = rCell.fValue;
155cdf0e10cSrcweir             else
156cdf0e10cSrcweir                 m_rData[m_nIndex] = m_fNaN;
157cdf0e10cSrcweir         }
158cdf0e10cSrcweir         ++m_nIndex;
159cdf0e10cSrcweir     }
160cdf0e10cSrcweir 
161cdf0e10cSrcweir     sal_Int32 getCurrentIndex() const
162cdf0e10cSrcweir     {
163cdf0e10cSrcweir         return m_nIndex;
164cdf0e10cSrcweir     }
165cdf0e10cSrcweir 
166cdf0e10cSrcweir private:
167cdf0e10cSrcweir     Sequence< double > & m_rData;
168cdf0e10cSrcweir     sal_Int32 m_nIndex;
169cdf0e10cSrcweir     sal_Int32 m_nSize;
170cdf0e10cSrcweir     double m_fNaN;
171cdf0e10cSrcweir };
172cdf0e10cSrcweir 
173cdf0e10cSrcweir Sequence< Sequence< double > > lcl_getSwappedArray( const Sequence< Sequence< double > > & rData )
174cdf0e10cSrcweir {
175cdf0e10cSrcweir     sal_Int32 nOldOuterSize = rData.getLength();
176cdf0e10cSrcweir     sal_Int32 nOldInnerSize = (nOldOuterSize == 0 ? 0 : rData[0].getLength());
177cdf0e10cSrcweir     Sequence< Sequence< double > > aResult( nOldInnerSize );
178cdf0e10cSrcweir 
179cdf0e10cSrcweir     for( sal_Int32 i=0; i<nOldInnerSize; ++i )
180cdf0e10cSrcweir         aResult[i].realloc( nOldOuterSize );
181cdf0e10cSrcweir 
182cdf0e10cSrcweir     for( sal_Int32 nOuter=0; nOuter<nOldOuterSize; ++nOuter )
183cdf0e10cSrcweir         for( sal_Int32 nInner=0; nInner<nOldInnerSize; ++nInner )
184cdf0e10cSrcweir             aResult[nInner][nOuter] = rData[nOuter][nInner];
185cdf0e10cSrcweir 
186cdf0e10cSrcweir     return aResult;
187cdf0e10cSrcweir }
188cdf0e10cSrcweir 
189cdf0e10cSrcweir void lcl_fillRangeMapping(
190cdf0e10cSrcweir     const SchXMLTable & rTable,
191cdf0e10cSrcweir     lcl_tOriginalRangeToInternalRangeMap & rOutRangeMap,
192cdf0e10cSrcweir     chart::ChartDataRowSource eDataRowSource )
193cdf0e10cSrcweir {
194cdf0e10cSrcweir     sal_Int32 nRowOffset = ( rTable.bHasHeaderRow ? 1 : 0 );
195cdf0e10cSrcweir     sal_Int32 nColOffset = ( rTable.bHasHeaderColumn ? 1 : 0 );
196cdf0e10cSrcweir 
197cdf0e10cSrcweir     // Fill range mapping
198cdf0e10cSrcweir     const size_t nTableRowCount( rTable.aData.size());
199cdf0e10cSrcweir     for( size_t nRow = 0; nRow < nTableRowCount; ++nRow )
200cdf0e10cSrcweir     {
201cdf0e10cSrcweir         const ::std::vector< SchXMLCell > & rRow( rTable.aData[nRow] );
202cdf0e10cSrcweir         const size_t nTableColCount( rRow.size());
203cdf0e10cSrcweir         for( size_t nCol = 0; nCol < nTableColCount; ++nCol )
204cdf0e10cSrcweir         {
205cdf0e10cSrcweir             OUString aRangeId( rRow[nCol].aRangeId );
206cdf0e10cSrcweir             if( aRangeId.getLength())
207cdf0e10cSrcweir             {
208cdf0e10cSrcweir                 if( eDataRowSource == chart::ChartDataRowSource_COLUMNS )
209cdf0e10cSrcweir                 {
210cdf0e10cSrcweir                     if( nCol == 0 && rTable.bHasHeaderColumn )
211cdf0e10cSrcweir                     {
212cdf0e10cSrcweir                         OSL_ASSERT( static_cast< sal_Int32 >( nRow ) == nRowOffset );
213cdf0e10cSrcweir                         rOutRangeMap.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
214cdf0e10cSrcweir                                                  aRangeId, lcl_aCategoriesRange ));
215cdf0e10cSrcweir                     }
216cdf0e10cSrcweir                     else
217cdf0e10cSrcweir                     {
218cdf0e10cSrcweir                         OUString aColNumStr = OUString::valueOf( static_cast< sal_Int32 >( nCol - nColOffset ));
219cdf0e10cSrcweir                         if( nRow == 0 && rTable.bHasHeaderRow )
220cdf0e10cSrcweir                             rOutRangeMap.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
221cdf0e10cSrcweir                                                      aRangeId, lcl_aLabelPrefix + aColNumStr ));
222cdf0e10cSrcweir                         else
223cdf0e10cSrcweir                             rOutRangeMap.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
224cdf0e10cSrcweir                                                      aRangeId, aColNumStr ));
225cdf0e10cSrcweir                     }
226cdf0e10cSrcweir                 }
227cdf0e10cSrcweir                 else // eDataRowSource == chart::ChartDataRowSource_ROWS
228cdf0e10cSrcweir                 {
229cdf0e10cSrcweir                     if( nRow == 0 && rTable.bHasHeaderRow )
230cdf0e10cSrcweir                     {
231cdf0e10cSrcweir                         OSL_ASSERT( static_cast< sal_Int32 >( nCol ) == nColOffset );
232cdf0e10cSrcweir                         rOutRangeMap.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
233cdf0e10cSrcweir                                                  aRangeId, lcl_aCategoriesRange ));
234cdf0e10cSrcweir                     }
235cdf0e10cSrcweir                     else
236cdf0e10cSrcweir                     {
237cdf0e10cSrcweir                         OUString aRowNumStr = OUString::valueOf( static_cast< sal_Int32 >( nRow - nRowOffset ));
238cdf0e10cSrcweir                         if( nCol == 0 && rTable.bHasHeaderColumn )
239cdf0e10cSrcweir                             rOutRangeMap.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
240cdf0e10cSrcweir                                                      aRangeId, lcl_aLabelPrefix + aRowNumStr ));
241cdf0e10cSrcweir                         else
242cdf0e10cSrcweir                             rOutRangeMap.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
243cdf0e10cSrcweir                                                      aRangeId, aRowNumStr ));
244cdf0e10cSrcweir                     }
245cdf0e10cSrcweir                 }
246cdf0e10cSrcweir             }
247cdf0e10cSrcweir         }
248cdf0e10cSrcweir     }
249cdf0e10cSrcweir }
250cdf0e10cSrcweir 
251cdf0e10cSrcweir Reference< chart2::data::XDataSequence >
252cdf0e10cSrcweir     lcl_reassignDataSequence(
253cdf0e10cSrcweir         const Reference< chart2::data::XDataSequence > & xSequence,
254cdf0e10cSrcweir         const Reference< chart2::data::XDataProvider > & xDataProvider,
255cdf0e10cSrcweir         lcl_tOriginalRangeToInternalRangeMap & rRangeMap,
256cdf0e10cSrcweir         const OUString & rRange )
257cdf0e10cSrcweir {
258cdf0e10cSrcweir     Reference< chart2::data::XDataSequence > xResult( xSequence );
259cdf0e10cSrcweir     lcl_tOriginalRangeToInternalRangeMap::iterator aIt( rRangeMap.find( rRange ));
260cdf0e10cSrcweir     if( aIt != rRangeMap.end())
261cdf0e10cSrcweir     {
262cdf0e10cSrcweir         // set sequence with correct data
263cdf0e10cSrcweir         xResult.set( xDataProvider->createDataSequenceByRangeRepresentation( aIt->second ));
264cdf0e10cSrcweir         // remove translation, because it was used
265cdf0e10cSrcweir         rRangeMap.erase( aIt );
266cdf0e10cSrcweir     }
267cdf0e10cSrcweir 
268cdf0e10cSrcweir     return xResult;
269cdf0e10cSrcweir }
270cdf0e10cSrcweir 
271cdf0e10cSrcweir bool lcl_mapContainsRange(
272cdf0e10cSrcweir     lcl_tOriginalRangeToInternalRangeMap & rRangeMap,
273cdf0e10cSrcweir     const OUString & rRange )
274cdf0e10cSrcweir {
275cdf0e10cSrcweir     lcl_tOriginalRangeToInternalRangeMap::iterator aIt( rRangeMap.find( rRange ));
276cdf0e10cSrcweir     return ( aIt != rRangeMap.end());
277cdf0e10cSrcweir }
278cdf0e10cSrcweir 
279cdf0e10cSrcweir bool lcl_tableOfRangeMatches(
280cdf0e10cSrcweir     const ::rtl::OUString & rRange,
281cdf0e10cSrcweir     const ::rtl::OUString & rTableName )
282cdf0e10cSrcweir {
283cdf0e10cSrcweir     // both strings are non-empty and the table name is part of the range
284cdf0e10cSrcweir     return ( (rRange.getLength() > 0) &&
285cdf0e10cSrcweir              (rTableName.getLength() > 0) &&
286cdf0e10cSrcweir              (rRange.indexOf( rTableName ) != -1 ));
287cdf0e10cSrcweir }
288cdf0e10cSrcweir 
289cdf0e10cSrcweir template< typename T >
290cdf0e10cSrcweir ::std::vector< T > lcl_SequenceToVector( const uno::Sequence< T > & rSequence )
291cdf0e10cSrcweir {
292cdf0e10cSrcweir     ::std::vector< T > aResult( rSequence.getLength());
293cdf0e10cSrcweir     ::std::copy( rSequence.getConstArray(), rSequence.getConstArray() + rSequence.getLength(),
294cdf0e10cSrcweir                  aResult.begin());
295cdf0e10cSrcweir     return aResult;
296cdf0e10cSrcweir }
297cdf0e10cSrcweir 
298cdf0e10cSrcweir } // anonymous namespace
299cdf0e10cSrcweir 
300cdf0e10cSrcweir 
301cdf0e10cSrcweir // ----------------------------------------
302cdf0e10cSrcweir // class SchXMLTableContext
303cdf0e10cSrcweir // ----------------------------------------
304cdf0e10cSrcweir 
305cdf0e10cSrcweir SchXMLTableContext::SchXMLTableContext( SchXMLImportHelper& rImpHelper,
306cdf0e10cSrcweir 										SvXMLImport& rImport,
307cdf0e10cSrcweir 										const rtl::OUString& rLName,
308cdf0e10cSrcweir 										SchXMLTable& aTable ) :
309cdf0e10cSrcweir 		SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLName ),
310cdf0e10cSrcweir 		mrImportHelper( rImpHelper ),
311cdf0e10cSrcweir 		mrTable( aTable ),
312cdf0e10cSrcweir         mbHasRowPermutation( false ),
313cdf0e10cSrcweir         mbHasColumnPermutation( false )
314cdf0e10cSrcweir {
315cdf0e10cSrcweir 	mrTable.nColumnIndex = -1;
316cdf0e10cSrcweir 	mrTable.nMaxColumnIndex = -1;
317cdf0e10cSrcweir 	mrTable.nRowIndex = -1;
318cdf0e10cSrcweir 	mrTable.aData.clear();
319cdf0e10cSrcweir }
320cdf0e10cSrcweir 
321cdf0e10cSrcweir SchXMLTableContext::~SchXMLTableContext()
322cdf0e10cSrcweir {
323cdf0e10cSrcweir }
324cdf0e10cSrcweir 
325cdf0e10cSrcweir SvXMLImportContext *SchXMLTableContext::CreateChildContext(
326cdf0e10cSrcweir 	sal_uInt16 nPrefix,
327cdf0e10cSrcweir 	const rtl::OUString& rLocalName,
328cdf0e10cSrcweir 	const uno::Reference< xml::sax::XAttributeList >& )
329cdf0e10cSrcweir {
330cdf0e10cSrcweir 	SvXMLImportContext* pContext = 0;
331cdf0e10cSrcweir 	const SvXMLTokenMap& rTokenMap = mrImportHelper.GetTableElemTokenMap();
332cdf0e10cSrcweir 
333cdf0e10cSrcweir 	switch( rTokenMap.Get( nPrefix, rLocalName ))
334cdf0e10cSrcweir 	{
335cdf0e10cSrcweir 		case XML_TOK_TABLE_HEADER_COLS:
336cdf0e10cSrcweir             mrTable.bHasHeaderColumn = true;
337cdf0e10cSrcweir             // fall through intended
338cdf0e10cSrcweir 		case XML_TOK_TABLE_COLUMNS:
339cdf0e10cSrcweir 			pContext = new SchXMLTableColumnsContext( mrImportHelper, GetImport(), rLocalName, mrTable );
340cdf0e10cSrcweir 			break;
341cdf0e10cSrcweir 
342cdf0e10cSrcweir 		case XML_TOK_TABLE_COLUMN:
343cdf0e10cSrcweir 			pContext = new SchXMLTableColumnContext( mrImportHelper, GetImport(), rLocalName, mrTable );
344cdf0e10cSrcweir 			break;
345cdf0e10cSrcweir 
346cdf0e10cSrcweir 		case XML_TOK_TABLE_HEADER_ROWS:
347cdf0e10cSrcweir             mrTable.bHasHeaderRow = true;
348cdf0e10cSrcweir             // fall through intended
349cdf0e10cSrcweir 		case XML_TOK_TABLE_ROWS:
350cdf0e10cSrcweir 			pContext = new SchXMLTableRowsContext( mrImportHelper, GetImport(), rLocalName, mrTable );
351cdf0e10cSrcweir 			break;
352cdf0e10cSrcweir 
353cdf0e10cSrcweir 		case XML_TOK_TABLE_ROW:
354cdf0e10cSrcweir 			pContext = new SchXMLTableRowContext( mrImportHelper, GetImport(), rLocalName, mrTable );
355cdf0e10cSrcweir 			break;
356cdf0e10cSrcweir 
357cdf0e10cSrcweir 		default:
358cdf0e10cSrcweir 			pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
359cdf0e10cSrcweir 	}
360cdf0e10cSrcweir 
361cdf0e10cSrcweir 	return pContext;
362cdf0e10cSrcweir }
363cdf0e10cSrcweir 
364cdf0e10cSrcweir void SchXMLTableContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
365cdf0e10cSrcweir {
366cdf0e10cSrcweir     // get table-name
367cdf0e10cSrcweir 	sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
368cdf0e10cSrcweir 
369cdf0e10cSrcweir 	for( sal_Int16 i = 0; i < nAttrCount; i++ )
370cdf0e10cSrcweir 	{
371cdf0e10cSrcweir 		rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
372cdf0e10cSrcweir 		rtl::OUString aLocalName;
373cdf0e10cSrcweir 		sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
374cdf0e10cSrcweir         if ( nPrefix == XML_NAMESPACE_TABLE )
375cdf0e10cSrcweir         {
376cdf0e10cSrcweir             if ( IsXMLToken( aLocalName, XML_NAME ) )
377cdf0e10cSrcweir             {
378cdf0e10cSrcweir                 mrTable.aTableNameOfFile = xAttrList->getValueByIndex( i );
379cdf0e10cSrcweir             }
380cdf0e10cSrcweir             else if ( IsXMLToken( aLocalName, XML_PROTECTED ) )
381cdf0e10cSrcweir             {
382cdf0e10cSrcweir                 if ( IsXMLToken( xAttrList->getValueByIndex( i ), XML_TRUE ) )
383cdf0e10cSrcweir                 {
384cdf0e10cSrcweir                     mrTable.bProtected = true;
385cdf0e10cSrcweir                 }
386cdf0e10cSrcweir             }
387cdf0e10cSrcweir         }
388cdf0e10cSrcweir 	}
389cdf0e10cSrcweir }
390cdf0e10cSrcweir 
391cdf0e10cSrcweir void SchXMLTableContext::EndElement()
392cdf0e10cSrcweir {
393cdf0e10cSrcweir     if( mbHasColumnPermutation )
394cdf0e10cSrcweir     {
395cdf0e10cSrcweir         OSL_ASSERT( !mbHasRowPermutation );
396cdf0e10cSrcweir         ::std::vector< sal_Int32 > aPermutation( lcl_SequenceToVector( maColumnPermutation ));
397cdf0e10cSrcweir         OSL_ASSERT( !aPermutation.empty());
398cdf0e10cSrcweir         if( aPermutation.empty())
399cdf0e10cSrcweir             return;
400cdf0e10cSrcweir 
401cdf0e10cSrcweir         // permute the values of all rows according to aPermutation
402cdf0e10cSrcweir         for( ::std::vector< ::std::vector< SchXMLCell > >::iterator aRowIt( mrTable.aData.begin());
403cdf0e10cSrcweir              aRowIt != mrTable.aData.end(); ++aRowIt )
404cdf0e10cSrcweir         {
405cdf0e10cSrcweir             bool bModified = false;
406cdf0e10cSrcweir             ::std::vector< SchXMLCell > aModifiedRow;
407cdf0e10cSrcweir             const size_t nPermSize = aPermutation.size();
408cdf0e10cSrcweir             OSL_ASSERT( static_cast< sal_Int32 >( nPermSize ) - 1 == *(::std::max_element( aPermutation.begin(), aPermutation.end())));
409cdf0e10cSrcweir             const size_t nRowSize = aRowIt->size();
410cdf0e10cSrcweir             const size_t nDestSize = ::std::min( nPermSize, nRowSize );
411cdf0e10cSrcweir             for( size_t nDestinationIndex = 0; nDestinationIndex < nDestSize; ++nDestinationIndex )
412cdf0e10cSrcweir             {
413cdf0e10cSrcweir                 const size_t nSourceIndex = static_cast< size_t >( aPermutation[ nDestinationIndex ] );
414cdf0e10cSrcweir                 if( nSourceIndex != nDestinationIndex &&
415cdf0e10cSrcweir                     nSourceIndex < nRowSize )
416cdf0e10cSrcweir                 {
417cdf0e10cSrcweir                     // copy original on first real permutation
418cdf0e10cSrcweir                     if( !bModified )
419cdf0e10cSrcweir                     {
420cdf0e10cSrcweir                         OSL_ASSERT( aModifiedRow.empty());
421cdf0e10cSrcweir                         aModifiedRow.reserve( aRowIt->size());
422cdf0e10cSrcweir                         ::std::copy( aRowIt->begin(), aRowIt->end(), ::std::back_inserter( aModifiedRow ));
423cdf0e10cSrcweir                         OSL_ASSERT( !aModifiedRow.empty());
424cdf0e10cSrcweir                     }
425cdf0e10cSrcweir                     OSL_ASSERT( nDestinationIndex < aModifiedRow.size());
426cdf0e10cSrcweir                     aModifiedRow[ nDestinationIndex ] = (*aRowIt)[ nSourceIndex ];
427cdf0e10cSrcweir                     bModified = true;
428cdf0e10cSrcweir                 }
429cdf0e10cSrcweir             }
430cdf0e10cSrcweir             // copy back
431cdf0e10cSrcweir             if( bModified )
432cdf0e10cSrcweir                 ::std::copy( aModifiedRow.begin(), aModifiedRow.end(), aRowIt->begin());
433cdf0e10cSrcweir         }
434cdf0e10cSrcweir     }
435cdf0e10cSrcweir     else if( mbHasRowPermutation )
436cdf0e10cSrcweir     {
437cdf0e10cSrcweir         ::std::vector< sal_Int32 > aPermutation( lcl_SequenceToVector( maRowPermutation ));
438cdf0e10cSrcweir         OSL_ASSERT( !aPermutation.empty());
439cdf0e10cSrcweir         if( aPermutation.empty())
440cdf0e10cSrcweir             return;
441cdf0e10cSrcweir 
442cdf0e10cSrcweir         bool bModified = false;
443cdf0e10cSrcweir         const size_t nPermSize = aPermutation.size();
444cdf0e10cSrcweir         OSL_ASSERT( static_cast< sal_Int32 >( nPermSize ) - 1 == *(::std::max_element( aPermutation.begin(), aPermutation.end())));
445cdf0e10cSrcweir         const size_t nTableRowCount = mrTable.aData.size();
446cdf0e10cSrcweir         const size_t nDestSize = ::std::min( nPermSize, nTableRowCount );
447cdf0e10cSrcweir         ::std::vector< ::std::vector< SchXMLCell > > aDestination;
448cdf0e10cSrcweir         for( size_t nDestinationIndex = 0; nDestinationIndex < nDestSize; ++nDestinationIndex )
449cdf0e10cSrcweir         {
450cdf0e10cSrcweir             const size_t nSourceIndex = static_cast< size_t >( aPermutation[ nDestinationIndex ] );
451cdf0e10cSrcweir             if( nSourceIndex != nDestinationIndex &&
452cdf0e10cSrcweir                 nSourceIndex < nTableRowCount )
453cdf0e10cSrcweir             {
454cdf0e10cSrcweir                 // copy original on first real permutation
455cdf0e10cSrcweir                 if( !bModified )
456cdf0e10cSrcweir                 {
457cdf0e10cSrcweir                     OSL_ASSERT( aDestination.empty());
458cdf0e10cSrcweir                     aDestination.reserve( mrTable.aData.size());
459cdf0e10cSrcweir                     ::std::copy( mrTable.aData.begin(), mrTable.aData.end(), ::std::back_inserter( aDestination ));
460cdf0e10cSrcweir                     OSL_ASSERT( !aDestination.empty());
461cdf0e10cSrcweir                 }
462cdf0e10cSrcweir                 OSL_ASSERT( nDestinationIndex < aDestination.size());
463cdf0e10cSrcweir                 aDestination[ nDestinationIndex ] = mrTable.aData[ nSourceIndex ];
464cdf0e10cSrcweir                 bModified = true;
465cdf0e10cSrcweir             }
466cdf0e10cSrcweir         }
467cdf0e10cSrcweir         if( bModified )
468cdf0e10cSrcweir         {
469cdf0e10cSrcweir             // copy back
470cdf0e10cSrcweir             ::std::copy( aDestination.begin(), aDestination.end(), mrTable.aData.begin());
471cdf0e10cSrcweir         }
472cdf0e10cSrcweir     }
473cdf0e10cSrcweir }
474cdf0e10cSrcweir 
475cdf0e10cSrcweir void SchXMLTableContext::setRowPermutation( const uno::Sequence< sal_Int32 > & rPermutation )
476cdf0e10cSrcweir {
477cdf0e10cSrcweir     maRowPermutation = rPermutation;
478cdf0e10cSrcweir     mbHasRowPermutation = ( rPermutation.getLength() > 0 );
479cdf0e10cSrcweir 
480cdf0e10cSrcweir     if( mbHasRowPermutation && mbHasColumnPermutation )
481cdf0e10cSrcweir     {
482cdf0e10cSrcweir         mbHasColumnPermutation = false;
483cdf0e10cSrcweir         maColumnPermutation.realloc( 0 );
484cdf0e10cSrcweir     }
485cdf0e10cSrcweir }
486cdf0e10cSrcweir 
487cdf0e10cSrcweir void SchXMLTableContext::setColumnPermutation( const uno::Sequence< sal_Int32 > & rPermutation )
488cdf0e10cSrcweir {
489cdf0e10cSrcweir     maColumnPermutation = rPermutation;
490cdf0e10cSrcweir     mbHasColumnPermutation = ( rPermutation.getLength() > 0 );
491cdf0e10cSrcweir 
492cdf0e10cSrcweir     if( mbHasColumnPermutation && mbHasRowPermutation )
493cdf0e10cSrcweir     {
494cdf0e10cSrcweir         mbHasRowPermutation = false;
495cdf0e10cSrcweir         maRowPermutation.realloc( 0 );
496cdf0e10cSrcweir     }
497cdf0e10cSrcweir }
498cdf0e10cSrcweir 
499cdf0e10cSrcweir // ========================================
500cdf0e10cSrcweir // classes for columns
501cdf0e10cSrcweir // ========================================
502cdf0e10cSrcweir 
503cdf0e10cSrcweir // ----------------------------------------
504cdf0e10cSrcweir // class SchXMLTableColumnsContext
505cdf0e10cSrcweir // ----------------------------------------
506cdf0e10cSrcweir 
507cdf0e10cSrcweir SchXMLTableColumnsContext::SchXMLTableColumnsContext(
508cdf0e10cSrcweir 	SchXMLImportHelper& rImpHelper,
509cdf0e10cSrcweir 	SvXMLImport& rImport,
510cdf0e10cSrcweir 	const rtl::OUString& rLocalName,
511cdf0e10cSrcweir 	SchXMLTable& aTable ) :
512cdf0e10cSrcweir 		SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
513cdf0e10cSrcweir 		mrImportHelper( rImpHelper ),
514cdf0e10cSrcweir 		mrTable( aTable )
515cdf0e10cSrcweir {
516cdf0e10cSrcweir }
517cdf0e10cSrcweir 
518cdf0e10cSrcweir SchXMLTableColumnsContext::~SchXMLTableColumnsContext()
519cdf0e10cSrcweir {
520cdf0e10cSrcweir }
521cdf0e10cSrcweir 
522cdf0e10cSrcweir SvXMLImportContext* SchXMLTableColumnsContext::CreateChildContext(
523cdf0e10cSrcweir 	sal_uInt16 nPrefix,
524cdf0e10cSrcweir 	const rtl::OUString& rLocalName,
525cdf0e10cSrcweir 	const uno::Reference< xml::sax::XAttributeList >& )
526cdf0e10cSrcweir {
527cdf0e10cSrcweir 	SvXMLImportContext* pContext = 0;
528cdf0e10cSrcweir 
529cdf0e10cSrcweir 	if( nPrefix == XML_NAMESPACE_TABLE &&
530cdf0e10cSrcweir 		IsXMLToken( rLocalName, XML_TABLE_COLUMN ) )
531cdf0e10cSrcweir 	{
532cdf0e10cSrcweir 		pContext = new SchXMLTableColumnContext( mrImportHelper, GetImport(), rLocalName, mrTable );
533cdf0e10cSrcweir 	}
534cdf0e10cSrcweir 	else
535cdf0e10cSrcweir 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
536cdf0e10cSrcweir 
537cdf0e10cSrcweir 	return pContext;
538cdf0e10cSrcweir }
539cdf0e10cSrcweir 
540cdf0e10cSrcweir // ----------------------------------------
541cdf0e10cSrcweir // class SchXMLTableColumnContext
542cdf0e10cSrcweir // ----------------------------------------
543cdf0e10cSrcweir 
544cdf0e10cSrcweir SchXMLTableColumnContext::SchXMLTableColumnContext(
545cdf0e10cSrcweir 	SchXMLImportHelper& rImpHelper,
546cdf0e10cSrcweir 	SvXMLImport& rImport,
547cdf0e10cSrcweir 	const rtl::OUString& rLocalName,
548cdf0e10cSrcweir 	SchXMLTable& aTable ) :
549cdf0e10cSrcweir 		SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
550cdf0e10cSrcweir 		mrImportHelper( rImpHelper ),
551cdf0e10cSrcweir 		mrTable( aTable )
552cdf0e10cSrcweir {
553cdf0e10cSrcweir }
554cdf0e10cSrcweir 
555cdf0e10cSrcweir void SchXMLTableColumnContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
556cdf0e10cSrcweir {
557cdf0e10cSrcweir 	// get number-columns-repeated attribute
558cdf0e10cSrcweir 	sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
559cdf0e10cSrcweir 	sal_Int32 nRepeated = 1;
560cdf0e10cSrcweir     bool bHidden = false;
561cdf0e10cSrcweir 
562cdf0e10cSrcweir 	for( sal_Int16 i = 0; i < nAttrCount; i++ )
563cdf0e10cSrcweir 	{
564cdf0e10cSrcweir 		rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
565cdf0e10cSrcweir 		rtl::OUString aLocalName;
566cdf0e10cSrcweir 		sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
567cdf0e10cSrcweir 
568cdf0e10cSrcweir 		if( nPrefix == XML_NAMESPACE_TABLE &&
569cdf0e10cSrcweir 			IsXMLToken( aLocalName, XML_NUMBER_COLUMNS_REPEATED ) )
570cdf0e10cSrcweir 		{
571cdf0e10cSrcweir 			rtl::OUString aValue = xAttrList->getValueByIndex( i );
572cdf0e10cSrcweir             if( aValue.getLength())
573cdf0e10cSrcweir                 nRepeated = aValue.toInt32();
574cdf0e10cSrcweir 		}
575cdf0e10cSrcweir         else if( nPrefix == XML_NAMESPACE_TABLE &&
576cdf0e10cSrcweir 			IsXMLToken( aLocalName, XML_VISIBILITY ) )
577cdf0e10cSrcweir 		{
578cdf0e10cSrcweir 			rtl::OUString aVisibility = xAttrList->getValueByIndex( i );
579cdf0e10cSrcweir             bHidden = aVisibility.equals( GetXMLToken( XML_COLLAPSE ) );
580cdf0e10cSrcweir 		}
581cdf0e10cSrcweir 	}
582cdf0e10cSrcweir 
583cdf0e10cSrcweir     sal_Int32 nOldCount = mrTable.nNumberOfColsEstimate;
584cdf0e10cSrcweir     sal_Int32 nNewCount = nOldCount + nRepeated;
585cdf0e10cSrcweir     mrTable.nNumberOfColsEstimate = nNewCount;
586cdf0e10cSrcweir 
587cdf0e10cSrcweir     if( bHidden )
588cdf0e10cSrcweir     {
589cdf0e10cSrcweir         //i91578 display of hidden values (copy paste scenario; use hidden flag during migration to locale table upon paste )
590cdf0e10cSrcweir         sal_Int32 nColOffset = ( mrTable.bHasHeaderColumn ? 1 : 0 );
591cdf0e10cSrcweir         for( sal_Int32 nN = nOldCount; nN<nNewCount; nN++ )
592cdf0e10cSrcweir         {
593cdf0e10cSrcweir             sal_Int32 nHiddenColumnIndex = nN-nColOffset;
594cdf0e10cSrcweir             if( nHiddenColumnIndex>=0 )
595cdf0e10cSrcweir                 mrTable.aHiddenColumns.push_back(nHiddenColumnIndex);
596cdf0e10cSrcweir         }
597cdf0e10cSrcweir     }
598cdf0e10cSrcweir }
599cdf0e10cSrcweir 
600cdf0e10cSrcweir SchXMLTableColumnContext::~SchXMLTableColumnContext()
601cdf0e10cSrcweir {
602cdf0e10cSrcweir }
603cdf0e10cSrcweir 
604cdf0e10cSrcweir // ========================================
605cdf0e10cSrcweir // classes for rows
606cdf0e10cSrcweir // ========================================
607cdf0e10cSrcweir 
608cdf0e10cSrcweir // ----------------------------------------
609cdf0e10cSrcweir // class SchXMLTableRowsContext
610cdf0e10cSrcweir // ----------------------------------------
611cdf0e10cSrcweir 
612cdf0e10cSrcweir SchXMLTableRowsContext::SchXMLTableRowsContext(
613cdf0e10cSrcweir 	SchXMLImportHelper& rImpHelper,
614cdf0e10cSrcweir 	SvXMLImport& rImport,
615cdf0e10cSrcweir 	const rtl::OUString& rLocalName,
616cdf0e10cSrcweir 	SchXMLTable& aTable ) :
617cdf0e10cSrcweir 		SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
618cdf0e10cSrcweir 		mrImportHelper( rImpHelper ),
619cdf0e10cSrcweir 		mrTable( aTable )
620cdf0e10cSrcweir {
621cdf0e10cSrcweir }
622cdf0e10cSrcweir 
623cdf0e10cSrcweir SchXMLTableRowsContext::~SchXMLTableRowsContext()
624cdf0e10cSrcweir {
625cdf0e10cSrcweir }
626cdf0e10cSrcweir 
627cdf0e10cSrcweir SvXMLImportContext* SchXMLTableRowsContext::CreateChildContext(
628cdf0e10cSrcweir 	sal_uInt16 nPrefix,
629cdf0e10cSrcweir 	const rtl::OUString& rLocalName,
630cdf0e10cSrcweir 	const uno::Reference< xml::sax::XAttributeList >& )
631cdf0e10cSrcweir {
632cdf0e10cSrcweir 	SvXMLImportContext* pContext = 0;
633cdf0e10cSrcweir 
634cdf0e10cSrcweir 	if( nPrefix == XML_NAMESPACE_TABLE &&
635cdf0e10cSrcweir         IsXMLToken( rLocalName, XML_TABLE_ROW ) )
636cdf0e10cSrcweir 	{
637cdf0e10cSrcweir 		pContext = new SchXMLTableRowContext( mrImportHelper, GetImport(), rLocalName, mrTable );
638cdf0e10cSrcweir 	}
639cdf0e10cSrcweir 	else
640cdf0e10cSrcweir 	{
641cdf0e10cSrcweir 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
642cdf0e10cSrcweir 	}
643cdf0e10cSrcweir 
644cdf0e10cSrcweir 	return pContext;
645cdf0e10cSrcweir }
646cdf0e10cSrcweir 
647cdf0e10cSrcweir // ----------------------------------------
648cdf0e10cSrcweir // class SchXMLTableRowContext
649cdf0e10cSrcweir // ----------------------------------------
650cdf0e10cSrcweir 
651cdf0e10cSrcweir SchXMLTableRowContext::SchXMLTableRowContext(
652cdf0e10cSrcweir 	SchXMLImportHelper& rImpHelper,
653cdf0e10cSrcweir 	SvXMLImport& rImport,
654cdf0e10cSrcweir 	const rtl::OUString& rLocalName,
655cdf0e10cSrcweir 	SchXMLTable& aTable ) :
656cdf0e10cSrcweir 		SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
657cdf0e10cSrcweir 		mrImportHelper( rImpHelper ),
658cdf0e10cSrcweir 		mrTable( aTable )
659cdf0e10cSrcweir {
660cdf0e10cSrcweir 	mrTable.nColumnIndex = -1;
661cdf0e10cSrcweir 	mrTable.nRowIndex++;
662cdf0e10cSrcweir 
663cdf0e10cSrcweir 	std::vector< SchXMLCell > aNewRow;
664cdf0e10cSrcweir 	aNewRow.reserve( mrTable.nNumberOfColsEstimate );
665cdf0e10cSrcweir 	while( mrTable.aData.size() <= (unsigned long)mrTable.nRowIndex )
666cdf0e10cSrcweir 		mrTable.aData.push_back( aNewRow );
667cdf0e10cSrcweir }
668cdf0e10cSrcweir 
669cdf0e10cSrcweir SchXMLTableRowContext::~SchXMLTableRowContext()
670cdf0e10cSrcweir {
671cdf0e10cSrcweir }
672cdf0e10cSrcweir 
673cdf0e10cSrcweir SvXMLImportContext* SchXMLTableRowContext::CreateChildContext(
674cdf0e10cSrcweir 	sal_uInt16 nPrefix,
675cdf0e10cSrcweir 	const rtl::OUString& rLocalName,
676cdf0e10cSrcweir 	const uno::Reference< xml::sax::XAttributeList >& )
677cdf0e10cSrcweir {
678cdf0e10cSrcweir 	SvXMLImportContext* pContext = 0;
679cdf0e10cSrcweir 
680cdf0e10cSrcweir 	// <table:table-cell> element
681cdf0e10cSrcweir 	if( nPrefix == XML_NAMESPACE_TABLE &&
682cdf0e10cSrcweir         IsXMLToken(rLocalName, XML_TABLE_CELL ) )
683cdf0e10cSrcweir 	{
684cdf0e10cSrcweir 		pContext = new SchXMLTableCellContext( mrImportHelper, GetImport(), rLocalName, mrTable );
685cdf0e10cSrcweir 	}
686cdf0e10cSrcweir 	else
687cdf0e10cSrcweir 	{
688cdf0e10cSrcweir 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
689cdf0e10cSrcweir 	}
690cdf0e10cSrcweir 
691cdf0e10cSrcweir 	return pContext;
692cdf0e10cSrcweir }
693cdf0e10cSrcweir 
694cdf0e10cSrcweir //---------------------------------------------------------------------------------------------------
695cdf0e10cSrcweir //---------------------------------------------------------------------------------------------------
696cdf0e10cSrcweir 
697cdf0e10cSrcweir class SchXMLRangeSomewhereContext : public SvXMLImportContext
698cdf0e10cSrcweir {
699cdf0e10cSrcweir //#i113950# previously the range was exported to attribute text:id,
700cdf0e10cSrcweir //but that attribute does not allow arbitrary strings anymore
701cdf0e10cSrcweir //so we need to find an alternative to save that range info for copy/paste scenario ...
702cdf0e10cSrcweir //-> use description at an empty group element for now
703cdf0e10cSrcweir 
704cdf0e10cSrcweir private:
705cdf0e10cSrcweir 	::rtl::OUString& mrRangeString;
706cdf0e10cSrcweir     ::rtl::OUStringBuffer maRangeStringBuffer;
707cdf0e10cSrcweir 
708cdf0e10cSrcweir public:
709cdf0e10cSrcweir 	SchXMLRangeSomewhereContext( SvXMLImport& rImport,
710cdf0e10cSrcweir                             sal_uInt16 nPrefix,
711cdf0e10cSrcweir 							const ::rtl::OUString& rLocalName,
712cdf0e10cSrcweir 							::rtl::OUString& rRangeString );
713cdf0e10cSrcweir 	virtual ~SchXMLRangeSomewhereContext();
714cdf0e10cSrcweir 
715cdf0e10cSrcweir 	virtual SvXMLImportContext* CreateChildContext(
716cdf0e10cSrcweir 		sal_uInt16 nPrefix,
717cdf0e10cSrcweir 		const ::rtl::OUString& rLocalName,
718cdf0e10cSrcweir 		const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList );
719cdf0e10cSrcweir     virtual void EndElement();
720cdf0e10cSrcweir };
721cdf0e10cSrcweir 
722cdf0e10cSrcweir //---------------------------------------------------------------------------------------------------
723cdf0e10cSrcweir //---------------------------------------------------------------------------------------------------
724cdf0e10cSrcweir 
725cdf0e10cSrcweir // ========================================
726cdf0e10cSrcweir // classes for cells and their content
727cdf0e10cSrcweir // ========================================
728cdf0e10cSrcweir 
729cdf0e10cSrcweir // ----------------------------------------
730cdf0e10cSrcweir // class SchXMLTableCellContext
731cdf0e10cSrcweir // ----------------------------------------
732cdf0e10cSrcweir 
733cdf0e10cSrcweir SchXMLTableCellContext::SchXMLTableCellContext(
734cdf0e10cSrcweir 	SchXMLImportHelper& rImpHelper,
735cdf0e10cSrcweir 	SvXMLImport& rImport,
736cdf0e10cSrcweir 	const rtl::OUString& rLocalName,
737cdf0e10cSrcweir 	SchXMLTable& aTable ) :
738cdf0e10cSrcweir 		SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
739cdf0e10cSrcweir 		mrImportHelper( rImpHelper ),
740cdf0e10cSrcweir 		mrTable( aTable )
741cdf0e10cSrcweir {
742cdf0e10cSrcweir }
743cdf0e10cSrcweir 
744cdf0e10cSrcweir SchXMLTableCellContext::~SchXMLTableCellContext()
745cdf0e10cSrcweir {
746cdf0e10cSrcweir }
747cdf0e10cSrcweir 
748cdf0e10cSrcweir void SchXMLTableCellContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
749cdf0e10cSrcweir {
750cdf0e10cSrcweir 	sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
751cdf0e10cSrcweir 	rtl::OUString aValue;
752cdf0e10cSrcweir 	rtl::OUString aLocalName;
753cdf0e10cSrcweir 	rtl::OUString aCellContent;
754cdf0e10cSrcweir 	SchXMLCellType eValueType  = SCH_CELL_TYPE_UNKNOWN;
755cdf0e10cSrcweir 	const SvXMLTokenMap& rAttrTokenMap = mrImportHelper.GetCellAttrTokenMap();
756cdf0e10cSrcweir 
757cdf0e10cSrcweir 	for( sal_Int16 i = 0; i < nAttrCount; i++ )
758cdf0e10cSrcweir 	{
759cdf0e10cSrcweir 		rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
760cdf0e10cSrcweir 		sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
761cdf0e10cSrcweir 
762cdf0e10cSrcweir 		switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
763cdf0e10cSrcweir 		{
764cdf0e10cSrcweir 			case XML_TOK_CELL_VAL_TYPE:
765cdf0e10cSrcweir 				aValue = xAttrList->getValueByIndex( i );
766cdf0e10cSrcweir 				if( IsXMLToken( aValue, XML_FLOAT ) )
767cdf0e10cSrcweir 					eValueType = SCH_CELL_TYPE_FLOAT;
768cdf0e10cSrcweir 				else if( IsXMLToken( aValue, XML_STRING ) )
769cdf0e10cSrcweir 					eValueType = SCH_CELL_TYPE_STRING;
770cdf0e10cSrcweir 				break;
771cdf0e10cSrcweir 
772cdf0e10cSrcweir 			case XML_TOK_CELL_VALUE:
773cdf0e10cSrcweir 				aCellContent = xAttrList->getValueByIndex( i );
774cdf0e10cSrcweir 				break;
775cdf0e10cSrcweir 		}
776cdf0e10cSrcweir 	}
777cdf0e10cSrcweir 
778cdf0e10cSrcweir 	mbReadText = sal_True;
779cdf0e10cSrcweir 	SchXMLCell aCell;
780cdf0e10cSrcweir 	aCell.eType = eValueType;
781cdf0e10cSrcweir 
782cdf0e10cSrcweir 	if( eValueType == SCH_CELL_TYPE_FLOAT )
783cdf0e10cSrcweir 	{
784cdf0e10cSrcweir 		double fData;
785cdf0e10cSrcweir 		// the result may be false if a NaN is read, but that's ok
786cdf0e10cSrcweir 		SvXMLUnitConverter::convertDouble( fData, aCellContent );
787cdf0e10cSrcweir 
788cdf0e10cSrcweir 		aCell.fValue = fData;
789cdf0e10cSrcweir 		// dont read text from following <text:p> or <text:list> element
790cdf0e10cSrcweir 		mbReadText = sal_False;
791cdf0e10cSrcweir 	}
792cdf0e10cSrcweir 
793cdf0e10cSrcweir 	mrTable.aData[ mrTable.nRowIndex ].push_back( aCell );
794cdf0e10cSrcweir 	mrTable.nColumnIndex++;
795cdf0e10cSrcweir 	if( mrTable.nMaxColumnIndex < mrTable.nColumnIndex )
796cdf0e10cSrcweir 		mrTable.nMaxColumnIndex = mrTable.nColumnIndex;
797cdf0e10cSrcweir }
798cdf0e10cSrcweir 
799cdf0e10cSrcweir SvXMLImportContext* SchXMLTableCellContext::CreateChildContext(
800cdf0e10cSrcweir 	sal_uInt16 nPrefix,
801cdf0e10cSrcweir 	const rtl::OUString& rLocalName,
802cdf0e10cSrcweir 	const uno::Reference< xml::sax::XAttributeList >& )
803cdf0e10cSrcweir {
804cdf0e10cSrcweir 	SvXMLImportContext* pContext = 0;
805cdf0e10cSrcweir 
806cdf0e10cSrcweir     // <text:list> element
807cdf0e10cSrcweir     if( nPrefix == XML_NAMESPACE_TEXT && IsXMLToken( rLocalName, XML_LIST ) && mbReadText )
808cdf0e10cSrcweir 	{
809cdf0e10cSrcweir         SchXMLCell& rCell = mrTable.aData[ mrTable.nRowIndex ][ mrTable.nColumnIndex ];
810cdf0e10cSrcweir         rCell.pComplexString = new Sequence< OUString >();
811cdf0e10cSrcweir         rCell.eType = SCH_CELL_TYPE_COMPLEX_STRING;
812cdf0e10cSrcweir         pContext = new SchXMLTextListContext( GetImport(), rLocalName, *rCell.pComplexString );
813cdf0e10cSrcweir         mbReadText = sal_False;//don't apply text from <text:p>
814cdf0e10cSrcweir 	}
815cdf0e10cSrcweir 	// <text:p> element - read text (and range from text:id old version)
816cdf0e10cSrcweir 	else if( nPrefix == XML_NAMESPACE_TEXT && IsXMLToken( rLocalName, XML_P ) )
817cdf0e10cSrcweir 	{
818cdf0e10cSrcweir         pContext = new SchXMLParagraphContext( GetImport(), rLocalName, maCellContent, &maRangeId );
819cdf0e10cSrcweir 	}
820cdf0e10cSrcweir     // <draw:g> element - read range
821cdf0e10cSrcweir     else if( nPrefix == XML_NAMESPACE_DRAW && IsXMLToken( rLocalName, XML_G ) )
822cdf0e10cSrcweir 	{
823cdf0e10cSrcweir         //#i113950# previously the range was exported to attribute text:id, but that attribute does not allow arbitrary strings anymore
824cdf0e10cSrcweir         //so we need to find an alternative to save that range info for copy/paste scenario ... -> use description at an empty group element for now
825cdf0e10cSrcweir         pContext = new SchXMLRangeSomewhereContext( GetImport(), nPrefix, rLocalName, maRangeId );
826cdf0e10cSrcweir 	}
827cdf0e10cSrcweir 	else
828cdf0e10cSrcweir 	{
829cdf0e10cSrcweir 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
830cdf0e10cSrcweir 	}
831cdf0e10cSrcweir 
832cdf0e10cSrcweir 	return pContext;
833cdf0e10cSrcweir }
834cdf0e10cSrcweir 
835cdf0e10cSrcweir void SchXMLTableCellContext::EndElement()
836cdf0e10cSrcweir {
837cdf0e10cSrcweir 	if( mbReadText && maCellContent.getLength() ) //apply text from <text:p> element
838cdf0e10cSrcweir         mrTable.aData[ mrTable.nRowIndex ][ mrTable.nColumnIndex ].aString = maCellContent;
839cdf0e10cSrcweir     if( maRangeId.getLength())
840cdf0e10cSrcweir         mrTable.aData[ mrTable.nRowIndex ][ mrTable.nColumnIndex ].aRangeId = maRangeId;
841cdf0e10cSrcweir }
842cdf0e10cSrcweir 
843cdf0e10cSrcweir // ========================================
844cdf0e10cSrcweir 
845cdf0e10cSrcweir void lcl_ApplyCellToComplexLabel( const SchXMLCell& rCell, Sequence< uno::Any >& rComplexLabel )
846cdf0e10cSrcweir {
847cdf0e10cSrcweir     if( rCell.eType == SCH_CELL_TYPE_STRING )
848cdf0e10cSrcweir     {
849cdf0e10cSrcweir         rComplexLabel.realloc(1);
850cdf0e10cSrcweir         rComplexLabel[0] = uno::makeAny( rCell.aString );
851cdf0e10cSrcweir     }
852cdf0e10cSrcweir     else if( rCell.pComplexString && rCell.eType == SCH_CELL_TYPE_COMPLEX_STRING )
853cdf0e10cSrcweir     {
854cdf0e10cSrcweir         sal_Int32 nCount = rCell.pComplexString->getLength();
855cdf0e10cSrcweir         rComplexLabel.realloc( nCount );
856cdf0e10cSrcweir         for( sal_Int32 nN=0; nN<nCount; nN++)
857cdf0e10cSrcweir             rComplexLabel[nN] = uno::makeAny((*rCell.pComplexString)[nN]);
858cdf0e10cSrcweir     }
859cdf0e10cSrcweir     else if( rCell.eType == SCH_CELL_TYPE_FLOAT )
860cdf0e10cSrcweir     {
861cdf0e10cSrcweir         rComplexLabel.realloc(1);
862cdf0e10cSrcweir         rComplexLabel[0] = uno::makeAny( rCell.fValue );
863cdf0e10cSrcweir     }
864cdf0e10cSrcweir }
865cdf0e10cSrcweir 
866cdf0e10cSrcweir void SchXMLTableHelper::applyTableToInternalDataProvider(
867cdf0e10cSrcweir 	const SchXMLTable& rTable,
868cdf0e10cSrcweir 	uno::Reference< chart2::XChartDocument > xChartDoc )
869cdf0e10cSrcweir {
870cdf0e10cSrcweir     // apply all data read from the local table to the internal data provider
871cdf0e10cSrcweir     if( !xChartDoc.is() || !xChartDoc->hasInternalDataProvider() )
872cdf0e10cSrcweir         return;
873cdf0e10cSrcweir     Reference< chart2::data::XDataProvider >  xDataProv( xChartDoc->getDataProvider() );
874cdf0e10cSrcweir     if( !xDataProv.is() )
875cdf0e10cSrcweir         return;
876cdf0e10cSrcweir 
877cdf0e10cSrcweir     //prepare the read local table data
878cdf0e10cSrcweir     sal_Int32 nNumRows( static_cast< sal_Int32 >( rTable.aData.size()));
879cdf0e10cSrcweir     sal_Int32 nRowOffset = 0;
880cdf0e10cSrcweir     if( rTable.bHasHeaderRow )
881cdf0e10cSrcweir     {
882cdf0e10cSrcweir         --nNumRows;
883cdf0e10cSrcweir         nRowOffset = 1;
884cdf0e10cSrcweir     }
885cdf0e10cSrcweir     sal_Int32 nNumColumns( rTable.nMaxColumnIndex + 1 );
886cdf0e10cSrcweir     sal_Int32 nColOffset = 0;
887cdf0e10cSrcweir     if( rTable.bHasHeaderColumn )
888cdf0e10cSrcweir     {
889cdf0e10cSrcweir         --nNumColumns;
890cdf0e10cSrcweir         nColOffset = 1;
891cdf0e10cSrcweir     }
892cdf0e10cSrcweir 
893cdf0e10cSrcweir     Sequence< Sequence< double > > aDataInRows( nNumRows );
894cdf0e10cSrcweir     Sequence< Sequence< uno::Any > > aComplexRowDescriptions( nNumRows );
895cdf0e10cSrcweir     Sequence< Sequence< uno::Any > > aComplexColumnDescriptions( nNumColumns );
896cdf0e10cSrcweir     for( sal_Int32 i=0; i<nNumRows; ++i )
897cdf0e10cSrcweir         aDataInRows[i].realloc( nNumColumns );
898cdf0e10cSrcweir 
899cdf0e10cSrcweir     if( rTable.aData.begin() != rTable.aData.end())
900cdf0e10cSrcweir     {
901cdf0e10cSrcweir         //apply column labels
902cdf0e10cSrcweir         if( rTable.bHasHeaderRow )
903cdf0e10cSrcweir         {
904cdf0e10cSrcweir             const ::std::vector< SchXMLCell >& rFirstRow = rTable.aData.front();
905cdf0e10cSrcweir             const sal_Int32 nColumnLabelsSize = aComplexColumnDescriptions.getLength();
906cdf0e10cSrcweir             const sal_Int32 nMax = ::std::min< sal_Int32 >( nColumnLabelsSize, static_cast< sal_Int32 >( rFirstRow.size()) - nColOffset );
907cdf0e10cSrcweir             OSL_ASSERT( nMax == nColumnLabelsSize );
908cdf0e10cSrcweir             for( sal_Int32 i=0; i<nMax; ++i )
909cdf0e10cSrcweir                 lcl_ApplyCellToComplexLabel( rFirstRow[i+nColOffset], aComplexColumnDescriptions[i] );
910cdf0e10cSrcweir         }
911cdf0e10cSrcweir 
912cdf0e10cSrcweir         std::vector< ::std::vector< SchXMLCell > >::const_iterator aRowIter( rTable.aData.begin() + nRowOffset );
913cdf0e10cSrcweir         std::vector< ::std::vector< SchXMLCell > >::const_iterator aEnd( rTable.aData.end() );
914cdf0e10cSrcweir         for( sal_Int32 nRow = 0; aRowIter != aEnd && nRow < nNumRows; ++aRowIter, ++nRow )
915cdf0e10cSrcweir         {
916cdf0e10cSrcweir             const ::std::vector< SchXMLCell >& rRow = *aRowIter;
917cdf0e10cSrcweir             if( !rRow.empty() )
918cdf0e10cSrcweir             {
919cdf0e10cSrcweir                 // row label
920cdf0e10cSrcweir                 if( rTable.bHasHeaderColumn )
921cdf0e10cSrcweir                     lcl_ApplyCellToComplexLabel( rRow.front(), aComplexRowDescriptions[nRow] );
922cdf0e10cSrcweir 
923cdf0e10cSrcweir                 // values
924cdf0e10cSrcweir                 Sequence< double >& rTargetRow = aDataInRows[nRow];
925cdf0e10cSrcweir                 lcl_ApplyCellToData aApplyCellToData = ::std::for_each( rRow.begin() + nColOffset, rRow.end(), lcl_ApplyCellToData( rTargetRow ) );
926cdf0e10cSrcweir                 double fNaN = 0.0;
927cdf0e10cSrcweir                 ::rtl::math::setNan( &fNaN );
928cdf0e10cSrcweir                 for( sal_Int32 nCurrentIndex = aApplyCellToData.getCurrentIndex(); nCurrentIndex<nNumColumns; nCurrentIndex++ )
929cdf0e10cSrcweir                     rTargetRow[nCurrentIndex] = fNaN;//#i110615#
930cdf0e10cSrcweir             }
931cdf0e10cSrcweir         }
932cdf0e10cSrcweir     }
933cdf0e10cSrcweir 
934cdf0e10cSrcweir     //apply the collected data to the chart
935cdf0e10cSrcweir     Reference< chart2::XAnyDescriptionAccess > xDataAccess( xDataProv, uno::UNO_QUERY );
936cdf0e10cSrcweir     if( !xDataAccess.is() )
937cdf0e10cSrcweir         return;
938cdf0e10cSrcweir 
939cdf0e10cSrcweir     xDataAccess->setData( aDataInRows );
940cdf0e10cSrcweir     if( rTable.bHasHeaderColumn )
941cdf0e10cSrcweir         xDataAccess->setAnyRowDescriptions( aComplexRowDescriptions );
942cdf0e10cSrcweir     if( rTable.bHasHeaderRow )
943cdf0e10cSrcweir         xDataAccess->setAnyColumnDescriptions( aComplexColumnDescriptions );
944cdf0e10cSrcweir 
945cdf0e10cSrcweir     if ( rTable.bProtected )
946cdf0e10cSrcweir     {
947cdf0e10cSrcweir         try
948cdf0e10cSrcweir         {
949cdf0e10cSrcweir             Reference< beans::XPropertySet > xProps( xChartDoc, uno::UNO_QUERY_THROW );
950cdf0e10cSrcweir             xProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableDataTableDialog" ) ), uno::makeAny( sal_True ) );
951cdf0e10cSrcweir             xProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableComplexChartTypes" ) ), uno::makeAny( sal_True ) );
952cdf0e10cSrcweir         }
953cdf0e10cSrcweir         catch ( uno::Exception& )
954cdf0e10cSrcweir         {
955cdf0e10cSrcweir         }
956cdf0e10cSrcweir     }
957cdf0e10cSrcweir }
958cdf0e10cSrcweir 
959cdf0e10cSrcweir void SchXMLTableHelper::switchRangesFromOuterToInternalIfNecessary(
960cdf0e10cSrcweir 	const SchXMLTable& rTable,
961cdf0e10cSrcweir     const tSchXMLLSequencesPerIndex & rLSequencesPerIndex,
962cdf0e10cSrcweir 	uno::Reference< chart2::XChartDocument > xChartDoc,
963cdf0e10cSrcweir     chart::ChartDataRowSource eDataRowSource )
964cdf0e10cSrcweir {
965cdf0e10cSrcweir     if( ! (xChartDoc.is() && xChartDoc->hasInternalDataProvider()))
966cdf0e10cSrcweir         return;
967cdf0e10cSrcweir 
968cdf0e10cSrcweir     // If the range-strings are valid (starting with "local-table") they should
969cdf0e10cSrcweir     // be interpreted like given, otherwise (when the ranges refer to Calc- or
970cdf0e10cSrcweir     // Writer-ranges, but the container is not available like when pasting a
971cdf0e10cSrcweir     // chart from Calc to Impress) the range is ignored, and every object gets
972cdf0e10cSrcweir     // one table column in the order of appearance, which is: 1. categories,
973cdf0e10cSrcweir     // 2. data series: 2.a) domains, 2.b) values (main-role, usually y-values)
974cdf0e10cSrcweir 
975cdf0e10cSrcweir     Reference< chart2::data::XDataProvider >  xDataProv( xChartDoc->getDataProvider());
976cdf0e10cSrcweir 
977cdf0e10cSrcweir     // create a mapping from original ranges to new ranges
978cdf0e10cSrcweir     lcl_tOriginalRangeToInternalRangeMap aRangeMap;
979cdf0e10cSrcweir 
980cdf0e10cSrcweir     lcl_fillRangeMapping( rTable, aRangeMap, eDataRowSource );
981cdf0e10cSrcweir 
982cdf0e10cSrcweir     bool bCategoriesApplied = false;
983cdf0e10cSrcweir     // translate ranges (using the map created before)
984cdf0e10cSrcweir     for( tSchXMLLSequencesPerIndex::const_iterator aLSeqIt( rLSequencesPerIndex.begin());
985cdf0e10cSrcweir          aLSeqIt != rLSequencesPerIndex.end(); ++aLSeqIt )
986cdf0e10cSrcweir     {
987cdf0e10cSrcweir         if( aLSeqIt->second.is())
988cdf0e10cSrcweir         {
989cdf0e10cSrcweir             // values/error bars/categories
990cdf0e10cSrcweir             if( aLSeqIt->first.second == SCH_XML_PART_VALUES ||
991cdf0e10cSrcweir                 aLSeqIt->first.second == SCH_XML_PART_ERROR_BARS )
992cdf0e10cSrcweir             {
993cdf0e10cSrcweir                 Reference< chart2::data::XDataSequence > xSeq( aLSeqIt->second->getValues());
994cdf0e10cSrcweir                 OUString aRange;
995cdf0e10cSrcweir                 if( xSeq.is() &&
996cdf0e10cSrcweir                     SchXMLTools::getXMLRangePropertyFromDataSequence( xSeq, aRange, /* bClearProp = */ true ) &&
997cdf0e10cSrcweir                     lcl_mapContainsRange( aRangeMap, aRange ))
998cdf0e10cSrcweir                 {
999cdf0e10cSrcweir                     Reference< chart2::data::XDataSequence > xNewSeq(
1000cdf0e10cSrcweir                         lcl_reassignDataSequence( xSeq, xDataProv, aRangeMap, aRange ));
1001cdf0e10cSrcweir                     if( xNewSeq != xSeq )
1002cdf0e10cSrcweir                     {
1003cdf0e10cSrcweir                         SchXMLTools::copyProperties( Reference< beans::XPropertySet >( xSeq, uno::UNO_QUERY ),
1004cdf0e10cSrcweir                                             Reference< beans::XPropertySet >( xNewSeq, uno::UNO_QUERY ));
1005cdf0e10cSrcweir                         aLSeqIt->second->setValues( xNewSeq );
1006cdf0e10cSrcweir                     }
1007cdf0e10cSrcweir                 }
1008cdf0e10cSrcweir                 else
1009cdf0e10cSrcweir                 {
1010cdf0e10cSrcweir                     if( lcl_tableOfRangeMatches( aRange, rTable.aTableNameOfFile ))
1011cdf0e10cSrcweir                     {
1012cdf0e10cSrcweir                         if( aLSeqIt->first.first == SCH_XML_CATEGORIES_INDEX )
1013cdf0e10cSrcweir                             bCategoriesApplied = true;
1014cdf0e10cSrcweir                     }
1015cdf0e10cSrcweir                     else
1016cdf0e10cSrcweir                     {
1017cdf0e10cSrcweir                         if( aLSeqIt->first.first == SCH_XML_CATEGORIES_INDEX )
1018cdf0e10cSrcweir                         {
1019cdf0e10cSrcweir                             Reference< beans::XPropertySet > xOldSequenceProp( aLSeqIt->second->getValues(), uno::UNO_QUERY );
1020cdf0e10cSrcweir                             Reference< chart2::data::XDataSequence > xNewSequence(
1021cdf0e10cSrcweir                                 xDataProv->createDataSequenceByRangeRepresentation(
1022cdf0e10cSrcweir                                     OUString(RTL_CONSTASCII_USTRINGPARAM("categories"))));
1023cdf0e10cSrcweir                             SchXMLTools::copyProperties(
1024cdf0e10cSrcweir                                 xOldSequenceProp, Reference< beans::XPropertySet >( xNewSequence, uno::UNO_QUERY ));
1025cdf0e10cSrcweir                             aLSeqIt->second->setValues( xNewSequence );
1026cdf0e10cSrcweir                             bCategoriesApplied = true;
1027cdf0e10cSrcweir                         }
1028cdf0e10cSrcweir                         else
1029cdf0e10cSrcweir                         {
1030cdf0e10cSrcweir                             Reference< beans::XPropertySet > xOldSequenceProp( aLSeqIt->second->getValues(), uno::UNO_QUERY );
1031cdf0e10cSrcweir                             OUString aRep( OUString::valueOf( aLSeqIt->first.first ));
1032cdf0e10cSrcweir                             Reference< chart2::data::XDataSequence > xNewSequence(
1033cdf0e10cSrcweir                                 xDataProv->createDataSequenceByRangeRepresentation( aRep ));
1034cdf0e10cSrcweir                             SchXMLTools::copyProperties(
1035cdf0e10cSrcweir                                 xOldSequenceProp, Reference< beans::XPropertySet >( xNewSequence, uno::UNO_QUERY ));
1036cdf0e10cSrcweir                             aLSeqIt->second->setValues( xNewSequence );
1037cdf0e10cSrcweir                         }
1038cdf0e10cSrcweir                     }
1039cdf0e10cSrcweir                 }
1040cdf0e10cSrcweir             }
1041cdf0e10cSrcweir             else // labels
1042cdf0e10cSrcweir             {
1043cdf0e10cSrcweir                 OSL_ASSERT( aLSeqIt->first.second == SCH_XML_PART_LABEL );
1044cdf0e10cSrcweir                 // labels
1045cdf0e10cSrcweir                 Reference< chart2::data::XDataSequence > xSeq( aLSeqIt->second->getLabel());
1046cdf0e10cSrcweir                 OUString aRange;
1047cdf0e10cSrcweir                 if( xSeq.is() &&
1048cdf0e10cSrcweir                     SchXMLTools::getXMLRangePropertyFromDataSequence( xSeq, aRange, /* bClearProp = */ true ) &&
1049cdf0e10cSrcweir                     lcl_mapContainsRange( aRangeMap, aRange ))
1050cdf0e10cSrcweir                 {
1051cdf0e10cSrcweir                     Reference< chart2::data::XDataSequence > xNewSeq(
1052cdf0e10cSrcweir                         lcl_reassignDataSequence( xSeq, xDataProv, aRangeMap, aRange ));
1053cdf0e10cSrcweir                     if( xNewSeq != xSeq )
1054cdf0e10cSrcweir                     {
1055cdf0e10cSrcweir                         SchXMLTools::copyProperties( Reference< beans::XPropertySet >( xSeq, uno::UNO_QUERY ),
1056cdf0e10cSrcweir                                             Reference< beans::XPropertySet >( xNewSeq, uno::UNO_QUERY ));
1057cdf0e10cSrcweir                         aLSeqIt->second->setLabel( xNewSeq );
1058cdf0e10cSrcweir                     }
1059cdf0e10cSrcweir                 }
1060cdf0e10cSrcweir                 else if( ! lcl_tableOfRangeMatches( aRange, rTable.aTableNameOfFile ))
1061cdf0e10cSrcweir                 {
1062cdf0e10cSrcweir                     OUString aRep( RTL_CONSTASCII_USTRINGPARAM("label "));
1063cdf0e10cSrcweir                     aRep += OUString::valueOf( aLSeqIt->first.first );
1064cdf0e10cSrcweir 
1065cdf0e10cSrcweir                     Reference< chart2::data::XDataSequence > xNewSeq(
1066cdf0e10cSrcweir                         xDataProv->createDataSequenceByRangeRepresentation( aRep ));
1067cdf0e10cSrcweir                     SchXMLTools::copyProperties( Reference< beans::XPropertySet >( xSeq, uno::UNO_QUERY ),
1068cdf0e10cSrcweir                                         Reference< beans::XPropertySet >( xNewSeq, uno::UNO_QUERY ));
1069cdf0e10cSrcweir                     aLSeqIt->second->setLabel( xNewSeq );
1070cdf0e10cSrcweir                 }
1071cdf0e10cSrcweir             }
1072cdf0e10cSrcweir         }
1073cdf0e10cSrcweir     }
1074cdf0e10cSrcweir 
1075cdf0e10cSrcweir     // there exist files with own data without a categories element but with row
1076cdf0e10cSrcweir     // descriptions.  The row descriptions were used as categories even without
1077cdf0e10cSrcweir     // the categories element
1078cdf0e10cSrcweir     if( ! bCategoriesApplied )
1079cdf0e10cSrcweir     {
1080cdf0e10cSrcweir         SchXMLTools::CreateCategories(
1081cdf0e10cSrcweir             xDataProv, xChartDoc, OUString(RTL_CONSTASCII_USTRINGPARAM("categories")),
1082cdf0e10cSrcweir             0 /* nCooSysIndex */, 0 /* nDimension */ );
1083cdf0e10cSrcweir     }
1084cdf0e10cSrcweir 
1085cdf0e10cSrcweir     //i91578 display of hidden values (copy paste scenario; use hidden flag during migration to locale table upon paste )
1086cdf0e10cSrcweir     //remove series that consist only of hidden columns
1087cdf0e10cSrcweir     Reference< chart2::XInternalDataProvider > xInternalDataProvider( xDataProv, uno::UNO_QUERY );
1088cdf0e10cSrcweir     if( xInternalDataProvider.is() && !rTable.aHiddenColumns.empty() )
1089cdf0e10cSrcweir     {
1090cdf0e10cSrcweir         try
1091cdf0e10cSrcweir         {
1092cdf0e10cSrcweir             Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xChartDoc->getFirstDiagram(), uno::UNO_QUERY_THROW );
1093cdf0e10cSrcweir             Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
1094cdf0e10cSrcweir             for( sal_Int32 nC=0; nC<aCooSysSeq.getLength(); ++nC )
1095cdf0e10cSrcweir             {
1096cdf0e10cSrcweir                 Reference< chart2::XChartTypeContainer > xCooSysContainer( aCooSysSeq[nC], uno::UNO_QUERY_THROW );
1097cdf0e10cSrcweir                 Sequence< Reference< chart2::XChartType > > aChartTypeSeq( xCooSysContainer->getChartTypes());
1098cdf0e10cSrcweir                 for( sal_Int32 nT=0; nT<aChartTypeSeq.getLength(); ++nT )
1099cdf0e10cSrcweir                 {
1100cdf0e10cSrcweir                     Reference< chart2::XDataSeriesContainer > xSeriesContainer( aChartTypeSeq[nT], uno::UNO_QUERY );
1101cdf0e10cSrcweir                     if(!xSeriesContainer.is())
1102cdf0e10cSrcweir                         continue;
1103cdf0e10cSrcweir                     Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xSeriesContainer->getDataSeries() );
1104cdf0e10cSrcweir                     std::vector< Reference< chart2::XDataSeries > > aRemainingSeries;
1105cdf0e10cSrcweir 
1106cdf0e10cSrcweir                     for( sal_Int32 nS = 0; nS < aSeriesSeq.getLength(); nS++ )
1107cdf0e10cSrcweir                     {
1108cdf0e10cSrcweir                         Reference< chart2::data::XDataSource > xDataSource( aSeriesSeq[nS], uno::UNO_QUERY );
1109cdf0e10cSrcweir                         if( xDataSource.is() )
1110cdf0e10cSrcweir                         {
1111cdf0e10cSrcweir                             bool bHasUnhiddenColumns = false;
1112cdf0e10cSrcweir                             rtl::OUString aRange;
1113cdf0e10cSrcweir                             uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences() );
1114cdf0e10cSrcweir                             for( sal_Int32 nN=0; nN< aSequences.getLength(); ++nN )
1115cdf0e10cSrcweir                             {
1116cdf0e10cSrcweir                                 Reference< chart2::data::XLabeledDataSequence > xLabeledSequence( aSequences[nN] );
1117cdf0e10cSrcweir                                 if(!xLabeledSequence.is())
1118cdf0e10cSrcweir                                     continue;
1119cdf0e10cSrcweir                                 Reference< chart2::data::XDataSequence > xValues( xLabeledSequence->getValues() );
1120cdf0e10cSrcweir                                 if( xValues.is() )
1121cdf0e10cSrcweir                                 {
1122cdf0e10cSrcweir                                     aRange = xValues->getSourceRangeRepresentation();
1123cdf0e10cSrcweir                                     if( ::std::find( rTable.aHiddenColumns.begin(), rTable.aHiddenColumns.end(), aRange.toInt32() ) == rTable.aHiddenColumns.end() )
1124cdf0e10cSrcweir                                         bHasUnhiddenColumns = true;
1125cdf0e10cSrcweir                                 }
1126cdf0e10cSrcweir                                 if( !bHasUnhiddenColumns )
1127cdf0e10cSrcweir                                 {
1128cdf0e10cSrcweir                                     Reference< chart2::data::XDataSequence > xLabel( xLabeledSequence->getLabel() );
1129cdf0e10cSrcweir                                     if( xLabel.is() )
1130cdf0e10cSrcweir                                     {
1131cdf0e10cSrcweir                                         aRange = xLabel->getSourceRangeRepresentation();
1132cdf0e10cSrcweir                                         sal_Int32 nSearchIndex = 0;
1133cdf0e10cSrcweir                                         OUString aSecondToken = aRange.getToken( 1, ' ', nSearchIndex );
1134cdf0e10cSrcweir                                         if( ::std::find( rTable.aHiddenColumns.begin(), rTable.aHiddenColumns.end(), aSecondToken.toInt32() ) == rTable.aHiddenColumns.end() )
1135cdf0e10cSrcweir                                             bHasUnhiddenColumns = true;
1136cdf0e10cSrcweir                                     }
1137cdf0e10cSrcweir                                 }
1138cdf0e10cSrcweir                             }
1139cdf0e10cSrcweir                             if( bHasUnhiddenColumns )
1140cdf0e10cSrcweir                                 aRemainingSeries.push_back( aSeriesSeq[nS] );
1141cdf0e10cSrcweir                         }
1142cdf0e10cSrcweir                     }
1143cdf0e10cSrcweir 
1144cdf0e10cSrcweir                     if( static_cast<sal_Int32>(aRemainingSeries.size()) != aSeriesSeq.getLength() )
1145cdf0e10cSrcweir                     {
1146cdf0e10cSrcweir                         //remove the series that have only hidden data
1147cdf0e10cSrcweir                         Sequence< Reference< chart2::XDataSeries > > aRemainingSeriesSeq( aRemainingSeries.size());
1148cdf0e10cSrcweir                         ::std::copy( aRemainingSeries.begin(), aRemainingSeries.end(), aRemainingSeriesSeq.getArray());
1149cdf0e10cSrcweir                         xSeriesContainer->setDataSeries( aRemainingSeriesSeq );
1150cdf0e10cSrcweir 
1151cdf0e10cSrcweir                         //remove unused sequences
1152cdf0e10cSrcweir                         Reference< chart2::data::XDataSource > xDataSource( xChartDoc, uno::UNO_QUERY );
1153cdf0e10cSrcweir                         if( xDataSource.is() )
1154cdf0e10cSrcweir                         {
1155cdf0e10cSrcweir                             //first detect which collumns are really used
1156cdf0e10cSrcweir                             std::map< sal_Int32, bool > aUsageMap;
1157cdf0e10cSrcweir                             rtl::OUString aRange;
1158cdf0e10cSrcweir                             Sequence< Reference< chart2::data::XLabeledDataSequence > > aUsedSequences( xDataSource->getDataSequences() );
1159cdf0e10cSrcweir                             for( sal_Int32 nN=0; nN< aUsedSequences.getLength(); ++nN )
1160cdf0e10cSrcweir                             {
1161cdf0e10cSrcweir                                 Reference< chart2::data::XLabeledDataSequence > xLabeledSequence( aUsedSequences[nN] );
1162cdf0e10cSrcweir                                 if(!xLabeledSequence.is())
1163cdf0e10cSrcweir                                     continue;
1164cdf0e10cSrcweir                                 Reference< chart2::data::XDataSequence > xValues( xLabeledSequence->getValues() );
1165cdf0e10cSrcweir                                 if( xValues.is() )
1166cdf0e10cSrcweir                                 {
1167cdf0e10cSrcweir                                     aRange = xValues->getSourceRangeRepresentation();
1168cdf0e10cSrcweir                                     sal_Int32 nIndex = aRange.toInt32();
1169cdf0e10cSrcweir                                     if( nIndex!=0 || !aRange.equals(lcl_aCategoriesRange) )
1170cdf0e10cSrcweir                                         aUsageMap[nIndex] = true;
1171cdf0e10cSrcweir                                 }
1172cdf0e10cSrcweir                                 Reference< chart2::data::XDataSequence > xLabel( xLabeledSequence->getLabel() );
1173cdf0e10cSrcweir                                 if( xLabel.is() )
1174cdf0e10cSrcweir                                 {
1175cdf0e10cSrcweir                                     aRange = xLabel->getSourceRangeRepresentation();
1176cdf0e10cSrcweir                                     sal_Int32 nSearchIndex = 0;
1177cdf0e10cSrcweir                                     OUString aSecondToken = aRange.getToken( 1, ' ', nSearchIndex );
1178cdf0e10cSrcweir                                     if( aSecondToken.getLength() )
1179cdf0e10cSrcweir                                         aUsageMap[aSecondToken.toInt32()] = true;
1180cdf0e10cSrcweir                                 }
1181cdf0e10cSrcweir                             }
1182cdf0e10cSrcweir 
1183cdf0e10cSrcweir                             ::std::vector< sal_Int32 > aSequenceIndexesToDelete;
1184cdf0e10cSrcweir                             for( ::std::vector< sal_Int32 >::const_iterator aIt(
1185cdf0e10cSrcweir                                      rTable.aHiddenColumns.begin()); aIt != rTable.aHiddenColumns.end(); ++aIt )
1186cdf0e10cSrcweir                             {
1187cdf0e10cSrcweir                                 sal_Int32 nSequenceIndex = *aIt;
1188cdf0e10cSrcweir                                 if( aUsageMap.find(nSequenceIndex) != aUsageMap.end() )
1189cdf0e10cSrcweir                                     continue;
1190cdf0e10cSrcweir                                 aSequenceIndexesToDelete.push_back(nSequenceIndex);
1191cdf0e10cSrcweir                             }
1192cdf0e10cSrcweir 
1193cdf0e10cSrcweir                             // delete unnecessary sequences of the internal data
1194cdf0e10cSrcweir                             // iterate using greatest index first, so that deletion does not
1195cdf0e10cSrcweir                             // shift other sequences that will be deleted later
1196cdf0e10cSrcweir                             ::std::sort( aSequenceIndexesToDelete.begin(), aSequenceIndexesToDelete.end());
1197cdf0e10cSrcweir                             for( ::std::vector< sal_Int32 >::reverse_iterator aIt(
1198cdf0e10cSrcweir                                      aSequenceIndexesToDelete.rbegin()); aIt != aSequenceIndexesToDelete.rend(); ++aIt )
1199cdf0e10cSrcweir                             {
1200cdf0e10cSrcweir                                 if( *aIt != -1 )
1201cdf0e10cSrcweir                                     xInternalDataProvider->deleteSequence( *aIt );
1202cdf0e10cSrcweir                             }
1203cdf0e10cSrcweir                         }
1204cdf0e10cSrcweir                     }
1205cdf0e10cSrcweir                 }
1206cdf0e10cSrcweir             }
1207cdf0e10cSrcweir         }
1208cdf0e10cSrcweir         catch( uno::Exception & ex )
1209cdf0e10cSrcweir         {
1210cdf0e10cSrcweir             (void)ex; // avoid warning for pro build
1211cdf0e10cSrcweir         }
1212cdf0e10cSrcweir     }
1213cdf0e10cSrcweir }
1214cdf0e10cSrcweir 
1215cdf0e10cSrcweir //---------------------------------------------------------------------------------------------------
1216cdf0e10cSrcweir 
1217cdf0e10cSrcweir SchXMLRangeSomewhereContext::SchXMLRangeSomewhereContext( SvXMLImport& rImport,
1218cdf0e10cSrcweir                                                 sal_uInt16 nPrefix,
1219cdf0e10cSrcweir 												const OUString& rLocalName,
1220cdf0e10cSrcweir 												OUString& rRangeString ) :
1221cdf0e10cSrcweir 		SvXMLImportContext( rImport, nPrefix, rLocalName ),
1222cdf0e10cSrcweir 		mrRangeString( rRangeString )
1223cdf0e10cSrcweir {
1224cdf0e10cSrcweir }
1225cdf0e10cSrcweir 
1226cdf0e10cSrcweir SchXMLRangeSomewhereContext::~SchXMLRangeSomewhereContext()
1227cdf0e10cSrcweir {
1228cdf0e10cSrcweir }
1229cdf0e10cSrcweir 
1230cdf0e10cSrcweir SvXMLImportContext* SchXMLRangeSomewhereContext::CreateChildContext(
1231cdf0e10cSrcweir     sal_uInt16 nPrefix,
1232cdf0e10cSrcweir     const OUString& rLocalName,
1233cdf0e10cSrcweir     const uno::Reference< xml::sax::XAttributeList >& )
1234cdf0e10cSrcweir {
1235cdf0e10cSrcweir     if( XML_NAMESPACE_SVG == nPrefix && IsXMLToken( rLocalName, XML_DESC ) )
1236cdf0e10cSrcweir 	{
1237cdf0e10cSrcweir 		return new XMLStringBufferImportContext(
1238cdf0e10cSrcweir 			GetImport(), nPrefix, rLocalName, maRangeStringBuffer );
1239cdf0e10cSrcweir 	}
1240cdf0e10cSrcweir 	return new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
1241cdf0e10cSrcweir }
1242cdf0e10cSrcweir 
1243cdf0e10cSrcweir void SchXMLRangeSomewhereContext::EndElement()
1244cdf0e10cSrcweir {
1245cdf0e10cSrcweir     mrRangeString = maRangeStringBuffer.makeStringAndClear();
1246cdf0e10cSrcweir }
1247