LibreOffice Module xmloff (master)  1
SchXMLTableContext.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sax/tools/converter.hxx>
21 
22 #include "SchXMLTableContext.hxx"
25 #include <SchXMLImport.hxx>
26 #include "SchXMLTools.hxx"
27 #include "transporttypes.hxx"
29 #include <o3tl/safeint.hxx>
30 #include <rtl/math.hxx>
31 #include <sal/log.hxx>
32 #include <xmloff/xmlnamespace.hxx>
33 #include <xmloff/xmltoken.hxx>
34 #include <xmloff/namespacemap.hxx>
35 #include <comphelper/sequence.hxx>
36 #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
37 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
38 #include <com/sun/star/chart2/XChartDocument.hpp>
39 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
40 #include <com/sun/star/chart2/XInternalDataProvider.hpp>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 
43 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
44 
45 #include <vector>
46 #include <algorithm>
47 #include <iterator>
48 
49 using namespace com::sun::star;
50 using namespace ::xmloff::token;
51 using ::com::sun::star::uno::Sequence;
52 using ::com::sun::star::uno::Reference;
53 
54 namespace
55 {
56 
57 const char aCategoriesRange[] = "categories";
58 
59 typedef ::std::multimap< OUString, OUString >
60  lcl_tOriginalRangeToInternalRangeMap;
61 
62 struct lcl_ApplyCellToData
63 {
64  explicit lcl_ApplyCellToData( Sequence< double > & rOutData ) :
65  m_rData( rOutData ),
66  m_nIndex( 0 ),
67  m_nSize( rOutData.getLength()),
68  m_fNaN( 0.0 )
69  {
70  ::rtl::math::setNan( &m_fNaN );
71  }
72 
73  void operator() ( const SchXMLCell & rCell )
74  {
75  if( m_nIndex < m_nSize )
76  {
77  if( rCell.eType == SCH_CELL_TYPE_FLOAT )
78  m_rData[m_nIndex] = rCell.fValue;
79  else
80  m_rData[m_nIndex] = m_fNaN;
81  }
82  ++m_nIndex;
83  }
84 
85  sal_Int32 getCurrentIndex() const
86  {
87  return m_nIndex;
88  }
89 
90 private:
91  Sequence< double > & m_rData;
92  sal_Int32 m_nIndex;
93  sal_Int32 m_nSize;
94  double m_fNaN;
95 };
96 
97 void lcl_fillRangeMapping(
98  const SchXMLTable & rTable,
99  lcl_tOriginalRangeToInternalRangeMap & rOutRangeMap,
100  chart::ChartDataRowSource eDataRowSource )
101 {
102  sal_Int32 nRowOffset = ( rTable.bHasHeaderRow ? 1 : 0 );
103  sal_Int32 nColOffset = ( rTable.bHasHeaderColumn ? 1 : 0 );
104 
105  const OUString lcl_aCategoriesRange(aCategoriesRange);
106  const OUString lcl_aLabelPrefix("label ");
107 
108  // Fill range mapping
109  const size_t nTableRowCount( rTable.aData.size());
110  for( size_t nRow = 0; nRow < nTableRowCount; ++nRow )
111  {
112  const ::std::vector< SchXMLCell > & rRow( rTable.aData[nRow] );
113  const size_t nTableColCount( rRow.size());
114  for( size_t nCol = 0; nCol < nTableColCount; ++nCol )
115  {
116  const OUString aRangeId( rRow[nCol].aRangeId );
117  if( !aRangeId.isEmpty())
118  {
119  if( eDataRowSource == chart::ChartDataRowSource_COLUMNS )
120  {
121  if( nCol == 0 && rTable.bHasHeaderColumn )
122  {
123  SAL_WARN_IF( static_cast< sal_Int32 >( nRow ) != nRowOffset, "xmloff.chart", "nRow != nRowOffset" );
124  rOutRangeMap.emplace(aRangeId, lcl_aCategoriesRange);
125  }
126  else
127  {
128  OUString aColNumStr = OUString::number( nCol - nColOffset);
129  if( nRow == 0 && rTable.bHasHeaderRow )
130  rOutRangeMap.emplace( aRangeId, lcl_aLabelPrefix + aColNumStr );
131  else
132  rOutRangeMap.emplace( aRangeId, aColNumStr );
133  }
134  }
135  else // eDataRowSource == chart::ChartDataRowSource_ROWS
136  {
137  if( nRow == 0 && rTable.bHasHeaderRow )
138  {
139  SAL_WARN_IF( static_cast< sal_Int32 >( nCol ) != nColOffset, "xmloff.chart", "nCol != nColOffset" );
140  rOutRangeMap.emplace( aRangeId, lcl_aCategoriesRange );
141  }
142  else
143  {
144  OUString aRowNumStr = OUString::number( nRow - nRowOffset);
145  if( nCol == 0 && rTable.bHasHeaderColumn )
146  rOutRangeMap.emplace( aRangeId, lcl_aLabelPrefix + aRowNumStr );
147  else
148  rOutRangeMap.emplace( aRangeId, aRowNumStr );
149  }
150  }
151  }
152  }
153  }
154 }
155 
156 Reference< chart2::data::XDataSequence >
157  lcl_reassignDataSequence(
158  const Reference< chart2::data::XDataSequence > & xSequence,
159  const Reference< chart2::data::XDataProvider > & xDataProvider,
160  lcl_tOriginalRangeToInternalRangeMap & rRangeMap,
161  const OUString & rRange )
162 {
163  Reference< chart2::data::XDataSequence > xResult( xSequence );
164  lcl_tOriginalRangeToInternalRangeMap::iterator aIt( rRangeMap.find( rRange ));
165  if( aIt != rRangeMap.end())
166  {
167  // set sequence with correct data
168  xResult.set( xDataProvider->createDataSequenceByRangeRepresentation( aIt->second ));
169  // remove translation, because it was used
170  rRangeMap.erase( aIt );
171  }
172 
173  return xResult;
174 }
175 
176 bool lcl_mapContainsRange(
177  lcl_tOriginalRangeToInternalRangeMap & rRangeMap,
178  const OUString & rRange )
179 {
180  lcl_tOriginalRangeToInternalRangeMap::iterator aIt( rRangeMap.find( rRange ));
181  return ( aIt != rRangeMap.end());
182 }
183 
184 bool lcl_tableOfRangeMatches(
185  const OUString & rRange,
186  const OUString & rTableName )
187 {
188  // both strings are non-empty and the table name is part of the range
189  return ( !rRange.isEmpty() &&
190  !rTableName.isEmpty() &&
191  (rRange.indexOf( rTableName ) != -1 ));
192 }
193 
194 } // anonymous namespace
195 
196 // class SchXMLTableContext
198  SvXMLImport& rImport,
199  const OUString& rLName,
200  SchXMLTable& aTable ) :
201  SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLName ),
202  mrImportHelper( rImpHelper ),
203  mrTable( aTable ),
204  mbHasRowPermutation( false ),
205  mbHasColumnPermutation( false )
206 {
207  mrTable.nColumnIndex = -1;
209  mrTable.nRowIndex = -1;
210  mrTable.aData.clear();
211 }
212 
214 {
215 }
216 
218  sal_uInt16 nPrefix,
219  const OUString& rLocalName,
220  const uno::Reference< xml::sax::XAttributeList >& )
221 {
222  SvXMLImportContext* pContext = nullptr;
224 
225  switch( rTokenMap.Get( nPrefix, rLocalName ))
226  {
228  mrTable.bHasHeaderColumn = true;
229  [[fallthrough]];
231  pContext = new SchXMLTableColumnsContext( GetImport(), rLocalName, mrTable );
232  break;
233 
235  pContext = new SchXMLTableColumnContext( GetImport(), rLocalName, mrTable );
236  break;
237 
239  mrTable.bHasHeaderRow = true;
240  [[fallthrough]];
241  case XML_TOK_TABLE_ROWS:
242  pContext = new SchXMLTableRowsContext( mrImportHelper, GetImport(), rLocalName, mrTable );
243  break;
244 
245  case XML_TOK_TABLE_ROW:
246  pContext = new SchXMLTableRowContext( mrImportHelper, GetImport(), rLocalName, mrTable );
247  break;
248  }
249 
250  return pContext;
251 }
252 
253 void SchXMLTableContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
254 {
255  // get table-name
256  sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
257 
258  for( sal_Int16 i = 0; i < nAttrCount; i++ )
259  {
260  OUString sAttrName = xAttrList->getNameByIndex( i );
261  OUString aLocalName;
262  sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
263  if ( nPrefix == XML_NAMESPACE_TABLE )
264  {
265  if ( IsXMLToken( aLocalName, XML_NAME ) )
266  {
267  mrTable.aTableNameOfFile = xAttrList->getValueByIndex( i );
268  }
269  else if ( IsXMLToken( aLocalName, XML_PROTECTED ) )
270  {
271  if ( IsXMLToken( xAttrList->getValueByIndex( i ), XML_TRUE ) )
272  {
273  mrTable.bProtected = true;
274  }
275  }
276  }
277  }
278 }
279 
281 {
283  {
284  SAL_WARN_IF( mbHasRowPermutation, "xmloff.chart", "mbHasColumnPermutation is true" );
285  auto aPermutation( comphelper::sequenceToContainer<std::vector< sal_Int32 >>( maColumnPermutation ));
286  SAL_WARN_IF( aPermutation.empty(), "xmloff.chart", "aPermutation is NULL");
287  if( aPermutation.empty())
288  return;
289 
290  // permute the values of all rows according to aPermutation
291  for( auto& rRow : mrTable.aData )
292  {
293  bool bModified = false;
294  ::std::vector< SchXMLCell > aModifiedRow;
295  const size_t nPermSize = aPermutation.size();
296  SAL_WARN_IF( static_cast< sal_Int32 >( nPermSize ) - 1 != *(::std::max_element( aPermutation.begin(), aPermutation.end())), "xmloff.chart", "nPermSize - 1 != *(::std::max_element( aPermutation.begin(), aPermutation.end())");
297  const size_t nRowSize = rRow.size();
298  const size_t nDestSize = ::std::min( nPermSize, nRowSize );
299  for( size_t nDestinationIndex = 0; nDestinationIndex < nDestSize; ++nDestinationIndex )
300  {
301  const size_t nSourceIndex = static_cast< size_t >( aPermutation[ nDestinationIndex ] );
302  if( nSourceIndex != nDestinationIndex &&
303  nSourceIndex < nRowSize )
304  {
305  // copy original on first real permutation
306  if( !bModified )
307  {
308  SAL_WARN_IF( !aModifiedRow.empty(), "xmloff.chart", "aModifiedRow is NOT NULL");
309  aModifiedRow.insert( aModifiedRow.end(), rRow.begin(), rRow.end() );
310  SAL_WARN_IF( aModifiedRow.empty(), "xmloff.chart", "aModifiedRow is NULL");
311  }
312  SAL_WARN_IF( nDestinationIndex >= aModifiedRow.size(), "xmloff.chart", "nDestinationIndex >= aModifiedRow.size()");
313  aModifiedRow[ nDestinationIndex ] = rRow[ nSourceIndex ];
314  bModified = true;
315  }
316  }
317  // copy back
318  if( bModified )
319  ::std::copy( aModifiedRow.begin(), aModifiedRow.end(), rRow.begin());
320  }
321  }
322  else if( mbHasRowPermutation )
323  {
324  auto aPermutation( comphelper::sequenceToContainer<std::vector< sal_Int32 >>( maRowPermutation ));
325  SAL_WARN_IF( aPermutation.empty(), "xmloff.chart", "aPermutation is NULL");
326  if( aPermutation.empty())
327  return;
328 
329  bool bModified = false;
330  const size_t nPermSize = aPermutation.size();
331  SAL_WARN_IF( static_cast< sal_Int32 >( nPermSize ) - 1 != *(::std::max_element( aPermutation.begin(), aPermutation.end())), "xmloff.chart", "nPermSize - 1 != *(::std::max_element( aPermutation.begin(), aPermutation.end())");
332  const size_t nTableRowCount = mrTable.aData.size();
333  const size_t nDestSize = ::std::min( nPermSize, nTableRowCount );
334  ::std::vector< ::std::vector< SchXMLCell > > aDestination;
335  for( size_t nDestinationIndex = 0; nDestinationIndex < nDestSize; ++nDestinationIndex )
336  {
337  const size_t nSourceIndex = static_cast< size_t >( aPermutation[ nDestinationIndex ] );
338  if( nSourceIndex != nDestinationIndex &&
339  nSourceIndex < nTableRowCount )
340  {
341  // copy original on first real permutation
342  if( !bModified )
343  {
344  SAL_WARN_IF( !aDestination.empty(), "xmloff.chart", "aDestination is NOT NULL");
345  aDestination.insert( aDestination.end(), mrTable.aData.begin(), mrTable.aData.end());
346  SAL_WARN_IF( aDestination.empty(), "xmloff.chart", "aDestination is NULL");
347  }
348  SAL_WARN_IF( nDestinationIndex >= aDestination.size(), "xmloff.chart", "nDestinationIndex >= aDestination.size()");
349  aDestination[ nDestinationIndex ] = mrTable.aData[ nSourceIndex ];
350  bModified = true;
351  }
352  }
353  if( bModified )
354  {
355  // copy back
356  ::std::copy( aDestination.begin(), aDestination.end(), mrTable.aData.begin());
357  }
358  }
359 }
360 
361 void SchXMLTableContext::setRowPermutation( const uno::Sequence< sal_Int32 > & rPermutation )
362 {
363  maRowPermutation = rPermutation;
364  mbHasRowPermutation = rPermutation.hasElements();
365 
367  {
368  mbHasColumnPermutation = false;
369  maColumnPermutation.realloc( 0 );
370  }
371 }
372 
373 void SchXMLTableContext::setColumnPermutation( const uno::Sequence< sal_Int32 > & rPermutation )
374 {
375  maColumnPermutation = rPermutation;
376  mbHasColumnPermutation = rPermutation.hasElements();
377 
379  {
380  mbHasRowPermutation = false;
381  maRowPermutation.realloc( 0 );
382  }
383 }
384 
385 // classes for columns
386 // class SchXMLTableColumnsContext
388  SvXMLImport& rImport,
389  const OUString& rLocalName,
390  SchXMLTable& aTable ) :
391  SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
392  mrTable( aTable )
393 {
394 }
395 
397 {
398 }
399 
401  sal_uInt16 nPrefix,
402  const OUString& rLocalName,
403  const uno::Reference< xml::sax::XAttributeList >& )
404 {
405  SvXMLImportContext* pContext = nullptr;
406 
407  if( nPrefix == XML_NAMESPACE_TABLE &&
408  IsXMLToken( rLocalName, XML_TABLE_COLUMN ) )
409  {
410  pContext = new SchXMLTableColumnContext( GetImport(), rLocalName, mrTable );
411  }
412 
413  return pContext;
414 }
415 
416 // class SchXMLTableColumnContext
418  SvXMLImport& rImport,
419  const OUString& rLocalName,
420  SchXMLTable& aTable ) :
421  SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
422  mrTable( aTable )
423 {
424 }
425 
426 void SchXMLTableColumnContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
427 {
428  // get number-columns-repeated attribute
429  sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
430  sal_Int32 nRepeated = 1;
431  bool bHidden = false;
432 
433  for( sal_Int16 i = 0; i < nAttrCount; i++ )
434  {
435  OUString sAttrName = xAttrList->getNameByIndex( i );
436  OUString aLocalName;
437  sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
438 
439  if( nPrefix == XML_NAMESPACE_TABLE &&
440  IsXMLToken( aLocalName, XML_NUMBER_COLUMNS_REPEATED ) )
441  {
442  OUString aValue = xAttrList->getValueByIndex( i );
443  if( !aValue.isEmpty())
444  nRepeated = aValue.toInt32();
445  }
446  else if( nPrefix == XML_NAMESPACE_TABLE &&
447  IsXMLToken( aLocalName, XML_VISIBILITY ) )
448  {
449  OUString aVisibility = xAttrList->getValueByIndex( i );
450  bHidden = aVisibility == GetXMLToken( XML_COLLAPSE );
451  }
452  }
453 
454  sal_Int32 nOldCount = mrTable.nNumberOfColsEstimate;
455  sal_Int32 nNewCount = nOldCount + nRepeated;
456  mrTable.nNumberOfColsEstimate = nNewCount;
457 
458  if( bHidden )
459  {
460  //i91578 display of hidden values (copy paste scenario; use hidden flag during migration to locale table upon paste )
461  sal_Int32 nColOffset = ( mrTable.bHasHeaderColumn ? 1 : 0 );
462  for( sal_Int32 nN = nOldCount; nN<nNewCount; nN++ )
463  {
464  sal_Int32 nHiddenColumnIndex = nN-nColOffset;
465  if( nHiddenColumnIndex>=0 )
466  mrTable.aHiddenColumns.push_back(nHiddenColumnIndex);
467  }
468  }
469 }
470 
472 {
473 }
474 
475 // classes for rows
476 // class SchXMLTableRowsContext
478  SchXMLImportHelper& rImpHelper,
479  SvXMLImport& rImport,
480  const OUString& rLocalName,
481  SchXMLTable& aTable ) :
482  SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
483  mrImportHelper( rImpHelper ),
484  mrTable( aTable )
485 {
486 }
487 
489 {
490 }
491 
493  sal_uInt16 nPrefix,
494  const OUString& rLocalName,
495  const uno::Reference< xml::sax::XAttributeList >& )
496 {
497  SvXMLImportContext* pContext = nullptr;
498 
499  if( nPrefix == XML_NAMESPACE_TABLE &&
500  IsXMLToken( rLocalName, XML_TABLE_ROW ) )
501  {
502  pContext = new SchXMLTableRowContext( mrImportHelper, GetImport(), rLocalName, mrTable );
503  }
504 
505  return pContext;
506 }
507 
508 // class SchXMLTableRowContext
510  SchXMLImportHelper& rImpHelper,
511  SvXMLImport& rImport,
512  const OUString& rLocalName,
513  SchXMLTable& aTable ) :
514  SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
515  mrImportHelper( rImpHelper ),
516  mrTable( aTable )
517 {
518  mrTable.nColumnIndex = -1;
519  mrTable.nRowIndex++;
520 
521  std::vector< SchXMLCell > aNewRow;
522  aNewRow.reserve( mrTable.nNumberOfColsEstimate );
524  mrTable.aData.push_back( aNewRow );
525 }
526 
528 {
529 }
530 
532  sal_uInt16 nPrefix,
533  const OUString& rLocalName,
534  const uno::Reference< xml::sax::XAttributeList >& )
535 {
536  SvXMLImportContext* pContext = nullptr;
537 
538  // <table:table-cell> element
539  if( nPrefix == XML_NAMESPACE_TABLE &&
540  IsXMLToken(rLocalName, XML_TABLE_CELL ) )
541  {
542  pContext = new SchXMLTableCellContext( mrImportHelper, GetImport(), rLocalName, mrTable );
543  }
544  else
545  {
546  assert(false);
547  }
548 
549  return pContext;
550 }
551 
552 namespace {
553 
554 class SchXMLRangeSomewhereContext : public SvXMLImportContext
555 {
556 //#i113950# previously the range was exported to attribute text:id,
557 //but that attribute does not allow arbitrary strings anymore
558 //so we need to find an alternative to save that range info for copy/paste scenario ...
559 //-> use description at an empty group element for now
560 
561 private:
562  OUString& mrRangeString;
563  OUStringBuffer maRangeStringBuffer;
564 
565 public:
566  SchXMLRangeSomewhereContext( SvXMLImport& rImport,
567  sal_uInt16 nPrefix,
568  const OUString& rLocalName,
569  OUString& rRangeString );
570 
572  sal_uInt16 nPrefix,
573  const OUString& rLocalName,
574  const css::uno::Reference< css::xml::sax::XAttributeList >& xAttrList ) override;
575  virtual void EndElement() override;
576 };
577 
578 }
579 
580 // classes for cells and their content
581 // class SchXMLTableCellContext
583  SchXMLImportHelper& rImpHelper, SvXMLImport& rImport,
584  const OUString& rLocalName, SchXMLTable& aTable)
585  : SvXMLImportContext(rImport, XML_NAMESPACE_TABLE, rLocalName)
586  , mrImportHelper(rImpHelper)
587  , mrTable(aTable)
588  , mbReadText(false)
589 {
590 }
591 
593 {
594 }
595 
596 void SchXMLTableCellContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
597 {
598  sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
599  OUString aValue;
600  OUString aLocalName;
601  OUString aCellContent;
603  const SvXMLTokenMap& rAttrTokenMap = mrImportHelper.GetCellAttrTokenMap();
604 
605  for( sal_Int16 i = 0; i < nAttrCount; i++ )
606  {
607  OUString sAttrName = xAttrList->getNameByIndex( i );
608  sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
609 
610  switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
611  {
613  aValue = xAttrList->getValueByIndex( i );
614  if( IsXMLToken( aValue, XML_FLOAT ) )
615  eValueType = SCH_CELL_TYPE_FLOAT;
616  else if( IsXMLToken( aValue, XML_STRING ) )
617  eValueType = SCH_CELL_TYPE_STRING;
618  break;
619 
620  case XML_TOK_CELL_VALUE:
621  aCellContent = xAttrList->getValueByIndex( i );
622  break;
623  }
624  }
625 
626  mbReadText = true;
627  SchXMLCell aCell;
628  aCell.eType = eValueType;
629 
630  if( eValueType == SCH_CELL_TYPE_FLOAT )
631  {
632  double fData;
633  // the result may be false if a NaN is read, but that's ok
634  ::sax::Converter::convertDouble( fData, aCellContent );
635 
636  aCell.fValue = fData;
637  // don't read text from following <text:p> or <text:list> element
638  mbReadText = false;
639  }
640 
641  mrTable.aData[ mrTable.nRowIndex ].push_back( aCell );
645 }
646 
648  sal_uInt16 nPrefix,
649  const OUString& rLocalName,
650  const uno::Reference< xml::sax::XAttributeList >& )
651 {
652  SvXMLImportContext* pContext = nullptr;
653 
654  // <text:list> element
655  if( nPrefix == XML_NAMESPACE_TEXT && IsXMLToken( rLocalName, XML_LIST ) && mbReadText )
656  {
660  pContext = new SchXMLTextListContext( GetImport(), rLocalName, rCell.aComplexString );
661  mbReadText = false;//don't apply text from <text:p>
662  }
663  // <text:p> element - read text (and range from text:id old version)
664  else if( (nPrefix == XML_NAMESPACE_TEXT ||
665  nPrefix == XML_NAMESPACE_LO_EXT) && IsXMLToken( rLocalName, XML_P ) )
666  {
667  pContext = new SchXMLParagraphContext( GetImport(), rLocalName, maCellContent, &maRangeId );
668  }
669  // <draw:g> element - read range
670  else if( nPrefix == XML_NAMESPACE_DRAW && IsXMLToken( rLocalName, XML_G ) )
671  {
672  //#i113950# previously the range was exported to attribute text:id, but that attribute does not allow arbitrary strings anymore
673  //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
674  pContext = new SchXMLRangeSomewhereContext( GetImport(), nPrefix, rLocalName, maRangeId );
675  }
676 
677  return pContext;
678 }
679 
681 {
682  if( mbReadText && !maCellContent.isEmpty() ) //apply text from <text:p> element
684  if( !maRangeId.isEmpty())
686 }
687 
688 static void lcl_ApplyCellToComplexLabel( const SchXMLCell& rCell, Sequence< uno::Any >& rComplexLabel )
689 {
690  if( rCell.eType == SCH_CELL_TYPE_STRING )
691  {
692  rComplexLabel.realloc(1);
693  rComplexLabel[0] <<= rCell.aString;
694  }
695  else if( rCell.aComplexString.hasElements() && rCell.eType == SCH_CELL_TYPE_COMPLEX_STRING )
696  {
697  sal_Int32 nCount = rCell.aComplexString.getLength();
698  rComplexLabel.realloc( nCount );
699  for( sal_Int32 nN=0; nN<nCount; nN++)
700  rComplexLabel[nN] <<= (rCell.aComplexString)[nN];
701  }
702  else if( rCell.eType == SCH_CELL_TYPE_FLOAT )
703  {
704  rComplexLabel.realloc(1);
705  rComplexLabel[0] <<= rCell.fValue;
706  }
707 }
708 
710  const SchXMLTable& rTable,
711  const uno::Reference< chart2::XChartDocument >& xChartDoc )
712 {
713  // apply all data read from the local table to the internal data provider
714  if( !xChartDoc.is() || !xChartDoc->hasInternalDataProvider() )
715  return;
716  Reference< chart2::data::XDataProvider > xDataProv( xChartDoc->getDataProvider() );
717  if( !xDataProv.is() )
718  return;
719 
720  //prepare the read local table data
721  sal_Int32 nNumRows( static_cast< sal_Int32 >( rTable.aData.size()));
722  sal_Int32 nRowOffset = 0;
723  if( rTable.bHasHeaderRow )
724  {
725  --nNumRows;
726  nRowOffset = 1;
727  }
728  sal_Int32 nNumColumns( rTable.nMaxColumnIndex + 1 );
729  sal_Int32 nColOffset = 0;
730  if( rTable.bHasHeaderColumn )
731  {
732  --nNumColumns;
733  nColOffset = 1;
734  }
735 
736  Sequence< Sequence< double > > aDataInRows( nNumRows );
737  Sequence< Sequence< uno::Any > > aComplexRowDescriptions( nNumRows );
738  Sequence< Sequence< uno::Any > > aComplexColumnDescriptions( nNumColumns );
739  for( sal_Int32 i=0; i<nNumRows; ++i )
740  aDataInRows[i].realloc( nNumColumns );
741 
742  if( !rTable.aData.empty() )
743  {
744  //apply column labels
745  if( rTable.bHasHeaderRow )
746  {
747  const ::std::vector< SchXMLCell >& rFirstRow = rTable.aData.front();
748  const sal_Int32 nColumnLabelsSize = aComplexColumnDescriptions.getLength();
749  const sal_Int32 nMax = ::std::min< sal_Int32 >( nColumnLabelsSize, static_cast< sal_Int32 >( rFirstRow.size()) - nColOffset );
750  SAL_WARN_IF( nMax != nColumnLabelsSize, "xmloff.chart", "nMax != nColumnLabelsSize");
751  for( sal_Int32 i=0; i<nMax; ++i )
752  lcl_ApplyCellToComplexLabel( rFirstRow[i+nColOffset], aComplexColumnDescriptions[i] );
753  }
754 
755  std::vector< ::std::vector< SchXMLCell > >::const_iterator aRowIter( rTable.aData.begin() + nRowOffset );
756  std::vector< ::std::vector< SchXMLCell > >::const_iterator aEnd( rTable.aData.end() );
757  for( sal_Int32 nRow = 0; aRowIter != aEnd && nRow < nNumRows; ++aRowIter, ++nRow )
758  {
759  const ::std::vector< SchXMLCell >& rRow = *aRowIter;
760  if( !rRow.empty() )
761  {
762  // row label
763  if( rTable.bHasHeaderColumn )
764  lcl_ApplyCellToComplexLabel( rRow.front(), aComplexRowDescriptions[nRow] );
765 
766  // values
767  Sequence< double >& rTargetRow = aDataInRows[nRow];
768  lcl_ApplyCellToData aApplyCellToData = ::std::for_each( rRow.begin() + nColOffset, rRow.end(), lcl_ApplyCellToData( rTargetRow ) );
769  double fNaN = 0.0;
770  ::rtl::math::setNan( &fNaN );
771  for( sal_Int32 nCurrentIndex = aApplyCellToData.getCurrentIndex(); nCurrentIndex<nNumColumns; nCurrentIndex++ )
772  rTargetRow[nCurrentIndex] = fNaN;//#i110615#
773  }
774  }
775  }
776 
777  //apply the collected data to the chart
778  Reference< chart2::XAnyDescriptionAccess > xDataAccess( xDataProv, uno::UNO_QUERY );
779  if( !xDataAccess.is() )
780  return;
781 
782  xDataAccess->setData( aDataInRows );
783  if( rTable.bHasHeaderColumn )
784  xDataAccess->setAnyRowDescriptions( aComplexRowDescriptions );
785  if( rTable.bHasHeaderRow )
786  xDataAccess->setAnyColumnDescriptions( aComplexColumnDescriptions );
787 
788  if ( rTable.bProtected )
789  {
790  try
791  {
792  Reference< beans::XPropertySet > xProps( xChartDoc, uno::UNO_QUERY_THROW );
793  xProps->setPropertyValue( "DisableDataTableDialog", uno::makeAny( true ) );
794  xProps->setPropertyValue( "DisableComplexChartTypes", uno::makeAny( true ) );
795  }
796  catch ( uno::Exception& )
797  {
798  }
799  }
800 }
801 
803  const SchXMLTable& rTable,
804  const tSchXMLLSequencesPerIndex & rLSequencesPerIndex,
805  const uno::Reference< chart2::XChartDocument >& xChartDoc,
806  chart::ChartDataRowSource eDataRowSource )
807 {
808  if( ! (xChartDoc.is() && xChartDoc->hasInternalDataProvider()))
809  return;
810 
811  // If the range-strings are valid (starting with "local-table") they should
812  // be interpreted like given, otherwise (when the ranges refer to Calc- or
813  // Writer-ranges, but the container is not available like when pasting a
814  // chart from Calc to Impress) the range is ignored, and every object gets
815  // one table column in the order of appearance, which is: 1. categories,
816  // 2. data series: 2.a) domains, 2.b) values (main-role, usually y-values)
817 
818  Reference< chart2::data::XDataProvider > xDataProv( xChartDoc->getDataProvider());
819 
820  // create a mapping from original ranges to new ranges
821  lcl_tOriginalRangeToInternalRangeMap aRangeMap;
822 
823  lcl_fillRangeMapping( rTable, aRangeMap, eDataRowSource );
824 
825  const OUString lcl_aCategoriesRange(aCategoriesRange);
826 
827  bool bCategoriesApplied = false;
828  // translate ranges (using the map created before)
829  for( const auto& rLSeq : rLSequencesPerIndex )
830  {
831  if( rLSeq.second.is())
832  {
833  // values/error bars/categories
834  if( rLSeq.first.second == SCH_XML_PART_VALUES ||
835  rLSeq.first.second == SCH_XML_PART_ERROR_BARS )
836  {
837  Reference< chart2::data::XDataSequence > xSeq( rLSeq.second->getValues());
838 
839  OUString aRange;
840  if( xSeq.is() &&
841  SchXMLTools::getXMLRangePropertyFromDataSequence( xSeq, aRange, /* bClearProp = */ true ) &&
842  lcl_mapContainsRange( aRangeMap, aRange ))
843  {
844  Reference< chart2::data::XDataSequence > xNewSeq(
845  lcl_reassignDataSequence( xSeq, xDataProv, aRangeMap, aRange ));
846  if( xNewSeq != xSeq )
847  {
849  Reference< beans::XPropertySet >( xNewSeq, uno::UNO_QUERY ));
850  rLSeq.second->setValues( xNewSeq );
851  }
852  }
853  else
854  {
855  if( lcl_tableOfRangeMatches( aRange, rTable.aTableNameOfFile ))
856  {
857  if( rLSeq.first.first == SCH_XML_CATEGORIES_INDEX )
858  bCategoriesApplied = true;
859  }
860  else
861  {
862  if( rLSeq.first.first == SCH_XML_CATEGORIES_INDEX )
863  {
864  Reference< beans::XPropertySet > xOldSequenceProp( rLSeq.second->getValues(), uno::UNO_QUERY );
865  Reference< chart2::data::XDataSequence > xNewSequence(
866  xDataProv->createDataSequenceByRangeRepresentation("categories"));
868  xOldSequenceProp, Reference< beans::XPropertySet >( xNewSequence, uno::UNO_QUERY ));
869  rLSeq.second->setValues( xNewSequence );
870  bCategoriesApplied = true;
871  }
872  else
873  {
874  Reference< beans::XPropertySet > xOldSequenceProp( rLSeq.second->getValues(), uno::UNO_QUERY );
875  OUString aRep( OUString::number( rLSeq.first.first ));
876  Reference< chart2::data::XDataSequence > xNewSequence(
877  xDataProv->createDataSequenceByRangeRepresentation( aRep ));
879  xOldSequenceProp, Reference< beans::XPropertySet >( xNewSequence, uno::UNO_QUERY ));
880  rLSeq.second->setValues( xNewSequence );
881  }
882  }
883  }
884  }
885  else // labels
886  {
887  SAL_WARN_IF( rLSeq.first.second != SCH_XML_PART_LABEL, "xmloff.chart", "rLSeq.first.second != SCH_XML_PART_LABEL" );
888  // labels
889  Reference< chart2::data::XDataSequence > xSeq( rLSeq.second->getLabel());
890  OUString aRange;
891  if( xSeq.is() &&
892  SchXMLTools::getXMLRangePropertyFromDataSequence( xSeq, aRange, /* bClearProp = */ true ) &&
893  lcl_mapContainsRange( aRangeMap, aRange ))
894  {
895  Reference< chart2::data::XDataSequence > xNewSeq(
896  lcl_reassignDataSequence( xSeq, xDataProv, aRangeMap, aRange ));
897  if( xNewSeq != xSeq )
898  {
900  Reference< beans::XPropertySet >( xNewSeq, uno::UNO_QUERY ));
901  rLSeq.second->setLabel( xNewSeq );
902  }
903  }
904  else if( ! lcl_tableOfRangeMatches( aRange, rTable.aTableNameOfFile ))
905  {
906  OUString aRep = "label " + OUString::number( rLSeq.first.first );
907 
908  Reference< chart2::data::XDataSequence > xNewSeq(
909  xDataProv->createDataSequenceByRangeRepresentation( aRep ));
911  Reference< beans::XPropertySet >( xNewSeq, uno::UNO_QUERY ));
912  rLSeq.second->setLabel( xNewSeq );
913  }
914  }
915  }
916  }
917 
918  // there exist files with own data without a categories element but with row
919  // descriptions. The row descriptions were used as categories even without
920  // the categories element
921  if( ! bCategoriesApplied )
922  {
924  xDataProv, xChartDoc, "categories",
925  0 /* nCooSysIndex */, 0 /* nDimension */ );
926  }
927 
928  //i91578 display of hidden values (copy paste scenario; use hidden flag during migration to locale table upon paste )
929  //remove series that consist only of hidden columns
930  Reference< chart2::XInternalDataProvider > xInternalDataProvider( xDataProv, uno::UNO_QUERY );
931  if( !xInternalDataProvider.is() || rTable.aHiddenColumns.empty() )
932  return;
933 
934  try
935  {
936  Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xChartDoc->getFirstDiagram(), uno::UNO_QUERY_THROW );
937  const Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
938  for( const auto& rCooSys : aCooSysSeq )
939  {
940  Reference< chart2::XChartTypeContainer > xCooSysContainer( rCooSys, uno::UNO_QUERY_THROW );
941  const Sequence< Reference< chart2::XChartType > > aChartTypeSeq( xCooSysContainer->getChartTypes());
942  for( const auto& rChartType : aChartTypeSeq )
943  {
944  Reference< chart2::XDataSeriesContainer > xSeriesContainer( rChartType, uno::UNO_QUERY );
945  if(!xSeriesContainer.is())
946  continue;
947  const Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xSeriesContainer->getDataSeries() );
948  std::vector< Reference< chart2::XDataSeries > > aRemainingSeries;
949 
950  for( const auto& rSeries : aSeriesSeq )
951  {
952  Reference< chart2::data::XDataSource > xDataSource( rSeries, uno::UNO_QUERY );
953  if( xDataSource.is() )
954  {
955  bool bHasUnhiddenColumns = false;
956  OUString aRange;
957  const uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences() );
958  for( const auto& xLabeledSequence : aSequences )
959  {
960  if(!xLabeledSequence.is())
961  continue;
962  Reference< chart2::data::XDataSequence > xValues( xLabeledSequence->getValues() );
963  if( xValues.is() )
964  {
965  aRange = xValues->getSourceRangeRepresentation();
966  if( ::std::find( rTable.aHiddenColumns.begin(), rTable.aHiddenColumns.end(), aRange.toInt32() ) == rTable.aHiddenColumns.end() )
967  bHasUnhiddenColumns = true;
968  }
969  if( !bHasUnhiddenColumns )
970  {
971  Reference< chart2::data::XDataSequence > xLabel( xLabeledSequence->getLabel() );
972  if( xLabel.is() )
973  {
974  aRange = xLabel->getSourceRangeRepresentation();
975  const sal_Int32 nId {aRange.getToken(1, ' ').toInt32()};
976  if( ::std::find( rTable.aHiddenColumns.begin(), rTable.aHiddenColumns.end(), nId ) == rTable.aHiddenColumns.end() )
977  bHasUnhiddenColumns = true;
978  }
979  }
980  }
981  if( bHasUnhiddenColumns )
982  aRemainingSeries.push_back( rSeries );
983  }
984  }
985 
986  if( static_cast<sal_Int32>(aRemainingSeries.size()) != aSeriesSeq.getLength() )
987  {
988  //remove the series that have only hidden data
989  xSeriesContainer->setDataSeries( comphelper::containerToSequence(aRemainingSeries) );
990 
991  //remove unused sequences
992  Reference< chart2::data::XDataSource > xDataSource( xChartDoc, uno::UNO_QUERY );
993  if( xDataSource.is() )
994  {
995  //first detect which columns are really used
996  std::map< sal_Int32, bool > aUsageMap;
997  OUString aRange;
998  const Sequence< Reference< chart2::data::XLabeledDataSequence > > aUsedSequences( xDataSource->getDataSequences() );
999  for( const auto& xLabeledSequence : aUsedSequences )
1000  {
1001  if(!xLabeledSequence.is())
1002  continue;
1003  Reference< chart2::data::XDataSequence > xValues( xLabeledSequence->getValues() );
1004  if( xValues.is() )
1005  {
1006  aRange = xValues->getSourceRangeRepresentation();
1007  sal_Int32 nIndex = aRange.toInt32();
1008  if( nIndex!=0 || aRange != lcl_aCategoriesRange )
1009  aUsageMap[nIndex] = true;
1010  }
1011  Reference< chart2::data::XDataSequence > xLabel( xLabeledSequence->getLabel() );
1012  if( xLabel.is() )
1013  {
1014  aRange = xLabel->getSourceRangeRepresentation();
1015  OUString aSecondToken = aRange.getToken(1, ' ');
1016  if( !aSecondToken.isEmpty() )
1017  aUsageMap[aSecondToken.toInt32()] = true;
1018  }
1019  }
1020 
1021  ::std::vector< sal_Int32 > aSequenceIndexesToDelete;
1022  std::copy_if(rTable.aHiddenColumns.begin(), rTable.aHiddenColumns.end(),
1023  std::back_inserter(aSequenceIndexesToDelete),
1024  [&aUsageMap](sal_Int32 nSequenceIndex) { return aUsageMap.find(nSequenceIndex) == aUsageMap.end(); });
1025 
1026  // delete unnecessary sequences of the internal data
1027  // iterate using greatest index first, so that deletion does not
1028  // shift other sequences that will be deleted later
1029  ::std::sort( aSequenceIndexesToDelete.begin(), aSequenceIndexesToDelete.end());
1030  for( ::std::vector< sal_Int32 >::reverse_iterator aIt(
1031  aSequenceIndexesToDelete.rbegin()); aIt != aSequenceIndexesToDelete.rend(); ++aIt )
1032  {
1033  if( *aIt != -1 )
1034  xInternalDataProvider->deleteSequence( *aIt );
1035  }
1036  }
1037  }
1038  }
1039  }
1040  }
1041  catch( const uno::Exception & )
1042  {
1043  }
1044 }
1045 
1046 SchXMLRangeSomewhereContext::SchXMLRangeSomewhereContext( SvXMLImport& rImport,
1047  sal_uInt16 nPrefix,
1048  const OUString& rLocalName,
1049  OUString& rRangeString ) :
1050  SvXMLImportContext( rImport, nPrefix, rLocalName ),
1051  mrRangeString( rRangeString )
1052 {
1053 }
1054 
1055 SvXMLImportContextRef SchXMLRangeSomewhereContext::CreateChildContext(
1056  sal_uInt16 nPrefix,
1057  const OUString& rLocalName,
1058  const uno::Reference< xml::sax::XAttributeList >& )
1059 {
1060  if( XML_NAMESPACE_SVG == nPrefix && IsXMLToken( rLocalName, XML_DESC ) )
1061  {
1062  return new XMLStringBufferImportContext(
1063  GetImport(), nPrefix, rLocalName, maRangeStringBuffer );
1064  }
1065  return nullptr;
1066 }
1067 
1068 void SchXMLRangeSomewhereContext::EndElement()
1069 {
1070  mrRangeString = maRangeStringBuffer.makeStringAndClear();
1071 }
1072 
1073 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SchXMLCellType
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3434
sal_Int32 nIndex
OUString aString
virtual ~SchXMLTableColumnContext() override
virtual void EndElement()
EndElement is called before a context will be destructed, but after an elements context has been pars...
Definition: xmlictxt.cxx:62
SchXMLTableContext(SchXMLImportHelper &rImpHelper, SvXMLImport &rImport, const OUString &rLocalName, SchXMLTable &aTable)
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
Create a children element context.
virtual void StartElement(const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
StartElement is called after a context has been constructed and before an elements context is parsed...
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:62
sal_Int16 nId
SvXMLNamespaceMap & GetNamespaceMap()
Definition: xmlimp.hxx:402
SchXMLTableColumnContext(SvXMLImport &rImport, const OUString &rLocalName, SchXMLTable &aTable)
void setRowPermutation(const css::uno::Sequence< sal_Int32 > &rPermutation)
constexpr sal_uInt16 XML_NAMESPACE_LO_EXT
virtual void EndElement() override
EndElement is called before a context will be destructed, but after an elements context has been pars...
SchXMLImportHelper & mrImportHelper
sal_uInt16 GetKeyByAttrName(const OUString &rAttrName, OUString *pPrefix, OUString *pLocalName, OUString *pNamespace) const
css::uno::Sequence< OUString > aComplexString
static void convertDouble(OUStringBuffer &rBuffer, double fNumber, bool bWriteUnits, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
virtual void StartElement(const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
StartElement is called after a context has been constructed and before an elements context is parsed...
DstType sequenceToContainer(const css::uno::Sequence< SrcType > &i_Sequence)
css::uno::Sequence< sal_Int32 > maRowPermutation
const Sequence< Sequence< double > > & m_rData
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
int nCount
const SvXMLTokenMap & GetTableElemTokenMap()
css::uno::Sequence< sal_Int32 > maColumnPermutation
virtual ~SchXMLTableContext() override
constexpr sal_uInt16 XML_NAMESPACE_DRAW
sal_Int32 nNumberOfColsEstimate
the greatest number of columns detected
static void lcl_ApplyCellToComplexLabel(const SchXMLCell &rCell, Sequence< uno::Any > &rComplexLabel)
SchXMLTableRowContext(SchXMLImportHelper &rImpHelper, SvXMLImport &rImport, const OUString &rLocalName, SchXMLTable &aTable)
virtual ~SchXMLTableRowsContext() override
constexpr sal_uInt16 XML_NAMESPACE_SVG
int i
#define SCH_XML_CATEGORIES_INDEX
virtual ~SchXMLTableCellContext() override
constexpr sal_uInt16 XML_NAMESPACE_TEXT
SchXMLImportHelper & mrImportHelper
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
sal_uInt16 Get(sal_uInt16 nPrefix, const OUString &rLName) const
Definition: xmltkmap.cxx:99
sal_Int32 nColumnIndex
reflects the index of the row currently parsed
std::vector< std::vector< SchXMLCell > > aData
Import all text into a string buffer.
With this class you can import a element containing its data as element o...
This class deliberately does not support XWeak, to improve performance when loading large documents...
Definition: xmlictxt.hxx:44
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
Create a children element context.
void CreateCategories(const uno::Reference< chart2::data::XDataProvider > &xDataProvider, const uno::Reference< chart2::XChartDocument > &xNewDoc, const OUString &rRangeAddress, sal_Int32 nCooSysIndex, sal_Int32 nDimensionIndex, tSchXMLLSequencesPerIndex *pLSequencesPerIndex)
SchXMLTableRowsContext(SchXMLImportHelper &rImpHelper, SvXMLImport &rImport, const OUString &rLocalName, SchXMLTable &aTable)
bool bHasHeaderRow
parsing column-elements may yield an estimate
constexpr sal_uInt16 XML_NAMESPACE_TABLE
static void switchRangesFromOuterToInternalIfNecessary(const SchXMLTable &rTable, const tSchXMLLSequencesPerIndex &rLSequencesPerIndex, const css::uno::Reference< css::chart2::XChartDocument > &xChartDoc, css::chart::ChartDataRowSource eDataRowSource)
This function reorders local data to fit the correct data structure.
OUString aTableNameOfFile
#define SAL_WARN_IF(condition, area, stream)
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Definition: xmltoken.cxx:3378
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Handling of tokens in XML:
SchXMLTableCellContext(SchXMLImportHelper &rImpHelper, SvXMLImport &rImport, const OUString &rLocalName, SchXMLTable &aTable)
bool getXMLRangePropertyFromDataSequence(const Reference< chart2::data::XDataSequence > &xDataSequence, OUString &rOutXMLRange, bool bClearProp)
double getLength(const B2DPolygon &rCandidate)
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList)
Create a children element context.
Definition: xmlictxt.cxx:51
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
Create a children element context.
sal_Int32 nMaxColumnIndex
reflects the index of the column currently parsed
SchXMLImportHelper & mrImportHelper
SchXMLImportHelper & mrImportHelper
const SvXMLTokenMap & GetCellAttrTokenMap()
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
Create a children element context.
virtual ~SchXMLTableRowContext() override
SchXMLCellType eType
virtual void StartElement(const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
StartElement is called after a context has been constructed and before an elements context is parsed...
::std::vector< sal_Int32 > aHiddenColumns
the table name read at the table:table element
With this context all column elements are parsed to determine the index of the column containing the ...
::std::multimap< tSchXMLIndexWithPart, css::uno::Reference< css::chart2::data::XLabeledDataSequence > > tSchXMLLSequencesPerIndex
void copyProperties(const Reference< beans::XPropertySet > &xSource, const Reference< beans::XPropertySet > &xDestination)
SchXMLTableColumnsContext(SvXMLImport &rImport, const OUString &rLocalName, SchXMLTable &aTable)
void setColumnPermutation(const css::uno::Sequence< sal_Int32 > &rPermutation)
static void applyTableToInternalDataProvider(const SchXMLTable &rTable, const css::uno::Reference< css::chart2::XChartDocument > &xChartDoc)
virtual ~SchXMLTableColumnsContext() override
sal_uInt32 m_nSize
sal_Int32 nRowIndex
an array of rows containing the table contents
virtual void EndElement() override
EndElement is called before a context will be destructed, but after an elements context has been pars...
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
Create a children element context.