LibreOffice Module sc (master)  1
xmlexprt.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 <sal/config.h>
21 #include <sal/log.hxx>
22 
23 #include "xmlexprt.hxx"
24 #include "XMLConverter.hxx"
25 #include "xmlstyle.hxx"
26 #include <unonames.hxx>
27 #include <document.hxx>
28 #include <olinetab.hxx>
29 #include <formulacell.hxx>
30 #include <rangenam.hxx>
32 #include <drwlayer.hxx>
33 #include "XMLExportDataPilot.hxx"
35 #include "XMLExportDDELinks.hxx"
36 #include "XMLExportIterator.hxx"
40 #include <sheetdata.hxx>
41 #include <docoptio.hxx>
42 #include "XMLExportSharedData.hxx"
43 #include <chgviset.hxx>
44 #include <docuno.hxx>
45 #include <textuno.hxx>
46 #include <chartlis.hxx>
47 #include <scitems.hxx>
48 #include <docpool.hxx>
49 #include <userdat.hxx>
50 #include <chgtrack.hxx>
51 #include <rangeutl.hxx>
52 #include <postit.hxx>
53 #include <externalrefmgr.hxx>
54 #include <editutil.hxx>
55 #include <tabprotection.hxx>
56 #include "cachedattraccess.hxx"
57 #include <colorscale.hxx>
58 #include <conditio.hxx>
59 #include <cellvalue.hxx>
60 #include <stylehelper.hxx>
61 #include <edittextiterator.hxx>
62 #include "editattributemap.hxx"
63 #include <arealink.hxx>
64 #include <datastream.hxx>
65 #include <documentlinkmgr.hxx>
66 #include <tokenstringcontext.hxx>
67 #include <cellform.hxx>
68 #include <datamapper.hxx>
69 #include <datatransformation.hxx>
70 
71 #include <xmloff/xmltoken.hxx>
72 #include <xmloff/xmlnamespace.hxx>
73 #include <xmloff/xmluconv.hxx>
74 #include <xmloff/namespacemap.hxx>
75 #include <xmloff/families.hxx>
76 #include <xmloff/numehelp.hxx>
77 #include <xmloff/txtparae.hxx>
78 #include <editeng/autokernitem.hxx>
81 #include <editeng/colritem.hxx>
82 #include <editeng/contouritem.hxx>
86 #include <editeng/fhgtitem.hxx>
87 #include <editeng/fontitem.hxx>
88 #include <editeng/kernitem.hxx>
89 #include <editeng/langitem.hxx>
90 #include <editeng/postitem.hxx>
91 #include <editeng/section.hxx>
92 #include <editeng/shdditem.hxx>
93 #include <editeng/udlnitem.hxx>
94 #include <editeng/wghtitem.hxx>
95 #include <editeng/wrlmitem.hxx>
96 #include <editeng/xmlcnitm.hxx>
97 #include <editeng/flditem.hxx>
98 #include <editeng/eeitem.hxx>
99 #include <formula/errorcodes.hxx>
100 #include <xmloff/xmlerror.hxx>
101 #include <xmloff/XMLEventExport.hxx>
102 #include <xmloff/xmlprmap.hxx>
105 
106 #include <sax/tools/converter.hxx>
107 #include <tools/fldunit.hxx>
108 
109 #include <rtl/ustring.hxx>
110 
111 #include <tools/color.hxx>
112 #include <rtl/math.hxx>
113 #include <svl/zforlist.hxx>
114 #include <svx/unoshape.hxx>
115 #include <comphelper/base64.hxx>
116 #include <comphelper/extract.hxx>
117 #include <svx/svdobj.hxx>
118 #include <svx/svdocapt.hxx>
119 #include <svtools/miscopt.hxx>
120 #include <vcl/svapp.hxx>
121 
123 #include <com/sun/star/beans/XPropertySet.hpp>
124 #include <com/sun/star/container/XNamed.hpp>
125 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
126 #include <com/sun/star/form/XFormsSupplier2.hpp>
127 #include <com/sun/star/io/XActiveDataSource.hpp>
128 #include <com/sun/star/io/XSeekable.hpp>
129 #include <com/sun/star/sheet/XUsedAreaCursor.hpp>
130 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
131 #include <com/sun/star/sheet/XPrintAreas.hpp>
132 #include <com/sun/star/sheet/XUniqueCellFormatRangesSupplier.hpp>
133 #include <com/sun/star/sheet/XLabelRange.hpp>
134 #include <com/sun/star/sheet/NamedRangeFlag.hpp>
135 #include <com/sun/star/sheet/XSheetCellCursor.hpp>
136 #include <com/sun/star/sheet/XSheetCellRanges.hpp>
137 #include <com/sun/star/sheet/XSheetLinkable.hpp>
138 #include <com/sun/star/sheet/GlobalSheetSettings.hpp>
139 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
140 #include <com/sun/star/table/XColumnRowRange.hpp>
141 #include <com/sun/star/util/XProtectable.hpp>
142 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
143 #include <com/sun/star/chart2/XChartDocument.hpp>
144 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
145 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
146 
147 #include <com/sun/star/document/XDocumentProperties.hpp>
148 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
149 
150 #include "XMLCodeNameProvider.hxx"
151 
152 #include <sfx2/linkmgr.hxx>
153 #include <sfx2/objsh.hxx>
154 
155 #include <memory>
156 #include <vector>
158 
159 namespace com::sun::star::uno { class XComponentContext; }
160 
161 
162 
164 #define SC_LAYERID "LayerID"
165 
166 #define SC_VIEWCHANGES_COUNT 13
167 #define SC_SHOW_CHANGES 0
168 #define SC_SHOW_ACCEPTED_CHANGES 1
169 #define SC_SHOW_REJECTED_CHANGES 2
170 #define SC_SHOW_CHANGES_BY_DATETIME 3
171 #define SC_SHOW_CHANGES_BY_DATETIME_MODE 4
172 #define SC_SHOW_CHANGES_BY_DATETIME_FIRST_DATETIME 5
173 #define SC_SHOW_CHANGES_BY_DATETIME_SECOND_DATETIME 6
174 #define SC_SHOW_CHANGES_BY_AUTHOR 7
175 #define SC_SHOW_CHANGES_BY_AUTHOR_NAME 8
176 #define SC_SHOW_CHANGES_BY_COMMENT 9
177 #define SC_SHOW_CHANGES_BY_COMMENT_TEXT 10
178 #define SC_SHOW_CHANGES_BY_RANGES 11
179 #define SC_SHOW_CHANGES_BY_RANGES_LIST 12
180 
181 using namespace formula;
182 using namespace com::sun::star;
183 using namespace xmloff::token;
184 using ::std::vector;
185 using ::com::sun::star::uno::UNO_QUERY;
186 
187 namespace
188 {
189 OUString lcl_RangeSequenceToString(
190  const uno::Sequence< OUString > & rRanges,
191  const uno::Reference< chart2::data::XRangeXMLConversion > & xFormatConverter )
192 {
193  OUStringBuffer aResult;
194  const sal_Int32 nMaxIndex( rRanges.getLength() - 1 );
195  const sal_Unicode cSep(' ');
196  for( sal_Int32 i=0; i<=nMaxIndex; ++i )
197  {
198  OUString aRange( rRanges[i] );
199  if( xFormatConverter.is())
200  aRange = xFormatConverter->convertRangeToXML( aRange );
201  aResult.append( aRange );
202  if( i < nMaxIndex )
203  aResult.append( cSep );
204  }
205  return aResult.makeStringAndClear();
206 }
207 
208 OUString lcl_GetFormattedString(ScDocument* pDoc, const ScRefCellValue& rCell, const ScAddress& rAddr)
209 {
210  // return text/edit cell string content, with line feeds in edit cells
211 
212  if (!pDoc)
213  return EMPTY_OUSTRING;
214 
215  switch (rCell.meType)
216  {
217  case CELLTYPE_STRING:
218  {
219  OUString aStr;
220  const Color* pColor;
221  SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
222 
223  sal_uInt32 nFormat = pDoc->GetNumberFormat(rAddr);
224  ScCellFormat::GetString(rCell, nFormat, aStr, &pColor, *pFormatter, *pDoc);
225  return aStr;
226  }
227  case CELLTYPE_EDIT:
228  {
229  const EditTextObject* pData = rCell.mpEditText;
230  if (!pData)
231  return EMPTY_OUSTRING;
232 
233  EditEngine& rEngine = pDoc->GetEditEngine();
234  rEngine.SetText(*pData);
235  return rEngine.GetText();
236  }
237  break;
238  default:
239  ;
240  }
241 
242  return EMPTY_OUSTRING;
243 }
244 
245 } // anonymous namespace
246 
247 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
248 Calc_XMLExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
249 {
250  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLExporter", SvXMLExportFlags::ALL));
251 }
252 
253 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
254 Calc_XMLMetaExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
255 {
256  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLMetaExporter", SvXMLExportFlags::META));
257 }
258 
259 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
260 Calc_XMLStylesExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
261 {
262  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLStylesExporter", SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS));
263 }
264 
265 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
266 Calc_XMLContentExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
267 {
268  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLContentExporter", SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::FONTDECLS));
269 }
270 
271 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
272 Calc_XMLSettingsExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
273 {
274  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLSettingsExporter", SvXMLExportFlags::SETTINGS));
275 }
276 
277 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
278 Calc_XMLOasisExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
279 {
280  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisExporter", SvXMLExportFlags::ALL|SvXMLExportFlags::OASIS));
281 }
282 
283 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
284 Calc_XMLOasisMetaExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
285 {
286  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisMetaExporter", SvXMLExportFlags::META|SvXMLExportFlags::OASIS));
287 }
288 
289 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
290 Calc_XMLOasisStylesExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
291 {
292  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisStylesExporter", SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::OASIS));
293 }
294 
295 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
296 Calc_XMLOasisContentExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
297 {
298  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisContentExporter", SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::OASIS));
299 }
300 
301 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
302 Calc_XMLOasisSettingsExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
303 {
304  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisSettingsExporter", SvXMLExportFlags::SETTINGS|SvXMLExportFlags::OASIS));
305 }
306 
307 namespace {
308 
309 class ScXMLShapeExport : public XMLShapeExport
310 {
311 public:
312  explicit ScXMLShapeExport(SvXMLExport& rExp) : XMLShapeExport(rExp) {}
313 
315  virtual void onExport( const uno::Reference < drawing::XShape >& xShape ) override;
316 };
317 
318 }
319 
320 void ScXMLShapeExport::onExport( const uno::Reference < drawing::XShape >& xShape )
321 {
322  uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
323  if( xShapeProp.is() )
324  {
325  sal_Int16 nLayerID = 0;
326  if( (xShapeProp->getPropertyValue( SC_LAYERID ) >>= nLayerID) && (SdrLayerID(nLayerID) == SC_LAYER_BACK) )
327  GetExport().AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_BACKGROUND, XML_TRUE);
328  }
329 }
330 
332 {
333  css::uno::Reference<css::sheet::XGlobalSheetSettings> xProperties =
334  css::sheet::GlobalSheetSettings::create( comphelper::getProcessComponentContext() );
335  const FieldUnit eFieldUnit = static_cast<FieldUnit>(xProperties->getMetric());
336  return SvXMLUnitConverter::GetMeasureUnit(eFieldUnit);
337 }
338 
339 constexpr OUStringLiteral gsLayerID( u"" SC_LAYERID );
340 
342  const css::uno::Reference< css::uno::XComponentContext >& rContext,
343  OUString const & implementationName, SvXMLExportFlags nExportFlag)
344 : SvXMLExport(
345  rContext, implementationName, GetMeasureUnit(), XML_SPREADSHEET, nExportFlag ),
346  pDoc(nullptr),
347  nSourceStreamPos(0),
348  aTableStyles(),
349  pCurrentCell(nullptr),
350  nOpenRow(-1),
351  nProgressCount(0),
352  nCurrentTable(0),
353  bHasRowHeader(false),
354  bRowHeaderOpen(false)
355 {
356  if (getExportFlags() & SvXMLExportFlags::CONTENT)
357  {
360  pColumnStyles.reset( new ScColumnStyles() );
361  pRowStyles.reset( new ScRowStyles() );
362  pRowFormatRanges.reset( new ScRowFormatRanges() );
365  mpCellsItr.reset(new ScMyNotEmptyCellsIterator(*this));
366  pDefaults.reset( new ScMyDefaultStyles );
367  }
368  pCellStyles.reset( new ScFormatRangeStyles() );
369 
370  // document is not set here - create ScChangeTrackingExportHelper later
371 
382 
383  GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_CELL, XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME,
385  GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_COLUMN, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_NAME,
387  GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_ROW, XML_STYLE_FAMILY_TABLE_ROW_STYLES_NAME,
389  GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_TABLE, XML_STYLE_FAMILY_TABLE_TABLE_STYLES_NAME,
391 
392  if( !(getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT)) )
393  return;
394 
395  // This name is reserved for the external ref cache tables. This
396  // should not conflict with user-defined styles since this name is
397  // used for a table style which is not available in the UI.
398  sExternalRefTabStyleName = "ta_extref";
399  GetAutoStylePool()->RegisterName(XmlStyleFamily::TABLE_TABLE, sExternalRefTabStyleName);
400 
413 }
414 
416 {
417  pGroupColumns.reset();
418  pGroupRows.reset();
419  pColumnStyles.reset();
420  pRowStyles.reset();
421  pCellStyles.reset();
422  pRowFormatRanges.reset();
423  pMergedRangesContainer.reset();
424  pValidationsContainer.reset();
426  pDefaults.reset();
428 }
429 
430 void ScXMLExport::SetSourceStream( const uno::Reference<io::XInputStream>& xNewStream )
431 {
432  xSourceStream = xNewStream;
433 
434  if ( !xSourceStream.is() )
435  return;
436 
437  // make sure it's a plain UTF-8 stream as written by OOo itself
438 
439  const char pXmlHeader[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
440  sal_Int32 nLen = strlen(pXmlHeader);
441 
442  uno::Sequence<sal_Int8> aFileStart(nLen);
443  sal_Int32 nRead = xSourceStream->readBytes( aFileStart, nLen );
444 
445  if ( nRead != nLen || memcmp( aFileStart.getConstArray(), pXmlHeader, nLen ) != 0 )
446  {
447  // invalid - ignore stream, save normally
448  xSourceStream.clear();
449  }
450  else
451  {
452  // keep track of the bytes already read
453  nSourceStreamPos = nRead;
454 
455  const ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(GetModel())->GetSheetSaveData();
456  if (pSheetData)
457  {
458  // add the loaded namespaces to the name space map
459 
460  if ( !pSheetData->AddLoadedNamespaces( GetNamespaceMap_() ) )
461  {
462  // conflicts in the namespaces - ignore the stream, save normally
463  xSourceStream.clear();
464  }
465  }
466  }
467 }
468 
469 sal_Int32 ScXMLExport::GetNumberFormatStyleIndex(sal_Int32 nNumFmt) const
470 {
471  NumberFormatIndexMap::const_iterator itr = aNumFmtIndexMap.find(nNumFmt);
472  if (itr == aNumFmtIndexMap.end())
473  return -1;
474 
475  return itr->second;
476 }
477 
478 void ScXMLExport::CollectSharedData(SCTAB& nTableCount, sal_Int32& nShapesCount)
479 {
480  if (!GetModel().is())
481  return;
482 
483  uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc(GetModel(), uno::UNO_QUERY);
484  if (!xSpreadDoc.is())
485  return;
486 
487  uno::Reference<container::XIndexAccess> xIndex(xSpreadDoc->getSheets(), uno::UNO_QUERY);
488  if (!xIndex.is())
489  return;
490 
491  nTableCount = xIndex->getCount();
492  if (!pSharedData)
493  pSharedData.reset(new ScMySharedData(nTableCount));
494 
495  pCellStyles->AddNewTable(nTableCount - 1);
496 
497  for (SCTAB nTable = 0; nTable < nTableCount; ++nTable)
498  {
499  nCurrentTable = sal::static_int_cast<sal_uInt16>(nTable);
500  uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xIndex->getByIndex(nTable), uno::UNO_QUERY);
501  if (!xDrawPageSupplier.is())
502  continue;
503 
504  uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage());
505  ScMyDrawPage aDrawPage;
506  aDrawPage.bHasForms = false;
507  aDrawPage.xDrawPage.set(xDrawPage);
508  pSharedData->AddDrawPage(aDrawPage, nTable);
509  if (!xDrawPage.is())
510  continue;
511 
512  sal_Int32 nShapes = xDrawPage->getCount();
513  for (sal_Int32 nShape = 0; nShape < nShapes; ++nShape)
514  {
515  uno::Reference<drawing::XShape> xShape(xDrawPage->getByIndex(nShape), uno::UNO_QUERY);
516  if (!xShape.is())
517  continue;
518 
519  uno::Reference<beans::XPropertySet> xShapeProp(xShape, uno::UNO_QUERY);
520  if (!xShapeProp.is())
521  continue;
522 
523  sal_Int16 nLayerID = 0;
524  bool bExtracted = xShapeProp->getPropertyValue(gsLayerID) >>= nLayerID;
525  if (!bExtracted)
526  continue;
527 
528  if ((SdrLayerID(nLayerID) == SC_LAYER_INTERN) || (SdrLayerID(nLayerID) == SC_LAYER_HIDDEN))
529  {
530  CollectInternalShape(xShape);
531  continue;
532  }
533 
534  ++nShapesCount;
535 
536  SvxShape* pShapeImp = comphelper::getUnoTunnelImplementation<SvxShape>(xShape);
537  if (!pShapeImp)
538  continue;
539 
540  SdrObject* pSdrObj = pShapeImp->GetSdrObject();
541  if (!pSdrObj)
542  continue;
543 
544  if (ScDrawObjData *pAnchor = ScDrawLayer::GetNonRotatedObjData(pSdrObj))
545  {
546  ScMyShape aMyShape;
547  aMyShape.aAddress = pAnchor->maStart;
548  SAL_WARN_IF(aMyShape.aAddress.Tab() != nTable, "sc", "not anchored to current sheet!");
549  aMyShape.aAddress.SetTab(nTable);
550  aMyShape.aEndAddress = pAnchor->maEnd;
551  aMyShape.aEndAddress.SetTab( nTable );
552  aMyShape.nEndX = pAnchor->maEndOffset.X();
553  aMyShape.nEndY = pAnchor->maEndOffset.Y();
554  aMyShape.xShape = xShape;
555  aMyShape.bResizeWithCell = ScDrawLayer::IsResizeWithCell(*pSdrObj);
556  pSharedData->AddNewShape(aMyShape);
557  pSharedData->SetLastColumn(nTable, pAnchor->maStart.Col());
558  pSharedData->SetLastRow(nTable, pAnchor->maStart.Row());
559  }
560  else
561  pSharedData->AddTableShape(nTable, xShape);
562  }
563  }
564 }
565 
567 {
568  // #i84077# To avoid compiler warnings about uninitialized aShapeItr,
569  // it's initialized using this dummy list. The iterator contains shapes
570  // from all sheets, so it can't be declared inside the nTable loop where
571  // it is used.
572  ScMyShapeList aDummyInitList;
573 
574  pSharedData->SortShapesContainer();
575  pSharedData->SortNoteShapes();
576  const ScMyShapeList* pShapeList(nullptr);
577  ScMyShapeList::const_iterator aShapeItr = aDummyInitList.end();
578  if (pSharedData->GetShapesContainer())
579  {
580  pShapeList = &pSharedData->GetShapesContainer()->GetShapes();
581  aShapeItr = pShapeList->begin();
582  }
583  if (pSharedData->HasDrawPage())
584  {
585  for (SCTAB nTable = 0; nTable < nTableCount; ++nTable)
586  {
587  uno::Reference<drawing::XDrawPage> xDrawPage(pSharedData->GetDrawPage(nTable));
588 
589  if (xDrawPage.is())
590  {
591  GetShapeExport()->seekShapes(xDrawPage);
592  uno::Reference< form::XFormsSupplier2 > xFormsSupplier( xDrawPage, uno::UNO_QUERY );
593  if( xFormsSupplier.is() && xFormsSupplier->hasForms() )
594  {
595  GetFormExport()->examineForms(xDrawPage);
596  pSharedData->SetDrawPageHasForms(nTable, true);
597  }
598  ScMyTableShapes* pTableShapes(pSharedData->GetTableShapes());
599  if (pTableShapes)
600  {
601  for (const auto& rxShape : (*pTableShapes)[nTable])
602  {
603  GetShapeExport()->collectShapeAutoStyles(rxShape);
604  IncrementProgressBar(false);
605  }
606  }
607  if (pShapeList)
608  {
609  ScMyShapeList::const_iterator aEndItr(pShapeList->end());
610  while ( aShapeItr != aEndItr && ( aShapeItr->aAddress.Tab() == nTable ) )
611  {
612  GetShapeExport()->collectShapeAutoStyles(aShapeItr->xShape);
613  IncrementProgressBar(false);
614  ++aShapeItr;
615  }
616  }
617  if (pSharedData->GetNoteShapes())
618  {
619  const ScMyNoteShapeList& rNoteShapes = pSharedData->GetNoteShapes()->GetNotes();
620  for (const auto& rNoteShape : rNoteShapes)
621  {
622  if ( rNoteShape.aPos.Tab() == nTable )
623  GetShapeExport()->collectShapeAutoStyles(rNoteShape.xShape);
624  }
625  }
626  }
627  }
628  }
629  pSharedData->SortNoteShapes(); // sort twice, because some more shapes are added
630 }
631 
633 {
634  sal_Int32 nCellCount(pDoc ? pDoc->GetCellCount() : 0);
635  SCTAB nTableCount(0);
636  sal_Int32 nShapesCount(0);
637  GetAutoStylePool()->ClearEntries();
638  CollectSharedData(nTableCount, nShapesCount);
639 
640  uno::Sequence<beans::NamedValue> stats
641  {
642  { "TableCount", uno::makeAny(static_cast<sal_Int32>(nTableCount)) },
643  { "CellCount", uno::makeAny(nCellCount) },
644  { "ObjectCount", uno::makeAny(nShapesCount) }
645  };
646 
647  // update document statistics at the model
648  uno::Reference<document::XDocumentPropertiesSupplier> xPropSup(GetModel(),
649  uno::UNO_QUERY_THROW);
650  uno::Reference<document::XDocumentProperties> xDocProps(
651  xPropSup->getDocumentProperties());
652  if (xDocProps.is()) {
653  xDocProps->setDocumentStatistics(stats);
654  }
655 
656  // export document properties
658 }
659 
661 {
662  GetFontAutoStylePool(); // make sure the pool is created
664 }
665 
666 table::CellRangeAddress ScXMLExport::GetEndAddress(const uno::Reference<sheet::XSpreadsheet>& xTable)
667 {
668  table::CellRangeAddress aCellAddress;
669  uno::Reference<sheet::XSheetCellCursor> xCursor(xTable->createCursor());
670  uno::Reference<sheet::XUsedAreaCursor> xUsedArea (xCursor, uno::UNO_QUERY);
671  uno::Reference<sheet::XCellRangeAddressable> xCellAddress (xCursor, uno::UNO_QUERY);
672  if (xUsedArea.is() && xCellAddress.is())
673  {
674  xUsedArea->gotoEndOfUsedArea(true);
675  aCellAddress = xCellAddress->getRangeAddress();
676  }
677  return aCellAddress;
678 }
679 
681 {
682  if (pDoc->GetLinkManager())
683  {
684  const sfx2::SvBaseLinks& rLinks = pDoc->GetLinkManager()->GetLinks();
685  for (const auto & rLink : rLinks)
686  {
687  ScAreaLink *pLink = dynamic_cast<ScAreaLink*>(rLink.get());
688  if (pLink)
689  {
690  ScMyAreaLink aAreaLink;
691  aAreaLink.aDestRange = pLink->GetDestArea();
692  aAreaLink.sSourceStr = pLink->GetSource();
693  aAreaLink.sFilter = pLink->GetFilter();
694  aAreaLink.sFilterOptions = pLink->GetOptions();
695  aAreaLink.sURL = pLink->GetFile();
696  aAreaLink.nRefresh = pLink->GetRefreshDelay();
697  rAreaLinks.AddNewAreaLink( aAreaLink );
698  }
699  }
700  }
701  rAreaLinks.Sort();
702 }
703 
704 // core implementation
706 {
707  if (!pDoc)
708  return;
709 
710  ScDetOpList* pOpList(pDoc->GetDetOpList());
711  if( !pOpList )
712  return;
713 
714  size_t nCount = pOpList->Count();
715  for (size_t nIndex = 0; nIndex < nCount; ++nIndex )
716  {
717  const ScDetOpData& rDetData = pOpList->GetObject( nIndex);
718  const ScAddress& rDetPos = rDetData.GetPos();
719  SCTAB nTab = rDetPos.Tab();
720  if ( nTab < pDoc->GetTableCount() )
721  {
722  rDetOp.AddOperation( rDetData.GetOperation(), rDetPos, static_cast<sal_uInt32>( nIndex) );
723 
724  // cells with detective operations are written even if empty
725  pSharedData->SetLastColumn( nTab, rDetPos.Col() );
726  pSharedData->SetLastRow( nTab, rDetPos.Row() );
727  }
728  }
729  rDetOp.Sort();
730 }
731 
732 void ScXMLExport::WriteSingleColumn(const sal_Int32 nRepeatColumns, const sal_Int32 nStyleIndex,
733  const sal_Int32 nIndex, const bool bIsAutoStyle, const bool bIsVisible)
734 {
735  CheckAttrList();
736  AddAttribute(sAttrStyleName, pColumnStyles->GetStyleNameByIndex(nStyleIndex));
737  if (!bIsVisible)
739  if (nRepeatColumns > 1)
740  {
741  OUString sOUEndCol(OUString::number(nRepeatColumns));
743  }
744  if (nIndex != -1)
745  AddAttribute(XML_NAMESPACE_TABLE, XML_DEFAULT_CELL_STYLE_NAME, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
746  SvXMLElementExport aElemC(*this, sElemCol, true, true);
747 }
748 
749 void ScXMLExport::WriteColumn(const sal_Int32 nColumn, const sal_Int32 nRepeatColumns,
750  const sal_Int32 nStyleIndex, const bool bIsVisible)
751 {
752  sal_Int32 nRepeat(1);
753  sal_Int32 nPrevIndex(pDefaults->GetColDefaults()[nColumn].nIndex);
754  bool bPrevAutoStyle(pDefaults->GetColDefaults()[nColumn].bIsAutoStyle);
755  for (sal_Int32 i = nColumn + 1; i < nColumn + nRepeatColumns; ++i)
756  {
757  if ((pDefaults->GetColDefaults()[i].nIndex != nPrevIndex) ||
758  (pDefaults->GetColDefaults()[i].bIsAutoStyle != bPrevAutoStyle))
759  {
760  WriteSingleColumn(nRepeat, nStyleIndex, nPrevIndex, bPrevAutoStyle, bIsVisible);
761  nPrevIndex = pDefaults->GetColDefaults()[i].nIndex;
762  bPrevAutoStyle = pDefaults->GetColDefaults()[i].bIsAutoStyle;
763  nRepeat = 1;
764  }
765  else
766  ++nRepeat;
767  }
768  WriteSingleColumn(nRepeat, nStyleIndex, nPrevIndex, bPrevAutoStyle, bIsVisible);
769 }
770 
772 {
774 }
775 
777 {
779 }
780 
781 void ScXMLExport::ExportColumns(const sal_Int32 nTable, const ScRange& aColumnHeaderRange, const bool bHasColumnHeader)
782 {
783  sal_Int32 nColsRepeated (1);
784  sal_Int32 nIndex;
785  sal_Int32 nPrevColumn(0);
786  bool bPrevIsVisible (true);
787  bool bWasHeader (false);
788  bool bIsClosed (true);
789  sal_Int32 nPrevIndex (-1);
790  sal_Int32 nColumn;
791  for (nColumn = 0; nColumn <= pSharedData->GetLastColumn(nTable); ++nColumn)
792  {
793  CheckAttrList();
794  bool bIsVisible(true);
795  nIndex = pColumnStyles->GetStyleNameIndex(nTable, nColumn, bIsVisible);
796 
797  const bool bIsHeader = bHasColumnHeader && (aColumnHeaderRange.aStart.Col() <= nColumn) && (nColumn <= aColumnHeaderRange.aEnd.Col());
798  if (bIsHeader != bWasHeader)
799  {
800  if (bIsHeader)
801  {
802  if (nColumn > 0)
803  {
804  WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
805  if (pGroupColumns->IsGroupEnd(nColumn - 1))
806  pGroupColumns->CloseGroups(nColumn - 1);
807  }
808  bPrevIsVisible = bIsVisible;
809  nPrevIndex = nIndex;
810  nPrevColumn = nColumn;
811  nColsRepeated = 1;
812  if(pGroupColumns->IsGroupStart(nColumn))
813  pGroupColumns->OpenGroups(nColumn);
815  bWasHeader = true;
816  bIsClosed = false;
817  }
818  else
819  {
820  WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
822  if (pGroupColumns->IsGroupEnd(nColumn - 1))
823  pGroupColumns->CloseGroups(nColumn - 1);
824  if(pGroupColumns->IsGroupStart(nColumn))
825  pGroupColumns->OpenGroups(nColumn);
826  bPrevIsVisible = bIsVisible;
827  nPrevIndex = nIndex;
828  nPrevColumn = nColumn;
829  nColsRepeated = 1;
830  bWasHeader = false;
831  bIsClosed = true;
832  }
833  }
834  else if (nColumn == 0)
835  {
836  if (pGroupColumns->IsGroupStart(nColumn))
837  pGroupColumns->OpenGroups(nColumn);
838  bPrevIsVisible = bIsVisible;
839  nPrevIndex = nIndex;
840  }
841  else if ((bIsVisible == bPrevIsVisible) && (nIndex == nPrevIndex) &&
842  !pGroupColumns->IsGroupStart(nColumn) && !pGroupColumns->IsGroupEnd(nColumn - 1))
843  ++nColsRepeated;
844  else
845  {
846  WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
847  if (pGroupColumns->IsGroupEnd(nColumn - 1))
848  {
849  if (bIsHeader)
851  pGroupColumns->CloseGroups(nColumn - 1);
852  if (bIsHeader)
854  }
855  if (pGroupColumns->IsGroupStart(nColumn))
856  {
857  if (bIsHeader)
859  pGroupColumns->OpenGroups(nColumn);
860  if (bIsHeader)
862  }
863  bPrevIsVisible = bIsVisible;
864  nPrevIndex = nIndex;
865  nPrevColumn = nColumn;
866  nColsRepeated = 1;
867  }
868  }
869  assert(nPrevIndex >= 0 && "coverity#1438402");
870  WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
871  if (!bIsClosed)
873  if (pGroupColumns->IsGroupEnd(nColumn - 1))
874  pGroupColumns->CloseGroups(nColumn - 1);
875 }
876 
878 {
879  sal_Int32 nEntryIndex = GetCellStylesPropertySetMapper()->FindEntryIndex(
880  "NumberFormat", XML_NAMESPACE_STYLE, "data-style-name");
881 
882  if (nEntryIndex < 0)
883  // No entry index for the number format is found.
884  return;
885 
887  if (!pRefMgr->hasExternalData())
888  // No external reference data cached.
889  return;
890 
891  // Export each unique number format used in the external ref cache.
892  vector<sal_uInt32> aNumFmts;
893  pRefMgr->getAllCachedNumberFormats(aNumFmts);
894  const OUString aDefaultStyle = OUString("Default").intern();
895  for (const auto& rNumFmt : aNumFmts)
896  {
897  sal_Int32 nNumFmt = static_cast<sal_Int32>(rNumFmt);
898 
899  addDataStyle(nNumFmt);
900 
901  uno::Any aVal;
902  aVal <<= nNumFmt;
903  vector<XMLPropertyState> aProps;
904  aVal <<= aDefaultStyle;
905  aProps.emplace_back(nEntryIndex, aVal);
906 
907  OUString aName;
908  sal_Int32 nIndex;
909  if (GetAutoStylePool()->Add(aName, XmlStyleFamily::TABLE_CELL, aDefaultStyle, aProps))
910  {
911  pCellStyles->AddStyleName(aName, nIndex);
912  }
913  else
914  {
915  bool bIsAuto;
916  nIndex = pCellStyles->GetIndexOfStyleName(
918  }
919 
920  // store the number format to index mapping for later use.
921  aNumFmtIndexMap.emplace(nNumFmt, nIndex);
922  }
923 }
924 
925 namespace {
926 
927 void handleFont(
928  std::vector<XMLPropertyState>& rPropStates,
929  const SfxPoolItem* p, const rtl::Reference<XMLPropertySetMapper>& xMapper, const OUString& rXMLName )
930 {
931  sal_Int32 nEntryCount = xMapper->GetEntryCount();
932 
933  // Apparently font info needs special handling.
934  const SvxFontItem* pItem = static_cast<const SvxFontItem*>(p);
935 
936  sal_Int32 nIndexFontName = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, rXMLName, 0);
937 
938  if (nIndexFontName == -1 || nIndexFontName >= nEntryCount)
939  return;
940 
941  uno::Any aAny;
942  if (!pItem->QueryValue(aAny, MID_FONT_FAMILY_NAME))
943  return;
944 
945  rPropStates.emplace_back(nIndexFontName, aAny);
946 }
947 
948 const SvxFieldData* toXMLPropertyStates(
949  std::vector<XMLPropertyState>& rPropStates, const std::vector<const SfxPoolItem*>& rSecAttrs,
950  const rtl::Reference<XMLPropertySetMapper>& xMapper, const ScXMLEditAttributeMap& rAttrMap )
951 {
952  const SvxFieldData* pField = nullptr;
953  sal_Int32 nEntryCount = xMapper->GetEntryCount();
954  rPropStates.reserve(rSecAttrs.size());
955  for (const SfxPoolItem* p : rSecAttrs)
956  {
957  if (p->Which() == EE_FEATURE_FIELD)
958  {
959  pField = static_cast<const SvxFieldItem*>(p)->GetField();
960  continue;
961  }
962 
963  const ScXMLEditAttributeMap::Entry* pEntry = rAttrMap.getEntryByItemID(p->Which());
964  if (!pEntry)
965  continue;
966 
967  sal_Int32 nIndex = xMapper->GetEntryIndex(
968  pEntry->nmXMLNS, OUString::createFromAscii(pEntry->mpXMLName), 0);
969 
970  if (nIndex == -1 || nIndex >= nEntryCount)
971  continue;
972 
973  uno::Any aAny;
974  switch (p->Which())
975  {
976  case EE_CHAR_FONTINFO:
977  handleFont(rPropStates, p, xMapper, "font-name");
978  break;
980  handleFont(rPropStates, p, xMapper, "font-name-asian");
981  break;
983  handleFont(rPropStates, p, xMapper, "font-name-complex");
984  break;
985  case EE_CHAR_WEIGHT:
986  case EE_CHAR_WEIGHT_CJK:
987  case EE_CHAR_WEIGHT_CTL:
988  {
989  if (!static_cast<const SvxWeightItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
990  continue;
991 
992  rPropStates.emplace_back(nIndex, aAny);
993  }
994  break;
995  case EE_CHAR_FONTHEIGHT:
998  {
999  if (!static_cast<const SvxFontHeightItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1000  continue;
1001 
1002  rPropStates.emplace_back(nIndex, aAny);
1003  }
1004  break;
1005  case EE_CHAR_ITALIC:
1006  case EE_CHAR_ITALIC_CJK:
1007  case EE_CHAR_ITALIC_CTL:
1008  {
1009  if (!static_cast<const SvxPostureItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1010  continue;
1011 
1012  rPropStates.emplace_back(nIndex, aAny);
1013  }
1014  break;
1015  case EE_CHAR_UNDERLINE:
1016  {
1017  // Underline attribute needs to export multiple entries.
1018  sal_Int32 nIndexStyle = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-underline-style", 0);
1019  if (nIndexStyle == -1 || nIndexStyle > nEntryCount)
1020  break;
1021 
1022  sal_Int32 nIndexWidth = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-underline-width", 0);
1023  if (nIndexWidth == -1 || nIndexWidth > nEntryCount)
1024  break;
1025 
1026  sal_Int32 nIndexType = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-underline-type", 0);
1027  if (nIndexType == -1 || nIndexType > nEntryCount)
1028  break;
1029 
1030  sal_Int32 nIndexColor = xMapper->FindEntryIndex("CharUnderlineColor", XML_NAMESPACE_STYLE, "text-underline-color");
1031  if (nIndexColor == -1 || nIndexColor > nEntryCount)
1032  break;
1033 
1034  sal_Int32 nIndexHasColor = xMapper->FindEntryIndex("CharUnderlineHasColor", XML_NAMESPACE_STYLE, "text-underline-color");
1035  if (nIndexHasColor == -1 || nIndexHasColor > nEntryCount)
1036  break;
1037 
1038  const SvxUnderlineItem* pUL = static_cast<const SvxUnderlineItem*>(p);
1039  pUL->QueryValue(aAny, MID_TL_STYLE);
1040  rPropStates.emplace_back(nIndexStyle, aAny);
1041  rPropStates.emplace_back(nIndexType, aAny);
1042  rPropStates.emplace_back(nIndexWidth, aAny);
1043 
1044  pUL->QueryValue(aAny, MID_TL_COLOR);
1045  rPropStates.emplace_back(nIndexColor, aAny);
1046 
1047  pUL->QueryValue(aAny, MID_TL_HASCOLOR);
1048  rPropStates.emplace_back(nIndexHasColor, aAny);
1049  }
1050  break;
1051  case EE_CHAR_OVERLINE:
1052  {
1053  // Same with overline. Do just as we do with underline attributes.
1054  sal_Int32 nIndexStyle = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-overline-style", 0);
1055  if (nIndexStyle == -1 || nIndexStyle > nEntryCount)
1056  break;
1057 
1058  sal_Int32 nIndexWidth = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-overline-width", 0);
1059  if (nIndexWidth == -1 || nIndexWidth > nEntryCount)
1060  break;
1061 
1062  sal_Int32 nIndexType = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-overline-type", 0);
1063  if (nIndexType == -1 || nIndexType > nEntryCount)
1064  break;
1065 
1066  sal_Int32 nIndexColor = xMapper->FindEntryIndex("CharOverlineColor", XML_NAMESPACE_STYLE, "text-overline-color");
1067  if (nIndexColor == -1 || nIndexColor > nEntryCount)
1068  break;
1069 
1070  sal_Int32 nIndexHasColor = xMapper->FindEntryIndex("CharOverlineHasColor", XML_NAMESPACE_STYLE, "text-overline-color");
1071  if (nIndexHasColor == -1 || nIndexHasColor > nEntryCount)
1072  break;
1073 
1074  const SvxOverlineItem* pOL = static_cast<const SvxOverlineItem*>(p);
1075  pOL->QueryValue(aAny, MID_TL_STYLE);
1076  rPropStates.emplace_back(nIndexStyle, aAny);
1077  rPropStates.emplace_back(nIndexType, aAny);
1078  rPropStates.emplace_back(nIndexWidth, aAny);
1079 
1080  pOL->QueryValue(aAny, MID_TL_COLOR);
1081  rPropStates.emplace_back(nIndexColor, aAny);
1082 
1083  pOL->QueryValue(aAny, MID_TL_HASCOLOR);
1084  rPropStates.emplace_back(nIndexHasColor, aAny);
1085  }
1086  break;
1087  case EE_CHAR_COLOR:
1088  {
1089  if (!static_cast<const SvxColorItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1090  continue;
1091 
1092  ::Color nColor;
1093  if ( aAny >>= nColor )
1094  {
1095  sal_Int32 nIndexColor = ( nColor == COL_AUTO ) ? xMapper->GetEntryIndex(
1096  XML_NAMESPACE_STYLE, GetXMLToken( XML_USE_WINDOW_FONT_COLOR ), 0 ) : nIndex;
1097  rPropStates.emplace_back( nIndexColor, aAny );
1098  }
1099  }
1100  break;
1101  case EE_CHAR_WLM:
1102  {
1103  if (!static_cast<const SvxWordLineModeItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1104  continue;
1105 
1106  rPropStates.emplace_back(nIndex, aAny);
1107  }
1108  break;
1109  case EE_CHAR_STRIKEOUT:
1110  {
1111  if (!static_cast<const SvxCrossedOutItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1112  continue;
1113 
1114  rPropStates.emplace_back(nIndex, aAny);
1115  }
1116  break;
1117  case EE_CHAR_RELIEF:
1118  {
1119  if (!static_cast<const SvxCharReliefItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1120  continue;
1121 
1122  rPropStates.emplace_back(nIndex, aAny);
1123  }
1124  break;
1125  case EE_CHAR_OUTLINE:
1126  {
1127  if (!static_cast<const SvxContourItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1128  continue;
1129 
1130  rPropStates.emplace_back(nIndex, aAny);
1131  }
1132  break;
1133  case EE_CHAR_SHADOW:
1134  {
1135  if (!static_cast<const SvxShadowedItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1136  continue;
1137 
1138  rPropStates.emplace_back(nIndex, aAny);
1139  }
1140  break;
1141  case EE_CHAR_KERNING:
1142  {
1143  if (!static_cast<const SvxKerningItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1144  continue;
1145 
1146  rPropStates.emplace_back(nIndex, aAny);
1147  }
1148  break;
1149  case EE_CHAR_PAIRKERNING:
1150  {
1151  if (!static_cast<const SvxAutoKernItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1152  continue;
1153 
1154  rPropStates.emplace_back(nIndex, aAny);
1155  }
1156  break;
1157  case EE_CHAR_FONTWIDTH:
1158  {
1159  if (!static_cast<const SvxCharScaleWidthItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1160  continue;
1161 
1162  rPropStates.emplace_back(nIndex, aAny);
1163  }
1164  break;
1165  case EE_CHAR_ESCAPEMENT:
1166  {
1167  sal_Int32 nIndexEsc = xMapper->FindEntryIndex("CharEscapement", XML_NAMESPACE_STYLE, "text-position");
1168  if (nIndexEsc == -1 || nIndexEsc > nEntryCount)
1169  break;
1170 
1171  sal_Int32 nIndexEscHeight = xMapper->FindEntryIndex("CharEscapementHeight", XML_NAMESPACE_STYLE, "text-position");
1172  if (nIndexEscHeight == -1 || nIndexEscHeight > nEntryCount)
1173  break;
1174 
1175  const SvxEscapementItem* pEsc = static_cast<const SvxEscapementItem*>(p);
1176 
1177  pEsc->QueryValue(aAny);
1178  rPropStates.emplace_back(nIndexEsc, aAny);
1179 
1180  pEsc->QueryValue(aAny, MID_ESC_HEIGHT);
1181  rPropStates.emplace_back(nIndexEscHeight, aAny);
1182 
1183  }
1184  break;
1185  case EE_CHAR_EMPHASISMARK:
1186  {
1187  if (!static_cast<const SvxEmphasisMarkItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1188  continue;
1189 
1190  rPropStates.emplace_back(nIndex, aAny);
1191  }
1192  break;
1193  case EE_CHAR_LANGUAGE:
1194  case EE_CHAR_LANGUAGE_CJK:
1195  case EE_CHAR_LANGUAGE_CTL:
1196  {
1197  if (!static_cast<const SvxLanguageItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1198  continue;
1199 
1200  // Export multiple entries.
1201  sal_Int32 nIndexLanguage, nIndexCountry, nIndexScript, nIndexTag;
1202  switch (p->Which())
1203  {
1204  case EE_CHAR_LANGUAGE:
1205  nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_FO, "language", 0);
1206  nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_FO, "country", 0);
1207  nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_FO, "script", 0);
1208  nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "rfc-language-tag", 0);
1209  break;
1210  case EE_CHAR_LANGUAGE_CJK:
1211  nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "language-asian", 0);
1212  nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "country-asian", 0);
1213  nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "script-asian", 0);
1214  nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "rfc-language-tag-asian", 0);
1215  break;
1216  case EE_CHAR_LANGUAGE_CTL:
1217  nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "language-complex", 0);
1218  nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "country-complex", 0);
1219  nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "script-complex", 0);
1220  nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "rfc-language-tag-complex", 0);
1221  break;
1222  default:
1223  nIndexLanguage = nIndexCountry = nIndexScript = nIndexTag = -1;
1224  }
1225  assert( nIndexLanguage >= 0 && nIndexCountry >= 0 && nIndexScript >= 0 && nIndexTag >= 0);
1226  rPropStates.emplace_back( nIndexLanguage, aAny);
1227  rPropStates.emplace_back( nIndexCountry, aAny);
1228  rPropStates.emplace_back( nIndexScript, aAny);
1229  rPropStates.emplace_back( nIndexTag, aAny);
1230  }
1231  break;
1232  default:
1233  continue;
1234  }
1235  }
1236 
1237  return pField;
1238 }
1239 
1240 }
1241 
1243 {
1244  if (!ValidTab(nTable))
1245  return;
1246 
1247  rtl::Reference<XMLPropertySetMapper> xMapper = GetTextParagraphExport()->GetTextPropMapper()->getPropertySetMapper();
1249  const ScXMLEditAttributeMap& rAttrMap = GetEditAttributeMap();
1250 
1251  sc::EditTextIterator aIter(*pDoc, nTable);
1252  sal_Int32 nCellCount = 0;
1253  for (const EditTextObject* pEdit = aIter.first(); pEdit; pEdit = aIter.next(), ++nCellCount)
1254  {
1255  std::vector<editeng::Section> aAttrs;
1256  pEdit->GetAllSections(aAttrs);
1257  if (aAttrs.empty())
1258  continue;
1259 
1260  for (const auto& rSec : aAttrs)
1261  {
1262  const std::vector<const SfxPoolItem*>& rSecAttrs = rSec.maAttributes;
1263  if (rSecAttrs.empty())
1264  // No formats applied to this section. Skip it.
1265  continue;
1266 
1267  std::vector<XMLPropertyState> aPropStates;
1268  toXMLPropertyStates(aPropStates, rSecAttrs, xMapper, rAttrMap);
1269  if (!aPropStates.empty())
1270  xStylePool->Add(XmlStyleFamily::TEXT_TEXT, OUString(), aPropStates);
1271  }
1272  }
1273 
1274  GetProgressBarHelper()->ChangeReference(GetProgressBarHelper()->GetReference() + nCellCount);
1275 }
1276 
1278 {
1279  ScMyRowFormatRange aRange;
1280  sal_Int32 nIndex(-1);
1281 #if OSL_DEBUG_LEVEL > 0
1282  sal_Int32 nPrevCol(0);
1283 #endif
1284  sal_Int32 nCols(0);
1285  sal_Int32 nPrevValidationIndex(-1);
1286  bool bIsAutoStyle(true);
1287  bool bIsFirst(true);
1288  while (pRowFormatRanges->GetNext(aRange))
1289  {
1290 #if OSL_DEBUG_LEVEL > 0
1291  OSL_ENSURE(bIsFirst || (!bIsFirst && (nPrevCol + nCols == aRange.nStartColumn)), "here are some columns missing");
1292 #endif
1293  if (bIsFirst)
1294  {
1295  nIndex = aRange.nIndex;
1296  nPrevValidationIndex = aRange.nValidationIndex;
1297  bIsAutoStyle = aRange.bIsAutoStyle;
1298  nCols = aRange.nRepeatColumns;
1299  bIsFirst = false;
1300 #if OSL_DEBUG_LEVEL > 0
1301  nPrevCol = aRange.nStartColumn;
1302 #endif
1303  }
1304  else
1305  {
1306  if (((aRange.nIndex == nIndex && aRange.bIsAutoStyle == bIsAutoStyle) ||
1307  (aRange.nIndex == nIndex && nIndex == -1)) &&
1308  nPrevValidationIndex == aRange.nValidationIndex)
1309  nCols += aRange.nRepeatColumns;
1310  else
1311  {
1312  if (nIndex != -1)
1313  AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
1314  if (nPrevValidationIndex > -1)
1315  AddAttribute(XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, pValidationsContainer->GetValidationName(nPrevValidationIndex));
1316  if (nCols > 1)
1317  {
1318  AddAttribute(sAttrColumnsRepeated, OUString::number(nCols));
1319  }
1320  SvXMLElementExport aElemC(*this, sElemCell, true, true);
1321  nIndex = aRange.nIndex;
1322  bIsAutoStyle = aRange.bIsAutoStyle;
1323  nCols = aRange.nRepeatColumns;
1324  nPrevValidationIndex = aRange.nValidationIndex;
1325 #if OSL_DEBUG_LEVEL > 0
1326  nPrevCol = aRange.nStartColumn;
1327 #endif
1328  }
1329  }
1330  }
1331  if (!bIsFirst)
1332  {
1333  if (nIndex != -1)
1334  AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
1335  if (nPrevValidationIndex > -1)
1336  AddAttribute(XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, pValidationsContainer->GetValidationName(nPrevValidationIndex));
1337  if (nCols > 1)
1338  {
1339  AddAttribute(sAttrColumnsRepeated, OUString::number(nCols));
1340  }
1341  SvXMLElementExport aElemC(*this, sElemCell, true, true);
1342  }
1343 }
1344 
1346  const sal_Int32 nIndex, const sal_Int32 nEqualRows,
1347  bool bHidden, bool bFiltered)
1348 {
1349  AddAttribute(sAttrStyleName, pRowStyles->GetStyleNameByIndex(nIndex));
1350  if (bHidden)
1351  {
1352  if (bFiltered)
1354  else
1356  }
1357  if (nEqualRows > 1)
1358  {
1359  AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, OUString::number(nEqualRows));
1360  }
1361 
1362  StartElement( sElemRow, true);
1363 }
1364 
1366 {
1368  bRowHeaderOpen = true;
1369 }
1370 
1372 {
1374 }
1375 
1377  const sal_Int32 nIndex, const sal_Int32 nStartRow, const sal_Int32 nEqualRows,
1378  bool bHidden, bool bFiltered)
1379 {
1380  nOpenRow = nStartRow;
1381  if (pGroupRows->IsGroupStart(nStartRow))
1382  {
1384  CloseHeaderRows();
1385  pGroupRows->OpenGroups(nStartRow);
1387  OpenHeaderRows();
1388  }
1389  if (bHasRowHeader && !bRowHeaderOpen && nStartRow >= aRowHeaderRange.aStart.Row() && nStartRow <= aRowHeaderRange.aEnd.Row())
1390  {
1391  if (nStartRow == aRowHeaderRange.aStart.Row())
1392  OpenHeaderRows();
1393  sal_Int32 nEquals;
1394  if (aRowHeaderRange.aEnd.Row() < nStartRow + nEqualRows - 1)
1395  nEquals = aRowHeaderRange.aEnd.Row() - nStartRow + 1;
1396  else
1397  nEquals = nEqualRows;
1398  WriteRowStartTag(nIndex, nEquals, bHidden, bFiltered);
1399  nOpenRow = nStartRow + nEquals - 1;
1400  if (nEquals < nEqualRows)
1401  {
1402  CloseRow(nStartRow + nEquals - 1);
1403  WriteRowStartTag(nIndex, nEqualRows - nEquals, bHidden, bFiltered);
1404  nOpenRow = nStartRow + nEqualRows - 1;
1405  }
1406  }
1407  else
1408  WriteRowStartTag(nIndex, nEqualRows, bHidden, bFiltered);
1409 }
1410 
1412  const sal_Int32 nIndex, const sal_Int32 nStartRow, const sal_Int32 nEqualRows,
1413  bool bHidden, bool bFiltered)
1414 {
1415  OpenNewRow(nIndex, nStartRow, nEqualRows, bHidden, bFiltered);
1416  WriteRowContent();
1417  CloseRow(nStartRow + nEqualRows - 1);
1418  pRowFormatRanges->Clear();
1419 }
1420 
1421 void ScXMLExport::OpenRow(const sal_Int32 nTable, const sal_Int32 nStartRow, const sal_Int32 nRepeatRow, ScXMLCachedRowAttrAccess& rRowAttr)
1422 {
1423  if (nRepeatRow > 1)
1424  {
1425  sal_Int32 nPrevIndex(0), nIndex;
1426  bool bPrevHidden = false;
1427  bool bPrevFiltered = false;
1428  bool bHidden = false;
1429  bool bFiltered = false;
1430  sal_Int32 nEqualRows(1);
1431  sal_Int32 nEndRow(nStartRow + nRepeatRow);
1432  sal_Int32 nEndRowHidden = nStartRow - 1;
1433  sal_Int32 nEndRowFiltered = nStartRow - 1;
1434  sal_Int32 nRow;
1435  for (nRow = nStartRow; nRow < nEndRow; ++nRow)
1436  {
1437  if (nRow == nStartRow)
1438  {
1439  nPrevIndex = pRowStyles->GetStyleNameIndex(nTable, nRow);
1440  if (pDoc)
1441  {
1442  if (nRow > nEndRowHidden)
1443  {
1444  bPrevHidden = rRowAttr.rowHidden(nTable, nRow, nEndRowHidden);
1445  bHidden = bPrevHidden;
1446  }
1447  if (nRow > nEndRowFiltered)
1448  {
1449  bPrevFiltered = rRowAttr.rowFiltered(nTable, nRow, nEndRowFiltered);
1450  bFiltered = bPrevFiltered;
1451  }
1452  }
1453 
1454  }
1455  else
1456  {
1457  nIndex = pRowStyles->GetStyleNameIndex(nTable, nRow);
1458  if (pDoc)
1459  {
1460  if (nRow > nEndRowHidden)
1461  bHidden = rRowAttr.rowHidden(nTable, nRow, nEndRowHidden);
1462  if (nRow > nEndRowFiltered)
1463  bFiltered = rRowAttr.rowFiltered(nTable, nRow, nEndRowFiltered);
1464  }
1465  if (nIndex == nPrevIndex && bHidden == bPrevHidden && bFiltered == bPrevFiltered &&
1466  !(bHasRowHeader && ((nRow == aRowHeaderRange.aStart.Row()) || (nRow - 1 == aRowHeaderRange.aEnd.Row()))) &&
1467  !(pGroupRows->IsGroupStart(nRow)) &&
1468  !(pGroupRows->IsGroupEnd(nRow - 1)))
1469  ++nEqualRows;
1470  else
1471  {
1472  assert(nPrevIndex >= 0 && "coverity#1438402");
1473  ScRowFormatRanges* pTempRowFormatRanges = new ScRowFormatRanges(pRowFormatRanges.get());
1474  OpenAndCloseRow(nPrevIndex, nRow - nEqualRows, nEqualRows, bPrevHidden, bPrevFiltered);
1475  pRowFormatRanges.reset(pTempRowFormatRanges);
1476  nEqualRows = 1;
1477  nPrevIndex = nIndex;
1478  bPrevHidden = bHidden;
1479  bPrevFiltered = bFiltered;
1480  }
1481  }
1482  }
1483  assert(nPrevIndex >= 0 && "coverity#1438402");
1484  OpenNewRow(nPrevIndex, nRow - nEqualRows, nEqualRows, bPrevHidden, bPrevFiltered);
1485  }
1486  else
1487  {
1488  sal_Int32 nIndex = pRowStyles->GetStyleNameIndex(nTable, nStartRow);
1489  bool bHidden = false;
1490  bool bFiltered = false;
1491  if (pDoc)
1492  {
1493  sal_Int32 nEndRowHidden;
1494  sal_Int32 nEndRowFiltered;
1495  bHidden = rRowAttr.rowHidden(nTable, nStartRow, nEndRowHidden);
1496  bFiltered = rRowAttr.rowFiltered(nTable, nStartRow, nEndRowFiltered);
1497  }
1498  assert(nIndex >= 0 && "coverity#1438402");
1499  OpenNewRow(nIndex, nStartRow, 1, bHidden, bFiltered);
1500  }
1501  nOpenRow = nStartRow + nRepeatRow - 1;
1502 }
1503 
1504 void ScXMLExport::CloseRow(const sal_Int32 nRow)
1505 {
1506  if (nOpenRow > -1)
1507  {
1508  EndElement(sElemRow, true);
1509  if (bHasRowHeader && nRow == aRowHeaderRange.aEnd.Row())
1510  {
1511  CloseHeaderRows();
1512  bRowHeaderOpen = false;
1513  }
1514  if (pGroupRows->IsGroupEnd(nRow))
1515  {
1517  CloseHeaderRows();
1518  pGroupRows->CloseGroups(nRow);
1520  OpenHeaderRows();
1521  }
1522  }
1523  nOpenRow = -1;
1524 }
1525 
1526 void ScXMLExport::ExportFormatRanges(const sal_Int32 nStartCol, const sal_Int32 nStartRow,
1527  const sal_Int32 nEndCol, const sal_Int32 nEndRow, const sal_Int32 nSheet)
1528 {
1529  pRowFormatRanges->Clear();
1530  ScXMLCachedRowAttrAccess aRowAttr(pDoc);
1531  if (nStartRow == nEndRow)
1532  {
1533  pCellStyles->GetFormatRanges(nStartCol, nEndCol, nStartRow, nSheet, pRowFormatRanges.get());
1534  if (nOpenRow == - 1)
1535  OpenRow(nSheet, nStartRow, 1, aRowAttr);
1536  WriteRowContent();
1537  pRowFormatRanges->Clear();
1538  }
1539  else
1540  {
1541  if (nOpenRow > -1)
1542  {
1543  pCellStyles->GetFormatRanges(nStartCol, pSharedData->GetLastColumn(nSheet), nStartRow, nSheet, pRowFormatRanges.get());
1544  WriteRowContent();
1545  CloseRow(nStartRow);
1546  sal_Int32 nRows(1);
1547  sal_Int32 nTotalRows(nEndRow - nStartRow + 1 - 1);
1548  while (nRows < nTotalRows)
1549  {
1550  pRowFormatRanges->Clear();
1551  pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1552  sal_Int32 nMaxRows = pRowFormatRanges->GetMaxRows();
1553  OSL_ENSURE(nMaxRows, "something went wrong");
1554  if (nMaxRows >= nTotalRows - nRows)
1555  {
1556  OpenRow(nSheet, nStartRow + nRows, nTotalRows - nRows, aRowAttr);
1557  nRows += nTotalRows - nRows;
1558  }
1559  else
1560  {
1561  OpenRow(nSheet, nStartRow + nRows, nMaxRows, aRowAttr);
1562  nRows += nMaxRows;
1563  }
1564  if (!pRowFormatRanges->GetSize())
1565  pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1566  WriteRowContent();
1567  CloseRow(nStartRow + nRows - 1);
1568  }
1569  if (nTotalRows == 1)
1570  CloseRow(nStartRow);
1571  OpenRow(nSheet, nEndRow, 1, aRowAttr);
1572  pRowFormatRanges->Clear();
1573  pCellStyles->GetFormatRanges(0, nEndCol, nEndRow, nSheet, pRowFormatRanges.get());
1574  WriteRowContent();
1575  }
1576  else
1577  {
1578  sal_Int32 nRows(0);
1579  sal_Int32 nTotalRows(nEndRow - nStartRow + 1 - 1);
1580  while (nRows < nTotalRows)
1581  {
1582  pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1583  sal_Int32 nMaxRows = pRowFormatRanges->GetMaxRows();
1584  OSL_ENSURE(nMaxRows, "something went wrong");
1585  if (nMaxRows >= nTotalRows - nRows)
1586  {
1587  OpenRow(nSheet, nStartRow + nRows, nTotalRows - nRows, aRowAttr);
1588  nRows += nTotalRows - nRows;
1589  }
1590  else
1591  {
1592  OpenRow(nSheet, nStartRow + nRows, nMaxRows, aRowAttr);
1593  nRows += nMaxRows;
1594  }
1595  if (!pRowFormatRanges->GetSize())
1596  pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1597  WriteRowContent();
1598  CloseRow(nStartRow + nRows - 1);
1599  }
1600  OpenRow(nSheet, nEndRow, 1, aRowAttr);
1601  pRowFormatRanges->Clear();
1602  pCellStyles->GetFormatRanges(0, nEndCol, nEndRow, nSheet, pRowFormatRanges.get());
1603  WriteRowContent();
1604  }
1605  }
1606 }
1607 
1608 void ScXMLExport::GetColumnRowHeader(bool& rHasColumnHeader, ScRange& rColumnHeaderRange,
1609  bool& rHasRowHeader, ScRange& rRowHeaderRange,
1610  OUString& rPrintRanges) const
1611 {
1612  uno::Reference <sheet::XPrintAreas> xPrintAreas (xCurrentTable, uno::UNO_QUERY);
1613  if (!xPrintAreas.is())
1614  return;
1615 
1616  rHasRowHeader = xPrintAreas->getPrintTitleRows();
1617  rHasColumnHeader = xPrintAreas->getPrintTitleColumns();
1618  table::CellRangeAddress rTempRowHeaderRange = xPrintAreas->getTitleRows();
1619  rRowHeaderRange = ScRange(rTempRowHeaderRange.StartColumn,
1620  rTempRowHeaderRange.StartRow,
1621  rTempRowHeaderRange.Sheet,
1622  rTempRowHeaderRange.EndColumn,
1623  rTempRowHeaderRange.EndRow,
1624  rTempRowHeaderRange.Sheet);
1625  table::CellRangeAddress rTempColumnHeaderRange = xPrintAreas->getTitleColumns();
1626  rColumnHeaderRange = ScRange(rTempColumnHeaderRange.StartColumn,
1627  rTempColumnHeaderRange.StartRow,
1628  rTempColumnHeaderRange.Sheet,
1629  rTempColumnHeaderRange.EndColumn,
1630  rTempColumnHeaderRange.EndRow,
1631  rTempColumnHeaderRange.Sheet);
1632  uno::Sequence< table::CellRangeAddress > aRangeList( xPrintAreas->getPrintAreas() );
1633  ScRangeStringConverter::GetStringFromRangeList( rPrintRanges, aRangeList, pDoc, FormulaGrammar::CONV_OOO );
1634 }
1635 
1637 {
1638  size_t nDepth = pFields->GetDepth();
1639  for (size_t i = 0; i < nDepth; ++i)
1640  {
1641  size_t nFields = pFields->GetCount(i);
1642  for (size_t j = 0; j < nFields; ++j)
1643  {
1644  ScMyColumnRowGroup aGroup;
1645  const ScOutlineEntry* pEntry = pFields->GetEntry(i, j);
1646  aGroup.nField = pEntry->GetStart();
1647  aGroup.nLevel = static_cast<sal_Int16>(i);
1648  aGroup.bDisplay = !(pEntry->IsHidden());
1649  pGroups->AddGroup(aGroup, pEntry->GetEnd());
1650  }
1651  }
1652  if (nDepth)
1653  pGroups->Sort();
1654 }
1655 
1657 {
1658  if (!pDoc)
1659  return;
1660 
1661  ScOutlineTable* pOutlineTable = pDoc->GetOutlineTable( static_cast<SCTAB>(nCurrentTable) );
1662  if(pOutlineTable)
1663  {
1664  ScOutlineArray& rCols(pOutlineTable->GetColArray());
1665  ScOutlineArray& rRows(pOutlineTable->GetRowArray());
1666  FillFieldGroup(&rCols, pGroupColumns.get());
1667  FillFieldGroup(&rRows, pGroupRows.get());
1668  pSharedData->SetLastColumn(nCurrentTable, pGroupColumns->GetLast());
1669  pSharedData->SetLastRow(nCurrentTable, pGroupRows->GetLast());
1670  }
1671 }
1672 
1674 {
1675  if (!(pDoc && pDoc->IsDocProtected()))
1676  return;
1677 
1679  OUStringBuffer aBuffer;
1680  uno::Sequence<sal_Int8> aPassHash;
1682  const ScDocProtection* p = pDoc->GetDocProtection();
1683  if (p)
1684  {
1686  {
1687  aPassHash = p->getPasswordHash(PASSHASH_SHA1);
1688  eHashUsed = PASSHASH_SHA1;
1689  }
1690  else if (p->hasPasswordHash(PASSHASH_SHA256))
1691  {
1692  aPassHash = p->getPasswordHash(PASSHASH_SHA256);
1693  eHashUsed = PASSHASH_SHA256;
1694  }
1696  {
1697  aPassHash = p->getPasswordHash(PASSHASH_XL, PASSHASH_SHA1);
1698  eHashUsed = PASSHASH_XL;
1699  }
1700  }
1701  ::comphelper::Base64::encode(aBuffer, aPassHash);
1702  if (aBuffer.isEmpty())
1703  return;
1704 
1705  AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
1707  return;
1708 
1709  if (eHashUsed == PASSHASH_XL)
1710  {
1716  }
1717  else if (eHashUsed == PASSHASH_SHA1)
1718  {
1721  }
1722  else if (eHashUsed == PASSHASH_SHA256)
1723  {
1726  }
1727 }
1728 
1729 static bool lcl_CopyStreamElement( const uno::Reference< io::XInputStream >& xInput,
1730  const uno::Reference< io::XOutputStream >& xOutput,
1731  sal_Int32 nCount )
1732 {
1733  const sal_Int32 nBufSize = 16*1024;
1734  uno::Sequence<sal_Int8> aSequence(nBufSize);
1735 
1736  sal_Int32 nRemaining = nCount;
1737  bool bFirst = true;
1738 
1739  while ( nRemaining > 0 )
1740  {
1741  sal_Int32 nRead = xInput->readBytes( aSequence, std::min( nRemaining, nBufSize ) );
1742  if (bFirst)
1743  {
1744  // safety check: Make sure the copied part actually points to the start of an element
1745  if ( nRead < 1 || aSequence[0] != static_cast<sal_Int8>('<') )
1746  {
1747  return false; // abort and set an error
1748  }
1749  bFirst = false;
1750  }
1751  if (nRead == nRemaining)
1752  {
1753  // safety check: Make sure the copied part also ends at the end of an element
1754  if ( aSequence[nRead-1] != static_cast<sal_Int8>('>') )
1755  {
1756  return false; // abort and set an error
1757  }
1758  }
1759 
1760  if ( nRead == nBufSize )
1761  {
1762  xOutput->writeBytes( aSequence );
1763  nRemaining -= nRead;
1764  }
1765  else
1766  {
1767  if ( nRead > 0 )
1768  {
1769  uno::Sequence<sal_Int8> aTempBuf( aSequence.getConstArray(), nRead );
1770  xOutput->writeBytes( aTempBuf );
1771  }
1772  nRemaining = 0;
1773  }
1774  }
1775  return true; // successful
1776 }
1777 
1778 static void lcl_SkipBytesInBlocks( const uno::Reference< io::XInputStream >& xInput, sal_Int32 nBytesToSkip )
1779 {
1780  // skipBytes in zip stream is implemented as reading.
1781  // For now, split into several calls to avoid allocating a large buffer.
1782  // Later, skipBytes should be changed.
1783 
1784  const sal_Int32 nMaxSize = 32*1024;
1785 
1786  if ( nBytesToSkip > 0 )
1787  {
1788  sal_Int32 nRemaining = nBytesToSkip;
1789  while ( nRemaining > 0 )
1790  {
1791  sal_Int32 nSkip = std::min( nRemaining, nMaxSize );
1792  xInput->skipBytes( nSkip );
1793  nRemaining -= nSkip;
1794  }
1795  }
1796 }
1797 
1798 void ScXMLExport::CopySourceStream( sal_Int32 nStartOffset, sal_Int32 nEndOffset, sal_Int32& rNewStart, sal_Int32& rNewEnd )
1799 {
1800  uno::Reference<xml::sax::XDocumentHandler> xHandler = GetDocHandler();
1801  uno::Reference<io::XActiveDataSource> xDestSource( xHandler, uno::UNO_QUERY );
1802  if ( !xDestSource.is() )
1803  return;
1804 
1805  uno::Reference<io::XOutputStream> xDestStream = xDestSource->getOutputStream();
1806  uno::Reference<io::XSeekable> xDestSeek( xDestStream, uno::UNO_QUERY );
1807  if ( !xDestSeek.is() )
1808  return;
1809 
1810  // temporary: set same stream again to clear buffer
1811  xDestSource->setOutputStream( xDestStream );
1812 
1813  if ( getExportFlags() & SvXMLExportFlags::PRETTY )
1814  {
1815  const OString aOutStr("\n ");
1816  uno::Sequence<sal_Int8> aOutSeq( reinterpret_cast<sal_Int8 const *>(aOutStr.getStr()), aOutStr.getLength() );
1817  xDestStream->writeBytes( aOutSeq );
1818  }
1819 
1820  rNewStart = static_cast<sal_Int32>(xDestSeek->getPosition());
1821 
1822  if ( nStartOffset > nSourceStreamPos )
1824 
1825  if ( !lcl_CopyStreamElement( xSourceStream, xDestStream, nEndOffset - nStartOffset ) )
1826  {
1827  // If copying went wrong, set an error.
1828  // ScXMLImportWrapper then resets all stream flags, so the next save attempt will use normal saving.
1829 
1830  uno::Sequence<OUString> aEmptySeq;
1832  }
1833  nSourceStreamPos = nEndOffset;
1834 
1835  rNewEnd = static_cast<sal_Int32>(xDestSeek->getPosition());
1836 }
1837 
1839 {
1840  if (!mpEditAttrMap)
1842  return *mpEditAttrMap;
1843 }
1844 
1845 void ScXMLExport::RegisterDefinedStyleNames( const uno::Reference< css::sheet::XSpreadsheetDocument > & xSpreadDoc )
1846 {
1847  ScFormatSaveData* pFormatData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetFormatSaveData();
1848  auto xAutoStylePool = GetAutoStylePool();
1849  for (const auto& rFormatInfo : pFormatData->maIDToName)
1850  {
1851  xAutoStylePool->RegisterDefinedName(XmlStyleFamily::TABLE_CELL, rFormatInfo.second);
1852  }
1853 }
1854 
1856 {
1857  nCurrentTable = 0;
1858  if (!pSharedData)
1859  {
1860  SCTAB nTableCount(0);
1861  sal_Int32 nShapesCount(0);
1862  CollectSharedData(nTableCount, nShapesCount);
1863  OSL_FAIL("no shared data set");
1864  if (!pSharedData)
1865  return;
1866  }
1867  ScXMLExportDatabaseRanges aExportDatabaseRanges(*this);
1868  if (!GetModel().is())
1869  return;
1870 
1871  uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
1872  if ( !xSpreadDoc.is() )
1873  return;
1874 
1875  ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetSheetSaveData();
1876  if (pSheetData)
1877  pSheetData->ResetSaveEntries();
1878 
1879  uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
1880  if ( xIndex.is() )
1881  {
1882  //_GetNamespaceMap().ClearQNamesCache();
1883  pChangeTrackingExportHelper->CollectAndWriteChanges();
1884  WriteCalculationSettings(xSpreadDoc);
1885  sal_Int32 nTableCount(xIndex->getCount());
1886  ScMyAreaLinksContainer aAreaLinks;
1887  GetAreaLinks( aAreaLinks );
1888  ScMyEmptyDatabaseRangesContainer aEmptyRanges(aExportDatabaseRanges.GetEmptyDatabaseRanges());
1889  ScMyDetectiveOpContainer aDetectiveOpContainer;
1890  GetDetectiveOpList( aDetectiveOpContainer );
1891 
1892  pCellStyles->Sort();
1893  pMergedRangesContainer->Sort();
1894  pSharedData->GetDetectiveObjContainer()->Sort();
1895 
1896  mpCellsItr->Clear();
1897  mpCellsItr->SetShapes( pSharedData->GetShapesContainer() );
1898  mpCellsItr->SetNoteShapes( pSharedData->GetNoteShapes() );
1899  mpCellsItr->SetMergedRanges( pMergedRangesContainer.get() );
1900  mpCellsItr->SetAreaLinks( &aAreaLinks );
1901  mpCellsItr->SetEmptyDatabaseRanges( &aEmptyRanges );
1902  mpCellsItr->SetDetectiveObj( pSharedData->GetDetectiveObjContainer() );
1903  mpCellsItr->SetDetectiveOp( &aDetectiveOpContainer );
1904 
1905  if (nTableCount > 0)
1906  pValidationsContainer->WriteValidations(*this);
1907  WriteTheLabelRanges( xSpreadDoc );
1908  for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable)
1909  {
1910  sal_Int32 nStartOffset = -1;
1911  sal_Int32 nEndOffset = -1;
1912  if (pSheetData && pDoc && pDoc->IsStreamValid(static_cast<SCTAB>(nTable)) && !pDoc->GetChangeTrack())
1913  pSheetData->GetStreamPos( nTable, nStartOffset, nEndOffset );
1914 
1915  if ( nStartOffset >= 0 && nEndOffset >= 0 && xSourceStream.is() )
1916  {
1917  sal_Int32 nNewStart = -1;
1918  sal_Int32 nNewEnd = -1;
1919  CopySourceStream( nStartOffset, nEndOffset, nNewStart, nNewEnd );
1920 
1921  // store position of copied sheet in output
1922  pSheetData->AddSavePos( nTable, nNewStart, nNewEnd );
1923 
1924  // skip iterator entries for this sheet
1925  mpCellsItr->SkipTable(static_cast<SCTAB>(nTable));
1926  }
1927  else
1928  {
1929  uno::Reference<sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
1930  WriteTable(nTable, xTable);
1931  }
1932  IncrementProgressBar(false);
1933  }
1934  }
1937  WriteDataStream();
1938  aExportDatabaseRanges.WriteDatabaseRanges();
1940  ScXMLExportDataPilot aExportDataPilot(*this);
1941  aExportDataPilot.WriteDataPilots();
1943  ScXMLExportDDELinks aExportDDELinks(*this);
1944  aExportDDELinks.WriteDDELinks(xSpreadDoc);
1945  IncrementProgressBar(true, 0);
1946  GetProgressBarHelper()->SetValue(GetProgressBarHelper()->GetReference());
1947 }
1948 
1949 void ScXMLExport::ExportStyles_( bool bUsed )
1950 {
1951  uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
1952  if (xSpreadDoc.is())
1953  RegisterDefinedStyleNames( xSpreadDoc);
1954 
1955  if (!pSharedData)
1956  {
1957  SCTAB nTableCount(0);
1958  sal_Int32 nShapesCount(0);
1959  CollectSharedData(nTableCount, nShapesCount);
1960  }
1962  if (GetModel().is())
1963  {
1964  uno::Reference <lang::XMultiServiceFactory> xMultiServiceFactory(GetModel(), uno::UNO_QUERY);
1965  if (xMultiServiceFactory.is())
1966  {
1967  uno::Reference <beans::XPropertySet> xProperties(xMultiServiceFactory->createInstance("com.sun.star.sheet.Defaults"), uno::UNO_QUERY);
1968  if (xProperties.is())
1969  aStylesExp->exportDefaultStyle(xProperties, XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME, xCellStylesExportPropertySetMapper);
1970  if (pSharedData->HasShapes())
1971  {
1972  GetShapeExport()->ExportGraphicDefaults();
1973  }
1974  }
1975  collectDataStyles(false);
1976  }
1977  exportDataStyles();
1978 
1979  aStylesExp->exportStyleFamily(OUString("CellStyles"),
1980  OUString(XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME), xCellStylesExportPropertySetMapper, false, XmlStyleFamily::TABLE_CELL);
1981 
1983 }
1984 
1985 void ScXMLExport::AddStyleFromCells(const uno::Reference<beans::XPropertySet>& xProperties,
1986  const uno::Reference<sheet::XSpreadsheet>& xTable,
1987  sal_Int32 nTable, const OUString* pOldName)
1988 {
1989  css::uno::Any aAny = xProperties->getPropertyValue("FormatID");
1990  sal_uInt64 nKey = 0;
1991  aAny >>= nKey;
1992 
1994  uno::Reference<sheet::XSheetCellRanges> xCellRanges( xProperties, uno::UNO_QUERY );
1995 
1996  OUString sStyleName;
1997  sal_Int32 nNumberFormat(-1);
1998  sal_Int32 nValidationIndex(-1);
1999  std::vector< XMLPropertyState > aPropStates(xCellStylesExportPropertySetMapper->Filter( xProperties ));
2000  std::vector< XMLPropertyState >::iterator aItr(aPropStates.begin());
2001  std::vector< XMLPropertyState >::iterator aEndItr(aPropStates.end());
2002  sal_Int32 nCount(0);
2003  while (aItr != aEndItr)
2004  {
2005  if (aItr->mnIndex != -1)
2006  {
2007  switch (xCellStylesPropertySetMapper->GetEntryContextId(aItr->mnIndex))
2008  {
2009  case CTF_SC_VALIDATION :
2010  {
2011  pValidationsContainer->AddValidation(aItr->maValue, nValidationIndex);
2012  // this is not very slow, because it is most the last property or
2013  // if it is not the last property it is the property before the last property,
2014  // so in the worst case only one property has to be copied, but in the best case no
2015  // property has to be copied
2016  aItr = aPropStates.erase(aItr);
2017  aEndItr = aPropStates.end(); // old aEndItr is invalidated!
2018  }
2019  break;
2020  case CTF_SC_CELLSTYLE :
2021  {
2022  aItr->maValue >>= sStyleName;
2023  aItr->mnIndex = -1;
2024  ++aItr;
2025  ++nCount;
2026  }
2027  break;
2028  case CTF_SC_NUMBERFORMAT :
2029  {
2030  if (aItr->maValue >>= nNumberFormat)
2031  addDataStyle(nNumberFormat);
2032  ++aItr;
2033  ++nCount;
2034  }
2035  break;
2036  default:
2037  {
2038  ++aItr;
2039  ++nCount;
2040  }
2041  break;
2042  }
2043  }
2044  else
2045  {
2046  ++aItr;
2047  ++nCount;
2048  }
2049  }
2050  if (nCount == 1) // this is the CellStyle and should be removed if alone
2051  aPropStates.clear();
2052  if (nNumberFormat == -1)
2053  xProperties->getPropertyValue(SC_UNONAME_NUMFMT) >>= nNumberFormat;
2054  if (sStyleName.isEmpty())
2055  return;
2056 
2057  if (!aPropStates.empty())
2058  {
2059  sal_Int32 nIndex;
2060  if (pOldName)
2061  {
2062  if (GetAutoStylePool()->AddNamed(*pOldName, XmlStyleFamily::TABLE_CELL, sStyleName, aPropStates))
2063  {
2064  GetAutoStylePool()->RegisterName(XmlStyleFamily::TABLE_CELL, *pOldName);
2065  // add to pCellStyles, so the name is found for normal sheets
2066  pCellStyles->AddStyleName(*pOldName, nIndex);
2067  }
2068  }
2069  else
2070  {
2071  OUString sName;
2072  bool bAdded = false;
2073  if (nKey)
2074  {
2075  uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
2076  ScFormatSaveData* pFormatData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetFormatSaveData();
2077  auto itr = pFormatData->maIDToName.find(nKey);
2078  if (itr != pFormatData->maIDToName.end())
2079  {
2080  sName = itr->second;
2081  bAdded = GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TABLE_CELL, sStyleName, aPropStates);
2082  if (bAdded)
2083  GetAutoStylePool()->RegisterName(XmlStyleFamily::TABLE_CELL, sName);
2084  }
2085  }
2086  bool bIsAutoStyle(true);
2087  if (bAdded || GetAutoStylePool()->Add(sName, XmlStyleFamily::TABLE_CELL, sStyleName, aPropStates))
2088  {
2089  pCellStyles->AddStyleName(sName, nIndex);
2090  }
2091  else
2092  nIndex = pCellStyles->GetIndexOfStyleName(sName, XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX, bIsAutoStyle);
2093 
2094  const uno::Sequence<table::CellRangeAddress> aAddresses(xCellRanges->getRangeAddresses());
2095  bool bGetMerge(true);
2096  for (table::CellRangeAddress const & address : aAddresses)
2097  {
2098  pSharedData->SetLastColumn(nTable, address.EndColumn);
2099  pSharedData->SetLastRow(nTable, address.EndRow);
2100  pCellStyles->AddRangeStyleName(address, nIndex, bIsAutoStyle, nValidationIndex, nNumberFormat);
2101  if (bGetMerge)
2102  bGetMerge = GetMerged(&address, xTable);
2103  }
2104  }
2105  }
2106  else
2107  {
2108  OUString sEncodedStyleName(EncodeStyleName(sStyleName));
2109  sal_Int32 nIndex(0);
2110  pCellStyles->AddStyleName(sEncodedStyleName, nIndex, false);
2111  if ( !pOldName )
2112  {
2113  const uno::Sequence<table::CellRangeAddress> aAddresses(xCellRanges->getRangeAddresses());
2114  bool bGetMerge(true);
2115  for (table::CellRangeAddress const & address : aAddresses)
2116  {
2117  if (bGetMerge)
2118  bGetMerge = GetMerged(&address, xTable);
2119  pCellStyles->AddRangeStyleName(address, nIndex, false, nValidationIndex, nNumberFormat);
2120  if( sStyleName != "Default" || nValidationIndex != -1 )
2121  {
2122  pSharedData->SetLastColumn(nTable, address.EndColumn);
2123  pSharedData->SetLastRow(nTable, address.EndRow);
2124  }
2125  }
2126  }
2127  }
2128 }
2129 
2130 void ScXMLExport::AddStyleFromColumn(const uno::Reference<beans::XPropertySet>& xColumnProperties,
2131  const OUString* pOldName, sal_Int32& rIndex, bool& rIsVisible)
2132 {
2133  std::vector<XMLPropertyState> aPropStates(xColumnStylesExportPropertySetMapper->Filter(xColumnProperties));
2134  if(aPropStates.empty())
2135  return;
2136 
2137  auto aItr = std::find_if(aPropStates.begin(), aPropStates.end(),
2138  [this](const XMLPropertyState& rPropState) {
2139  return xColumnStylesPropertySetMapper->GetEntryContextId(rPropState.mnIndex) == CTF_SC_ISVISIBLE; });
2140  if (aItr != aPropStates.end())
2141  {
2142  aItr->maValue >>= rIsVisible;
2143  }
2144 
2145  const OUString sParent;
2146  if (pOldName)
2147  {
2148  if (GetAutoStylePool()->AddNamed(*pOldName, XmlStyleFamily::TABLE_COLUMN, sParent, aPropStates))
2149  {
2150  GetAutoStylePool()->RegisterName(XmlStyleFamily::TABLE_COLUMN, *pOldName);
2151  // add to pColumnStyles, so the name is found for normal sheets
2152  rIndex = pColumnStyles->AddStyleName(*pOldName);
2153  }
2154  }
2155  else
2156  {
2157  OUString sName;
2158  if (GetAutoStylePool()->Add(sName, XmlStyleFamily::TABLE_COLUMN, sParent, aPropStates))
2159  {
2160  rIndex = pColumnStyles->AddStyleName(sName);
2161  }
2162  else
2163  rIndex = pColumnStyles->GetIndexOfStyleName(sName, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_PREFIX);
2164  }
2165 }
2166 
2167 void ScXMLExport::AddStyleFromRow(const uno::Reference<beans::XPropertySet>& xRowProperties,
2168  const OUString* pOldName, sal_Int32& rIndex)
2169 {
2170  std::vector<XMLPropertyState> aPropStates(xRowStylesExportPropertySetMapper->Filter(xRowProperties));
2171  if(aPropStates.empty())
2172  return;
2173 
2174  const OUString sParent;
2175  if (pOldName)
2176  {
2177  if (GetAutoStylePool()->AddNamed(*pOldName, XmlStyleFamily::TABLE_ROW, sParent, aPropStates))
2178  {
2179  GetAutoStylePool()->RegisterName(XmlStyleFamily::TABLE_ROW, *pOldName);
2180  // add to pRowStyles, so the name is found for normal sheets
2181  rIndex = pRowStyles->AddStyleName(*pOldName);
2182  }
2183  }
2184  else
2185  {
2186  OUString sName;
2187  if (GetAutoStylePool()->Add(sName, XmlStyleFamily::TABLE_ROW, sParent, aPropStates))
2188  {
2189  rIndex = pRowStyles->AddStyleName(sName);
2190  }
2191  else
2192  rIndex = pRowStyles->GetIndexOfStyleName(sName, XML_STYLE_FAMILY_TABLE_ROW_STYLES_PREFIX);
2193  }
2194 }
2195 
2196 static uno::Any lcl_GetEnumerated( uno::Reference<container::XEnumerationAccess> const & xEnumAccess, sal_Int32 nIndex )
2197 {
2198  uno::Any aRet;
2199  uno::Reference<container::XEnumeration> xEnum( xEnumAccess->createEnumeration() );
2200  try
2201  {
2202  sal_Int32 nSkip = nIndex;
2203  while ( nSkip > 0 )
2204  {
2205  (void) xEnum->nextElement();
2206  --nSkip;
2207  }
2208  aRet = xEnum->nextElement();
2209  }
2210  catch (container::NoSuchElementException&)
2211  {
2212  // leave aRet empty
2213  }
2214  return aRet;
2215 }
2216 
2218 {
2220 
2222  return;
2223 
2224  if (!GetModel().is())
2225  return;
2226 
2227  uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
2228  if (!xSpreadDoc.is())
2229  return;
2230 
2231  uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
2232  if (!xIndex.is())
2233  return;
2234 
2235  if (getExportFlags() & SvXMLExportFlags::CONTENT)
2236  {
2237  // Reserve the loaded cell style names.
2238  RegisterDefinedStyleNames( xSpreadDoc);
2239 
2240  // re-create automatic styles with old names from stored data
2241  ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetSheetSaveData();
2242  if (pSheetData && pDoc)
2243  {
2244  // formulas have to be calculated now, to detect changed results
2245  // (during normal save, they will be calculated anyway)
2246  SCTAB nTabCount = pDoc->GetTableCount();
2247  for (SCTAB nTab=0; nTab<nTabCount; ++nTab)
2248  if (pDoc->IsStreamValid(nTab))
2249  pDoc->InterpretDirtyCells(ScRange(0, 0, nTab, pDoc->MaxCol(), pDoc->MaxRow(), nTab));
2250 
2251  // stored cell styles
2252  const std::vector<ScCellStyleEntry>& rCellEntries = pSheetData->GetCellStyles();
2253  for (const auto& rCellEntry : rCellEntries)
2254  {
2255  ScAddress aPos = rCellEntry.maCellPos;
2256  sal_Int32 nTable = aPos.Tab();
2257  bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2258  if (bCopySheet)
2259  {
2260  uno::Reference <sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2261  uno::Reference <beans::XPropertySet> xProperties(
2262  xTable->getCellByPosition( aPos.Col(), aPos.Row() ), uno::UNO_QUERY );
2263 
2264  AddStyleFromCells(xProperties, xTable, nTable, &rCellEntry.maName);
2265  }
2266  }
2267 
2268  // stored column styles
2269  const std::vector<ScCellStyleEntry>& rColumnEntries = pSheetData->GetColumnStyles();
2270  for (const auto& rColumnEntry : rColumnEntries)
2271  {
2272  ScAddress aPos = rColumnEntry.maCellPos;
2273  sal_Int32 nTable = aPos.Tab();
2274  bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2275  if (bCopySheet)
2276  {
2277  uno::Reference<table::XColumnRowRange> xColumnRowRange(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2278  uno::Reference<table::XTableColumns> xTableColumns(xColumnRowRange->getColumns());
2279  uno::Reference<beans::XPropertySet> xColumnProperties(xTableColumns->getByIndex( aPos.Col() ), uno::UNO_QUERY);
2280 
2281  sal_Int32 nIndex(-1);
2282  bool bIsVisible(true);
2283  AddStyleFromColumn( xColumnProperties, &rColumnEntry.maName, nIndex, bIsVisible );
2284  }
2285  }
2286 
2287  // stored row styles
2288  const std::vector<ScCellStyleEntry>& rRowEntries = pSheetData->GetRowStyles();
2289  for (const auto& rRowEntry : rRowEntries)
2290  {
2291  ScAddress aPos = rRowEntry.maCellPos;
2292  sal_Int32 nTable = aPos.Tab();
2293  bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2294  if (bCopySheet)
2295  {
2296  uno::Reference<table::XColumnRowRange> xColumnRowRange(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2297  uno::Reference<table::XTableRows> xTableRows(xColumnRowRange->getRows());
2298  uno::Reference<beans::XPropertySet> xRowProperties(xTableRows->getByIndex( aPos.Row() ), uno::UNO_QUERY);
2299 
2300  sal_Int32 nIndex(-1);
2301  AddStyleFromRow( xRowProperties, &rRowEntry.maName, nIndex );
2302  }
2303  }
2304 
2305  // stored table styles
2306  const std::vector<ScCellStyleEntry>& rTableEntries = pSheetData->GetTableStyles();
2307  for (const auto& rTableEntry : rTableEntries)
2308  {
2309  ScAddress aPos = rTableEntry.maCellPos;
2310  sal_Int32 nTable = aPos.Tab();
2311  bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2312  if (bCopySheet)
2313  {
2315  uno::Reference<beans::XPropertySet> xTableProperties(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2316  if (xTableProperties.is())
2317  {
2318  std::vector<XMLPropertyState> aPropStates(xTableStylesExportPropertySetMapper->Filter(xTableProperties));
2319  OUString sName( rTableEntry.maName );
2320  GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TABLE_TABLE, OUString(), aPropStates);
2321  GetAutoStylePool()->RegisterName(XmlStyleFamily::TABLE_TABLE, sName);
2322  }
2323  }
2324  }
2325 
2326  // stored styles for notes
2327 
2329  GetShapeExport(); // make sure the graphics styles family is added
2330 
2331  const std::vector<ScNoteStyleEntry>& rNoteEntries = pSheetData->GetNoteStyles();
2332  for (const auto& rNoteEntry : rNoteEntries)
2333  {
2334  ScAddress aPos = rNoteEntry.maCellPos;
2335  SCTAB nTable = aPos.Tab();
2336  bool bCopySheet = pDoc->IsStreamValid( nTable );
2337  if (bCopySheet)
2338  {
2340 
2341  ScPostIt* pNote = pDoc->GetNote(aPos);
2342  OSL_ENSURE( pNote, "note not found" );
2343  if (pNote)
2344  {
2345  SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
2346  // all uno shapes are created anyway in CollectSharedData
2347  uno::Reference<beans::XPropertySet> xShapeProperties( pDrawObj->getUnoShape(), uno::UNO_QUERY );
2348  if (xShapeProperties.is())
2349  {
2350  if ( !rNoteEntry.maStyleName.isEmpty() )
2351  {
2352  std::vector<XMLPropertyState> aPropStates(xShapeMapper->Filter(xShapeProperties));
2353  OUString sName( rNoteEntry.maStyleName );
2354  GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::SD_GRAPHICS_ID, OUString(), aPropStates);
2355  GetAutoStylePool()->RegisterName(XmlStyleFamily::SD_GRAPHICS_ID, sName);
2356  }
2357  if ( !rNoteEntry.maTextStyle.isEmpty() )
2358  {
2359  std::vector<XMLPropertyState> aPropStates(
2360  GetTextParagraphExport()->GetParagraphPropertyMapper()->Filter(xShapeProperties));
2361  OUString sName( rNoteEntry.maTextStyle );
2362  GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TEXT_PARAGRAPH, OUString(), aPropStates);
2363  GetAutoStylePool()->RegisterName(XmlStyleFamily::TEXT_PARAGRAPH, sName);
2364  }
2365  }
2366  }
2367  }
2368  }
2369 
2370  // note paragraph styles
2371 
2372  rtl::Reference<SvXMLExportPropertyMapper> xParaPropMapper = GetTextParagraphExport()->GetParagraphPropertyMapper();
2373 
2374  const std::vector<ScTextStyleEntry>& rNoteParaEntries = pSheetData->GetNoteParaStyles();
2375  for (const auto& rNoteParaEntry : rNoteParaEntries)
2376  {
2377  ScAddress aPos = rNoteParaEntry.maCellPos;
2378  SCTAB nTable = aPos.Tab();
2379  bool bCopySheet = pDoc->IsStreamValid( nTable );
2380  if (bCopySheet)
2381  {
2382  ScPostIt* pNote = pDoc->GetNote( aPos );
2383  OSL_ENSURE( pNote, "note not found" );
2384  if (pNote)
2385  {
2386  SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
2387  uno::Reference<container::XEnumerationAccess> xCellText(pDrawObj->getUnoShape(), uno::UNO_QUERY);
2388  uno::Reference<beans::XPropertySet> xParaProp(
2389  lcl_GetEnumerated( xCellText, rNoteParaEntry.maSelection.nStartPara ), uno::UNO_QUERY );
2390  if ( xParaProp.is() )
2391  {
2392  std::vector<XMLPropertyState> aPropStates(xParaPropMapper->Filter(xParaProp));
2393  OUString sName( rNoteParaEntry.maName );
2394  GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TEXT_PARAGRAPH, OUString(), aPropStates);
2395  GetAutoStylePool()->RegisterName(XmlStyleFamily::TEXT_PARAGRAPH, sName);
2396  }
2397  }
2398  }
2399  }
2400 
2401  // note text styles
2402 
2404 
2405  const std::vector<ScTextStyleEntry>& rNoteTextEntries = pSheetData->GetNoteTextStyles();
2406  for (const auto& rNoteTextEntry : rNoteTextEntries)
2407  {
2408  ScAddress aPos = rNoteTextEntry.maCellPos;
2409  SCTAB nTable = aPos.Tab();
2410  bool bCopySheet = pDoc->IsStreamValid( nTable );
2411  if (bCopySheet)
2412  {
2413  ScPostIt* pNote = pDoc->GetNote( aPos );
2414  OSL_ENSURE( pNote, "note not found" );
2415  if (pNote)
2416  {
2417  SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
2418  uno::Reference<text::XSimpleText> xCellText(pDrawObj->getUnoShape(), uno::UNO_QUERY);
2419  uno::Reference<beans::XPropertySet> xCursorProp(xCellText->createTextCursor(), uno::UNO_QUERY);
2420  ScDrawTextCursor* pCursor = comphelper::getUnoTunnelImplementation<ScDrawTextCursor>( xCursorProp );
2421  if (pCursor)
2422  {
2423  pCursor->SetSelection( rNoteTextEntry.maSelection );
2424 
2425  std::vector<XMLPropertyState> aPropStates(xTextPropMapper->Filter(xCursorProp));
2426  OUString sName( rNoteTextEntry.maName );
2427  GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TEXT_TEXT, OUString(), aPropStates);
2428  GetAutoStylePool()->RegisterName(XmlStyleFamily::TEXT_TEXT, sName);
2429  }
2430  }
2431  }
2432  }
2433 
2434  // stored text styles
2435 
2436  // Calling createTextCursor fires up editeng, which is very slow, and often subsequent style entries
2437  // refer to the same cell, so cache it.
2438  ScAddress aPrevPos;
2439  uno::Reference<beans::XPropertySet> xPrevCursorProp;
2440  const std::vector<ScTextStyleEntry>& rTextEntries = pSheetData->GetTextStyles();
2441  for (const auto& rTextEntry : rTextEntries)
2442  {
2443  ScAddress aPos = rTextEntry.maCellPos;
2444  sal_Int32 nTable = aPos.Tab();
2445  bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2446  if (!bCopySheet)
2447  continue;
2448 
2451 
2452  uno::Reference<beans::XPropertySet> xCursorProp;
2453  if (xPrevCursorProp && aPrevPos == aPos)
2454  xCursorProp = xPrevCursorProp;
2455  else
2456  {
2457  uno::Reference<table::XCellRange> xCellRange(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2458  uno::Reference<text::XSimpleText> xCellText(xCellRange->getCellByPosition(aPos.Col(), aPos.Row()), uno::UNO_QUERY);
2459  xCursorProp.set(xCellText->createTextCursor(), uno::UNO_QUERY);
2460  }
2461  ScCellTextCursor* pCursor = comphelper::getUnoTunnelImplementation<ScCellTextCursor>( xCursorProp );
2462  if (!pCursor)
2463  continue;
2464  pCursor->SetSelection( rTextEntry.maSelection );
2465 
2466  std::vector<XMLPropertyState> aPropStates(xTextPropMapper->Filter(xCursorProp));
2467  OUString sName( rTextEntry.maName );
2468  GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TEXT_TEXT, OUString(), aPropStates);
2469  GetAutoStylePool()->RegisterName(XmlStyleFamily::TEXT_TEXT, sName);
2470  xPrevCursorProp = xCursorProp;
2471  aPrevPos = aPos;
2472  }
2473  }
2474 
2476 
2477  if (!pSharedData)
2478  {
2479  SCTAB nTableCount(0);
2480  sal_Int32 nShapesCount(0);
2481  CollectSharedData(nTableCount, nShapesCount);
2482  }
2483  sal_Int32 nTableCount(xIndex->getCount());
2484  pCellStyles->AddNewTable(nTableCount - 1);
2485  CollectShapesAutoStyles(nTableCount);
2486  for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable, IncrementProgressBar(false))
2487  {
2488  uno::Reference <sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2489  if (!xTable.is())
2490  continue;
2491 
2492  // table styles array must be complete, including copied tables - Add should find the stored style
2493  uno::Reference<beans::XPropertySet> xTableProperties(xTable, uno::UNO_QUERY);
2494  if (xTableProperties.is())
2495  {
2496  std::vector<XMLPropertyState> aPropStates(xTableStylesExportPropertySetMapper->Filter(xTableProperties));
2497  if(!aPropStates.empty())
2498  {
2499  OUString sName;
2500  GetAutoStylePool()->Add(sName, XmlStyleFamily::TABLE_TABLE, OUString(), aPropStates);
2501  aTableStyles.push_back(sName);
2502  }
2503  }
2504 
2505  // collect other auto-styles only for non-copied sheets
2506  uno::Reference<sheet::XUniqueCellFormatRangesSupplier> xCellFormatRanges ( xTable, uno::UNO_QUERY );
2507  if ( xCellFormatRanges.is() )
2508  {
2509  uno::Reference<container::XIndexAccess> xFormatRangesIndex(xCellFormatRanges->getUniqueCellFormatRanges());
2510  if (xFormatRangesIndex.is())
2511  {
2512  sal_Int32 nFormatRangesCount(xFormatRangesIndex->getCount());
2513  GetProgressBarHelper()->ChangeReference(GetProgressBarHelper()->GetReference() + nFormatRangesCount);
2514  for (sal_Int32 nFormatRange = 0; nFormatRange < nFormatRangesCount; ++nFormatRange)
2515  {
2516  uno::Reference< sheet::XSheetCellRanges> xCellRanges(xFormatRangesIndex->getByIndex(nFormatRange), uno::UNO_QUERY);
2517  if (xCellRanges.is())
2518  {
2519  uno::Reference <beans::XPropertySet> xProperties (xCellRanges, uno::UNO_QUERY);
2520  if (xProperties.is())
2521  {
2522  AddStyleFromCells(xProperties, xTable, nTable, nullptr);
2523  IncrementProgressBar(false);
2524  }
2525  }
2526  }
2527  }
2528  }
2529  uno::Reference<table::XColumnRowRange> xColumnRowRange (xTable, uno::UNO_QUERY);
2530  if (xColumnRowRange.is() && pDoc)
2531  {
2532  pDoc->SyncColRowFlags();
2533  uno::Reference<table::XTableColumns> xTableColumns(xColumnRowRange->getColumns());
2534  if (xTableColumns.is())
2535  {
2536  sal_Int32 nColumns(pDoc->GetLastChangedCol(sal::static_int_cast<SCTAB>(nTable)));
2537  pSharedData->SetLastColumn(nTable, nColumns);
2538  table::CellRangeAddress aCellAddress(GetEndAddress(xTable));
2539  if (aCellAddress.EndColumn > nColumns)
2540  {
2541  ++nColumns;
2542  pColumnStyles->AddNewTable(nTable, aCellAddress.EndColumn);
2543  }
2544  else
2545  pColumnStyles->AddNewTable(nTable, nColumns);
2546  sal_Int32 nColumn = 0;
2547  while (nColumn <= pDoc->MaxCol())
2548  {
2549  sal_Int32 nIndex(-1);
2550  bool bIsVisible(true);
2551  uno::Reference <beans::XPropertySet> xColumnProperties(xTableColumns->getByIndex(nColumn), uno::UNO_QUERY);
2552  if (xColumnProperties.is())
2553  {
2554  AddStyleFromColumn( xColumnProperties, nullptr, nIndex, bIsVisible );
2555  pColumnStyles->AddFieldStyleName(nTable, nColumn, nIndex, bIsVisible);
2556  }
2557  sal_Int32 nOld(nColumn);
2558  nColumn = pDoc->GetNextDifferentChangedCol(sal::static_int_cast<SCTAB>(nTable), static_cast<SCCOL>(nColumn));
2559  for (sal_Int32 i = nOld + 1; i < nColumn; ++i)
2560  pColumnStyles->AddFieldStyleName(nTable, i, nIndex, bIsVisible);
2561  }
2562  if (aCellAddress.EndColumn > nColumns)
2563  {
2564  bool bIsVisible(true);
2565  sal_Int32 nIndex(pColumnStyles->GetStyleNameIndex(nTable, nColumns, bIsVisible));
2566  for (sal_Int32 i = nColumns + 1; i <= aCellAddress.EndColumn; ++i)
2567  pColumnStyles->AddFieldStyleName(nTable, i, nIndex, bIsVisible);
2568  }
2569  }
2570  uno::Reference<table::XTableRows> xTableRows(xColumnRowRange->getRows());
2571  if (xTableRows.is())
2572  {
2573  sal_Int32 nRows(pDoc->GetLastChangedRow(sal::static_int_cast<SCTAB>(nTable)));
2574  pSharedData->SetLastRow(nTable, nRows);
2575 
2576  pRowStyles->AddNewTable(nTable, pDoc->MaxRow());
2577  sal_Int32 nRow = 0;
2578  while (nRow <= pDoc->MaxRow())
2579  {
2580  sal_Int32 nIndex = 0;
2581  uno::Reference <beans::XPropertySet> xRowProperties(xTableRows->getByIndex(nRow), uno::UNO_QUERY);
2582  if(xRowProperties.is())
2583  {
2584  AddStyleFromRow( xRowProperties, nullptr, nIndex );
2585  pRowStyles->AddFieldStyleName(nTable, nRow, nIndex);
2586  }
2587  sal_Int32 nOld(nRow);
2588  nRow = pDoc->GetNextDifferentChangedRow(sal::static_int_cast<SCTAB>(nTable), static_cast<SCROW>(nRow));
2589  if (nRow > nOld + 1)
2590  pRowStyles->AddFieldStyleName(nTable, nOld + 1, nIndex, nRow - 1);
2591  }
2592  }
2593  }
2594  ExportCellTextAutoStyles(nTable);
2595  }
2596 
2597  pChangeTrackingExportHelper->CollectAutoStyles();
2598  }
2599 
2600  if (getExportFlags() & SvXMLExportFlags::MASTERSTYLES)
2601  GetPageExport()->collectAutoStyles(true);
2602 
2603  mbAutoStylesCollected = true;
2604 }
2605 
2607 {
2608  if (!GetModel().is())
2609  return;
2610 
2611  uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
2612  if (!xSpreadDoc.is())
2613  return;
2614 
2615  uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
2616  if (!xIndex.is())
2617  return;
2618 
2620 
2621  if (getExportFlags() & SvXMLExportFlags::CONTENT)
2622  {
2623  GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_COLUMN);
2624  GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_ROW);
2625  GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_TABLE);
2627  GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_CELL);
2628 
2629  GetShapeExport()->exportAutoStyles();
2630  GetFormExport()->exportAutoStyles( );
2631 
2632  if (pDoc)
2633  {
2635  // #i100879# write the table style for cached tables only if there are cached tables
2636  // (same logic as in ExportExternalRefCacheStyles)
2637  if (pRefMgr->hasExternalData())
2638  {
2639  // Special table style for the external ref cache tables.
2642  SvXMLElementExport aElemStyle(*this, XML_NAMESPACE_STYLE, XML_STYLE, true, true);
2644  SvXMLElementExport aElemStyleTabProps(*this, XML_NAMESPACE_STYLE, XML_TABLE_PROPERTIES, true, true);
2645  }
2646  }
2647  }
2648 
2649  if (getExportFlags() & SvXMLExportFlags::MASTERSTYLES)
2650  {
2652  GetPageExport()->exportAutoStyles();
2653  }
2654 
2655  // #i30251#; only write Text Styles once
2656 
2657  if ((getExportFlags() & SvXMLExportFlags::CONTENT) || (getExportFlags() & SvXMLExportFlags::MASTERSTYLES))
2658  GetTextParagraphExport()->exportTextAutoStyles();
2659 }
2660 
2662 {
2663  GetPageExport()->exportMasterStyles( true );
2664 }
2665 
2666 void ScXMLExport::CollectInternalShape( uno::Reference< drawing::XShape > const & xShape )
2667 {
2668  // detective objects and notes
2669  SvxShape* pShapeImp = comphelper::getUnoTunnelImplementation<SvxShape>( xShape );
2670  if( !pShapeImp )
2671  return;
2672 
2673  SdrObject* pObject = pShapeImp->GetSdrObject();
2674  if( !pObject )
2675  return;
2676 
2677  // collect note caption objects from all layers (internal or hidden)
2678  if( ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( pObject, static_cast< SCTAB >( nCurrentTable ) ) )
2679  {
2680  if(pDoc->GetNote(pCaptData->maStart))
2681  {
2682  pSharedData->AddNoteObj( xShape, pCaptData->maStart );
2683 
2684  // #i60851# When the file is saved while editing a new note,
2685  // the cell is still empty -> last column/row must be updated
2686  OSL_ENSURE( pCaptData->maStart.Tab() == nCurrentTable, "invalid table in object data" );
2687  pSharedData->SetLastColumn( nCurrentTable, pCaptData->maStart.Col() );
2688  pSharedData->SetLastRow( nCurrentTable, pCaptData->maStart.Row() );
2689  }
2690  }
2691  // other objects from internal layer only (detective)
2692  else if( pObject->GetLayer() == SC_LAYER_INTERN )
2693  {
2694  ScDetectiveFunc aDetFunc( *pDoc, static_cast<SCTAB>(nCurrentTable) );
2695  ScAddress aPosition;
2696  ScRange aSourceRange;
2697  bool bRedLine;
2698  ScDetectiveObjType eObjType = aDetFunc.GetDetectiveObjectType(
2699  pObject, nCurrentTable, aPosition, aSourceRange, bRedLine );
2700  pSharedData->GetDetectiveObjContainer()->AddObject( eObjType, static_cast<SCTAB>(nCurrentTable), aPosition, aSourceRange, bRedLine );
2701  }
2702 }
2703 
2704 bool ScXMLExport::GetMerged (const table::CellRangeAddress* pCellAddress,
2705  const uno::Reference <sheet::XSpreadsheet>& xTable)
2706 {
2707  bool bReady(false);
2708  sal_Int32 nRow(pCellAddress->StartRow);
2709  sal_Int32 nCol(pCellAddress->StartColumn);
2710  sal_Int32 nEndRow(pCellAddress->EndRow);
2711  sal_Int32 nEndCol(pCellAddress->EndColumn);
2712  bool bRowInc(nEndRow > nRow);
2713  while(!bReady && nRow <= nEndRow && nCol <= nEndCol)
2714  {
2715  uno::Reference<sheet::XSheetCellRange> xSheetCellRange(xTable->getCellRangeByPosition(nCol, nRow, nCol, nRow), uno::UNO_QUERY);
2716  if (xSheetCellRange.is())
2717  {
2718  uno::Reference<sheet::XSheetCellCursor> xCursor(xTable->createCursorByRange(xSheetCellRange));
2719  if(xCursor.is())
2720  {
2721  uno::Reference<sheet::XCellRangeAddressable> xCellAddress (xCursor, uno::UNO_QUERY);
2722  xCursor->collapseToMergedArea();
2723  table::CellRangeAddress aCellAddress2(xCellAddress->getRangeAddress());
2724  ScRange aScRange( aCellAddress2.StartColumn, aCellAddress2.StartRow, aCellAddress2.Sheet,
2725  aCellAddress2.EndColumn, aCellAddress2.EndRow, aCellAddress2.Sheet );
2726 
2727  if ((aScRange.aEnd.Row() > nRow ||
2728  aScRange.aEnd.Col() > nCol) &&
2729  aScRange.aStart.Row() == nRow &&
2730  aScRange.aStart.Col() == nCol)
2731  {
2732  pMergedRangesContainer->AddRange(aScRange);
2733  pSharedData->SetLastColumn(aScRange.aEnd.Tab(), aScRange.aEnd.Col());
2734  pSharedData->SetLastRow(aScRange.aEnd.Tab(), aScRange.aEnd.Row());
2735  }
2736  else
2737  bReady = true;
2738  }
2739  }
2740  if (!bReady)
2741  {
2742  if (bRowInc)
2743  ++nRow;
2744  else
2745  ++nCol;
2746  }
2747  }
2748  OSL_ENSURE(!(!bReady && nEndRow > nRow && nEndCol > nCol), "should not be possible");
2749  return !bReady;
2750 }
2751 
2753  ScRange& aCellAddress, bool& bIsFirst) const
2754 {
2755  bIsFirst = false;
2756 
2757  ScRange aMatrixRange;
2758 
2759  if (pDoc && pDoc->GetMatrixFormulaRange(aCell, aMatrixRange))
2760  {
2761  aCellAddress = aMatrixRange;
2762  if ((aCellAddress.aStart.Col() == aCell.Col() && aCellAddress.aStart.Row() == aCell.Row()) &&
2763  (aCellAddress.aEnd.Col() > aCell.Col() || aCellAddress.aEnd.Row() > aCell.Row()))
2764  {
2765  bIsFirst = true;
2766  return true;
2767  }
2768  else if (aCellAddress.aStart.Col() != aCell.Col() || aCellAddress.aStart.Row() != aCell.Row() ||
2769  aCellAddress.aEnd.Col() != aCell.Col() || aCellAddress.aEnd.Row()!= aCell.Row())
2770  return true;
2771  else
2772  {
2773  bIsFirst = true;
2774  return true;
2775  }
2776  }
2777 
2778  return false;
2779 }
2780 
2781 void ScXMLExport::WriteTable(sal_Int32 nTable, const uno::Reference<sheet::XSpreadsheet>& xTable)
2782 {
2783  if (!xTable.is())
2784  return;
2785 
2786  xCurrentTable.set(xTable);
2787  uno::Reference<container::XNamed> xName (xTable, uno::UNO_QUERY );
2788  if (!xName.is())
2789  return;
2790 
2791  nCurrentTable = sal::static_int_cast<sal_uInt16>( nTable );
2792  OUString sOUTableName(xName->getName());
2793  AddAttribute(sAttrName, sOUTableName);
2795 
2796  uno::Reference<util::XProtectable> xProtectable (xTable, uno::UNO_QUERY);
2797  ScTableProtection* pProtect = nullptr;
2798  if (xProtectable.is() && xProtectable->isProtected())
2799  {
2801  if (pDoc)
2802  {
2803  pProtect = pDoc->GetTabProtection(nTable);
2804  if (pProtect)
2805  {
2806  OUStringBuffer aBuffer;
2808  if (pProtect->hasPasswordHash(PASSHASH_SHA1))
2809  {
2811  pProtect->getPasswordHash(PASSHASH_SHA1));
2812  eHashUsed = PASSHASH_SHA1;
2813  }
2814  else if (pProtect->hasPasswordHash(PASSHASH_SHA256))
2815  {
2817  pProtect->getPasswordHash(PASSHASH_SHA256));
2818  eHashUsed = PASSHASH_SHA256;
2819  }
2820  else if (pProtect->hasPasswordHash(PASSHASH_XL, PASSHASH_SHA1))
2821  {
2822  // Double-hash this by SHA1 on top of the legacy xls hash.
2823  uno::Sequence<sal_Int8> aHash = pProtect->getPasswordHash(PASSHASH_XL, PASSHASH_SHA1);
2824  ::comphelper::Base64::encode(aBuffer, aHash);
2825  eHashUsed = PASSHASH_XL;
2826  }
2827  if (!aBuffer.isEmpty())
2828  {
2829  AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
2831  {
2832  if (eHashUsed == PASSHASH_XL)
2833  {
2839  }
2840  else if (eHashUsed == PASSHASH_SHA1)
2841  {
2844  }
2845  else if (eHashUsed == PASSHASH_SHA256)
2846  {
2849  }
2850  }
2851  }
2852  }
2853  }
2854  }
2855  OUString sPrintRanges;
2856  ScRange aColumnHeaderRange;
2857  bool bHasColumnHeader;
2858  GetColumnRowHeader(bHasColumnHeader, aColumnHeaderRange, bHasRowHeader, aRowHeaderRange, sPrintRanges);
2859  if( !sPrintRanges.isEmpty() )
2861  else if (pDoc && !pDoc->IsPrintEntireSheet(static_cast<SCTAB>(nTable)))
2863  SvXMLElementExport aElemT(*this, sElemTab, true, true);
2864 
2865  if (pProtect && pProtect->isProtected() && getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2866  {
2871 
2876 
2881 
2882  OUString aElemName = GetNamespaceMap().GetQNameByKey(
2884 
2885  SvXMLElementExport aElemProtected(*this, aElemName, true, true);
2886  }
2887 
2888  CheckAttrList();
2889 
2890  if ( pDoc && pDoc->GetSheetEvents( static_cast<SCTAB>(nTable) ) &&
2892  {
2893  // store sheet events
2894  uno::Reference<document::XEventsSupplier> xSupplier(xTable, uno::UNO_QUERY);
2895  uno::Reference<container::XNameAccess> xEvents = xSupplier->getEvents();
2896  GetEventExport().ExportExt( xEvents );
2897  }
2898 
2899  WriteTableSource();
2900  WriteScenario();
2901  uno::Reference<drawing::XDrawPage> xDrawPage;
2902  if (pSharedData->HasForm(nTable, xDrawPage) && xDrawPage.is())
2903  {
2904  ::xmloff::OOfficeFormsExport aForms(*this);
2905  GetFormExport()->exportForms( xDrawPage );
2906  bool bRet(GetFormExport()->seekPage( xDrawPage ));
2907  OSL_ENSURE( bRet, "OFormLayerXMLExport::seekPage failed!" );
2908  }
2909  if (pSharedData->HasDrawPage())
2910  {
2911  GetShapeExport()->seekShapes(pSharedData->GetDrawPage(nTable));
2912  WriteTableShapes();
2913  }
2914  table::CellRangeAddress aRange(GetEndAddress(xTable));
2915  pSharedData->SetLastColumn(nTable, aRange.EndColumn);
2916  pSharedData->SetLastRow(nTable, aRange.EndRow);
2917  mpCellsItr->SetCurrentTable(static_cast<SCTAB>(nTable), xCurrentTable);
2918  pGroupColumns->NewTable();
2919  pGroupRows->NewTable();
2921  if (bHasColumnHeader)
2922  pSharedData->SetLastColumn(nTable, aColumnHeaderRange.aEnd.Col());
2923  bRowHeaderOpen = false;
2924  if (bHasRowHeader)
2925  pSharedData->SetLastRow(nTable, aRowHeaderRange.aEnd.Row());
2926  pDefaults->FillDefaultStyles(nTable, pSharedData->GetLastRow(nTable),
2927  pSharedData->GetLastColumn(nTable), pCellStyles.get(), pDoc);
2928  pRowFormatRanges->SetColDefaults(&pDefaults->GetColDefaults());
2929  pCellStyles->SetColDefaults(&pDefaults->GetColDefaults());
2930  ExportColumns(nTable, aColumnHeaderRange, bHasColumnHeader);
2931  bool bIsFirst(true);
2932  sal_Int32 nEqualCells(0);
2933  ScMyCell aCell;
2934  ScMyCell aPrevCell;
2935  while (mpCellsItr->GetNext(aCell, pCellStyles.get()))
2936  {
2937  if (bIsFirst)
2938  {
2939  ExportFormatRanges(0, 0, aCell.maCellAddress.Col()-1, aCell.maCellAddress.Row(), nTable);
2940  aPrevCell = aCell;
2941  bIsFirst = false;
2942  }
2943  else
2944  {
2945  if ((aPrevCell.maCellAddress.Row() == aCell.maCellAddress.Row()) &&
2946  (aPrevCell.maCellAddress.Col() + nEqualCells + 1 == aCell.maCellAddress.Col()))
2947  {
2948  if(IsCellEqual(aPrevCell, aCell))
2949  ++nEqualCells;
2950  else
2951  {
2952  WriteCell(aPrevCell, nEqualCells);
2953  nEqualCells = 0;
2954  aPrevCell = aCell;
2955  }
2956  }
2957  else
2958  {
2959  WriteCell(aPrevCell, nEqualCells);
2960  ExportFormatRanges(aPrevCell.maCellAddress.Col() + nEqualCells + 1, aPrevCell.maCellAddress.Row(),
2961  aCell.maCellAddress.Col()-1, aCell.maCellAddress.Row(), nTable);
2962  nEqualCells = 0;
2963  aPrevCell = aCell;
2964  }
2965  }
2966  }
2967  if (!bIsFirst)
2968  {
2969  WriteCell(aPrevCell, nEqualCells);
2970  ExportFormatRanges(aPrevCell.maCellAddress.Col() + nEqualCells + 1, aPrevCell.maCellAddress.Row(),
2971  pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
2972  }
2973  else
2974  ExportFormatRanges(0, 0, pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
2975 
2976  CloseRow(pSharedData->GetLastRow(nTable));
2977 
2978  if (!pDoc)
2979  return;
2980 
2981  // Export sheet-local named ranges.
2982  ScRangeName* pRangeName = pDoc->GetRangeName(nTable);
2983  if (pRangeName && !pRangeName->empty())
2984  {
2985  WriteNamedRange(pRangeName);
2986  }
2987 
2989  {
2990  //export new conditional format information
2991  ExportConditionalFormat(nTable);
2992  }
2993 }
2994 
2995 namespace {
2996 
2997 void writeContent(
2998  ScXMLExport& rExport, const OUString& rStyleName, const OUString& rContent, const SvxFieldData* pField )
2999 {
3000  std::unique_ptr<SvXMLElementExport> pElem;
3001  if (!rStyleName.isEmpty())
3002  {
3003  // Formatted section with automatic style.
3004  rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME, rStyleName);
3005  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3006  XML_NAMESPACE_TEXT, GetXMLToken(XML_SPAN));
3007  pElem.reset(new SvXMLElementExport(rExport, aElemName, false, false));
3008  }
3009 
3010  if (pField)
3011  {
3012  // Write a field item.
3013  OUString aFieldVal = ScEditUtil::GetCellFieldValue(*pField, rExport.GetDocument(), nullptr);
3014  switch (pField->GetClassId())
3015  {
3016  case text::textfield::Type::URL:
3017  {
3018  // <text:a xlink:href="url" xlink:type="simple">value</text:a>
3019 
3020  const SvxURLField* pURLField = static_cast<const SvxURLField*>(pField);
3021  const OUString& aURL = pURLField->GetURL();
3022  rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, rExport.GetRelativeReference(aURL));
3023  rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, "simple");
3024  const OUString& aTargetFrame = pURLField->GetTargetFrame();
3025  if (!aTargetFrame.isEmpty())
3026  rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_TARGET_FRAME_NAME, aTargetFrame);
3027 
3028  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3029  XML_NAMESPACE_TEXT, GetXMLToken(XML_A));
3030  SvXMLElementExport aElem(rExport, aElemName, false, false);
3031  rExport.Characters(aFieldVal);
3032  }
3033  break;
3035  {
3036  // <text:date style:data-style-name="N2" text:date-value="YYYY-MM-DD">value</text:date>
3037 
3038  Date aDate(Date::SYSTEM);
3039  OUStringBuffer aBuf;
3040  sal_Int32 nVal = aDate.GetYear();
3041  aBuf.append(nVal);
3042  aBuf.append('-');
3043  nVal = aDate.GetMonth();
3044  if (nVal < 10)
3045  aBuf.append('0');
3046  aBuf.append(nVal);
3047  aBuf.append('-');
3048  nVal = aDate.GetDay();
3049  if (nVal < 10)
3050  aBuf.append('0');
3051  aBuf.append(nVal);
3052  rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_DATA_STYLE_NAME, "N2");
3053  rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_DATE_VALUE, aBuf.makeStringAndClear());
3054 
3055  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3056  XML_NAMESPACE_TEXT, GetXMLToken(XML_DATE));
3057  SvXMLElementExport aElem(rExport, aElemName, false, false);
3058  rExport.Characters(aFieldVal);
3059  }
3060  break;
3061  case text::textfield::Type::DOCINFO_TITLE:
3062  {
3063  // <text:title>value</text:title>
3064 
3065  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3066  XML_NAMESPACE_TEXT, GetXMLToken(XML_TITLE));
3067  SvXMLElementExport aElem(rExport, aElemName, false, false);
3068  rExport.Characters(aFieldVal);
3069  }
3070  break;
3072  {
3073  // <text:sheet-name>value</text:sheet-name>
3074 
3075  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3076  XML_NAMESPACE_TEXT, GetXMLToken(XML_SHEET_NAME));
3077  SvXMLElementExport aElem(rExport, aElemName, false, false);
3078  rExport.Characters(aFieldVal);
3079  }
3080  break;
3081  default:
3082  rExport.Characters(aFieldVal);
3083  }
3084  }
3085  else
3086  rExport.Characters(rContent);
3087 }
3088 
3089 void flushParagraph(
3090  ScXMLExport& rExport, const OUString& rParaText,
3092  const ScXMLEditAttributeMap& rAttrMap,
3093  std::vector<editeng::Section>::const_iterator it, std::vector<editeng::Section>::const_iterator const & itEnd )
3094 {
3095  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3096  XML_NAMESPACE_TEXT, GetXMLToken(XML_P));
3097  SvXMLElementExport aElemP(rExport, aElemName, false, false);
3098 
3099  for (; it != itEnd; ++it)
3100  {
3101  const editeng::Section& rSec = *it;
3102 
3103  OUString aContent(rParaText.copy(rSec.mnStart, rSec.mnEnd - rSec.mnStart));
3104 
3105  std::vector<XMLPropertyState> aPropStates;
3106  const SvxFieldData* pField = toXMLPropertyStates(aPropStates, rSec.maAttributes, xMapper, rAttrMap);
3107  OUString aStyleName = xStylePool->Find(XmlStyleFamily::TEXT_TEXT, OUString(), aPropStates);
3108  writeContent(rExport, aStyleName, aContent, pField);
3109  }
3110 }
3111 
3112 }
3113 
3114 void ScXMLExport::WriteCell(ScMyCell& aCell, sal_Int32 nEqualCellCount)
3115 {
3116  // nEqualCellCount is the number of additional cells
3117  SetRepeatAttribute(nEqualCellCount, (aCell.nType != table::CellContentType_EMPTY));
3118 
3119  if (aCell.nStyleIndex != -1)
3120  AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(aCell.nStyleIndex, aCell.bIsAutoStyle));
3121  if (aCell.nValidationIndex > -1)
3123  const bool bIsFirstMatrixCell(aCell.bIsMatrixBase);
3124  if (bIsFirstMatrixCell)
3125  {
3126  SCCOL nColumns( aCell.aMatrixRange.aEnd.Col() - aCell.aMatrixRange.aStart.Col() + 1 );
3127  SCROW nRows( aCell.aMatrixRange.aEnd.Row() - aCell.aMatrixRange.aStart.Row() + 1 );
3130  }
3131  bool bIsEmpty(false);
3132  switch (aCell.nType)
3133  {
3134  case table::CellContentType_EMPTY :
3135  {
3136  bIsEmpty = true;
3137  }
3138  break;
3139  case table::CellContentType_VALUE :
3140  {
3142  aCell.nNumberFormat, aCell.maBaseCell.mfValue);
3145  aCell.nNumberFormat, aCell.maBaseCell.mfValue, false, XML_NAMESPACE_CALC_EXT, false);
3146  }
3147  break;
3148  case table::CellContentType_TEXT :
3149  {
3150  OUString sFormattedString(lcl_GetFormattedString(pDoc, aCell.maBaseCell, aCell.maCellAddress));
3151  OUString sCellString = aCell.maBaseCell.getString(pDoc);
3153  sCellString, sFormattedString);
3156  sCellString, sFormattedString, false, XML_NAMESPACE_CALC_EXT);
3157  }
3158  break;
3159  case table::CellContentType_FORMULA :
3160  {
3161  if (aCell.maBaseCell.meType == CELLTYPE_FORMULA)
3162  {
3163  const bool bIsMatrix(bIsFirstMatrixCell || aCell.bIsMatrixCovered);
3164  ScFormulaCell* pFormulaCell = aCell.maBaseCell.mpFormula;
3165  if (!bIsMatrix || bIsFirstMatrixCell)
3166  {
3167  if (!mpCompileFormulaCxt)
3168  {
3170  mpCompileFormulaCxt.reset(new sc::CompileFormulaContext(*pDoc, eGrammar));
3171  }
3172 
3173  OUString aFormula = pFormulaCell->GetFormula(*mpCompileFormulaCxt);
3174  sal_uInt16 nNamespacePrefix =
3176 
3177  if (!bIsMatrix)
3178  {
3179  AddAttribute(sAttrFormula, GetNamespaceMap().GetQNameByKey(nNamespacePrefix, aFormula, false));
3180  }
3181  else
3182  {
3183  AddAttribute(sAttrFormula, GetNamespaceMap().GetQNameByKey(nNamespacePrefix, aFormula.copy(1, aFormula.getLength()-2), false));
3184  }
3185  }
3186  if (pFormulaCell->GetErrCode() != FormulaError::NONE)
3187  {
3191  {
3192  //export calcext:value-type="error"
3194  }
3195  }
3196  else if (pFormulaCell->IsValue())
3197  {
3198  bool bIsStandard;
3199  OUString sCurrency;
3200  GetNumberFormatAttributesExportHelper()->GetCellType(aCell.nNumberFormat, sCurrency, bIsStandard);
3201  if (pDoc)
3202  {
3204  aCell.nNumberFormat, pDoc->GetValue(aCell.maCellAddress));
3206  {
3208  aCell.nNumberFormat, pDoc->GetValue(aCell.maCellAddress), false, XML_NAMESPACE_CALC_EXT, false );
3209  }
3210  }
3211  }
3212  else
3213  {
3214  if (!aCell.maBaseCell.getString(pDoc).isEmpty())
3215  {
3219  {
3221  }
3222  }
3223  }
3224  }
3225  }
3226  break;
3227  default:
3228  break;
3229  }
3230  OUString* pCellString(&sElemCell);
3231  if (aCell.bIsCovered)
3232  {
3233  pCellString = &sElemCoveredCell;
3234  }
3235  else
3236  {
3237  if (aCell.bIsMergedBase)
3238  {
3239  SCCOL nColumns( aCell.aMergeRange.aEnd.Col() - aCell.aMergeRange.aStart.Col() + 1 );
3240  SCROW nRows( aCell.aMergeRange.aEnd.Row() - aCell.aMergeRange.aStart.Row() + 1 );
3241  AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED, OUString::number(nColumns));
3242  AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED, OUString::number(nRows));
3243  }
3244  }
3245  SvXMLElementExport aElemC(*this, *pCellString, true, true);
3246  CheckAttrList();
3247  WriteAreaLink(aCell);
3248  WriteAnnotation(aCell);
3249  WriteDetective(aCell);
3250 
3251  if (!bIsEmpty)
3252  {
3253  if (aCell.maBaseCell.meType == CELLTYPE_EDIT)
3254  {
3256  }
3258  {
3260  }
3261  else
3262  {
3263  SvXMLElementExport aElemP(*this, sElemP, true, false);
3264 
3265  OUString aParaStr =
3267 
3268  bool bPrevCharWasSpace = true;
3269  GetTextParagraphExport()->exportCharacterData(aParaStr, bPrevCharWasSpace);
3270  }
3271  }
3272  WriteShapes(aCell);
3273  if (!bIsEmpty)
3274  IncrementProgressBar(false);
3275 }
3276 
3278 {
3279  rtl::Reference<XMLPropertySetMapper> xMapper = GetTextParagraphExport()->GetTextPropMapper()->getPropertySetMapper();
3281  const ScXMLEditAttributeMap& rAttrMap = GetEditAttributeMap();
3282 
3283  // Get raw paragraph texts first.
3284  std::vector<OUString> aParaTexts;
3285  sal_Int32 nParaCount = pText->GetParagraphCount();
3286  aParaTexts.reserve(nParaCount);
3287  for (sal_Int32 i = 0; i < nParaCount; ++i)
3288  aParaTexts.push_back(pText->GetText(i));
3289 
3290  // Get all section data and iterate through them.
3291  std::vector<editeng::Section> aAttrs;
3292  pText->GetAllSections(aAttrs);
3293  std::vector<editeng::Section>::const_iterator itSec = aAttrs.begin(), itSecEnd = aAttrs.end();
3294  std::vector<editeng::Section>::const_iterator itPara = itSec;
3295  sal_Int32 nCurPara = 0; // current paragraph
3296  for (; itSec != itSecEnd; ++itSec)
3297  {
3298  const editeng::Section& rSec = *itSec;
3299  if (nCurPara == rSec.mnParagraph)
3300  // Still in the same paragraph.
3301  continue;
3302 
3303  // Start of a new paragraph. Flush the old paragraph.
3304  flushParagraph(*this, aParaTexts[nCurPara], xMapper, xStylePool, rAttrMap, itPara, itSec);
3305  nCurPara = rSec.mnParagraph;
3306  itPara = itSec;
3307  }
3308 
3309  flushParagraph(*this, aParaTexts[nCurPara], xMapper, xStylePool, rAttrMap, itPara, itSecEnd);
3310 }
3311 
3313 {
3315 
3316  OUString aResStr = pCell->GetResultString().getString();
3317  const sal_Unicode* p = aResStr.getStr();
3318  const sal_Unicode* pEnd = p + static_cast<size_t>(aResStr.getLength());
3319  const sal_Unicode* pPara = p; // paragraph head.
3320  for (; p != pEnd; ++p)
3321  {
3322  if (*p != '\n')
3323  continue;
3324 
3325  // flush the paragraph.
3326  OUString aContent;
3327  if (*pPara == '\n')
3328  ++pPara;
3329  if (p > pPara)
3330  aContent = OUString(pPara, p-pPara);
3331 
3332  SvXMLElementExport aElem(*this, aElemName, false, false);
3333  Characters(aContent);
3334 
3335  pPara = p;
3336  }
3337 
3338  OUString aContent;
3339  if (*pPara == '\n')
3340  ++pPara;
3341  if (pEnd > pPara)
3342  aContent = OUString(pPara, pEnd-pPara);
3343 
3344  SvXMLElementExport aElem(*this, aElemName, false, false);
3345  Characters(aContent);
3346 }
3347 
3348 void ScXMLExport::ExportShape(const uno::Reference < drawing::XShape >& xShape, awt::Point* pPoint)
3349 {
3350  uno::Reference < beans::XPropertySet > xShapeProps ( xShape, uno::UNO_QUERY );
3351  bool bIsChart( false );
3352  if (xShapeProps.is())
3353  {
3354  sal_Int32 nZOrder = 0;
3355  if (xShapeProps->getPropertyValue("ZOrder") >>= nZOrder)
3356  {
3357  AddAttribute(XML_NAMESPACE_DRAW, XML_ZINDEX, OUString::number(nZOrder));
3358  }
3359  uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xShapeProps->getPropertySetInfo();
3360  OUString sPropCLSID ("CLSID");
3361  if( xPropSetInfo->hasPropertyByName( sPropCLSID ) )
3362  {
3363  OUString sCLSID;
3364  if (xShapeProps->getPropertyValue( sPropCLSID ) >>= sCLSID)
3365  {
3366  if ( sCLSID.equalsIgnoreAsciiCase(GetChartExport()->getChartCLSID()) )
3367  {
3368  // we have a chart
3369  OUString sRanges;
3370  if ( pDoc )
3371  {
3372  OUString aChartName;
3373  xShapeProps->getPropertyValue( "PersistName" ) >>= aChartName;
3375  if (pCollection)
3376  {
3377  ScChartListener* pListener = pCollection->findByName(aChartName);
3378  if (pListener)
3379  {
3380  const ScRangeListRef& rRangeList = pListener->GetRangeList();
3381  if ( rRangeList.is() )
3382  {
3383  ScRangeStringConverter::GetStringFromRangeList( sRanges, rRangeList.get(), pDoc, FormulaGrammar::CONV_OOO );
3384  if ( !sRanges.isEmpty() )
3385  {
3386  bIsChart = true;
3387  SvXMLAttributeList* pAttrList = new SvXMLAttributeList();
3388  pAttrList->AddAttribute(
3390  GetShapeExport()->exportShape( xShape, SEF_DEFAULT, pPoint, pAttrList );
3391  }
3392  }
3393  }
3394  }
3395  }
3396 
3397  if ( sRanges.isEmpty() )
3398  {
3399  uno::Reference< frame::XModel > xChartModel;
3400  if( ( xShapeProps->getPropertyValue( "Model" ) >>= xChartModel ) &&
3401  xChartModel.is())
3402  {
3403  uno::Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY );
3404  uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartModel, uno::UNO_QUERY );
3405  if( xChartDoc.is() && xReceiver.is() &&
3406  ! xChartDoc->hasInternalDataProvider())
3407  {
3408  // we have a chart that gets its data from Calc
3409  bIsChart = true;
3410  uno::Sequence< OUString > aRepresentations(
3411  xReceiver->getUsedRangeRepresentations());
3412  SvXMLAttributeList* pAttrList = nullptr;
3413  if(aRepresentations.hasElements())
3414  {
3415  // add the ranges used by the chart to the shape
3416  // element to be able to start listening after
3417  // load (when the chart is not yet loaded)
3418  uno::Reference< chart2::data::XRangeXMLConversion > xRangeConverter( xChartDoc->getDataProvider(), uno::UNO_QUERY );
3419  sRanges = lcl_RangeSequenceToString( aRepresentations, xRangeConverter );
3420  pAttrList = new SvXMLAttributeList();
3421  pAttrList->AddAttribute(
3423  }
3424  GetShapeExport()->exportShape(xShape, SEF_DEFAULT, pPoint, pAttrList);
3425  }
3426  }
3427  }
3428  }
3429  }
3430  }
3431  }
3432  if (!bIsChart)
3433  {
3434  OUString sHlink;
3435  try
3436  {
3437  uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );
3438  if ( xProps.is() )
3439  xProps->getPropertyValue( SC_UNONAME_HYPERLINK ) >>= sHlink;
3440  }
3441  catch ( const beans::UnknownPropertyException& )
3442  {
3443  // no hyperlink property
3444  }
3445 
3446  std::unique_ptr< SvXMLElementExport > pDrawA;
3447  // enclose shapes with <draw:a> element only if sHlink contains something
3448  if ( !sHlink.isEmpty() )
3449  {
3450  // need to get delete the attributes that are pre-loaded
3451  // for the shape export ( otherwise they will become
3452  // attributes of the draw:a element ) This *shouldn't*
3453  // affect performance adversely as there are only a
3454  // couple of attributes involved
3455  uno::Reference< xml::sax::XAttributeList > xSaveAttribs( new SvXMLAttributeList( GetAttrList() ) );
3456  ClearAttrList();
3457  // Add Hlink
3460  pDrawA.reset( new SvXMLElementExport( *this, XML_NAMESPACE_DRAW, XML_A, false, false ) );
3461  // Attribute list has been cleared by previous operation
3462  // re-add pre-loaded attributes
3463  AddAttributeList( xSaveAttribs );
3464  }
3465  GetShapeExport()->exportShape(xShape, SEF_DEFAULT, pPoint);
3466  }
3467  IncrementProgressBar(false);
3468 }
3469 
3471 {
3472  if( !(rMyCell.bHasShape && !rMyCell.aShapeList.empty() && pDoc) )
3473  return;
3474 
3475  awt::Point aPoint;
3476  tools::Rectangle aRect = pDoc->GetMMRect(rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(),
3477  rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(), rMyCell.maCellAddress.Tab());
3478  bool bNegativePage = pDoc->IsNegativePage(rMyCell.maCellAddress.Tab());
3479  if (bNegativePage)
3480  aPoint.X = aRect.Right();
3481  else
3482  aPoint.X = aRect.Left();
3483  aPoint.Y = aRect.Top();
3484  for (const auto& rShape : rMyCell.aShapeList)
3485  {
3486  if (rShape.xShape.is())
3487  {
3488  if (bNegativePage)
3489  aPoint.X = 2 * rShape.xShape->getPosition().X + rShape.xShape->getSize().Width - aPoint.X;
3490 
3491  // We only write the end address if we want the shape to resize with the cell
3492  if ( rShape.bResizeWithCell &&
3493  rShape.xShape->getShapeType() != "com.sun.star.drawing.CaptionShape" )
3494  {
3495  OUString sEndAddress;
3496  ScRangeStringConverter::GetStringFromAddress(sEndAddress, rShape.aEndAddress, pDoc, FormulaGrammar::CONV_OOO);
3498  OUStringBuffer sBuffer;
3500  sBuffer, rShape.nEndX);
3501  AddAttribute(XML_NAMESPACE_TABLE, XML_END_X, sBuffer.makeStringAndClear());
3503  sBuffer, rShape.nEndY);
3504  AddAttribute(XML_NAMESPACE_TABLE, XML_END_Y, sBuffer.makeStringAndClear());
3505  }
3506  ExportShape(rShape.xShape, &aPoint);
3507  }
3508  }
3509 }
3510 
3512 {
3513  ScMyTableShapes* pTableShapes(pSharedData->GetTableShapes());
3514  if (!pTableShapes || (*pTableShapes)[nCurrentTable].empty())
3515  return;
3516 
3517  OSL_ENSURE(pTableShapes->size() > static_cast<size_t>(nCurrentTable), "wrong Table");
3518  SvXMLElementExport aShapesElem(*this, XML_NAMESPACE_TABLE, XML_SHAPES, true, false);
3519  for (const auto& rxShape : (*pTableShapes)[nCurrentTable])
3520  {
3521  if (rxShape.is())
3522  {
3523  if (pDoc->IsNegativePage(static_cast<SCTAB>(nCurrentTable)))
3524  {
3525  awt::Point aPoint(rxShape->getPosition());
3526  awt::Size aSize(rxShape->getSize());
3527  aPoint.X += aPoint.X + aSize.Width;
3528  aPoint.Y = 0;
3529  ExportShape(rxShape, &aPoint);
3530  }
3531  else
3532  ExportShape(rxShape, nullptr);
3533  }
3534  }
3535  (*pTableShapes)[nCurrentTable].clear();
3536 }
3537 
3538 void ScXMLExport::WriteAreaLink( const ScMyCell& rMyCell )
3539 {
3540  if( !rMyCell.bHasAreaLink )
3541  return;
3542 
3543  const ScMyAreaLink& rAreaLink = rMyCell.aAreaLink;
3548  if( !rAreaLink.sFilterOptions.isEmpty() )
3550  AddAttribute( XML_NAMESPACE_TABLE, XML_LAST_COLUMN_SPANNED, OUString::number(rAreaLink.GetColCount()) );
3551  AddAttribute( XML_NAMESPACE_TABLE, XML_LAST_ROW_SPANNED, OUString::number(rAreaLink.GetRowCount()) );
3552  if( rAreaLink.nRefresh )
3553  {
3554  OUStringBuffer sValue;
3556  static_cast<double>(rAreaLink.nRefresh) / 86400 );
3557  AddAttribute( XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, sValue.makeStringAndClear() );
3558  }
3559  SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_CELL_RANGE_SOURCE, true, true );
3560 }
3561 
3562 void ScXMLExport::exportAnnotationMeta( const uno::Reference < drawing::XShape >& xShape)
3563 {
3564  ScPostIt* pNote = pCurrentCell->pNote;
3565 
3566  if (!pNote)
3567  return;
3568 
3569  // TODO : notes
3570  //is it still useful, as this call back is only called from ScXMLExport::WriteAnnotation
3571  // and should be in sync with pCurrentCell
3573  uno::Reference<drawing::XShape> xCurrentShape( pNoteCaption->getUnoShape(), uno::UNO_QUERY );
3574  if (xCurrentShape.get()!=xShape.get())
3575  return;
3576 
3577  const OUString& sAuthor(pNote->GetAuthor());
3578  if (!sAuthor.isEmpty())
3579  {
3580  SvXMLElementExport aCreatorElem( *this, XML_NAMESPACE_DC,
3581  XML_CREATOR, true,
3582  false );
3583  Characters(sAuthor);
3584  }
3585 
3586  const OUString& aDate(pNote->GetDate());
3587  if (pDoc)
3588  {
3589  SvNumberFormatter* pNumForm = pDoc->GetFormatTable();
3590  double fDate;
3591  sal_uInt32 nfIndex = pNumForm->GetFormatIndex(NF_DATE_SYS_DDMMYYYY, LANGUAGE_SYSTEM);
3592  if (pNumForm->IsNumberFormat(aDate, nfIndex, fDate))
3593  {
3594  OUStringBuffer sBuf;
3595  GetMM100UnitConverter().convertDateTime(sBuf, fDate,true);
3596  SvXMLElementExport aDateElem( *this, XML_NAMESPACE_DC,
3597  XML_DATE, true,
3598  false );
3599  Characters(sBuf.makeStringAndClear());
3600  }
3601  else
3602  {
3603  SvXMLElementExport aDateElem( *this, XML_NAMESPACE_META,
3604  XML_DATE_STRING, true,
3605  false );
3606  Characters(aDate);
3607  }
3608  }
3609  else
3610  {
3611  SvXMLElementExport aDateElem( *this, XML_NAMESPACE_META,
3612  XML_DATE_STRING, true,
3613  false );
3614  Characters(aDate);
3615  }
3616 }
3617 
3619 {
3620  ScPostIt* pNote = pDoc->GetNote(rMyCell.maCellAddress);
3621  if (!pNote)
3622  return;
3623 
3624  if (pNote->IsCaptionShown())
3626 
3627  pCurrentCell = &rMyCell;
3628 
3629  SdrCaptionObj* pNoteCaption = pNote->GetOrCreateCaption(rMyCell.maCellAddress);
3630  if (pNoteCaption)
3631  {
3632  uno::Reference<drawing::XShape> xShape( pNoteCaption->getUnoShape(), uno::UNO_QUERY );
3633  if (xShape.is())
3634  GetShapeExport()->exportShape(xShape, SEF_DEFAULT|XMLShapeExportFlags::ANNOTATION);
3635  }
3636 
3637  pCurrentCell = nullptr;
3638 }
3639 
3641 {
3642  if( !(rMyCell.bHasDetectiveObj || rMyCell.bHasDetectiveOp) )
3643  return;
3644 
3645  const ScMyDetectiveObjVec& rObjVec = rMyCell.aDetectiveObjVec;
3646  const ScMyDetectiveOpVec& rOpVec = rMyCell.aDetectiveOpVec;
3647  sal_Int32 nObjCount(rObjVec.size());
3648  sal_Int32 nOpCount(rOpVec.size());
3649  if( !(nObjCount || nOpCount) )
3650  return;
3651 
3652  SvXMLElementExport aDetElem( *this, XML_NAMESPACE_TABLE, XML_DETECTIVE, true, true );
3653  OUString sString;
3654  for(const auto& rObj : rObjVec)
3655  {
3656  if (rObj.eObjType != SC_DETOBJ_CIRCLE)
3657  {
3658  if( (rObj.eObjType == SC_DETOBJ_ARROW) || (rObj.eObjType == SC_DETOBJ_TOOTHERTAB))
3659  {
3660  ScRangeStringConverter::GetStringFromRange( sString, rObj.aSourceRange, pDoc, FormulaGrammar::CONV_OOO );
3662  }
3663  ScXMLConverter::GetStringFromDetObjType( sString, rObj.eObjType );
3665  if( rObj.bHasError )
3667  }
3668  else
3670  SvXMLElementExport aRangeElem( *this, XML_NAMESPACE_TABLE, XML_HIGHLIGHTED_RANGE, true, true );
3671  }
3672  for(const auto& rOp : rOpVec)
3673  {
3674  OUString sOpString;
3675  ScXMLConverter::GetStringFromDetOpType( sOpString, rOp.eOpType );
3676  AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, sOpString );
3677  AddAttribute( XML_NAMESPACE_TABLE, XML_INDEX, OUString::number(rOp.nIndex) );
3678  SvXMLElementExport aRangeElem( *this, XML_NAMESPACE_TABLE, XML_OPERATION, true, true );
3679  }
3680 }
3681 
3682 void ScXMLExport::SetRepeatAttribute(sal_Int32 nEqualCellCount, bool bIncProgress)
3683 {
3684  // nEqualCellCount is additional cells, so the attribute value is nEqualCellCount+1
3685  if (nEqualCellCount > 0)
3686  {
3687  sal_Int32 nTemp(nEqualCellCount + 1);
3688  OUString sOUEqualCellCount(OUString::number(nTemp));
3689  AddAttribute(sAttrColumnsRepeated, sOUEqualCellCount);
3690  if (bIncProgress)
3691  IncrementProgressBar(false, nEqualCellCount);
3692  }
3693 }
3694 
3696 {
3697  return rCell.maBaseCell.meType == CELLTYPE_EDIT;
3698 }
3699 
3700 bool ScXMLExport::IsCellEqual (const ScMyCell& aCell1, const ScMyCell& aCell2)
3701 {
3702  bool bIsEqual = false;
3703  if( !aCell1.bIsMergedBase && !aCell2.bIsMergedBase &&
3704  aCell1.bIsCovered == aCell2.bIsCovered &&
3705  !aCell1.bIsMatrixBase && !aCell2.bIsMatrixBase &&
3706  aCell1.bIsMatrixCovered == aCell2.bIsMatrixCovered &&
3707  aCell1.bHasAnnotation == aCell2.bHasAnnotation &&
3708  !aCell1.bHasShape && !aCell2.bHasShape &&
3709  aCell1.bHasAreaLink == aCell2.bHasAreaLink &&
3710  !aCell1.bHasDetectiveObj && !aCell2.bHasDetectiveObj)
3711  {
3712  if( (aCell1.bHasAreaLink &&
3713  (aCell1.aAreaLink.GetColCount() == 1) &&
3714  (aCell2.aAreaLink.GetColCount() == 1) &&
3715  aCell1.aAreaLink.Compare( aCell2.aAreaLink ) ) ||
3716  !aCell1.bHasAreaLink )
3717  {
3718  if (!aCell1.bHasAnnotation)
3719  {
3720  if ((((aCell1.nStyleIndex == aCell2.nStyleIndex) && (aCell1.bIsAutoStyle == aCell2.bIsAutoStyle)) ||
3721  ((aCell1.nStyleIndex == aCell2.nStyleIndex) && (aCell1.nStyleIndex == -1))) &&
3722  aCell1.nValidationIndex == aCell2.nValidationIndex &&
3723  aCell1.nType == aCell2.nType)
3724  {
3725  switch ( aCell1.nType )
3726  {
3727  case table::CellContentType_EMPTY :
3728  {
3729  bIsEqual = true;
3730  }
3731  break;
3732  case table::CellContentType_VALUE :
3733  {
3734  // #i29101# number format may be different from column default styles,
3735  // but can lead to different value types, so it must also be compared
3736  bIsEqual = (aCell1.nNumberFormat == aCell2.nNumberFormat) &&
3737  (aCell1.maBaseCell.mfValue == aCell2.maBaseCell.mfValue);
3738  }
3739  break;
3740  case table::CellContentType_TEXT :
3741  {
3742  if (IsEditCell(aCell1) || IsEditCell(aCell2))
3743  bIsEqual = false;
3744  else
3745  {
3746  bIsEqual = (aCell1.maBaseCell.getString(pDoc) == aCell2.maBaseCell.getString(pDoc));
3747  }
3748  }
3749  break;
3750  case table::CellContentType_FORMULA :
3751  {
3752  bIsEqual = false;
3753  }
3754  break;
3755  default :
3756  {
3757  bIsEqual = false;
3758  }
3759  break;
3760  }
3761  }
3762  }
3763  }
3764  }
3765  return bIsEqual;
3766 }
3767 
3768 void ScXMLExport::WriteCalculationSettings(const uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc)
3769 {
3770  uno::Reference<beans::XPropertySet> xPropertySet(xSpreadDoc, uno::UNO_QUERY);
3771  if (!xPropertySet.is())
3772  return;
3773 
3774  bool bCalcAsShown (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_CALCASSHOWN) ));
3775  bool bIgnoreCase (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_IGNORECASE) ));
3776  bool bLookUpLabels (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_LOOKUPLABELS) ));
3777  bool bMatchWholeCell (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_MATCHWHOLE) ));
3778  bool bUseRegularExpressions (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_REGEXENABLED) ));
3779  bool bUseWildcards (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_WILDCARDSENABLED) ));
3780  if (bUseWildcards && bUseRegularExpressions)
3781  bUseRegularExpressions = false; // mutually exclusive, wildcards take precedence
3782  bool bIsIterationEnabled (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_ITERENABLED) ));
3783  sal_uInt16 nYear2000 (pDoc ? pDoc->GetDocOptions().GetYear2000() : 0);
3784  sal_Int32 nIterationCount(100);
3785  xPropertySet->getPropertyValue( SC_UNO_ITERCOUNT ) >>= nIterationCount;
3786  double fIterationEpsilon = 0;
3787  xPropertySet->getPropertyValue( SC_UNO_ITEREPSILON ) >>= fIterationEpsilon;
3788  util::Date aNullDate;
3789  xPropertySet->getPropertyValue( SC_UNO_NULLDATE ) >>= aNullDate;
3790  if (!(bCalcAsShown || bIgnoreCase || !bLookUpLabels || !bMatchWholeCell || !bUseRegularExpressions ||
3791  bUseWildcards ||
3792  bIsIterationEnabled || nIterationCount != 100 || !::rtl::math::approxEqual(fIterationEpsilon, 0.001) ||
3793  aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899 || nYear2000 != 1930))
3794  return;
3795 
3796  if (bIgnoreCase)
3798  if (bCalcAsShown)
3800  if (!bMatchWholeCell)
3802  if (!bLookUpLabels)
3804  if (!bUseRegularExpressions)
3806  if (bUseWildcards)
3808  if (nYear2000 != 1930)
3809  {
3810  AddAttribute(XML_NAMESPACE_TABLE, XML_NULL_YEAR, OUString::number(nYear2000));
3811  }
3812  SvXMLElementExport aCalcSettings(*this, XML_NAMESPACE_TABLE, XML_CALCULATION_SETTINGS, true, true);
3813  {
3814  if (aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899)
3815  {
3816  OUStringBuffer sDate;
3817  SvXMLUnitConverter::convertDateTime(sDate, 0.0, aNullDate);
3818  AddAttribute(XML_NAMESPACE_TABLE, XML_DATE_VALUE, sDate.makeStringAndClear());
3819  SvXMLElementExport aElemNullDate(*this, XML_NAMESPACE_TABLE, XML_NULL_DATE, true, true);
3820  }
3821  if (bIsIterationEnabled || nIterationCount != 100 || !::rtl::math::approxEqual(fIterationEpsilon, 0.001))
3822  {
3823  if (bIsIterationEnabled)
3825  if (nIterationCount != 100)
3826  {
3827  AddAttribute(XML_NAMESPACE_TABLE, XML_STEPS, OUString::number(nIterationCount));
3828  }
3829  if (!::rtl::math::approxEqual(fIterationEpsilon, 0.001))
3830  {
3831  OUStringBuffer sBuffer;
3833  fIterationEpsilon);
3834  AddAttribute(XML_NAMESPACE_TABLE, XML_MAXIMUM_DIFFERENCE, sBuffer.makeStringAndClear());
3835  }
3836  SvXMLElementExport aElemIteration(*this, XML_NAMESPACE_TABLE, XML_ITERATION, true, true);
3837  }
3838  }
3839 }
3840 
3842 {
3843  uno::Reference <sheet::XSheetLinkable> xLinkable (xCurrentTable, uno::UNO_QUERY);
3844  if (!(xLinkable.is() && GetModel().is()))
3845  return;
3846 
3847  sheet::SheetLinkMode nMode (xLinkable->getLinkMode());
3848  if (nMode == sheet::SheetLinkMode_NONE)
3849  return;
3850 
3851  OUString sLink (xLinkable->getLinkUrl());
3852  uno::Reference <beans::XPropertySet> xProps (GetModel(), uno::UNO_QUERY);
3853  if (!xProps.is())
3854  return;
3855 
3856  uno::Reference <container::XIndexAccess> xIndex(xProps->getPropertyValue(SC_UNO_SHEETLINKS), uno::UNO_QUERY);
3857  if (!xIndex.is())
3858  return;
3859 
3860  sal_Int32 nCount(xIndex->getCount());
3861  if (!nCount)
3862  return;
3863 
3864  bool bFound(false);
3865  uno::Reference <beans::XPropertySet> xLinkProps;
3866  for (sal_Int32 i = 0; (i < nCount) && !bFound; ++i)
3867  {
3868  xLinkProps.set(xIndex->getByIndex(i), uno::UNO_QUERY);
3869  if (xLinkProps.is())
3870  {
3871  OUString sNewLink;
3872  if (xLinkProps->getPropertyValue(SC_UNONAME_LINKURL) >>= sNewLink)
3873  bFound = sLink == sNewLink;
3874  }
3875  }
3876  if (!(bFound && xLinkProps.is()))
3877  return;
3878 
3879  OUString sFilter;
3880  OUString sFilterOptions;
3881  OUString sTableName (xLinkable->getLinkSheetName());
3882  sal_Int32 nRefresh(0);
3883  xLinkProps->getPropertyValue(SC_UNONAME_FILTER) >>= sFilter;
3884  xLinkProps->getPropertyValue(SC_UNONAME_FILTOPT) >>= sFilterOptions;
3885  xLinkProps->getPropertyValue(SC_UNONAME_REFDELAY) >>= nRefresh;
3886  if (sLink.isEmpty())
3887  return;
3888 
3891  if (!sTableName.isEmpty())
3893  if (!sFilter.isEmpty())
3895  if (!sFilterOptions.isEmpty())
3897  if (nMode != sheet::SheetLinkMode_NORMAL)
3899  if( nRefresh )
3900  {
3901  OUStringBuffer sBuffer;
3903  static_cast<double>(nRefresh) / 86400 );
3904  AddAttribute( XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, sBuffer.makeStringAndClear() );
3905  }
3906  SvXMLElementExport aSourceElem(*this, XML_NAMESPACE_TABLE, XML_TABLE_SOURCE, true, true);
3907 }
3908 
3909 // core implementation
3911 {
3912  if (!(pDoc && pDoc->IsScenario(static_cast<SCTAB>(nCurrentTable))))
3913  return;
3914 
3915  OUString sComment;
3916  Color aColor;
3917  ScScenarioFlags nFlags;
3918  pDoc->GetScenarioData(static_cast<SCTAB>(nCurrentTable), sComment, aColor, nFlags);
3919  if (!(nFlags & ScScenarioFlags::ShowFrame))
3921  OUStringBuffer aBuffer;
3922  ::sax::Converter::convertColor(aBuffer, aColor);
3923  AddAttribute(XML_NAMESPACE_TABLE, XML_BORDER_COLOR, aBuffer.makeStringAndClear());
3924  if (!(nFlags & ScScenarioFlags::TwoWay))
3926  if (!(nFlags & ScScenarioFlags::Attrib))
3928  if (nFlags & ScScenarioFlags::Value)
3930  if (nFlags & ScScenarioFlags::Protected)
3933  pDoc->IsActiveScenario(static_cast<SCTAB>(nCurrentTable)));
3934  AddAttribute(XML_NAMESPACE_TABLE, XML_IS_ACTIVE, aBuffer.makeStringAndClear());
3935  const ScRangeList* pRangeList = pDoc->GetScenarioRanges(static_cast<SCTAB>(nCurrentTable));
3936  OUString sRangeListStr;
3937  ScRangeStringConverter::GetStringFromRangeList( sRangeListStr, pRangeList, pDoc, FormulaGrammar::CONV_OOO );
3939  if (!sComment.isEmpty())
3941  SvXMLElementExport aElem(*this, XML_NAMESPACE_TABLE, XML_SCENARIO, true, true);
3942 }
3943 
3944 void ScXMLExport::WriteTheLabelRanges( const uno::Reference< sheet::XSpreadsheetDocument >& xSpreadDoc )
3945 {
3946  uno::Reference< beans::XPropertySet > xDocProp( xSpreadDoc, uno::UNO_QUERY );
3947  if( !xDocProp.is() ) return;
3948 
3949  sal_Int32 nCount(0);
3950  uno::Reference< container::XIndexAccess > xColRangesIAccess(xDocProp->getPropertyValue( SC_UNO_COLLABELRNG ), uno::UNO_QUERY);
3951  if( xColRangesIAccess.is() )
3952  nCount += xColRangesIAccess->getCount();
3953 
3954  uno::Reference< container::XIndexAccess > xRowRangesIAccess(xDocProp->getPropertyValue( SC_UNO_ROWLABELRNG ), uno::UNO_QUERY);
3955  if( xRowRangesIAccess.is() )
3956  nCount += xRowRangesIAccess->getCount();
3957 
3958  if( nCount )
3959  {
3960  SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_LABEL_RANGES, true, true );
3961  WriteLabelRanges( xColRangesIAccess, true );
3962  WriteLabelRanges( xRowRangesIAccess, false );
3963  }
3964 }
3965 
3966 void ScXMLExport::WriteLabelRanges( const uno::Reference< container::XIndexAccess >& xRangesIAccess, bool bColumn )
3967 {
3968  if( !xRangesIAccess.is() ) return;
3969 
3970  sal_Int32 nCount(xRangesIAccess->getCount());
3971  for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
3972  {
3973  uno::Reference< sheet::XLabelRange > xRange(xRangesIAccess->getByIndex( nIndex ), uno::UNO_QUERY);
3974  if( xRange.is() )
3975  {
3976  OUString sRangeStr;
3977  table::CellRangeAddress aCellRange( xRange->getLabelArea() );
3978  ScRangeStringConverter::GetStringFromRange( sRangeStr, aCellRange, pDoc, FormulaGrammar::CONV_OOO );
3980  aCellRange = xRange->getDataArea();
3981  ScRangeStringConverter::GetStringFromRange( sRangeStr, aCellRange, pDoc, FormulaGrammar::CONV_OOO );
3984  SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_LABEL_RANGE, true, true );
3985  }
3986  }
3987 }
3988 
3990 {
3991  if (!pDoc)
3992  return;
3993  ScRangeName* pNamedRanges = pDoc->GetRangeName();
3994  WriteNamedRange(pNamedRanges);
3995 }
3996 
3998 {
3999  if (!pDoc)
4000  return;
4001 
4003  // Export this only for 1.2 extended and above.
4004  return;
4005 
4007  auto& rDataSources = rDataMapper.getDataSources();
4008 
4009  if (rDataSources.empty())
4010  return;
4011 
4012  SvXMLElementExport aMappings(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_MAPPINGS, true, true);
4013  for (const auto& itr : rDataSources)
4014  {
4015  AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, itr.getURL());
4016  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_PROVIDER, itr.getProvider());
4020 
4021  SvXMLElementExport aMapping(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_MAPPING, true, true);
4022  // Add the data transformations
4023  WriteExternalDataTransformations(itr.getDataTransformation());
4024  }
4025 }
4026 
4027 void ScXMLExport::WriteExternalDataTransformations(const std::vector<std::shared_ptr<sc::DataTransformation>>& aDataTransformations)
4028 {
4029  SvXMLElementExport aTransformations(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_TRANSFORMATIONS, true, true);
4030  for (auto& itr : aDataTransformations)
4031  {
4032  sc::TransformationType aTransformationType = itr->getTransformationType();
4033 
4034  switch(aTransformationType)
4035  {
4037  {
4038  // Delete Columns Transformation
4039  std::shared_ptr<sc::ColumnRemoveTransformation> aDeleteTransformation = std::dynamic_pointer_cast<sc::ColumnRemoveTransformation>(itr);
4040  std::set<SCCOL> aColumns = aDeleteTransformation->getColumns();
4041  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_REMOVE_TRANSFORMATION, true, true);
4042  for(auto& col : aColumns)
4043  {
4044  // Add Columns
4045  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4046  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4047  }
4048  }
4049  break;
4051  {
4052  std::shared_ptr<sc::SplitColumnTransformation> aSplitTransformation = std::dynamic_pointer_cast<sc::SplitColumnTransformation>(itr);
4053 
4054  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(aSplitTransformation->getColumn()));
4055  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_SEPARATOR, OUString::number(aSplitTransformation->getSeparator()));
4056  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_SPLIT_TRANSFORMATION, true, true);
4057  }
4058  break;
4060  {
4061  // Merge Transformation
4062  std::shared_ptr<sc::MergeColumnTransformation> aMergeTransformation = std::dynamic_pointer_cast<sc::MergeColumnTransformation>(itr);
4063  std::set<SCCOL> aColumns = aMergeTransformation->getColumns();
4064 
4065  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MERGE_STRING, aMergeTransformation->getMergeString());
4066  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_MERGE_TRANSFORMATION, true, true);
4067 
4068  for(auto& col : aColumns)
4069  {
4070  // Columns
4071  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4072  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4073  }
4074  }
4075  break;
4077  {
4078  // Sort Transformation
4079  std::shared_ptr<sc::SortTransformation> aSortTransformation = std::dynamic_pointer_cast<sc::SortTransformation>(itr);
4080  ScSortParam aSortParam = aSortTransformation->getSortParam();
4082  const sc::DataStream* pStrm = rMgr.getDataStream();
4083  if (!pStrm)
4084  // No data stream.
4085  return;
4086 
4087  // Streamed range
4088  ScRange aRange = pStrm->GetRange();
4089 
4090  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_SORT_TRANSFORMATION, true, true);
4091 
4092  writeSort(*this, aSortParam, aRange, pDoc);
4093  }
4094  break;
4096  {
4097  // Text Transformation
4098  std::shared_ptr<sc::TextTransformation> aTextTransformation = std::dynamic_pointer_cast<sc::TextTransformation>(itr);
4099 
4100  sc::TEXT_TRANSFORM_TYPE aTextTransformType = aTextTransformation->getTextTransformationType();
4101 
4102  switch ( aTextTransformType )
4103  {
4106  break;
4109  break;
4112  break;
4115  break;
4116  }
4117 
4118  std::set<SCCOL> aColumns = aTextTransformation->getColumns();
4119 
4120  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_TEXT_TRANSFORMATION, true, true);
4121 
4122  for(auto& col : aColumns)
4123  {
4124  // Columns
4125  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4126  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4127  }
4128  }
4129  break;
4131  {
4132  // Aggregate Transformation
4133  std::shared_ptr<sc::AggregateFunction> aAggregateFunction = std::dynamic_pointer_cast<sc::AggregateFunction>(itr);
4134  std::set<SCCOL> aColumns = aAggregateFunction->getColumns();
4135 
4136  sc::AGGREGATE_FUNCTION aAggregateType = aAggregateFunction->getAggregateType();
4137 
4138  switch (aAggregateType)
4139  {
4142  break;
4145  break;
4148  break;
4151  break;
4152  }
4153 
4155 
4156  for(auto& col : aColumns)
4157  {
4158  // Columns
4159  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4160  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4161  }
4162  }
4163  break;
4165  {
4166  // Number Transformation
4167  std::shared_ptr<sc::NumberTransformation> aNumberTransformation = std::dynamic_pointer_cast<sc::NumberTransformation>(itr);
4168 
4169  sc::NUMBER_TRANSFORM_TYPE aNumberTransformType = aNumberTransformation->getNumberTransformationType();
4170 
4171  switch ( aNumberTransformType )
4172  {
4175  break;
4178  break;
4181  break;
4184  break;
4187  break;
4190  break;
4193  break;
4196  break;
4199  break;
4202  break;
4205  break;
4208  break;
4211  break;
4212  }
4213 
4214  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_PRECISION, OUString::number(aNumberTransformation->getPrecision()));
4215  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_NUMBER_TRANSFORMATION, true, true);
4216 
4217  std::set<SCCOL> aColumns = aNumberTransformation->getColumn();
4218  for(auto& col : aColumns)
4219  {
4220  // Columns
4221  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4222  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4223  }
4224  }
4225  break;
4227  {
4228  // Replace Null Transformation
4229  std::shared_ptr<sc::ReplaceNullTransformation> aReplaceNullTransformation = std::dynamic_pointer_cast<sc::ReplaceNullTransformation>(itr);
4230  std::set<SCCOL> aColumns = aReplaceNullTransformation->getColumn();
4231 
4232  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_REPLACE_STRING, aReplaceNullTransformation->getReplaceString());
4234 
4235  for(auto& col : aColumns)
4236  {
4237  // Columns
4238  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4239  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4240  }
4241  }
4242  break;
4244  {
4245  // Number Transformation
4246  std::shared_ptr<sc::DateTimeTransformation> aDateTimeTransformation = std::dynamic_pointer_cast<sc::DateTimeTransformation>(itr);
4247 
4248  sc::DATETIME_TRANSFORMATION_TYPE aDateTimeTransformationType = aDateTimeTransformation->getDateTimeTransformationType();
4249 
4250  switch ( aDateTimeTransformationType )
4251  {
4254  break;
4257  break;
4260  break;
4263  break;
4266  break;
4269  break;
4272  break;
4275  break;
4278  break;
4281  break;
4284  break;
4287  break;
4290  break;
4293  break;
4296  break;
4299  break;
4302  break;
4305  break;
4306  }
4307 
4309 
4310  std::set<SCCOL> aColumns = aDateTimeTransformation->getColumn();
4311  for(auto& col : aColumns)
4312  {
4313  // Columns
4314  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4315  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4316  }
4317  }
4318  break;
4319  default:
4320  break;
4321  }
4322  }
4323 }
4324 
4326 {
4327  if (!pDoc)
4328  return;
4329 
4330  SvtMiscOptions aMiscOptions;
4331  if (!aMiscOptions.IsExperimentalMode())
4332  // Export this only in experimental mode.
4333  return;
4334 
4336  // Export this only for 1.2 extended and above.
4337  return;
4338 
4340  const sc::DataStream* pStrm = rMgr.getDataStream();
4341  if (!pStrm)
4342  // No data stream.
4343  return;
4344 
4345  // Source URL
4347 
4348  // Streamed range
4349  ScRange aRange = pStrm->GetRange();
4350  OUString aRangeStr;
4352  aRangeStr, aRange, pDoc, formula::FormulaGrammar::CONV_OOO);
4354 
4355  // Empty line refresh option.
4357 
4358  // New data insertion position. Either top of bottom. Default to bottom.
4359  xmloff::token::XMLTokenEnum eInsertPosition = XML_BOTTOM;
4360  if (pStrm->GetMove() == sc::DataStream::MOVE_DOWN)
4361  eInsertPosition = XML_TOP;
4362 
4364 
4366 }
4367 
4369 {
4370  //write a global or local ScRangeName
4371  SvXMLElementExport aElemNEs(*this, XML_NAMESPACE_TABLE, XML_NAMED_EXPRESSIONS, true, true);
4372  for (const auto& rxEntry : *pRangeName)
4373  {
4374  AddAttribute(sAttrName, rxEntry.second->GetName());
4375 
4376  OUString sBaseCellAddress;
4377  rxEntry.second->ValidateTabRefs();
4378  ScRangeStringConverter::GetStringFromAddress( sBaseCellAddress, rxEntry.second->GetPos(), pDoc,
4379  FormulaGrammar::CONV_OOO, ' ', false, ScRefFlags::ADDR_ABS_3D);
4381 
4382  OUString sSymbol;
4383  rxEntry.second->GetSymbol(sSymbol, pDoc->GetStorageGrammar());
4384  OUString sTempSymbol(sSymbol);
4385  ScRange aRange;
4386  if (rxEntry.second->IsReference(aRange))
4387  {