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/xmlnmspe.hxx>
33 #include <xmloff/xmltoken.hxx>
34 #include <xmloff/nmspmap.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.reserve( rRow.size());
310  ::std::copy( rRow.begin(), rRow.end(), ::std::back_inserter( aModifiedRow ));
311  SAL_WARN_IF( aModifiedRow.empty(), "xmloff.chart", "aModifiedRow is NULL");
312  }
313  SAL_WARN_IF( nDestinationIndex >= aModifiedRow.size(), "xmloff.chart", "nDestinationIndex >= aModifiedRow.size()");
314  aModifiedRow[ nDestinationIndex ] = rRow[ nSourceIndex ];
315  bModified = true;
316  }
317  }
318  // copy back
319  if( bModified )
320  ::std::copy( aModifiedRow.begin(), aModifiedRow.end(), rRow.begin());
321  }
322  }
323  else if( mbHasRowPermutation )
324  {
325  auto aPermutation( comphelper::sequenceToContainer<std::vector< sal_Int32 >>( maRowPermutation ));
326  SAL_WARN_IF( aPermutation.empty(), "xmloff.chart", "aPermutation is NULL");
327  if( aPermutation.empty())
328  return;
329 
330  bool bModified = false;
331  const size_t nPermSize = aPermutation.size();
332  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())");
333  const size_t nTableRowCount = mrTable.aData.size();
334  const size_t nDestSize = ::std::min( nPermSize, nTableRowCount );
335  ::std::vector< ::std::vector< SchXMLCell > > aDestination;
336  for( size_t nDestinationIndex = 0; nDestinationIndex < nDestSize; ++nDestinationIndex )
337  {
338  const size_t nSourceIndex = static_cast< size_t >( aPermutation[ nDestinationIndex ] );
339  if( nSourceIndex != nDestinationIndex &&
340  nSourceIndex < nTableRowCount )
341  {
342  // copy original on first real permutation
343  if( !bModified )
344  {
345  SAL_WARN_IF( !aDestination.empty(), "xmloff.chart", "aDestination is NOT NULL");
346  aDestination.reserve( mrTable.aData.size());
347  ::std::copy( mrTable.aData.begin(), mrTable.aData.end(), ::std::back_inserter( aDestination ));
348  SAL_WARN_IF( aDestination.empty(), "xmloff.chart", "aDestination is NULL");
349  }
350  SAL_WARN_IF( nDestinationIndex >= aDestination.size(), "xmloff.chart", "nDestinationIndex >= aDestination.size()");
351  aDestination[ nDestinationIndex ] = mrTable.aData[ nSourceIndex ];
352  bModified = true;
353  }
354  }
355  if( bModified )
356  {
357  // copy back
358  ::std::copy( aDestination.begin(), aDestination.end(), mrTable.aData.begin());
359  }
360  }
361 }
362 
363 void SchXMLTableContext::setRowPermutation( const uno::Sequence< sal_Int32 > & rPermutation )
364 {
365  maRowPermutation = rPermutation;
366  mbHasRowPermutation = rPermutation.hasElements();
367 
369  {
370  mbHasColumnPermutation = false;
371  maColumnPermutation.realloc( 0 );
372  }
373 }
374 
375 void SchXMLTableContext::setColumnPermutation( const uno::Sequence< sal_Int32 > & rPermutation )
376 {
377  maColumnPermutation = rPermutation;
378  mbHasColumnPermutation = rPermutation.hasElements();
379 
381  {
382  mbHasRowPermutation = false;
383  maRowPermutation.realloc( 0 );
384  }
385 }
386 
387 // classes for columns
388 // class SchXMLTableColumnsContext
390  SvXMLImport& rImport,
391  const OUString& rLocalName,
392  SchXMLTable& aTable ) :
393  SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
394  mrTable( aTable )
395 {
396 }
397 
399 {
400 }
401 
403  sal_uInt16 nPrefix,
404  const OUString& rLocalName,
405  const uno::Reference< xml::sax::XAttributeList >& )
406 {
407  SvXMLImportContext* pContext = nullptr;
408 
409  if( nPrefix == XML_NAMESPACE_TABLE &&
410  IsXMLToken( rLocalName, XML_TABLE_COLUMN ) )
411  {
412  pContext = new SchXMLTableColumnContext( GetImport(), rLocalName, mrTable );
413  }
414 
415  return pContext;
416 }
417 
418 // class SchXMLTableColumnContext
420  SvXMLImport& rImport,
421  const OUString& rLocalName,
422  SchXMLTable& aTable ) :
423  SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
424  mrTable( aTable )
425 {
426 }
427 
428 void SchXMLTableColumnContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
429 {
430  // get number-columns-repeated attribute
431  sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
432  sal_Int32 nRepeated = 1;
433  bool bHidden = false;
434 
435  for( sal_Int16 i = 0; i < nAttrCount; i++ )
436  {
437  OUString sAttrName = xAttrList->getNameByIndex( i );
438  OUString aLocalName;
439  sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
440 
441  if( nPrefix == XML_NAMESPACE_TABLE &&
442  IsXMLToken( aLocalName, XML_NUMBER_COLUMNS_REPEATED ) )
443  {
444  OUString aValue = xAttrList->getValueByIndex( i );
445  if( !aValue.isEmpty())
446  nRepeated = aValue.toInt32();
447  }
448  else if( nPrefix == XML_NAMESPACE_TABLE &&
449  IsXMLToken( aLocalName, XML_VISIBILITY ) )
450  {
451  OUString aVisibility = xAttrList->getValueByIndex( i );
452  bHidden = aVisibility == GetXMLToken( XML_COLLAPSE );
453  }
454  }
455 
456  sal_Int32 nOldCount = mrTable.nNumberOfColsEstimate;
457  sal_Int32 nNewCount = nOldCount + nRepeated;
458  mrTable.nNumberOfColsEstimate = nNewCount;
459 
460  if( bHidden )
461  {
462  //i91578 display of hidden values (copy paste scenario; use hidden flag during migration to locale table upon paste )
463  sal_Int32 nColOffset = ( mrTable.bHasHeaderColumn ? 1 : 0 );
464  for( sal_Int32 nN = nOldCount; nN<nNewCount; nN++ )
465  {
466  sal_Int32 nHiddenColumnIndex = nN-nColOffset;
467  if( nHiddenColumnIndex>=0 )
468  mrTable.aHiddenColumns.push_back(nHiddenColumnIndex);
469  }
470  }
471 }
472 
474 {
475 }
476 
477 // classes for rows
478 // class SchXMLTableRowsContext
480  SchXMLImportHelper& rImpHelper,
481  SvXMLImport& rImport,
482  const OUString& rLocalName,
483  SchXMLTable& aTable ) :
484  SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
485  mrImportHelper( rImpHelper ),
486  mrTable( aTable )
487 {
488 }
489 
491 {
492 }
493 
495  sal_uInt16 nPrefix,
496  const OUString& rLocalName,
497  const uno::Reference< xml::sax::XAttributeList >& )
498 {
499  SvXMLImportContext* pContext = nullptr;
500 
501  if( nPrefix == XML_NAMESPACE_TABLE &&
502  IsXMLToken( rLocalName, XML_TABLE_ROW ) )
503  {
504  pContext = new SchXMLTableRowContext( mrImportHelper, GetImport(), rLocalName, mrTable );
505  }
506 
507  return pContext;
508 }
509 
510 // class SchXMLTableRowContext
512  SchXMLImportHelper& rImpHelper,
513  SvXMLImport& rImport,
514  const OUString& rLocalName,
515  SchXMLTable& aTable ) :
516  SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
517  mrImportHelper( rImpHelper ),
518  mrTable( aTable )
519 {
520  mrTable.nColumnIndex = -1;
521  mrTable.nRowIndex++;
522 
523  std::vector< SchXMLCell > aNewRow;
524  aNewRow.reserve( mrTable.nNumberOfColsEstimate );
526  mrTable.aData.push_back( aNewRow );
527 }
528 
530 {
531 }
532 
534  sal_uInt16 nPrefix,
535  const OUString& rLocalName,
536  const uno::Reference< xml::sax::XAttributeList >& )
537 {
538  SvXMLImportContext* pContext = nullptr;
539 
540  // <table:table-cell> element
541  if( nPrefix == XML_NAMESPACE_TABLE &&
542  IsXMLToken(rLocalName, XML_TABLE_CELL ) )
543  {
544  pContext = new SchXMLTableCellContext( mrImportHelper, GetImport(), rLocalName, mrTable );
545  }
546  else
547  {
548  assert(false);
549  }
550 
551  return pContext;
552 }
553 
554 namespace {
555 
556 class SchXMLRangeSomewhereContext : public SvXMLImportContext
557 {
558 //#i113950# previously the range was exported to attribute text:id,
559 //but that attribute does not allow arbitrary strings anymore
560 //so we need to find an alternative to save that range info for copy/paste scenario ...
561 //-> use description at an empty group element for now
562 
563 private:
564  OUString& mrRangeString;
565  OUStringBuffer maRangeStringBuffer;
566 
567 public:
568  SchXMLRangeSomewhereContext( SvXMLImport& rImport,
569  sal_uInt16 nPrefix,
570  const OUString& rLocalName,
571  OUString& rRangeString );
572 
574  sal_uInt16 nPrefix,
575  const OUString& rLocalName,
576  const css::uno::Reference< css::xml::sax::XAttributeList >& xAttrList ) override;
577  virtual void EndElement() override;
578 };
579 
580 }
581 
582 // classes for cells and their content
583 // class SchXMLTableCellContext
585  SchXMLImportHelper& rImpHelper, SvXMLImport& rImport,
586  const OUString& rLocalName, SchXMLTable& aTable)
587  : SvXMLImportContext(rImport, XML_NAMESPACE_TABLE, rLocalName)
588  , mrImportHelper(rImpHelper)
589  , mrTable(aTable)
590  , mbReadText(false)
591 {
592 }
593 
595 {
596 }
597 
598 void SchXMLTableCellContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
599 {
600  sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
601  OUString aValue;
602  OUString aLocalName;
603  OUString aCellContent;
605  const SvXMLTokenMap& rAttrTokenMap = mrImportHelper.GetCellAttrTokenMap();
606 
607  for( sal_Int16 i = 0; i < nAttrCount; i++ )
608  {
609  OUString sAttrName = xAttrList->getNameByIndex( i );
610  sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
611 
612  switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
613  {
615  aValue = xAttrList->getValueByIndex( i );
616  if( IsXMLToken( aValue, XML_FLOAT ) )
617  eValueType = SCH_CELL_TYPE_FLOAT;
618  else if( IsXMLToken( aValue, XML_STRING ) )
619  eValueType = SCH_CELL_TYPE_STRING;
620  break;
621 
622  case XML_TOK_CELL_VALUE:
623  aCellContent = xAttrList->getValueByIndex( i );
624  break;
625  }
626  }
627 
628  mbReadText = true;
629  SchXMLCell aCell;
630  aCell.eType = eValueType;
631 
632  if( eValueType == SCH_CELL_TYPE_FLOAT )
633  {
634  double fData;
635  // the result may be false if a NaN is read, but that's ok
636  ::sax::Converter::convertDouble( fData, aCellContent );
637 
638  aCell.fValue = fData;
639  // don't read text from following <text:p> or <text:list> element
640  mbReadText = false;
641  }
642 
643  mrTable.aData[ mrTable.nRowIndex ].push_back( aCell );
647 }
648 
650  sal_uInt16 nPrefix,
651  const OUString& rLocalName,
652  const uno::Reference< xml::sax::XAttributeList >& )
653 {
654  SvXMLImportContext* pContext = nullptr;
655 
656  // <text:list> element
657  if( nPrefix == XML_NAMESPACE_TEXT && IsXMLToken( rLocalName, XML_LIST ) && mbReadText )
658  {
662  pContext = new SchXMLTextListContext( GetImport(), rLocalName, rCell.aComplexString );
663  mbReadText = false;//don't apply text from <text:p>
664  }
665  // <text:p> element - read text (and range from text:id old version)
666  else if( (nPrefix == XML_NAMESPACE_TEXT ||
667  nPrefix == XML_NAMESPACE_LO_EXT) && IsXMLToken( rLocalName, XML_P ) )
668  {
669  pContext = new SchXMLParagraphContext( GetImport(), rLocalName, maCellContent, &maRangeId );
670  }
671  // <draw:g> element - read range
672  else if( nPrefix == XML_NAMESPACE_DRAW && IsXMLToken( rLocalName, XML_G ) )
673  {
674  //#i113950# previously the range was exported to attribute text:id, but that attribute does not allow arbitrary strings anymore
675  //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
676  pContext = new SchXMLRangeSomewhereContext( GetImport(), nPrefix, rLocalName, maRangeId );
677  }
678 
679  return pContext;
680 }
681 
683 {
684  if( mbReadText && !maCellContent.isEmpty() ) //apply text from <text:p> element
686  if( !maRangeId.isEmpty())
688 }
689 
690 static void lcl_ApplyCellToComplexLabel( const SchXMLCell& rCell, Sequence< uno::Any >& rComplexLabel )
691 {
692  if( rCell.eType == SCH_CELL_TYPE_STRING )
693  {
694  rComplexLabel.realloc(1);
695  rComplexLabel[0] <<= rCell.aString;
696  }
697  else if( rCell.aComplexString.hasElements() && rCell.eType == SCH_CELL_TYPE_COMPLEX_STRING )
698  {
699  sal_Int32 nCount = rCell.aComplexString.getLength();
700  rComplexLabel.realloc( nCount );
701  for( sal_Int32 nN=0; nN<nCount; nN++)
702  rComplexLabel[nN] <<= (rCell.aComplexString)[nN];
703  }
704  else if( rCell.eType == SCH_CELL_TYPE_FLOAT )
705  {
706  rComplexLabel.realloc(1);
707  rComplexLabel[0] <<= rCell.fValue;
708  }
709 }
710 
712  const SchXMLTable& rTable,
713  const uno::Reference< chart2::XChartDocument >& xChartDoc )
714 {
715  // apply all data read from the local table to the internal data provider
716  if( !xChartDoc.is() || !xChartDoc->hasInternalDataProvider() )
717  return;
718  Reference< chart2::data::XDataProvider > xDataProv( xChartDoc->getDataProvider() );
719  if( !xDataProv.is() )
720  return;
721 
722  //prepare the read local table data
723  sal_Int32 nNumRows( static_cast< sal_Int32 >( rTable.aData.size()));
724  sal_Int32 nRowOffset = 0;
725  if( rTable.bHasHeaderRow )
726  {
727  --nNumRows;
728  nRowOffset = 1;
729  }
730  sal_Int32 nNumColumns( rTable.nMaxColumnIndex + 1 );
731  sal_Int32 nColOffset = 0;
732  if( rTable.bHasHeaderColumn )
733  {
734  --nNumColumns;
735  nColOffset = 1;
736  }
737 
738  Sequence< Sequence< double > > aDataInRows( nNumRows );
739  Sequence< Sequence< uno::Any > > aComplexRowDescriptions( nNumRows );
740  Sequence< Sequence< uno::Any > > aComplexColumnDescriptions( nNumColumns );
741  for( sal_Int32 i=0; i<nNumRows; ++i )
742  aDataInRows[i].realloc( nNumColumns );
743 
744  if( !rTable.aData.empty() )
745  {
746  //apply column labels
747  if( rTable.bHasHeaderRow )
748  {
749  const ::std::vector< SchXMLCell >& rFirstRow = rTable.aData.front();
750  const sal_Int32 nColumnLabelsSize = aComplexColumnDescriptions.getLength();
751  const sal_Int32 nMax = ::std::min< sal_Int32 >( nColumnLabelsSize, static_cast< sal_Int32 >( rFirstRow.size()) - nColOffset );
752  SAL_WARN_IF( nMax != nColumnLabelsSize, "xmloff.chart", "nMax != nColumnLabelsSize");
753  for( sal_Int32 i=0; i<nMax; ++i )
754  lcl_ApplyCellToComplexLabel( rFirstRow[i+nColOffset], aComplexColumnDescriptions[i] );
755  }
756 
757  std::vector< ::std::vector< SchXMLCell > >::const_iterator aRowIter( rTable.aData.begin() + nRowOffset );
758  std::vector< ::std::vector< SchXMLCell > >::const_iterator aEnd( rTable.aData.end() );
759  for( sal_Int32 nRow = 0; aRowIter != aEnd && nRow < nNumRows; ++aRowIter, ++nRow )
760  {
761  const ::std::vector< SchXMLCell >& rRow = *aRowIter;
762  if( !rRow.empty() )
763  {
764  // row label
765  if( rTable.bHasHeaderColumn )
766  lcl_ApplyCellToComplexLabel( rRow.front(), aComplexRowDescriptions[nRow] );
767 
768  // values
769  Sequence< double >& rTargetRow = aDataInRows[nRow];
770  lcl_ApplyCellToData aApplyCellToData = ::std::for_each( rRow.begin() + nColOffset, rRow.end(), lcl_ApplyCellToData( rTargetRow ) );
771  double fNaN = 0.0;
772  ::rtl::math::setNan( &fNaN );
773  for( sal_Int32 nCurrentIndex = aApplyCellToData.getCurrentIndex(); nCurrentIndex<nNumColumns; nCurrentIndex++ )
774  rTargetRow[nCurrentIndex] = fNaN;//#i110615#
775  }
776  }
777  }
778 
779  //apply the collected data to the chart
780  Reference< chart2::XAnyDescriptionAccess > xDataAccess( xDataProv, uno::UNO_QUERY );
781  if( !xDataAccess.is() )
782  return;
783 
784  xDataAccess->setData( aDataInRows );
785  if( rTable.bHasHeaderColumn )
786  xDataAccess->setAnyRowDescriptions( aComplexRowDescriptions );
787  if( rTable.bHasHeaderRow )
788  xDataAccess->setAnyColumnDescriptions( aComplexColumnDescriptions );
789 
790  if ( rTable.bProtected )
791  {
792  try
793  {
794  Reference< beans::XPropertySet > xProps( xChartDoc, uno::UNO_QUERY_THROW );
795  xProps->setPropertyValue( "DisableDataTableDialog", uno::makeAny( true ) );
796  xProps->setPropertyValue( "DisableComplexChartTypes", uno::makeAny( true ) );
797  }
798  catch ( uno::Exception& )
799  {
800  }
801  }
802 }
803 
805  const SchXMLTable& rTable,
806  const tSchXMLLSequencesPerIndex & rLSequencesPerIndex,
807  const uno::Reference< chart2::XChartDocument >& xChartDoc,
808  chart::ChartDataRowSource eDataRowSource )
809 {
810  if( ! (xChartDoc.is() && xChartDoc->hasInternalDataProvider()))
811  return;
812 
813  // If the range-strings are valid (starting with "local-table") they should
814  // be interpreted like given, otherwise (when the ranges refer to Calc- or
815  // Writer-ranges, but the container is not available like when pasting a
816  // chart from Calc to Impress) the range is ignored, and every object gets
817  // one table column in the order of appearance, which is: 1. categories,
818  // 2. data series: 2.a) domains, 2.b) values (main-role, usually y-values)
819 
820  Reference< chart2::data::XDataProvider > xDataProv( xChartDoc->getDataProvider());
821 
822  // create a mapping from original ranges to new ranges
823  lcl_tOriginalRangeToInternalRangeMap aRangeMap;
824 
825  lcl_fillRangeMapping( rTable, aRangeMap, eDataRowSource );
826 
827  const OUString lcl_aCategoriesRange(aCategoriesRange);
828 
829  bool bCategoriesApplied = false;
830  // translate ranges (using the map created before)
831  for( const auto& rLSeq : rLSequencesPerIndex )
832  {
833  if( rLSeq.second.is())
834  {
835  // values/error bars/categories
836  if( rLSeq.first.second == SCH_XML_PART_VALUES ||
837  rLSeq.first.second == SCH_XML_PART_ERROR_BARS )
838  {
839  Reference< chart2::data::XDataSequence > xSeq( rLSeq.second->getValues());
840 
841  OUString aRange;
842  if( xSeq.is() &&
843  SchXMLTools::getXMLRangePropertyFromDataSequence( xSeq, aRange, /* bClearProp = */ true ) &&
844  lcl_mapContainsRange( aRangeMap, aRange ))
845  {
846  Reference< chart2::data::XDataSequence > xNewSeq(
847  lcl_reassignDataSequence( xSeq, xDataProv, aRangeMap, aRange ));
848  if( xNewSeq != xSeq )
849  {
851  Reference< beans::XPropertySet >( xNewSeq, uno::UNO_QUERY ));
852  rLSeq.second->setValues( xNewSeq );
853  }
854  }
855  else
856  {
857  if( lcl_tableOfRangeMatches( aRange, rTable.aTableNameOfFile ))
858  {
859  if( rLSeq.first.first == SCH_XML_CATEGORIES_INDEX )
860  bCategoriesApplied = true;
861  }
862  else
863  {
864  if( rLSeq.first.first == SCH_XML_CATEGORIES_INDEX )
865  {
866  Reference< beans::XPropertySet > xOldSequenceProp( rLSeq.second->getValues(), uno::UNO_QUERY );
867  Reference< chart2::data::XDataSequence > xNewSequence(
868  xDataProv->createDataSequenceByRangeRepresentation("categories"));
870  xOldSequenceProp, Reference< beans::XPropertySet >( xNewSequence, uno::UNO_QUERY ));
871  rLSeq.second->setValues( xNewSequence );
872  bCategoriesApplied = true;
873  }
874  else
875  {
876  Reference< beans::XPropertySet > xOldSequenceProp( rLSeq.second->getValues(), uno::UNO_QUERY );
877  OUString aRep( OUString::number( rLSeq.first.first ));
878  Reference< chart2::data::XDataSequence > xNewSequence(
879  xDataProv->createDataSequenceByRangeRepresentation( aRep ));
881  xOldSequenceProp, Reference< beans::XPropertySet >( xNewSequence, uno::UNO_QUERY ));
882  rLSeq.second->setValues( xNewSequence );
883  }
884  }
885  }
886  }
887  else // labels
888  {
889  SAL_WARN_IF( rLSeq.first.second != SCH_XML_PART_LABEL, "xmloff.chart", "rLSeq.first.second != SCH_XML_PART_LABEL" );
890  // labels
891  Reference< chart2::data::XDataSequence > xSeq( rLSeq.second->getLabel());
892  OUString aRange;
893  if( xSeq.is() &&
894  SchXMLTools::getXMLRangePropertyFromDataSequence( xSeq, aRange, /* bClearProp = */ true ) &&
895  lcl_mapContainsRange( aRangeMap, aRange ))
896  {
897  Reference< chart2::data::XDataSequence > xNewSeq(
898  lcl_reassignDataSequence( xSeq, xDataProv, aRangeMap, aRange ));
899  if( xNewSeq != xSeq )
900  {
902  Reference< beans::XPropertySet >( xNewSeq, uno::UNO_QUERY ));
903  rLSeq.second->setLabel( xNewSeq );
904  }
905  }
906  else if( ! lcl_tableOfRangeMatches( aRange, rTable.aTableNameOfFile ))
907  {
908  OUString aRep = "label " + OUString::number( rLSeq.first.first );
909 
910  Reference< chart2::data::XDataSequence > xNewSeq(
911  xDataProv->createDataSequenceByRangeRepresentation( aRep ));
913  Reference< beans::XPropertySet >( xNewSeq, uno::UNO_QUERY ));
914  rLSeq.second->setLabel( xNewSeq );
915  }
916  }
917  }
918  }
919 
920  // there exist files with own data without a categories element but with row
921  // descriptions. The row descriptions were used as categories even without
922  // the categories element
923  if( ! bCategoriesApplied )
924  {
926  xDataProv, xChartDoc, "categories",
927  0 /* nCooSysIndex */, 0 /* nDimension */ );
928  }
929 
930  //i91578 display of hidden values (copy paste scenario; use hidden flag during migration to locale table upon paste )
931  //remove series that consist only of hidden columns
932  Reference< chart2::XInternalDataProvider > xInternalDataProvider( xDataProv, uno::UNO_QUERY );
933  if( xInternalDataProvider.is() && !rTable.aHiddenColumns.empty() )
934  {
935  try
936  {
937  Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xChartDoc->getFirstDiagram(), uno::UNO_QUERY_THROW );
938  const Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
939  for( const auto& rCooSys : aCooSysSeq )
940  {
941  Reference< chart2::XChartTypeContainer > xCooSysContainer( rCooSys, uno::UNO_QUERY_THROW );
942  const Sequence< Reference< chart2::XChartType > > aChartTypeSeq( xCooSysContainer->getChartTypes());
943  for( const auto& rChartType : aChartTypeSeq )
944  {
945  Reference< chart2::XDataSeriesContainer > xSeriesContainer( rChartType, uno::UNO_QUERY );
946  if(!xSeriesContainer.is())
947  continue;
948  const Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xSeriesContainer->getDataSeries() );
949  std::vector< Reference< chart2::XDataSeries > > aRemainingSeries;
950 
951  for( const auto& rSeries : aSeriesSeq )
952  {
953  Reference< chart2::data::XDataSource > xDataSource( rSeries, uno::UNO_QUERY );
954  if( xDataSource.is() )
955  {
956  bool bHasUnhiddenColumns = false;
957  OUString aRange;
958  const uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences() );
959  for( const auto& xLabeledSequence : aSequences )
960  {
961  if(!xLabeledSequence.is())
962  continue;
963  Reference< chart2::data::XDataSequence > xValues( xLabeledSequence->getValues() );
964  if( xValues.is() )
965  {
966  aRange = xValues->getSourceRangeRepresentation();
967  if( ::std::find( rTable.aHiddenColumns.begin(), rTable.aHiddenColumns.end(), aRange.toInt32() ) == rTable.aHiddenColumns.end() )
968  bHasUnhiddenColumns = true;
969  }
970  if( !bHasUnhiddenColumns )
971  {
972  Reference< chart2::data::XDataSequence > xLabel( xLabeledSequence->getLabel() );
973  if( xLabel.is() )
974  {
975  aRange = xLabel->getSourceRangeRepresentation();
976  const sal_Int32 nId {aRange.getToken(1, ' ').toInt32()};
977  if( ::std::find( rTable.aHiddenColumns.begin(), rTable.aHiddenColumns.end(), nId ) == rTable.aHiddenColumns.end() )
978  bHasUnhiddenColumns = true;
979  }
980  }
981  }
982  if( bHasUnhiddenColumns )
983  aRemainingSeries.push_back( rSeries );
984  }
985  }
986 
987  if( static_cast<sal_Int32>(aRemainingSeries.size()) != aSeriesSeq.getLength() )
988  {
989  //remove the series that have only hidden data
990  xSeriesContainer->setDataSeries( comphelper::containerToSequence(aRemainingSeries) );
991 
992  //remove unused sequences
993  Reference< chart2::data::XDataSource > xDataSource( xChartDoc, uno::UNO_QUERY );
994  if( xDataSource.is() )
995  {
996  //first detect which columns are really used
997  std::map< sal_Int32, bool > aUsageMap;
998  OUString aRange;
999  const Sequence< Reference< chart2::data::XLabeledDataSequence > > aUsedSequences( xDataSource->getDataSequences() );
1000  for( const auto& xLabeledSequence : aUsedSequences )
1001  {
1002  if(!xLabeledSequence.is())
1003  continue;
1004  Reference< chart2::data::XDataSequence > xValues( xLabeledSequence->getValues() );
1005  if( xValues.is() )
1006  {
1007  aRange = xValues->getSourceRangeRepresentation();
1008  sal_Int32 nIndex = aRange.toInt32();
1009  if( nIndex!=0 || aRange != lcl_aCategoriesRange )
1010  aUsageMap[nIndex] = true;
1011  }
1012  Reference< chart2::data::XDataSequence > xLabel( xLabeledSequence->getLabel() );
1013  if( xLabel.is() )
1014  {
1015  aRange = xLabel->getSourceRangeRepresentation();
1016  OUString aSecondToken = aRange.getToken(1, ' ');
1017  if( !aSecondToken.isEmpty() )
1018  aUsageMap[aSecondToken.toInt32()] = true;
1019  }
1020  }
1021 
1022  ::std::vector< sal_Int32 > aSequenceIndexesToDelete;
1023  std::copy_if(rTable.aHiddenColumns.begin(), rTable.aHiddenColumns.end(),
1024  std::back_inserter(aSequenceIndexesToDelete),
1025  [&aUsageMap](sal_Int32 nSequenceIndex) { return aUsageMap.find(nSequenceIndex) == aUsageMap.end(); });
1026 
1027  // delete unnecessary sequences of the internal data
1028  // iterate using greatest index first, so that deletion does not
1029  // shift other sequences that will be deleted later
1030  ::std::sort( aSequenceIndexesToDelete.begin(), aSequenceIndexesToDelete.end());
1031  for( ::std::vector< sal_Int32 >::reverse_iterator aIt(
1032  aSequenceIndexesToDelete.rbegin()); aIt != aSequenceIndexesToDelete.rend(); ++aIt )
1033  {
1034  if( *aIt != -1 )
1035  xInternalDataProvider->deleteSequence( *aIt );
1036  }
1037  }
1038  }
1039  }
1040  }
1041  }
1042  catch( const uno::Exception & )
1043  {
1044  }
1045  }
1046 }
1047 
1048 SchXMLRangeSomewhereContext::SchXMLRangeSomewhereContext( SvXMLImport& rImport,
1049  sal_uInt16 nPrefix,
1050  const OUString& rLocalName,
1051  OUString& rRangeString ) :
1052  SvXMLImportContext( rImport, nPrefix, rLocalName ),
1053  mrRangeString( rRangeString )
1054 {
1055 }
1056 
1057 SvXMLImportContextRef SchXMLRangeSomewhereContext::CreateChildContext(
1058  sal_uInt16 nPrefix,
1059  const OUString& rLocalName,
1060  const uno::Reference< xml::sax::XAttributeList >& )
1061 {
1062  if( XML_NAMESPACE_SVG == nPrefix && IsXMLToken( rLocalName, XML_DESC ) )
1063  {
1064  return new XMLStringBufferImportContext(
1065  GetImport(), nPrefix, rLocalName, maRangeStringBuffer );
1066  }
1067  return nullptr;
1068 }
1069 
1070 void SchXMLRangeSomewhereContext::EndElement()
1071 {
1072  mrRangeString = maRangeStringBuffer.makeStringAndClear();
1073 }
1074 
1075 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SchXMLCellType
constexpr sal_uInt16 XML_NAMESPACE_LO_EXT
Definition: xmlnmspe.hxx:80
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3422
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:397
SchXMLTableColumnContext(SvXMLImport &rImport, const OUString &rLocalName, SchXMLTable &aTable)
void setRowPermutation(const css::uno::Sequence< sal_Int32 > &rPermutation)
constexpr sal_uInt16 XML_NAMESPACE_TEXT
Definition: xmlnmspe.hxx:31
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
Definition: nmspmap.cxx:437
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
int nCount
const SvXMLTokenMap & GetTableElemTokenMap()
css::uno::Sequence< sal_Int32 > maColumnPermutation
virtual ~SchXMLTableContext() override
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)
constexpr sal_uInt16 XML_NAMESPACE_DRAW
Definition: xmlnmspe.hxx:33
virtual ~SchXMLTableRowsContext() override
int i
#define SCH_XML_CATEGORIES_INDEX
virtual ~SchXMLTableCellContext() override
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:93
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
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:3366
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Handling of tokens in XML:
constexpr sal_uInt16 XML_NAMESPACE_TABLE
Definition: xmlnmspe.hxx:32
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)
constexpr sal_uInt16 XML_NAMESPACE_SVG
Definition: xmlnmspe.hxx:40
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.