xref: /core/sc/source/filter/xml/xmlexprt.cxx (revision 09402293)
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>
31 #include "XMLTableMasterPageExport.hxx"
32 #include <drwlayer.hxx>
33 #include "XMLExportDataPilot.hxx"
34 #include "XMLExportDatabaseRanges.hxx"
35 #include "XMLExportDDELinks.hxx"
36 #include "XMLExportIterator.hxx"
37 #include "XMLColumnRowGroupExport.hxx"
38 #include "XMLStylesExportHelper.hxx"
39 #include "XMLChangeTrackingExportHelper.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/xmlnmspe.hxx>
73 #include <xmloff/xmluconv.hxx>
74 #include <xmloff/nmspmap.hxx>
75 #include <xmloff/families.hxx>
76 #include <xmloff/numehelp.hxx>
77 #include <xmloff/txtparae.hxx>
78 #include <editeng/autokernitem.hxx>
79 #include <editeng/charreliefitem.hxx>
80 #include <editeng/charscaleitem.hxx>
81 #include <editeng/colritem.hxx>
82 #include <editeng/contouritem.hxx>
83 #include <editeng/crossedoutitem.hxx>
84 #include <editeng/emphasismarkitem.hxx>
85 #include <editeng/escapementitem.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>
103 #include <xmloff/ProgressBarHelper.hxx>
104 
105 #include <sax/tools/converter.hxx>
106 
107 #include <rtl/ustring.hxx>
108 
109 #include <tools/color.hxx>
110 #include <rtl/math.hxx>
111 #include <svl/zforlist.hxx>
112 #include <svx/unoshape.hxx>
113 #include <comphelper/base64.hxx>
114 #include <comphelper/extract.hxx>
115 #include <svx/svdobj.hxx>
116 #include <svx/svdocapt.hxx>
117 #include <svtools/miscopt.hxx>
118 #include <vcl/svapp.hxx>
119 
120 #include <comphelper/processfactory.hxx>
121 #include <com/sun/star/beans/XPropertySet.hpp>
122 #include <com/sun/star/container/XNamed.hpp>
123 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
124 #include <com/sun/star/form/XFormsSupplier2.hpp>
125 #include <com/sun/star/io/XActiveDataSource.hpp>
126 #include <com/sun/star/io/XSeekable.hpp>
127 #include <com/sun/star/sheet/XUsedAreaCursor.hpp>
128 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
129 #include <com/sun/star/sheet/XPrintAreas.hpp>
130 #include <com/sun/star/sheet/XUniqueCellFormatRangesSupplier.hpp>
131 #include <com/sun/star/sheet/XLabelRange.hpp>
132 #include <com/sun/star/sheet/NamedRangeFlag.hpp>
133 #include <com/sun/star/sheet/XSheetCellCursor.hpp>
134 #include <com/sun/star/sheet/XSheetCellRanges.hpp>
135 #include <com/sun/star/sheet/XSheetLinkable.hpp>
136 #include <com/sun/star/sheet/GlobalSheetSettings.hpp>
137 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
138 #include <com/sun/star/table/XColumnRowRange.hpp>
139 #include <com/sun/star/util/XProtectable.hpp>
140 
141 #include <com/sun/star/chart2/XChartDocument.hpp>
142 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
143 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
144 
145 #include <com/sun/star/document/XDocumentProperties.hpp>
146 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
147 
148 #include "XMLCodeNameProvider.hxx"
149 
150 #include <sfx2/linkmgr.hxx>
151 #include <sfx2/objsh.hxx>
152 
153 #include <memory>
154 #include <vector>
155 #include <vbahelper/vbaaccesshelper.hxx>
156 
157 namespace com { namespace sun { namespace star { namespace uno { class XComponentContext; } } } }
158 
159 
160 
161 //! not found in unonames.hxx
162 #define SC_LAYERID "LayerID"
163 
164 #define SC_VIEWCHANGES_COUNT                        13
165 #define SC_SHOW_CHANGES                             0
166 #define SC_SHOW_ACCEPTED_CHANGES                    1
167 #define SC_SHOW_REJECTED_CHANGES                    2
168 #define SC_SHOW_CHANGES_BY_DATETIME                 3
169 #define SC_SHOW_CHANGES_BY_DATETIME_MODE            4
170 #define SC_SHOW_CHANGES_BY_DATETIME_FIRST_DATETIME  5
171 #define SC_SHOW_CHANGES_BY_DATETIME_SECOND_DATETIME 6
172 #define SC_SHOW_CHANGES_BY_AUTHOR                   7
173 #define SC_SHOW_CHANGES_BY_AUTHOR_NAME              8
174 #define SC_SHOW_CHANGES_BY_COMMENT                  9
175 #define SC_SHOW_CHANGES_BY_COMMENT_TEXT             10
176 #define SC_SHOW_CHANGES_BY_RANGES                   11
177 #define SC_SHOW_CHANGES_BY_RANGES_LIST              12
178 
179 using namespace formula;
180 using namespace com::sun::star;
181 using namespace xmloff::token;
182 using ::std::vector;
183 using ::com::sun::star::uno::UNO_QUERY;
184 
185 namespace
186 {
187 OUString lcl_RangeSequenceToString(
188     const uno::Sequence< OUString > & rRanges,
189     const uno::Reference< chart2::data::XRangeXMLConversion > & xFormatConverter )
190 {
191     OUStringBuffer aResult;
192     const sal_Int32 nMaxIndex( rRanges.getLength() - 1 );
193     const sal_Unicode cSep(' ');
194     for( sal_Int32 i=0; i<=nMaxIndex; ++i )
195     {
196         OUString aRange( rRanges[i] );
197         if( xFormatConverter.is())
198             aRange = xFormatConverter->convertRangeToXML( aRange );
199         aResult.append( aRange );
200         if( i < nMaxIndex )
201             aResult.append( cSep );
202     }
203     return aResult.makeStringAndClear();
204 }
205 
206 OUString lcl_GetFormattedString(ScDocument* pDoc, ScRefCellValue& rCell, const ScAddress& rAddr)
207 {
208     // return text/edit cell string content, with line feeds in edit cells
209 
210     if (!pDoc)
211         return EMPTY_OUSTRING;
212 
213     switch (rCell.meType)
214     {
215         case CELLTYPE_STRING:
216         {
217             OUString aStr;
218             Color* pColor;
219             SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
220 
221             sal_uInt32 nFormat = pDoc->GetNumberFormat(rAddr);
222             ScCellFormat::GetString(rCell, nFormat, aStr, &pColor, *pFormatter, pDoc);
223             return aStr;
224         }
225         case CELLTYPE_EDIT:
226         {
227             const EditTextObject* pData = rCell.mpEditText;
228             if (!pData)
229                 return EMPTY_OUSTRING;
230 
231             EditEngine& rEngine = pDoc->GetEditEngine();
232             rEngine.SetText(*pData);
233             return rEngine.GetText();
234         }
235         break;
236         default:
237             ;
238     }
239 
240     return EMPTY_OUSTRING;
241 }
242 
243 } // anonymous namespace
244 
245 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
246 Calc_XMLExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
247 {
248     return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLExporter", SvXMLExportFlags::ALL));
249 }
250 
251 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
252 Calc_XMLMetaExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
253 {
254     return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLMetaExporter", SvXMLExportFlags::META));
255 }
256 
257 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
258 Calc_XMLStylesExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
259 {
260     return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLStylesExporter", SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS));
261 }
262 
263 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
264 Calc_XMLContentExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
265 {
266     return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLContentExporter", SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::FONTDECLS));
267 }
268 
269 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
270 Calc_XMLSettingsExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
271 {
272     return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLSettingsExporter", SvXMLExportFlags::SETTINGS));
273 }
274 
275 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
276 Calc_XMLOasisExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
277 {
278     return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisExporter", SvXMLExportFlags::ALL|SvXMLExportFlags::OASIS));
279 }
280 
281 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
282 Calc_XMLOasisMetaExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
283 {
284     return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisMetaExporter", SvXMLExportFlags::META|SvXMLExportFlags::OASIS));
285 }
286 
287 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
288 Calc_XMLOasisStylesExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
289 {
290     return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisStylesExporter", SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::OASIS));
291 }
292 
293 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
294 Calc_XMLOasisContentExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
295 {
296     return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisContentExporter", SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::OASIS));
297 }
298 
299 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
300 Calc_XMLOasisSettingsExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
301 {
302     return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisSettingsExporter", SvXMLExportFlags::SETTINGS|SvXMLExportFlags::OASIS));
303 }
304 
305 class ScXMLShapeExport : public XMLShapeExport
306 {
307 public:
308     explicit ScXMLShapeExport(SvXMLExport& rExp) : XMLShapeExport(rExp) {}
309 
310     /** is called before a shape element for the given XShape is exported */
311     virtual void onExport( const uno::Reference < drawing::XShape >& xShape ) override;
312 };
313 
314 void ScXMLShapeExport::onExport( const uno::Reference < drawing::XShape >& xShape )
315 {
316     uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
317     if( xShapeProp.is() )
318     {
319         sal_Int16 nLayerID = 0;
320         if( (xShapeProp->getPropertyValue( SC_LAYERID ) >>= nLayerID) && (SdrLayerID(nLayerID) == SC_LAYER_BACK) )
321             GetExport().AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_BACKGROUND, XML_TRUE);
322     }
323 }
324 
325 sal_Int16 ScXMLExport::GetMeasureUnit()
326 {
327     css::uno::Reference<css::sheet::XGlobalSheetSettings> xProperties =
328                 css::sheet::GlobalSheetSettings::create( comphelper::getProcessComponentContext() );
329     return xProperties->getMetric();
330 }
331 
332 static const OUStringLiteral gsLayerID( SC_LAYERID );
333 
334 ScXMLExport::ScXMLExport(
335     const css::uno::Reference< css::uno::XComponentContext >& rContext,
336     OUString const & implementationName, SvXMLExportFlags nExportFlag)
337 :   SvXMLExport( GetMeasureUnit(),
338         rContext, implementationName, XML_SPREADSHEET, nExportFlag ),
339     pDoc(nullptr),
340     nSourceStreamPos(0),
341     aTableStyles(),
342     pCurrentCell(nullptr),
343     nOpenRow(-1),
344     nProgressCount(0),
345     nCurrentTable(0),
346     bHasRowHeader(false),
347     bRowHeaderOpen(false)
348 {
349     if (getExportFlags() & SvXMLExportFlags::CONTENT)
350     {
351         pGroupColumns.reset( new ScMyOpenCloseColumnRowGroup(*this, XML_TABLE_COLUMN_GROUP) );
352         pGroupRows.reset( new ScMyOpenCloseColumnRowGroup(*this, XML_TABLE_ROW_GROUP) );
353         pColumnStyles.reset( new ScColumnStyles() );
354         pRowStyles.reset( new ScRowStyles() );
355         pRowFormatRanges.reset( new ScRowFormatRanges() );
356         pMergedRangesContainer.reset( new ScMyMergedRangesContainer() );
357         pValidationsContainer.reset( new ScMyValidationsContainer() );
358         mpCellsItr.reset(new ScMyNotEmptyCellsIterator(*this));
359         pDefaults.reset( new ScMyDefaultStyles );
360     }
361     pCellStyles.reset( new ScFormatRangeStyles() );
362 
363     // document is not set here - create ScChangeTrackingExportHelper later
364 
365     xScPropHdlFactory = new XMLScPropHdlFactory;
366     xCellStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScCellStylesProperties, xScPropHdlFactory, true);
367     xColumnStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScColumnStylesProperties, xScPropHdlFactory, true);
368     xRowStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScRowStylesProperties, xScPropHdlFactory, true);
369     xTableStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScTableStylesProperties, xScPropHdlFactory, true);
370     xCellStylesExportPropertySetMapper = new ScXMLCellExportPropertyMapper(xCellStylesPropertySetMapper);
371     xCellStylesExportPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaExtPropMapper(*this));
372     xColumnStylesExportPropertySetMapper = new ScXMLColumnExportPropertyMapper(xColumnStylesPropertySetMapper);
373     xRowStylesExportPropertySetMapper = new ScXMLRowExportPropertyMapper(xRowStylesPropertySetMapper);
374     xTableStylesExportPropertySetMapper = new ScXMLTableExportPropertyMapper(xTableStylesPropertySetMapper);
375 
376     GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_CELL, XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME,
377         xCellStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX);
378     GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_COLUMN, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_NAME,
379         xColumnStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_PREFIX);
380     GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_ROW, XML_STYLE_FAMILY_TABLE_ROW_STYLES_NAME,
381         xRowStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_ROW_STYLES_PREFIX);
382     GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_TABLE, XML_STYLE_FAMILY_TABLE_TABLE_STYLES_NAME,
383         xTableStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_TABLE_STYLES_PREFIX);
384 
385     if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
386     {
387         // This name is reserved for the external ref cache tables.  This
388         // should not conflict with user-defined styles since this name is
389         // used for a table style which is not available in the UI.
390         sExternalRefTabStyleName = "ta_extref";
391         GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_TABLE, sExternalRefTabStyleName);
392 
393         sAttrName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_NAME));
394         sAttrStyleName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_STYLE_NAME));
395         sAttrColumnsRepeated = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_NUMBER_COLUMNS_REPEATED));
396         sAttrFormula = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_FORMULA));
397         sAttrStringValue = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_STRING_VALUE));
398         sAttrValueType = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_VALUE_TYPE));
399         sElemCell = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_TABLE_CELL));
400         sElemCoveredCell = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_COVERED_TABLE_CELL));
401         sElemCol = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_TABLE_COLUMN));
402         sElemRow = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_TABLE_ROW));
403         sElemTab = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_TABLE));
404         sElemP = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TEXT, GetXMLToken(XML_P));
405     }
406 }
407 
408 ScXMLExport::~ScXMLExport()
409 {
410     pGroupColumns.reset();
411     pGroupRows.reset();
412     pColumnStyles.reset();
413     pRowStyles.reset();
414     pCellStyles.reset();
415     pRowFormatRanges.reset();
416     pMergedRangesContainer.reset();
417     pValidationsContainer.reset();
418     pChangeTrackingExportHelper.reset();
419     pDefaults.reset();
420     pNumberFormatAttributesExportHelper.reset();
421 }
422 
423 void ScXMLExport::SetSourceStream( const uno::Reference<io::XInputStream>& xNewStream )
424 {
425     xSourceStream = xNewStream;
426 
427     if ( xSourceStream.is() )
428     {
429         // make sure it's a plain UTF-8 stream as written by OOo itself
430 
431         const sal_Char pXmlHeader[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
432         sal_Int32 nLen = strlen(pXmlHeader);
433 
434         uno::Sequence<sal_Int8> aFileStart(nLen);
435         sal_Int32 nRead = xSourceStream->readBytes( aFileStart, nLen );
436 
437         if ( nRead != nLen || memcmp( aFileStart.getConstArray(), pXmlHeader, nLen ) != 0 )
438         {
439             // invalid - ignore stream, save normally
440             xSourceStream.clear();
441         }
442         else
443         {
444             // keep track of the bytes already read
445             nSourceStreamPos = nRead;
446 
447             const ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(GetModel())->GetSheetSaveData();
448             if (pSheetData)
449             {
450                 // add the loaded namespaces to the name space map
451 
452                 if ( !pSheetData->AddLoadedNamespaces( GetNamespaceMap_() ) )
453                 {
454                     // conflicts in the namespaces - ignore the stream, save normally
455                     xSourceStream.clear();
456                 }
457             }
458         }
459     }
460 }
461 
462 sal_Int32 ScXMLExport::GetNumberFormatStyleIndex(sal_Int32 nNumFmt) const
463 {
464     NumberFormatIndexMap::const_iterator itr = aNumFmtIndexMap.find(nNumFmt);
465     if (itr == aNumFmtIndexMap.end())
466         return -1;
467 
468     return itr->second;
469 }
470 
471 void ScXMLExport::CollectSharedData(SCTAB& nTableCount, sal_Int32& nShapesCount)
472 {
473     if (!GetModel().is())
474         return;
475 
476     uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc(GetModel(), uno::UNO_QUERY);
477     if (!xSpreadDoc.is())
478         return;
479 
480     uno::Reference<container::XIndexAccess> xIndex(xSpreadDoc->getSheets(), uno::UNO_QUERY);
481     if (!xIndex.is())
482         return;
483 
484     nTableCount = xIndex->getCount();
485     if (!pSharedData)
486         pSharedData.reset(new ScMySharedData(nTableCount));
487 
488     pCellStyles->AddNewTable(nTableCount - 1);
489 
490     for (SCTAB nTable = 0; nTable < nTableCount; ++nTable)
491     {
492         nCurrentTable = sal::static_int_cast<sal_uInt16>(nTable);
493         uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xIndex->getByIndex(nTable), uno::UNO_QUERY);
494         if (!xDrawPageSupplier.is())
495             continue;
496 
497         uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage());
498         ScMyDrawPage aDrawPage;
499         aDrawPage.bHasForms = false;
500         aDrawPage.xDrawPage.set(xDrawPage);
501         pSharedData->AddDrawPage(aDrawPage, nTable);
502         if (!xDrawPage.is())
503             continue;
504 
505         sal_Int32 nShapes = xDrawPage->getCount();
506         for (sal_Int32 nShape = 0; nShape < nShapes; ++nShape)
507         {
508             uno::Reference<drawing::XShape> xShape(xDrawPage->getByIndex(nShape), uno::UNO_QUERY);
509             if (!xShape.is())
510                 continue;
511 
512             uno::Reference<beans::XPropertySet> xShapeProp(xShape, uno::UNO_QUERY);
513             if (!xShapeProp.is())
514                 continue;
515 
516             sal_Int16 nLayerID = 0;
517             bool bExtracted = xShapeProp->getPropertyValue(gsLayerID) >>= nLayerID;
518             if (!bExtracted)
519                 continue;
520 
521             if ((SdrLayerID(nLayerID) == SC_LAYER_INTERN) || (SdrLayerID(nLayerID) == SC_LAYER_HIDDEN))
522             {
523                 CollectInternalShape(xShape);
524                 continue;
525             }
526 
527             ++nShapesCount;
528 
529             SvxShape* pShapeImp = comphelper::getUnoTunnelImplementation<SvxShape>(xShape);
530             if (!pShapeImp)
531                 continue;
532 
533             SdrObject* pSdrObj = pShapeImp->GetSdrObject();
534             if (!pSdrObj)
535                 continue;
536 
537             if (ScDrawObjData *pAnchor = ScDrawLayer::GetNonRotatedObjData(pSdrObj))
538             {
539                 ScMyShape aMyShape;
540                 aMyShape.aAddress = pAnchor->maStart;
541                 SAL_WARN_IF(aMyShape.aAddress.Tab() != nTable, "sc", "not anchored to current sheet!");
542                 aMyShape.aAddress.SetTab(nTable);
543                 aMyShape.aEndAddress = pAnchor->maEnd;
544                 aMyShape.aEndAddress.SetTab( nTable );
545                 aMyShape.nEndX = pAnchor->maEndOffset.X();
546                 aMyShape.nEndY = pAnchor->maEndOffset.Y();
547                 aMyShape.xShape = xShape;
548                 aMyShape.bResizeWithCell = ScDrawLayer::IsResizeWithCell(*pSdrObj);
549                 pSharedData->AddNewShape(aMyShape);
550                 pSharedData->SetLastColumn(nTable, pAnchor->maStart.Col());
551                 pSharedData->SetLastRow(nTable, pAnchor->maStart.Row());
552             }
553             else
554                 pSharedData->AddTableShape(nTable, xShape);
555         }
556     }
557 }
558 
559 void ScXMLExport::CollectShapesAutoStyles(SCTAB nTableCount)
560 {
561     // #i84077# To avoid compiler warnings about uninitialized aShapeItr,
562     // it's initialized using this dummy list. The iterator contains shapes
563     // from all sheets, so it can't be declared inside the nTable loop where
564     // it is used.
565     ScMyShapeList aDummyInitList;
566 
567     pSharedData->SortShapesContainer();
568     pSharedData->SortNoteShapes();
569     const ScMyShapeList* pShapeList(nullptr);
570     ScMyShapeList::const_iterator aShapeItr = aDummyInitList.end();
571     if (pSharedData->GetShapesContainer())
572     {
573         pShapeList = &pSharedData->GetShapesContainer()->GetShapes();
574         aShapeItr = pShapeList->begin();
575     }
576     if (pSharedData->HasDrawPage())
577     {
578         for (SCTAB nTable = 0; nTable < nTableCount; ++nTable)
579         {
580             uno::Reference<drawing::XDrawPage> xDrawPage(pSharedData->GetDrawPage(nTable));
581 
582             if (xDrawPage.is())
583             {
584                 GetShapeExport()->seekShapes(xDrawPage);
585                 uno::Reference< form::XFormsSupplier2 > xFormsSupplier( xDrawPage, uno::UNO_QUERY );
586                 if( xFormsSupplier.is() && xFormsSupplier->hasForms() )
587                 {
588                     GetFormExport()->examineForms(xDrawPage);
589                     pSharedData->SetDrawPageHasForms(nTable, true);
590                 }
591                 ScMyTableShapes* pTableShapes(pSharedData->GetTableShapes());
592                 if (pTableShapes)
593                 {
594                     for (const auto& rxShape : (*pTableShapes)[nTable])
595                     {
596                         GetShapeExport()->collectShapeAutoStyles(rxShape);
597                         IncrementProgressBar(false);
598                     }
599                 }
600                 if (pShapeList)
601                 {
602                     ScMyShapeList::const_iterator aEndItr(pShapeList->end());
603                     while ( aShapeItr != aEndItr && ( aShapeItr->aAddress.Tab() == nTable ) )
604                     {
605                         GetShapeExport()->collectShapeAutoStyles(aShapeItr->xShape);
606                         IncrementProgressBar(false);
607                         ++aShapeItr;
608                     }
609                 }
610                 if (pSharedData->GetNoteShapes())
611                 {
612                     const ScMyNoteShapeList& rNoteShapes = pSharedData->GetNoteShapes()->GetNotes();
613                     for (const auto& rNoteShape : rNoteShapes)
614                     {
615                         if ( rNoteShape.aPos.Tab() == nTable )
616                             GetShapeExport()->collectShapeAutoStyles(rNoteShape.xShape);
617                     }
618                 }
619             }
620         }
621     }
622     pSharedData->SortNoteShapes(); // sort twice, because some more shapes are added
623 }
624 
625 void ScXMLExport::ExportMeta_()
626 {
627     sal_Int32 nCellCount(pDoc ? pDoc->GetCellCount() : 0);
628     SCTAB nTableCount(0);
629     sal_Int32 nShapesCount(0);
630     GetAutoStylePool()->ClearEntries();
631     CollectSharedData(nTableCount, nShapesCount);
632 
633     uno::Sequence<beans::NamedValue> stats
634     {
635         { "TableCount",  uno::makeAny(static_cast<sal_Int32>(nTableCount)) },
636         { "CellCount",   uno::makeAny(nCellCount) },
637         { "ObjectCount", uno::makeAny(nShapesCount) }
638     };
639 
640     // update document statistics at the model
641     uno::Reference<document::XDocumentPropertiesSupplier> xPropSup(GetModel(),
642         uno::UNO_QUERY_THROW);
643     uno::Reference<document::XDocumentProperties> xDocProps(
644         xPropSup->getDocumentProperties());
645     if (xDocProps.is()) {
646         xDocProps->setDocumentStatistics(stats);
647     }
648 
649     // export document properties
650     SvXMLExport::ExportMeta_();
651 }
652 
653 void ScXMLExport::ExportFontDecls_()
654 {
655     GetFontAutoStylePool(); // make sure the pool is created
656     SvXMLExport::ExportFontDecls_();
657 }
658 
659 table::CellRangeAddress ScXMLExport::GetEndAddress(const uno::Reference<sheet::XSpreadsheet>& xTable)
660 {
661     table::CellRangeAddress aCellAddress;
662     uno::Reference<sheet::XSheetCellCursor> xCursor(xTable->createCursor());
663     uno::Reference<sheet::XUsedAreaCursor> xUsedArea (xCursor, uno::UNO_QUERY);
664     uno::Reference<sheet::XCellRangeAddressable> xCellAddress (xCursor, uno::UNO_QUERY);
665     if (xUsedArea.is() && xCellAddress.is())
666     {
667         xUsedArea->gotoEndOfUsedArea(true);
668         aCellAddress = xCellAddress->getRangeAddress();
669     }
670     return aCellAddress;
671 }
672 
673 void ScXMLExport::GetAreaLinks( ScMyAreaLinksContainer& rAreaLinks )
674 {
675     if (pDoc->GetLinkManager())
676     {
677         const sfx2::SvBaseLinks& rLinks = pDoc->GetLinkManager()->GetLinks();
678         for (const auto & rLink : rLinks)
679         {
680             ScAreaLink *pLink = dynamic_cast<ScAreaLink*>(rLink.get());
681             if (pLink)
682             {
683                 ScMyAreaLink aAreaLink;
684                 aAreaLink.aDestRange = pLink->GetDestArea();
685                 aAreaLink.sSourceStr = pLink->GetSource();
686                 aAreaLink.sFilter = pLink->GetFilter();
687                 aAreaLink.sFilterOptions = pLink->GetOptions();
688                 aAreaLink.sURL = pLink->GetFile();
689                 aAreaLink.nRefresh = pLink->GetRefreshDelay();
690                 rAreaLinks.AddNewAreaLink( aAreaLink );
691             }
692         }
693     }
694     rAreaLinks.Sort();
695 }
696 
697 // core implementation
698 void ScXMLExport::GetDetectiveOpList( ScMyDetectiveOpContainer& rDetOp )
699 {
700     if (pDoc)
701     {
702         ScDetOpList* pOpList(pDoc->GetDetOpList());
703         if( pOpList )
704         {
705             size_t nCount = pOpList->Count();
706             for (size_t nIndex = 0; nIndex < nCount; ++nIndex )
707             {
708                 const ScDetOpData& rDetData = pOpList->GetObject( nIndex);
709                 const ScAddress& rDetPos = rDetData.GetPos();
710                 SCTAB nTab = rDetPos.Tab();
711                 if ( nTab < pDoc->GetTableCount() )
712                 {
713                     rDetOp.AddOperation( rDetData.GetOperation(), rDetPos, static_cast<sal_uInt32>( nIndex) );
714 
715                     // cells with detective operations are written even if empty
716                     pSharedData->SetLastColumn( nTab, rDetPos.Col() );
717                     pSharedData->SetLastRow( nTab, rDetPos.Row() );
718                 }
719             }
720             rDetOp.Sort();
721         }
722     }
723 }
724 
725 void ScXMLExport::WriteSingleColumn(const sal_Int32 nRepeatColumns, const sal_Int32 nStyleIndex,
726     const sal_Int32 nIndex, const bool bIsAutoStyle, const bool bIsVisible)
727 {
728     CheckAttrList();
729     AddAttribute(sAttrStyleName, pColumnStyles->GetStyleNameByIndex(nStyleIndex));
730     if (!bIsVisible)
731         AddAttribute(XML_NAMESPACE_TABLE, XML_VISIBILITY, XML_COLLAPSE);
732     if (nRepeatColumns > 1)
733     {
734         OUString sOUEndCol(OUString::number(nRepeatColumns));
735         AddAttribute(sAttrColumnsRepeated, sOUEndCol);
736     }
737     if (nIndex != -1)
738         AddAttribute(XML_NAMESPACE_TABLE, XML_DEFAULT_CELL_STYLE_NAME, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
739     SvXMLElementExport aElemC(*this, sElemCol, true, true);
740 }
741 
742 void ScXMLExport::WriteColumn(const sal_Int32 nColumn, const sal_Int32 nRepeatColumns,
743     const sal_Int32 nStyleIndex, const bool bIsVisible)
744 {
745     sal_Int32 nRepeat(1);
746     sal_Int32 nPrevIndex(pDefaults->GetColDefaults()[nColumn].nIndex);
747     bool bPrevAutoStyle(pDefaults->GetColDefaults()[nColumn].bIsAutoStyle);
748     for (sal_Int32 i = nColumn + 1; i < nColumn + nRepeatColumns; ++i)
749     {
750         if ((pDefaults->GetColDefaults()[i].nIndex != nPrevIndex) ||
751             (pDefaults->GetColDefaults()[i].bIsAutoStyle != bPrevAutoStyle))
752         {
753             WriteSingleColumn(nRepeat, nStyleIndex, nPrevIndex, bPrevAutoStyle, bIsVisible);
754             nPrevIndex = pDefaults->GetColDefaults()[i].nIndex;
755             bPrevAutoStyle = pDefaults->GetColDefaults()[i].bIsAutoStyle;
756             nRepeat = 1;
757         }
758         else
759             ++nRepeat;
760     }
761     WriteSingleColumn(nRepeat, nStyleIndex, nPrevIndex, bPrevAutoStyle, bIsVisible);
762 }
763 
764 void ScXMLExport::OpenHeaderColumn()
765 {
766     StartElement( XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS, true );
767 }
768 
769 void ScXMLExport::CloseHeaderColumn()
770 {
771     EndElement(XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS, true);
772 }
773 
774 void ScXMLExport::ExportColumns(const sal_Int32 nTable, const ScRange& aColumnHeaderRange, const bool bHasColumnHeader)
775 {
776     sal_Int32 nColsRepeated (1);
777     sal_Int32 nIndex;
778     sal_Int32 nPrevColumn(0);
779     bool bPrevIsVisible (true);
780     bool bWasHeader (false);
781     bool bIsClosed (true);
782     sal_Int32 nPrevIndex (-1);
783     sal_Int32 nColumn;
784     for (nColumn = 0; nColumn <= pSharedData->GetLastColumn(nTable); ++nColumn)
785     {
786         CheckAttrList();
787         bool bIsVisible(true);
788         nIndex = pColumnStyles->GetStyleNameIndex(nTable, nColumn, bIsVisible);
789 
790         const bool bIsHeader = bHasColumnHeader && (aColumnHeaderRange.aStart.Col() <= nColumn) && (nColumn <= aColumnHeaderRange.aEnd.Col());
791         if (bIsHeader != bWasHeader)
792         {
793             if (bIsHeader)
794             {
795                 if (nColumn > 0)
796                 {
797                     WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
798                     if (pGroupColumns->IsGroupEnd(nColumn - 1))
799                         pGroupColumns->CloseGroups(nColumn - 1);
800                 }
801                 bPrevIsVisible = bIsVisible;
802                 nPrevIndex = nIndex;
803                 nPrevColumn = nColumn;
804                 nColsRepeated = 1;
805                 if(pGroupColumns->IsGroupStart(nColumn))
806                     pGroupColumns->OpenGroups(nColumn);
807                 OpenHeaderColumn();
808                 bWasHeader = true;
809                 bIsClosed = false;
810             }
811             else
812             {
813                 WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
814                 CloseHeaderColumn();
815                 if (pGroupColumns->IsGroupEnd(nColumn - 1))
816                     pGroupColumns->CloseGroups(nColumn - 1);
817                 if(pGroupColumns->IsGroupStart(nColumn))
818                     pGroupColumns->OpenGroups(nColumn);
819                 bPrevIsVisible = bIsVisible;
820                 nPrevIndex = nIndex;
821                 nPrevColumn = nColumn;
822                 nColsRepeated = 1;
823                 bWasHeader = false;
824                 bIsClosed = true;
825             }
826         }
827         else if (nColumn == 0)
828         {
829             if (pGroupColumns->IsGroupStart(nColumn))
830                 pGroupColumns->OpenGroups(nColumn);
831             bPrevIsVisible = bIsVisible;
832             nPrevIndex = nIndex;
833         }
834         else if ((bIsVisible == bPrevIsVisible) && (nIndex == nPrevIndex) &&
835             !pGroupColumns->IsGroupStart(nColumn) && !pGroupColumns->IsGroupEnd(nColumn - 1))
836             ++nColsRepeated;
837         else
838         {
839             WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
840             if (pGroupColumns->IsGroupEnd(nColumn - 1))
841             {
842                 if (bIsHeader)
843                     CloseHeaderColumn();
844                 pGroupColumns->CloseGroups(nColumn - 1);
845                 if (bIsHeader)
846                     OpenHeaderColumn();
847             }
848             if (pGroupColumns->IsGroupStart(nColumn))
849             {
850                 if (bIsHeader)
851                     CloseHeaderColumn();
852                 pGroupColumns->OpenGroups(nColumn);
853                 if (bIsHeader)
854                     OpenHeaderColumn();
855             }
856             bPrevIsVisible = bIsVisible;
857             nPrevIndex = nIndex;
858             nPrevColumn = nColumn;
859             nColsRepeated = 1;
860         }
861     }
862     assert(nPrevIndex >= 0 && "coverity#1438402");
863     WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
864     if (!bIsClosed)
865         CloseHeaderColumn();
866     if (pGroupColumns->IsGroupEnd(nColumn - 1))
867         pGroupColumns->CloseGroups(nColumn - 1);
868 }
869 
870 void ScXMLExport::ExportExternalRefCacheStyles()
871 {
872     sal_Int32 nEntryIndex = GetCellStylesPropertySetMapper()->FindEntryIndex(
873         "NumberFormat", XML_NAMESPACE_STYLE, "data-style-name");
874 
875     if (nEntryIndex < 0)
876         // No entry index for the number format is found.
877         return;
878 
879     ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
880     if (!pRefMgr->hasExternalData())
881         // No external reference data cached.
882         return;
883 
884     // Export each unique number format used in the external ref cache.
885     vector<sal_uInt32> aNumFmts;
886     pRefMgr->getAllCachedNumberFormats(aNumFmts);
887     const OUString aDefaultStyle = OUString("Default").intern();
888     for (const auto& rNumFmt : aNumFmts)
889     {
890         sal_Int32 nNumFmt = static_cast<sal_Int32>(rNumFmt);
891 
892         addDataStyle(nNumFmt);
893 
894         uno::Any aVal;
895         aVal <<= nNumFmt;
896         vector<XMLPropertyState> aProps;
897         aVal <<= aDefaultStyle;
898         aProps.emplace_back(nEntryIndex, aVal);
899 
900         OUString aName;
901         sal_Int32 nIndex;
902         if (GetAutoStylePool()->Add(aName, XML_STYLE_FAMILY_TABLE_CELL, aDefaultStyle, aProps))
903         {
904             pCellStyles->AddStyleName(aName, nIndex);
905         }
906         else
907         {
908             bool bIsAuto;
909             nIndex = pCellStyles->GetIndexOfStyleName(
910                 aName, XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX, bIsAuto);
911         }
912 
913         // store the number format to index mapping for later use.
914         aNumFmtIndexMap.emplace(nNumFmt, nIndex);
915     }
916 }
917 
918 namespace {
919 
920 void handleFont(
921     std::vector<XMLPropertyState>& rPropStates,
922     const SfxPoolItem* p, const rtl::Reference<XMLPropertySetMapper>& xMapper, const OUString& rXMLName )
923 {
924     sal_Int32 nEntryCount = xMapper->GetEntryCount();
925 
926     // Apparently font info needs special handling.
927     const SvxFontItem* pItem = static_cast<const SvxFontItem*>(p);
928 
929     sal_Int32 nIndexFontName = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, rXMLName, 0);
930 
931     if (nIndexFontName == -1 || nIndexFontName >= nEntryCount)
932         return;
933 
934     uno::Any aAny;
935     if (!pItem->QueryValue(aAny, MID_FONT_FAMILY_NAME))
936         return;
937 
938     rPropStates.emplace_back(nIndexFontName, aAny);
939 }
940 
941 const SvxFieldData* toXMLPropertyStates(
942     std::vector<XMLPropertyState>& rPropStates, const std::vector<const SfxPoolItem*>& rSecAttrs,
943     const rtl::Reference<XMLPropertySetMapper>& xMapper, const ScXMLEditAttributeMap& rAttrMap )
944 {
945     const SvxFieldData* pField = nullptr;
946     sal_Int32 nEntryCount = xMapper->GetEntryCount();
947     rPropStates.reserve(rSecAttrs.size());
948     for (const SfxPoolItem* p : rSecAttrs)
949     {
950         if (p->Which() == EE_FEATURE_FIELD)
951         {
952             pField = static_cast<const SvxFieldItem*>(p)->GetField();
953             continue;
954         }
955 
956         const ScXMLEditAttributeMap::Entry* pEntry = rAttrMap.getEntryByItemID(p->Which());
957         if (!pEntry)
958             continue;
959 
960         sal_Int32 nIndex = xMapper->GetEntryIndex(
961             pEntry->nmXMLNS, OUString::createFromAscii(pEntry->mpXMLName), 0);
962 
963         if (nIndex == -1 || nIndex >= nEntryCount)
964             continue;
965 
966         uno::Any aAny;
967         switch (p->Which())
968         {
969             case EE_CHAR_FONTINFO:
970                 handleFont(rPropStates, p, xMapper, "font-name");
971             break;
972             case EE_CHAR_FONTINFO_CJK:
973                 handleFont(rPropStates, p, xMapper, "font-name-asian");
974             break;
975             case EE_CHAR_FONTINFO_CTL:
976                 handleFont(rPropStates, p, xMapper, "font-name-complex");
977             break;
978             case EE_CHAR_WEIGHT:
979             case EE_CHAR_WEIGHT_CJK:
980             case EE_CHAR_WEIGHT_CTL:
981             {
982                 if (!static_cast<const SvxWeightItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
983                     continue;
984 
985                 rPropStates.emplace_back(nIndex, aAny);
986             }
987             break;
988             case EE_CHAR_FONTHEIGHT:
989             case EE_CHAR_FONTHEIGHT_CJK:
990             case EE_CHAR_FONTHEIGHT_CTL:
991             {
992                 if (!static_cast<const SvxFontHeightItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
993                     continue;
994 
995                 rPropStates.emplace_back(nIndex, aAny);
996             }
997             break;
998             case EE_CHAR_ITALIC:
999             case EE_CHAR_ITALIC_CJK:
1000             case EE_CHAR_ITALIC_CTL:
1001             {
1002                 if (!static_cast<const SvxPostureItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1003                     continue;
1004 
1005                 rPropStates.emplace_back(nIndex, aAny);
1006             }
1007             break;
1008             case EE_CHAR_UNDERLINE:
1009             {
1010                 // Underline attribute needs to export multiple entries.
1011                 sal_Int32 nIndexStyle = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-underline-style", 0);
1012                 if (nIndexStyle == -1 || nIndexStyle > nEntryCount)
1013                     break;
1014 
1015                 sal_Int32 nIndexWidth = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-underline-width", 0);
1016                 if (nIndexWidth == -1 || nIndexWidth > nEntryCount)
1017                     break;
1018 
1019                 sal_Int32 nIndexType = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-underline-type", 0);
1020                 if (nIndexType == -1 || nIndexType > nEntryCount)
1021                     break;
1022 
1023                 sal_Int32 nIndexColor = xMapper->FindEntryIndex("CharUnderlineColor", XML_NAMESPACE_STYLE, "text-underline-color");
1024                 if (nIndexColor == -1 || nIndexColor > nEntryCount)
1025                     break;
1026 
1027                 sal_Int32 nIndexHasColor = xMapper->FindEntryIndex("CharUnderlineHasColor", XML_NAMESPACE_STYLE, "text-underline-color");
1028                 if (nIndexHasColor == -1 || nIndexHasColor > nEntryCount)
1029                     break;
1030 
1031                 const SvxUnderlineItem* pUL = static_cast<const SvxUnderlineItem*>(p);
1032                 pUL->QueryValue(aAny, MID_TL_STYLE);
1033                 rPropStates.emplace_back(nIndexStyle, aAny);
1034                 rPropStates.emplace_back(nIndexType,  aAny);
1035                 rPropStates.emplace_back(nIndexWidth, aAny);
1036 
1037                 pUL->QueryValue(aAny, MID_TL_COLOR);
1038                 rPropStates.emplace_back(nIndexColor, aAny);
1039 
1040                 pUL->QueryValue(aAny, MID_TL_HASCOLOR);
1041                 rPropStates.emplace_back(nIndexHasColor, aAny);
1042             }
1043             break;
1044             case EE_CHAR_OVERLINE:
1045             {
1046                 // Same with overline.  Do just as we do with underline attributes.
1047                 sal_Int32 nIndexStyle = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-overline-style", 0);
1048                 if (nIndexStyle == -1 || nIndexStyle > nEntryCount)
1049                     break;
1050 
1051                 sal_Int32 nIndexWidth = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-overline-width", 0);
1052                 if (nIndexWidth == -1 || nIndexWidth > nEntryCount)
1053                     break;
1054 
1055                 sal_Int32 nIndexType = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-overline-type", 0);
1056                 if (nIndexType == -1 || nIndexType > nEntryCount)
1057                     break;
1058 
1059                 sal_Int32 nIndexColor = xMapper->FindEntryIndex("CharOverlineColor", XML_NAMESPACE_STYLE, "text-overline-color");
1060                 if (nIndexColor == -1 || nIndexColor > nEntryCount)
1061                     break;
1062 
1063                 sal_Int32 nIndexHasColor = xMapper->FindEntryIndex("CharOverlineHasColor", XML_NAMESPACE_STYLE, "text-overline-color");
1064                 if (nIndexHasColor == -1 || nIndexHasColor > nEntryCount)
1065                     break;
1066 
1067                 const SvxOverlineItem* pOL = static_cast<const SvxOverlineItem*>(p);
1068                 pOL->QueryValue(aAny, MID_TL_STYLE);
1069                 rPropStates.emplace_back(nIndexStyle, aAny);
1070                 rPropStates.emplace_back(nIndexType,  aAny);
1071                 rPropStates.emplace_back(nIndexWidth, aAny);
1072 
1073                 pOL->QueryValue(aAny, MID_TL_COLOR);
1074                 rPropStates.emplace_back(nIndexColor, aAny);
1075 
1076                 pOL->QueryValue(aAny, MID_TL_HASCOLOR);
1077                 rPropStates.emplace_back(nIndexHasColor, aAny);
1078             }
1079             break;
1080             case EE_CHAR_COLOR:
1081             {
1082                 if (!static_cast<const SvxColorItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1083                     continue;
1084 
1085                 ::Color nColor;
1086                 if ( aAny >>= nColor )
1087                 {
1088                     sal_Int32 nIndexColor = ( nColor == COL_AUTO ) ? xMapper->GetEntryIndex(
1089                         XML_NAMESPACE_STYLE, GetXMLToken( XML_USE_WINDOW_FONT_COLOR ), 0 ) : nIndex;
1090                     rPropStates.emplace_back( nIndexColor, aAny );
1091                 }
1092             }
1093             break;
1094             case EE_CHAR_WLM:
1095             {
1096                 if (!static_cast<const SvxWordLineModeItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1097                     continue;
1098 
1099                 rPropStates.emplace_back(nIndex, aAny);
1100             }
1101             break;
1102             case EE_CHAR_STRIKEOUT:
1103             {
1104                 if (!static_cast<const SvxCrossedOutItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1105                     continue;
1106 
1107                 rPropStates.emplace_back(nIndex, aAny);
1108             }
1109             break;
1110             case EE_CHAR_RELIEF:
1111             {
1112                 if (!static_cast<const SvxCharReliefItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1113                     continue;
1114 
1115                 rPropStates.emplace_back(nIndex, aAny);
1116             }
1117             break;
1118             case EE_CHAR_OUTLINE:
1119             {
1120                 if (!static_cast<const SvxContourItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1121                     continue;
1122 
1123                 rPropStates.emplace_back(nIndex, aAny);
1124             }
1125             break;
1126             case EE_CHAR_SHADOW:
1127             {
1128                 if (!static_cast<const SvxShadowedItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1129                     continue;
1130 
1131                 rPropStates.emplace_back(nIndex, aAny);
1132             }
1133             break;
1134             case EE_CHAR_KERNING:
1135             {
1136                 if (!static_cast<const SvxKerningItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1137                     continue;
1138 
1139                 rPropStates.emplace_back(nIndex, aAny);
1140             }
1141             break;
1142             case EE_CHAR_PAIRKERNING:
1143             {
1144                 if (!static_cast<const SvxAutoKernItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1145                     continue;
1146 
1147                 rPropStates.emplace_back(nIndex, aAny);
1148             }
1149             break;
1150             case EE_CHAR_FONTWIDTH:
1151             {
1152                 if (!static_cast<const SvxCharScaleWidthItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1153                     continue;
1154 
1155                 rPropStates.emplace_back(nIndex, aAny);
1156             }
1157             break;
1158             case EE_CHAR_ESCAPEMENT:
1159             {
1160                 sal_Int32 nIndexEsc = xMapper->FindEntryIndex("CharEscapement", XML_NAMESPACE_STYLE, "text-position");
1161                 if (nIndexEsc == -1 || nIndexEsc > nEntryCount)
1162                     break;
1163 
1164                 sal_Int32 nIndexEscHeight = xMapper->FindEntryIndex("CharEscapementHeight", XML_NAMESPACE_STYLE, "text-position");
1165                 if (nIndexEscHeight == -1 || nIndexEscHeight > nEntryCount)
1166                     break;
1167 
1168                 const SvxEscapementItem* pEsc = static_cast<const SvxEscapementItem*>(p);
1169 
1170                 pEsc->QueryValue(aAny);
1171                 rPropStates.emplace_back(nIndexEsc, aAny);
1172 
1173                 pEsc->QueryValue(aAny, MID_ESC_HEIGHT);
1174                 rPropStates.emplace_back(nIndexEscHeight, aAny);
1175 
1176             }
1177             break;
1178             case EE_CHAR_EMPHASISMARK:
1179             {
1180                 if (!static_cast<const SvxEmphasisMarkItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1181                     continue;
1182 
1183                 rPropStates.emplace_back(nIndex, aAny);
1184             }
1185             break;
1186             case EE_CHAR_LANGUAGE:
1187             case EE_CHAR_LANGUAGE_CJK:
1188             case EE_CHAR_LANGUAGE_CTL:
1189             {
1190                 if (!static_cast<const SvxLanguageItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1191                     continue;
1192 
1193                 // Export multiple entries.
1194                 sal_Int32 nIndexLanguage, nIndexCountry, nIndexScript, nIndexTag;
1195                 switch (p->Which())
1196                 {
1197                     case EE_CHAR_LANGUAGE:
1198                         nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_FO, "language", 0);
1199                         nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_FO, "country", 0);
1200                         nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_FO, "script", 0);
1201                         nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "rfc-language-tag", 0);
1202                     break;
1203                     case EE_CHAR_LANGUAGE_CJK:
1204                         nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "language-asian", 0);
1205                         nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "country-asian", 0);
1206                         nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "script-asian", 0);
1207                         nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "rfc-language-tag-asian", 0);
1208                     break;
1209                     case EE_CHAR_LANGUAGE_CTL:
1210                         nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "language-complex", 0);
1211                         nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "country-complex", 0);
1212                         nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "script-complex", 0);
1213                         nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "rfc-language-tag-complex", 0);
1214                     break;
1215                     default:
1216                         nIndexLanguage = nIndexCountry = nIndexScript = nIndexTag = -1;
1217                 }
1218                 assert( nIndexLanguage >= 0 && nIndexCountry >= 0 && nIndexScript >= 0 && nIndexTag >= 0);
1219                 rPropStates.emplace_back( nIndexLanguage, aAny);
1220                 rPropStates.emplace_back( nIndexCountry, aAny);
1221                 rPropStates.emplace_back( nIndexScript, aAny);
1222                 rPropStates.emplace_back( nIndexTag, aAny);
1223             }
1224             break;
1225             default:
1226                 continue;
1227         }
1228     }
1229 
1230     return pField;
1231 }
1232 
1233 }
1234 
1235 void ScXMLExport::ExportCellTextAutoStyles(sal_Int32 nTable)
1236 {
1237     if (!ValidTab(nTable))
1238         return;
1239 
1240     rtl::Reference<XMLPropertySetMapper> xMapper = GetTextParagraphExport()->GetTextPropMapper()->getPropertySetMapper();
1241     rtl::Reference<SvXMLAutoStylePoolP> xStylePool = GetAutoStylePool();
1242     const ScXMLEditAttributeMap& rAttrMap = GetEditAttributeMap();
1243 
1244     sc::EditTextIterator aIter(*pDoc, nTable);
1245     sal_Int32 nCellCount = 0;
1246     for (const EditTextObject* pEdit = aIter.first(); pEdit; pEdit = aIter.next(), ++nCellCount)
1247     {
1248         std::vector<editeng::Section> aAttrs;
1249         pEdit->GetAllSections(aAttrs);
1250         if (aAttrs.empty())
1251             continue;
1252 
1253         for (const auto& rSec : aAttrs)
1254         {
1255             const std::vector<const SfxPoolItem*>& rSecAttrs = rSec.maAttributes;
1256             if (rSecAttrs.empty())
1257                 // No formats applied to this section. Skip it.
1258                 continue;
1259 
1260             std::vector<XMLPropertyState> aPropStates;
1261             toXMLPropertyStates(aPropStates, rSecAttrs, xMapper, rAttrMap);
1262             if (!aPropStates.empty())
1263                 xStylePool->Add(XML_STYLE_FAMILY_TEXT_TEXT, OUString(), aPropStates);
1264         }
1265     }
1266 
1267     GetProgressBarHelper()->ChangeReference(GetProgressBarHelper()->GetReference() + nCellCount);
1268 }
1269 
1270 void ScXMLExport::WriteRowContent()
1271 {
1272     ScMyRowFormatRange aRange;
1273     sal_Int32 nIndex(-1);
1274 #if OSL_DEBUG_LEVEL > 0
1275     sal_Int32 nPrevCol(0);
1276 #endif
1277     sal_Int32 nCols(0);
1278     sal_Int32 nPrevValidationIndex(-1);
1279     bool bIsAutoStyle(true);
1280     bool bIsFirst(true);
1281     while (pRowFormatRanges->GetNext(aRange))
1282     {
1283 #if OSL_DEBUG_LEVEL > 0
1284         OSL_ENSURE(bIsFirst || (!bIsFirst && (nPrevCol + nCols == aRange.nStartColumn)), "here are some columns missing");
1285 #endif
1286         if (bIsFirst)
1287         {
1288             nIndex = aRange.nIndex;
1289             nPrevValidationIndex = aRange.nValidationIndex;
1290             bIsAutoStyle = aRange.bIsAutoStyle;
1291             nCols = aRange.nRepeatColumns;
1292             bIsFirst = false;
1293 #if OSL_DEBUG_LEVEL > 0
1294             nPrevCol = aRange.nStartColumn;
1295 #endif
1296         }
1297         else
1298         {
1299             if (((aRange.nIndex == nIndex && aRange.bIsAutoStyle == bIsAutoStyle) ||
1300                 (aRange.nIndex == nIndex && nIndex == -1)) &&
1301                 nPrevValidationIndex == aRange.nValidationIndex)
1302                 nCols += aRange.nRepeatColumns;
1303             else
1304             {
1305                 if (nIndex != -1)
1306                     AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
1307                 if (nPrevValidationIndex > -1)
1308                     AddAttribute(XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, pValidationsContainer->GetValidationName(nPrevValidationIndex));
1309                 if (nCols > 1)
1310                 {
1311                     AddAttribute(sAttrColumnsRepeated, OUString::number(nCols));
1312                 }
1313                 SvXMLElementExport aElemC(*this, sElemCell, true, true);
1314                 nIndex = aRange.nIndex;
1315                 bIsAutoStyle = aRange.bIsAutoStyle;
1316                 nCols = aRange.nRepeatColumns;
1317                 nPrevValidationIndex = aRange.nValidationIndex;
1318 #if OSL_DEBUG_LEVEL > 0
1319                 nPrevCol = aRange.nStartColumn;
1320 #endif
1321             }
1322         }
1323     }
1324     if (!bIsFirst)
1325     {
1326         if (nIndex != -1)
1327             AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
1328         if (nPrevValidationIndex > -1)
1329             AddAttribute(XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, pValidationsContainer->GetValidationName(nPrevValidationIndex));
1330         if (nCols > 1)
1331         {
1332             AddAttribute(sAttrColumnsRepeated, OUString::number(nCols));
1333         }
1334         SvXMLElementExport aElemC(*this, sElemCell, true, true);
1335     }
1336 }
1337 
1338 void ScXMLExport::WriteRowStartTag(
1339     const sal_Int32 nIndex, const sal_Int32 nEqualRows,
1340     bool bHidden, bool bFiltered)
1341 {
1342     AddAttribute(sAttrStyleName, pRowStyles->GetStyleNameByIndex(nIndex));
1343     if (bHidden)
1344     {
1345         if (bFiltered)
1346             AddAttribute(XML_NAMESPACE_TABLE, XML_VISIBILITY, XML_FILTER);
1347         else
1348             AddAttribute(XML_NAMESPACE_TABLE, XML_VISIBILITY, XML_COLLAPSE);
1349     }
1350     if (nEqualRows > 1)
1351     {
1352         AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, OUString::number(nEqualRows));
1353     }
1354 
1355     StartElement( sElemRow, true);
1356 }
1357 
1358 void ScXMLExport::OpenHeaderRows()
1359 {
1360     StartElement( XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, true);
1361     bRowHeaderOpen = true;
1362 }
1363 
1364 void ScXMLExport::CloseHeaderRows()
1365 {
1366     EndElement(XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, true);
1367 }
1368 
1369 void ScXMLExport::OpenNewRow(
1370     const sal_Int32 nIndex, const sal_Int32 nStartRow, const sal_Int32 nEqualRows,
1371     bool bHidden, bool bFiltered)
1372 {
1373     nOpenRow = nStartRow;
1374     if (pGroupRows->IsGroupStart(nStartRow))
1375     {
1376         if (bHasRowHeader && bRowHeaderOpen)
1377             CloseHeaderRows();
1378         pGroupRows->OpenGroups(nStartRow);
1379         if (bHasRowHeader && bRowHeaderOpen)
1380             OpenHeaderRows();
1381     }
1382     if (bHasRowHeader && !bRowHeaderOpen && nStartRow >= aRowHeaderRange.aStart.Row() && nStartRow <= aRowHeaderRange.aEnd.Row())
1383     {
1384         if (nStartRow == aRowHeaderRange.aStart.Row())
1385             OpenHeaderRows();
1386         sal_Int32 nEquals;
1387         if (aRowHeaderRange.aEnd.Row() < nStartRow + nEqualRows - 1)
1388             nEquals = aRowHeaderRange.aEnd.Row() - nStartRow + 1;
1389         else
1390             nEquals = nEqualRows;
1391         WriteRowStartTag(nIndex, nEquals, bHidden, bFiltered);
1392         nOpenRow = nStartRow + nEquals - 1;
1393         if (nEquals < nEqualRows)
1394         {
1395             CloseRow(nStartRow + nEquals - 1);
1396             WriteRowStartTag(nIndex, nEqualRows - nEquals, bHidden, bFiltered);
1397             nOpenRow = nStartRow + nEqualRows - 1;
1398         }
1399     }
1400     else
1401         WriteRowStartTag(nIndex, nEqualRows, bHidden, bFiltered);
1402 }
1403 
1404 void ScXMLExport::OpenAndCloseRow(
1405     const sal_Int32 nIndex, const sal_Int32 nStartRow, const sal_Int32 nEqualRows,
1406     bool bHidden, bool bFiltered)
1407 {
1408     OpenNewRow(nIndex, nStartRow, nEqualRows, bHidden, bFiltered);
1409     WriteRowContent();
1410     CloseRow(nStartRow + nEqualRows - 1);
1411     pRowFormatRanges->Clear();
1412 }
1413 
1414 void ScXMLExport::OpenRow(const sal_Int32 nTable, const sal_Int32 nStartRow, const sal_Int32 nRepeatRow, ScXMLCachedRowAttrAccess& rRowAttr)
1415 {
1416     if (nRepeatRow > 1)
1417     {
1418         sal_Int32 nPrevIndex(0), nIndex;
1419         bool bPrevHidden = false;
1420         bool bPrevFiltered = false;
1421         bool bHidden = false;
1422         bool bFiltered = false;
1423         sal_Int32 nEqualRows(1);
1424         sal_Int32 nEndRow(nStartRow + nRepeatRow);
1425         sal_Int32 nEndRowHidden = nStartRow - 1;
1426         sal_Int32 nEndRowFiltered = nStartRow - 1;
1427         sal_Int32 nRow;
1428         for (nRow = nStartRow; nRow < nEndRow; ++nRow)
1429         {
1430             if (nRow == nStartRow)
1431             {
1432                 nPrevIndex = pRowStyles->GetStyleNameIndex(nTable, nRow);
1433                 if (pDoc)
1434                 {
1435                     if (nRow > nEndRowHidden)
1436                     {
1437                         bPrevHidden = rRowAttr.rowHidden(nTable, nRow, nEndRowHidden);
1438                         bHidden = bPrevHidden;
1439                     }
1440                     if (nRow > nEndRowFiltered)
1441                     {
1442                         bPrevFiltered = rRowAttr.rowFiltered(nTable, nRow, nEndRowFiltered);
1443                         bFiltered = bPrevFiltered;
1444                     }
1445                 }
1446 
1447             }
1448             else
1449             {
1450                 nIndex = pRowStyles->GetStyleNameIndex(nTable, nRow);
1451                 if (pDoc)
1452                 {
1453                     if (nRow > nEndRowHidden)
1454                         bHidden = rRowAttr.rowHidden(nTable, nRow, nEndRowHidden);
1455                     if (nRow > nEndRowFiltered)
1456                         bFiltered = rRowAttr.rowFiltered(nTable, nRow, nEndRowFiltered);
1457                 }
1458                 if (nIndex == nPrevIndex && bHidden == bPrevHidden && bFiltered == bPrevFiltered &&
1459                     !(bHasRowHeader && ((nRow == aRowHeaderRange.aStart.Row()) || (nRow - 1 == aRowHeaderRange.aEnd.Row()))) &&
1460                     !(pGroupRows->IsGroupStart(nRow)) &&
1461                     !(pGroupRows->IsGroupEnd(nRow - 1)))
1462                     ++nEqualRows;
1463                 else
1464                 {
1465                     assert(nPrevIndex >= 0 && "coverity#1438402");
1466                     ScRowFormatRanges* pTempRowFormatRanges = new ScRowFormatRanges(pRowFormatRanges.get());
1467                     OpenAndCloseRow(nPrevIndex, nRow - nEqualRows, nEqualRows, bPrevHidden, bPrevFiltered);
1468                     pRowFormatRanges.reset(pTempRowFormatRanges);
1469                     nEqualRows = 1;
1470                     nPrevIndex = nIndex;
1471                     bPrevHidden = bHidden;
1472                     bPrevFiltered = bFiltered;
1473                 }
1474             }
1475         }
1476         assert(nPrevIndex >= 0 && "coverity#1438402");
1477         OpenNewRow(nPrevIndex, nRow - nEqualRows, nEqualRows, bPrevHidden, bPrevFiltered);
1478     }
1479     else
1480     {
1481         sal_Int32 nIndex = pRowStyles->GetStyleNameIndex(nTable, nStartRow);
1482         bool bHidden = false;
1483         bool bFiltered = false;
1484         if (pDoc)
1485         {
1486             sal_Int32 nEndRowHidden;
1487             sal_Int32 nEndRowFiltered;
1488             bHidden = rRowAttr.rowHidden(nTable, nStartRow, nEndRowHidden);
1489             bFiltered = rRowAttr.rowFiltered(nTable, nStartRow, nEndRowFiltered);
1490         }
1491         assert(nIndex >= 0 && "coverity#1438402");
1492         OpenNewRow(nIndex, nStartRow, 1, bHidden, bFiltered);
1493     }
1494     nOpenRow = nStartRow + nRepeatRow - 1;
1495 }
1496 
1497 void ScXMLExport::CloseRow(const sal_Int32 nRow)
1498 {
1499     if (nOpenRow > -1)
1500     {
1501         EndElement(sElemRow, true);
1502         if (bHasRowHeader && nRow == aRowHeaderRange.aEnd.Row())
1503         {
1504             CloseHeaderRows();
1505             bRowHeaderOpen = false;
1506         }
1507         if (pGroupRows->IsGroupEnd(nRow))
1508         {
1509             if (bHasRowHeader && bRowHeaderOpen)
1510                 CloseHeaderRows();
1511             pGroupRows->CloseGroups(nRow);
1512             if (bHasRowHeader && bRowHeaderOpen)
1513                 OpenHeaderRows();
1514         }
1515     }
1516     nOpenRow = -1;
1517 }
1518 
1519 void ScXMLExport::ExportFormatRanges(const sal_Int32 nStartCol, const sal_Int32 nStartRow,
1520     const sal_Int32 nEndCol, const sal_Int32 nEndRow, const sal_Int32 nSheet)
1521 {
1522     pRowFormatRanges->Clear();
1523     ScXMLCachedRowAttrAccess aRowAttr(pDoc);
1524     if (nStartRow == nEndRow)
1525     {
1526         pCellStyles->GetFormatRanges(nStartCol, nEndCol, nStartRow, nSheet, pRowFormatRanges.get());
1527         if (nOpenRow == - 1)
1528             OpenRow(nSheet, nStartRow, 1, aRowAttr);
1529         WriteRowContent();
1530         pRowFormatRanges->Clear();
1531     }
1532     else
1533     {
1534         if (nOpenRow > -1)
1535         {
1536             pCellStyles->GetFormatRanges(nStartCol, pSharedData->GetLastColumn(nSheet), nStartRow, nSheet, pRowFormatRanges.get());
1537             WriteRowContent();
1538             CloseRow(nStartRow);
1539             sal_Int32 nRows(1);
1540             sal_Int32 nTotalRows(nEndRow - nStartRow + 1 - 1);
1541             while (nRows < nTotalRows)
1542             {
1543                 pRowFormatRanges->Clear();
1544                 pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1545                 sal_Int32 nMaxRows = pRowFormatRanges->GetMaxRows();
1546                 OSL_ENSURE(nMaxRows, "something went wrong");
1547                 if (nMaxRows >= nTotalRows - nRows)
1548                 {
1549                     OpenRow(nSheet, nStartRow + nRows, nTotalRows - nRows, aRowAttr);
1550                     nRows += nTotalRows - nRows;
1551                 }
1552                 else
1553                 {
1554                     OpenRow(nSheet, nStartRow + nRows, nMaxRows, aRowAttr);
1555                     nRows += nMaxRows;
1556                 }
1557                 if (!pRowFormatRanges->GetSize())
1558                     pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1559                 WriteRowContent();
1560                 CloseRow(nStartRow + nRows - 1);
1561             }
1562             if (nTotalRows == 1)
1563                 CloseRow(nStartRow);
1564             OpenRow(nSheet, nEndRow, 1, aRowAttr);
1565             pRowFormatRanges->Clear();
1566             pCellStyles->GetFormatRanges(0, nEndCol, nEndRow, nSheet, pRowFormatRanges.get());
1567             WriteRowContent();
1568         }
1569         else
1570         {
1571             sal_Int32 nRows(0);
1572             sal_Int32 nTotalRows(nEndRow - nStartRow + 1 - 1);
1573             while (nRows < nTotalRows)
1574             {
1575                 pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1576                 sal_Int32 nMaxRows = pRowFormatRanges->GetMaxRows();
1577                 if (nMaxRows >= nTotalRows - nRows)
1578                 {
1579                     OpenRow(nSheet, nStartRow + nRows, nTotalRows - nRows, aRowAttr);
1580                     nRows += nTotalRows - nRows;
1581                 }
1582                 else
1583                 {
1584                     OpenRow(nSheet, nStartRow + nRows, nMaxRows, aRowAttr);
1585                     nRows += nMaxRows;
1586                 }
1587                 if (!pRowFormatRanges->GetSize())
1588                     pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1589                 WriteRowContent();
1590                 CloseRow(nStartRow + nRows - 1);
1591             }
1592             OpenRow(nSheet, nEndRow, 1, aRowAttr);
1593             pRowFormatRanges->Clear();
1594             pCellStyles->GetFormatRanges(0, nEndCol, nEndRow, nSheet, pRowFormatRanges.get());
1595             WriteRowContent();
1596         }
1597     }
1598 }
1599 
1600 void ScXMLExport::GetColumnRowHeader(bool& rHasColumnHeader, ScRange& rColumnHeaderRange,
1601                                      bool& rHasRowHeader, ScRange& rRowHeaderRange,
1602                                      OUString& rPrintRanges) const
1603 {
1604     uno::Reference <sheet::XPrintAreas> xPrintAreas (xCurrentTable, uno::UNO_QUERY);
1605     if (xPrintAreas.is())
1606     {
1607         rHasRowHeader = xPrintAreas->getPrintTitleRows();
1608         rHasColumnHeader = xPrintAreas->getPrintTitleColumns();
1609         table::CellRangeAddress rTempRowHeaderRange = xPrintAreas->getTitleRows();
1610         rRowHeaderRange = ScRange(rTempRowHeaderRange.StartColumn,
1611                                   rTempRowHeaderRange.StartRow,
1612                                   rTempRowHeaderRange.Sheet,
1613                                   rTempRowHeaderRange.EndColumn,
1614                                   rTempRowHeaderRange.EndRow,
1615                                   rTempRowHeaderRange.Sheet);
1616         table::CellRangeAddress rTempColumnHeaderRange = xPrintAreas->getTitleColumns();
1617         rColumnHeaderRange = ScRange(rTempColumnHeaderRange.StartColumn,
1618                                   rTempColumnHeaderRange.StartRow,
1619                                   rTempColumnHeaderRange.Sheet,
1620                                   rTempColumnHeaderRange.EndColumn,
1621                                   rTempColumnHeaderRange.EndRow,
1622                                   rTempColumnHeaderRange.Sheet);
1623         uno::Sequence< table::CellRangeAddress > aRangeList( xPrintAreas->getPrintAreas() );
1624         ScRangeStringConverter::GetStringFromRangeList( rPrintRanges, aRangeList, pDoc, FormulaGrammar::CONV_OOO );
1625     }
1626 }
1627 
1628 void ScXMLExport::FillFieldGroup(ScOutlineArray* pFields, ScMyOpenCloseColumnRowGroup* pGroups)
1629 {
1630     size_t nDepth = pFields->GetDepth();
1631     for (size_t i = 0; i < nDepth; ++i)
1632     {
1633         size_t nFields = pFields->GetCount(i);
1634         for (size_t j = 0; j < nFields; ++j)
1635         {
1636             ScMyColumnRowGroup aGroup;
1637             const ScOutlineEntry* pEntry = pFields->GetEntry(i, j);
1638             aGroup.nField = pEntry->GetStart();
1639             aGroup.nLevel = static_cast<sal_Int16>(i);
1640             aGroup.bDisplay = !(pEntry->IsHidden());
1641             pGroups->AddGroup(aGroup, pEntry->GetEnd());
1642         }
1643     }
1644     if (nDepth)
1645         pGroups->Sort();
1646 }
1647 
1648 void ScXMLExport::FillColumnRowGroups()
1649 {
1650     if (pDoc)
1651     {
1652         ScOutlineTable* pOutlineTable = pDoc->GetOutlineTable( static_cast<SCTAB>(nCurrentTable) );
1653         if(pOutlineTable)
1654         {
1655             ScOutlineArray& rCols(pOutlineTable->GetColArray());
1656             ScOutlineArray& rRows(pOutlineTable->GetRowArray());
1657             FillFieldGroup(&rCols, pGroupColumns.get());
1658             FillFieldGroup(&rRows, pGroupRows.get());
1659             pSharedData->SetLastColumn(nCurrentTable, pGroupColumns->GetLast());
1660             pSharedData->SetLastRow(nCurrentTable, pGroupRows->GetLast());
1661         }
1662     }
1663 }
1664 
1665 void ScXMLExport::SetBodyAttributes()
1666 {
1667     if (pDoc && pDoc->IsDocProtected())
1668     {
1669         AddAttribute(XML_NAMESPACE_TABLE, XML_STRUCTURE_PROTECTED, XML_TRUE);
1670         OUStringBuffer aBuffer;
1671         uno::Sequence<sal_Int8> aPassHash;
1672         ScPasswordHash eHashUsed = PASSHASH_UNSPECIFIED;
1673         const ScDocProtection* p = pDoc->GetDocProtection();
1674         if (p)
1675         {
1676             if (p->hasPasswordHash(PASSHASH_SHA1))
1677             {
1678                 aPassHash = p->getPasswordHash(PASSHASH_SHA1);
1679                 eHashUsed = PASSHASH_SHA1;
1680             }
1681             else if (p->hasPasswordHash(PASSHASH_SHA256))
1682             {
1683                 aPassHash = p->getPasswordHash(PASSHASH_SHA256);
1684                 eHashUsed = PASSHASH_SHA256;
1685             }
1686             else if (p->hasPasswordHash(PASSHASH_XL, PASSHASH_SHA1))
1687             {
1688                 aPassHash = p->getPasswordHash(PASSHASH_XL, PASSHASH_SHA1);
1689                 eHashUsed = PASSHASH_XL;
1690             }
1691         }
1692         ::comphelper::Base64::encode(aBuffer, aPassHash);
1693         if (!aBuffer.isEmpty())
1694         {
1695             AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
1696             if ( getDefaultVersion() >= SvtSaveOptions::ODFVER_012 )
1697             {
1698                 if (eHashUsed == PASSHASH_XL)
1699                 {
1700                     AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
1701                                  ScPassHashHelper::getHashURI(PASSHASH_XL));
1702                     if (getDefaultVersion() > SvtSaveOptions::ODFVER_012)
1703                         AddAttribute(XML_NAMESPACE_LO_EXT, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2,
1704                                 ScPassHashHelper::getHashURI(PASSHASH_SHA1));
1705                 }
1706                 else if (eHashUsed == PASSHASH_SHA1)
1707                 {
1708                     AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
1709                                  ScPassHashHelper::getHashURI(PASSHASH_SHA1));
1710                 }
1711                 else if (eHashUsed == PASSHASH_SHA256)
1712                 {
1713                     AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
1714                                  ScPassHashHelper::getHashURI(PASSHASH_SHA256));
1715                 }
1716             }
1717         }
1718     }
1719 }
1720 
1721 static bool lcl_CopyStreamElement( const uno::Reference< io::XInputStream >& xInput,
1722                             const uno::Reference< io::XOutputStream >& xOutput,
1723                             sal_Int32 nCount )
1724 {
1725     const sal_Int32 nBufSize = 16*1024;
1726     uno::Sequence<sal_Int8> aSequence(nBufSize);
1727 
1728     sal_Int32 nRemaining = nCount;
1729     bool bFirst = true;
1730 
1731     while ( nRemaining > 0 )
1732     {
1733         sal_Int32 nRead = xInput->readBytes( aSequence, std::min( nRemaining, nBufSize ) );
1734         if (bFirst)
1735         {
1736             // safety check: Make sure the copied part actually points to the start of an element
1737             if ( nRead < 1 || aSequence[0] != static_cast<sal_Int8>('<') )
1738             {
1739                 return false;   // abort and set an error
1740             }
1741             bFirst = false;
1742         }
1743         if (nRead == nRemaining)
1744         {
1745             // safety check: Make sure the copied part also ends at the end of an element
1746             if ( aSequence[nRead-1] != static_cast<sal_Int8>('>') )
1747             {
1748                 return false;   // abort and set an error
1749             }
1750         }
1751 
1752         if ( nRead == nBufSize )
1753         {
1754             xOutput->writeBytes( aSequence );
1755             nRemaining -= nRead;
1756         }
1757         else
1758         {
1759             if ( nRead > 0 )
1760             {
1761                 uno::Sequence<sal_Int8> aTempBuf( aSequence.getConstArray(), nRead );
1762                 xOutput->writeBytes( aTempBuf );
1763             }
1764             nRemaining = 0;
1765         }
1766     }
1767     return true;    // successful
1768 }
1769 
1770 static void lcl_SkipBytesInBlocks( const uno::Reference< io::XInputStream >& xInput, sal_Int32 nBytesToSkip )
1771 {
1772     // skipBytes in zip stream is implemented as reading.
1773     // For now, split into several calls to avoid allocating a large buffer.
1774     // Later, skipBytes should be changed.
1775 
1776     const sal_Int32 nMaxSize = 32*1024;
1777 
1778     if ( nBytesToSkip > 0 )
1779     {
1780         sal_Int32 nRemaining = nBytesToSkip;
1781         while ( nRemaining > 0 )
1782         {
1783             sal_Int32 nSkip = std::min( nRemaining, nMaxSize );
1784             xInput->skipBytes( nSkip );
1785             nRemaining -= nSkip;
1786         }
1787     }
1788 }
1789 
1790 void ScXMLExport::CopySourceStream( sal_Int32 nStartOffset, sal_Int32 nEndOffset, sal_Int32& rNewStart, sal_Int32& rNewEnd )
1791 {
1792     uno::Reference<xml::sax::XDocumentHandler> xHandler = GetDocHandler();
1793     uno::Reference<io::XActiveDataSource> xDestSource( xHandler, uno::UNO_QUERY );
1794     if ( xDestSource.is() )
1795     {
1796         uno::Reference<io::XOutputStream> xDestStream = xDestSource->getOutputStream();
1797         uno::Reference<io::XSeekable> xDestSeek( xDestStream, uno::UNO_QUERY );
1798         if ( xDestSeek.is() )
1799         {
1800             // temporary: set same stream again to clear buffer
1801             xDestSource->setOutputStream( xDestStream );
1802 
1803             if ( getExportFlags() & SvXMLExportFlags::PRETTY )
1804             {
1805                 const OString aOutStr("\n   ");
1806                 uno::Sequence<sal_Int8> aOutSeq( reinterpret_cast<sal_Int8 const *>(aOutStr.getStr()), aOutStr.getLength() );
1807                 xDestStream->writeBytes( aOutSeq );
1808             }
1809 
1810             rNewStart = static_cast<sal_Int32>(xDestSeek->getPosition());
1811 
1812             if ( nStartOffset > nSourceStreamPos )
1813                 lcl_SkipBytesInBlocks( xSourceStream, nStartOffset - nSourceStreamPos );
1814 
1815             if ( !lcl_CopyStreamElement( xSourceStream, xDestStream, nEndOffset - nStartOffset ) )
1816             {
1817                 // If copying went wrong, set an error.
1818                 // ScXMLImportWrapper then resets all stream flags, so the next save attempt will use normal saving.
1819 
1820                 uno::Sequence<OUString> aEmptySeq;
1821                 SetError(XMLERROR_CANCEL|XMLERROR_FLAG_SEVERE, aEmptySeq);
1822             }
1823             nSourceStreamPos = nEndOffset;
1824 
1825             rNewEnd = static_cast<sal_Int32>(xDestSeek->getPosition());
1826         }
1827     }
1828 }
1829 
1830 const ScXMLEditAttributeMap& ScXMLExport::GetEditAttributeMap() const
1831 {
1832     if (!mpEditAttrMap)
1833         mpEditAttrMap.reset(new ScXMLEditAttributeMap);
1834     return *mpEditAttrMap;
1835 }
1836 
1837 void ScXMLExport::RegisterDefinedStyleNames( const uno::Reference< css::sheet::XSpreadsheetDocument > & xSpreadDoc )
1838 {
1839     ScFormatSaveData* pFormatData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetFormatSaveData();
1840     auto xAutoStylePool = GetAutoStylePool();
1841     for (const auto& rFormatInfo : pFormatData->maIDToName)
1842     {
1843         xAutoStylePool->RegisterDefinedName(XML_STYLE_FAMILY_TABLE_CELL, rFormatInfo.second);
1844     }
1845 }
1846 
1847 void ScXMLExport::ExportContent_()
1848 {
1849     nCurrentTable = 0;
1850     if (!pSharedData)
1851     {
1852         SCTAB nTableCount(0);
1853         sal_Int32 nShapesCount(0);
1854         CollectSharedData(nTableCount, nShapesCount);
1855         OSL_FAIL("no shared data set");
1856         if (!pSharedData)
1857             return;
1858     }
1859     ScXMLExportDatabaseRanges aExportDatabaseRanges(*this);
1860     if (!GetModel().is())
1861         return;
1862 
1863     uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
1864     if ( !xSpreadDoc.is() )
1865         return;
1866 
1867     ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetSheetSaveData();
1868     if (pSheetData)
1869         pSheetData->ResetSaveEntries();
1870 
1871     uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
1872     if ( xIndex.is() )
1873     {
1874         //_GetNamespaceMap().ClearQNamesCache();
1875         pChangeTrackingExportHelper->CollectAndWriteChanges();
1876         WriteCalculationSettings(xSpreadDoc);
1877         sal_Int32 nTableCount(xIndex->getCount());
1878         ScMyAreaLinksContainer aAreaLinks;
1879         GetAreaLinks( aAreaLinks );
1880         ScMyEmptyDatabaseRangesContainer aEmptyRanges(aExportDatabaseRanges.GetEmptyDatabaseRanges());
1881         ScMyDetectiveOpContainer aDetectiveOpContainer;
1882         GetDetectiveOpList( aDetectiveOpContainer );
1883 
1884         pCellStyles->Sort();
1885         pMergedRangesContainer->Sort();
1886         pSharedData->GetDetectiveObjContainer()->Sort();
1887 
1888         mpCellsItr->Clear();
1889         mpCellsItr->SetShapes( pSharedData->GetShapesContainer() );
1890         mpCellsItr->SetNoteShapes( pSharedData->GetNoteShapes() );
1891         mpCellsItr->SetMergedRanges( pMergedRangesContainer.get() );
1892         mpCellsItr->SetAreaLinks( &aAreaLinks );
1893         mpCellsItr->SetEmptyDatabaseRanges( &aEmptyRanges );
1894         mpCellsItr->SetDetectiveObj( pSharedData->GetDetectiveObjContainer() );
1895         mpCellsItr->SetDetectiveOp( &aDetectiveOpContainer );
1896 
1897         if (nTableCount > 0)
1898             pValidationsContainer->WriteValidations(*this);
1899         WriteTheLabelRanges( xSpreadDoc );
1900         for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable)
1901         {
1902             sal_Int32 nStartOffset = -1;
1903             sal_Int32 nEndOffset = -1;
1904             if (pSheetData && pDoc && pDoc->IsStreamValid(static_cast<SCTAB>(nTable)) && !pDoc->GetChangeTrack())
1905                 pSheetData->GetStreamPos( nTable, nStartOffset, nEndOffset );
1906 
1907             if ( nStartOffset >= 0 && nEndOffset >= 0 && xSourceStream.is() )
1908             {
1909                 sal_Int32 nNewStart = -1;
1910                 sal_Int32 nNewEnd = -1;
1911                 CopySourceStream( nStartOffset, nEndOffset, nNewStart, nNewEnd );
1912 
1913                 // store position of copied sheet in output
1914                 pSheetData->AddSavePos( nTable, nNewStart, nNewEnd );
1915 
1916                 // skip iterator entries for this sheet
1917                 mpCellsItr->SkipTable(static_cast<SCTAB>(nTable));
1918             }
1919             else
1920             {
1921                 uno::Reference<sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
1922                 WriteTable(nTable, xTable);
1923             }
1924             IncrementProgressBar(false);
1925         }
1926     }
1927     WriteExternalRefCaches();
1928     WriteNamedExpressions();
1929     WriteDataStream();
1930     aExportDatabaseRanges.WriteDatabaseRanges();
1931     WriteExternalDataMapping();
1932     ScXMLExportDataPilot aExportDataPilot(*this);
1933     aExportDataPilot.WriteDataPilots();
1934     WriteConsolidation();
1935     ScXMLExportDDELinks aExportDDELinks(*this);
1936     aExportDDELinks.WriteDDELinks(xSpreadDoc);
1937     IncrementProgressBar(true, 0);
1938     GetProgressBarHelper()->SetValue(GetProgressBarHelper()->GetReference());
1939 }
1940 
1941 void ScXMLExport::ExportStyles_( bool bUsed )
1942 {
1943     uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
1944     if (xSpreadDoc.is())
1945         RegisterDefinedStyleNames( xSpreadDoc);
1946 
1947     if (!pSharedData)
1948     {
1949         SCTAB nTableCount(0);
1950         sal_Int32 nShapesCount(0);
1951         CollectSharedData(nTableCount, nShapesCount);
1952     }
1953     rtl::Reference<ScXMLStyleExport> aStylesExp(new ScXMLStyleExport(*this, GetAutoStylePool().get()));
1954     if (GetModel().is())
1955     {
1956         uno::Reference <lang::XMultiServiceFactory> xMultiServiceFactory(GetModel(), uno::UNO_QUERY);
1957         if (xMultiServiceFactory.is())
1958         {
1959             uno::Reference <beans::XPropertySet> xProperties(xMultiServiceFactory->createInstance("com.sun.star.sheet.Defaults"), uno::UNO_QUERY);
1960             if (xProperties.is())
1961                 aStylesExp->exportDefaultStyle(xProperties, XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME, xCellStylesExportPropertySetMapper);
1962             if (pSharedData->HasShapes())
1963             {
1964                 GetShapeExport()->ExportGraphicDefaults();
1965             }
1966         }
1967         uno::Reference <style::XStyleFamiliesSupplier> xStyleFamiliesSupplier (GetModel(), uno::UNO_QUERY);
1968         if (xStyleFamiliesSupplier.is())
1969         {
1970             uno::Reference <container::XNameAccess> xStylesFamilies(xStyleFamiliesSupplier->getStyleFamilies());
1971             if (xStylesFamilies.is())
1972             {
1973                 uno::Reference <container::XIndexAccess> xCellStyles(xStylesFamilies->getByName("CellStyles"), uno::UNO_QUERY);
1974                 if (xCellStyles.is())
1975                 {
1976                     sal_Int32 nCount(xCellStyles->getCount());
1977                     for (sal_Int32 i = 0; i < nCount; ++i)
1978                     {
1979                         uno::Reference <beans::XPropertySet> xCellProperties(xCellStyles->getByIndex(i), uno::UNO_QUERY);
1980                         if (xCellProperties.is())
1981                         {
1982                             sal_Int32 nNumberFormat = 0;
1983                             if (xCellProperties->getPropertyValue(SC_UNONAME_NUMFMT) >>= nNumberFormat)
1984                                 addDataStyle(nNumberFormat);
1985                         }
1986                     }
1987                 }
1988             }
1989         }
1990     }
1991     exportDataStyles();
1992 
1993     aStylesExp->exportStyleFamily(OUString("CellStyles"),
1994         OUString(XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME), xCellStylesExportPropertySetMapper, false, XML_STYLE_FAMILY_TABLE_CELL);
1995 
1996     SvXMLExport::ExportStyles_(bUsed);
1997 }
1998 
1999 void ScXMLExport::AddStyleFromCells(const uno::Reference<beans::XPropertySet>& xProperties,
2000                                     const uno::Reference<sheet::XSpreadsheet>& xTable,
2001                                     sal_Int32 nTable, const OUString* pOldName)
2002 {
2003     css::uno::Any aAny = xProperties->getPropertyValue("FormatID");
2004     sal_uInt64 nKey = 0;
2005     aAny >>= nKey;
2006 
2007     //! pass xCellRanges instead
2008     uno::Reference<sheet::XSheetCellRanges> xCellRanges( xProperties, uno::UNO_QUERY );
2009 
2010     OUString sStyleName;
2011     sal_Int32 nNumberFormat(-1);
2012     sal_Int32 nValidationIndex(-1);
2013     std::vector< XMLPropertyState > aPropStates(xCellStylesExportPropertySetMapper->Filter( xProperties ));
2014     std::vector< XMLPropertyState >::iterator aItr(aPropStates.begin());
2015     std::vector< XMLPropertyState >::iterator aEndItr(aPropStates.end());
2016     sal_Int32 nCount(0);
2017     while (aItr != aEndItr)
2018     {
2019         if (aItr->mnIndex != -1)
2020         {
2021             switch (xCellStylesPropertySetMapper->GetEntryContextId(aItr->mnIndex))
2022             {
2023                 case CTF_SC_VALIDATION :
2024                 {
2025                     pValidationsContainer->AddValidation(aItr->maValue, nValidationIndex);
2026                     // this is not very slow, because it is most the last property or
2027                     // if it is not the last property it is the property before the last property,
2028                     // so in the worst case only one property has to be copied, but in the best case no
2029                     // property has to be copied
2030                     aItr = aPropStates.erase(aItr);
2031                     aEndItr = aPropStates.end();    // old aEndItr is invalidated!
2032                 }
2033                 break;
2034                 case CTF_SC_CELLSTYLE :
2035                 {
2036                     aItr->maValue >>= sStyleName;
2037                     aItr->mnIndex = -1;
2038                     ++aItr;
2039                     ++nCount;
2040                 }
2041                 break;
2042                 case CTF_SC_NUMBERFORMAT :
2043                 {
2044                     if (aItr->maValue >>= nNumberFormat)
2045                         addDataStyle(nNumberFormat);
2046                     ++aItr;
2047                     ++nCount;
2048                 }
2049                 break;
2050                 default:
2051                 {
2052                     ++aItr;
2053                     ++nCount;
2054                 }
2055                 break;
2056             }
2057         }
2058         else
2059         {
2060             ++aItr;
2061             ++nCount;
2062         }
2063     }
2064     if (nCount == 1) // this is the CellStyle and should be removed if alone
2065         aPropStates.clear();
2066     if (nNumberFormat == -1)
2067         xProperties->getPropertyValue(SC_UNONAME_NUMFMT) >>= nNumberFormat;
2068     if (!sStyleName.isEmpty())
2069     {
2070         if (!aPropStates.empty())
2071         {
2072             sal_Int32 nIndex;
2073             if (pOldName)
2074             {
2075                 if (GetAutoStylePool()->AddNamed(*pOldName, XML_STYLE_FAMILY_TABLE_CELL, sStyleName, aPropStates))
2076                 {
2077                     GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_CELL, *pOldName);
2078                     // add to pCellStyles, so the name is found for normal sheets
2079                     pCellStyles->AddStyleName(*pOldName, nIndex);
2080                 }
2081             }
2082             else
2083             {
2084                 OUString sName;
2085                 bool bAdded = false;
2086                 if (nKey)
2087                 {
2088                     uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
2089                     ScFormatSaveData* pFormatData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetFormatSaveData();
2090                     auto itr = pFormatData->maIDToName.find(nKey);
2091                     if (itr != pFormatData->maIDToName.end())
2092                     {
2093                         sName = itr->second;
2094                         bAdded = GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TABLE_CELL, sStyleName, aPropStates);
2095                         if (bAdded)
2096                             GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_CELL, sName);
2097                     }
2098                 }
2099                 bool bIsAutoStyle(true);
2100                 if (bAdded || GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_CELL, sStyleName, aPropStates))
2101                 {
2102                     pCellStyles->AddStyleName(sName, nIndex);
2103                 }
2104                 else
2105                     nIndex = pCellStyles->GetIndexOfStyleName(sName, XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX, bIsAutoStyle);
2106 
2107                 const uno::Sequence<table::CellRangeAddress> aAddresses(xCellRanges->getRangeAddresses());
2108                 bool bGetMerge(true);
2109                 for (table::CellRangeAddress const & address : aAddresses)
2110                 {
2111                     pSharedData->SetLastColumn(nTable, address.EndColumn);
2112                     pSharedData->SetLastRow(nTable, address.EndRow);
2113                     pCellStyles->AddRangeStyleName(address, nIndex, bIsAutoStyle, nValidationIndex, nNumberFormat);
2114                     if (bGetMerge)
2115                         bGetMerge = GetMerged(&address, xTable);
2116                 }
2117             }
2118         }
2119         else
2120         {
2121             OUString sEncodedStyleName(EncodeStyleName(sStyleName));
2122             sal_Int32 nIndex(0);
2123             pCellStyles->AddStyleName(sEncodedStyleName, nIndex, false);
2124             if ( !pOldName )
2125             {
2126                 const uno::Sequence<table::CellRangeAddress> aAddresses(xCellRanges->getRangeAddresses());
2127                 bool bGetMerge(true);
2128                 for (table::CellRangeAddress const & address : aAddresses)
2129                 {
2130                     if (bGetMerge)
2131                         bGetMerge = GetMerged(&address, xTable);
2132                     pCellStyles->AddRangeStyleName(address, nIndex, false, nValidationIndex, nNumberFormat);
2133                     if( sStyleName != "Default" || nValidationIndex != -1 )
2134                     {
2135                         pSharedData->SetLastColumn(nTable, address.EndColumn);
2136                         pSharedData->SetLastRow(nTable, address.EndRow);
2137                     }
2138                 }
2139             }
2140         }
2141     }
2142 }
2143 
2144 void ScXMLExport::AddStyleFromColumn(const uno::Reference<beans::XPropertySet>& xColumnProperties,
2145                                      const OUString* pOldName, sal_Int32& rIndex, bool& rIsVisible)
2146 {
2147     std::vector<XMLPropertyState> aPropStates(xColumnStylesExportPropertySetMapper->Filter(xColumnProperties));
2148     if(!aPropStates.empty())
2149     {
2150         auto aItr = std::find_if(aPropStates.begin(), aPropStates.end(),
2151             [this](const XMLPropertyState& rPropState) {
2152                 return xColumnStylesPropertySetMapper->GetEntryContextId(rPropState.mnIndex) == CTF_SC_ISVISIBLE; });
2153         if (aItr != aPropStates.end())
2154         {
2155             aItr->maValue >>= rIsVisible;
2156         }
2157 
2158         OUString sParent;
2159         if (pOldName)
2160         {
2161             if (GetAutoStylePool()->AddNamed(*pOldName, XML_STYLE_FAMILY_TABLE_COLUMN, sParent, aPropStates))
2162             {
2163                 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_COLUMN, *pOldName);
2164                 // add to pColumnStyles, so the name is found for normal sheets
2165                 rIndex = pColumnStyles->AddStyleName(*pOldName);
2166             }
2167         }
2168         else
2169         {
2170             OUString sName;
2171             if (GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_COLUMN, sParent, aPropStates))
2172             {
2173                 rIndex = pColumnStyles->AddStyleName(sName);
2174             }
2175             else
2176                 rIndex = pColumnStyles->GetIndexOfStyleName(sName, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_PREFIX);
2177         }
2178     }
2179 }
2180 
2181 void ScXMLExport::AddStyleFromRow(const uno::Reference<beans::XPropertySet>& xRowProperties,
2182                                   const OUString* pOldName, sal_Int32& rIndex)
2183 {
2184     std::vector<XMLPropertyState> aPropStates(xRowStylesExportPropertySetMapper->Filter(xRowProperties));
2185     if(!aPropStates.empty())
2186     {
2187         OUString sParent;
2188         if (pOldName)
2189         {
2190             if (GetAutoStylePool()->AddNamed(*pOldName, XML_STYLE_FAMILY_TABLE_ROW, sParent, aPropStates))
2191             {
2192                 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_ROW, *pOldName);
2193                 // add to pRowStyles, so the name is found for normal sheets
2194                 rIndex = pRowStyles->AddStyleName(*pOldName);
2195             }
2196         }
2197         else
2198         {
2199             OUString sName;
2200             if (GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_ROW, sParent, aPropStates))
2201             {
2202                 rIndex = pRowStyles->AddStyleName(sName);
2203             }
2204             else
2205                 rIndex = pRowStyles->GetIndexOfStyleName(sName, XML_STYLE_FAMILY_TABLE_ROW_STYLES_PREFIX);
2206         }
2207     }
2208 }
2209 
2210 static uno::Any lcl_GetEnumerated( uno::Reference<container::XEnumerationAccess> const & xEnumAccess, sal_Int32 nIndex )
2211 {
2212     uno::Any aRet;
2213     uno::Reference<container::XEnumeration> xEnum( xEnumAccess->createEnumeration() );
2214     try
2215     {
2216         sal_Int32 nSkip = nIndex;
2217         while ( nSkip > 0 )
2218         {
2219             (void) xEnum->nextElement();
2220             --nSkip;
2221         }
2222         aRet = xEnum->nextElement();
2223     }
2224     catch (container::NoSuchElementException&)
2225     {
2226         // leave aRet empty
2227     }
2228     return aRet;
2229 }
2230 
2231 void ScXMLExport::collectAutoStyles()
2232 {
2233     SvXMLExport::collectAutoStyles();
2234 
2235     if (mbAutoStylesCollected)
2236         return;
2237 
2238     if (!GetModel().is())
2239         return;
2240 
2241     uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
2242     if (!xSpreadDoc.is())
2243         return;
2244 
2245     uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
2246     if (!xIndex.is())
2247         return;
2248 
2249     if (getExportFlags() & SvXMLExportFlags::CONTENT)
2250     {
2251         // Reserve the loaded cell style names.
2252         RegisterDefinedStyleNames( xSpreadDoc);
2253 
2254         //  re-create automatic styles with old names from stored data
2255         ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetSheetSaveData();
2256         if (pSheetData && pDoc)
2257         {
2258             // formulas have to be calculated now, to detect changed results
2259             // (during normal save, they will be calculated anyway)
2260             SCTAB nTabCount = pDoc->GetTableCount();
2261             for (SCTAB nTab=0; nTab<nTabCount; ++nTab)
2262                 if (pDoc->IsStreamValid(nTab))
2263                     pDoc->InterpretDirtyCells(ScRange(0, 0, nTab, MAXCOL, MAXROW, nTab));
2264 
2265             // stored cell styles
2266             const std::vector<ScCellStyleEntry>& rCellEntries = pSheetData->GetCellStyles();
2267             for (const auto& rCellEntry : rCellEntries)
2268             {
2269                 ScAddress aPos = rCellEntry.maCellPos;
2270                 sal_Int32 nTable = aPos.Tab();
2271                 bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2272                 if (bCopySheet)
2273                 {
2274                     uno::Reference <sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2275                     uno::Reference <beans::XPropertySet> xProperties(
2276                         xTable->getCellByPosition( aPos.Col(), aPos.Row() ), uno::UNO_QUERY );
2277 
2278                     AddStyleFromCells(xProperties, xTable, nTable, &rCellEntry.maName);
2279                 }
2280             }
2281 
2282             // stored column styles
2283             const std::vector<ScCellStyleEntry>& rColumnEntries = pSheetData->GetColumnStyles();
2284             for (const auto& rColumnEntry : rColumnEntries)
2285             {
2286                 ScAddress aPos = rColumnEntry.maCellPos;
2287                 sal_Int32 nTable = aPos.Tab();
2288                 bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2289                 if (bCopySheet)
2290                 {
2291                     uno::Reference<table::XColumnRowRange> xColumnRowRange(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2292                     uno::Reference<table::XTableColumns> xTableColumns(xColumnRowRange->getColumns());
2293                     uno::Reference<beans::XPropertySet> xColumnProperties(xTableColumns->getByIndex( aPos.Col() ), uno::UNO_QUERY);
2294 
2295                     sal_Int32 nIndex(-1);
2296                     bool bIsVisible(true);
2297                     AddStyleFromColumn( xColumnProperties, &rColumnEntry.maName, nIndex, bIsVisible );
2298                 }
2299             }
2300 
2301             // stored row styles
2302             const std::vector<ScCellStyleEntry>& rRowEntries = pSheetData->GetRowStyles();
2303             for (const auto& rRowEntry : rRowEntries)
2304             {
2305                 ScAddress aPos = rRowEntry.maCellPos;
2306                 sal_Int32 nTable = aPos.Tab();
2307                 bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2308                 if (bCopySheet)
2309                 {
2310                     uno::Reference<table::XColumnRowRange> xColumnRowRange(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2311                     uno::Reference<table::XTableRows> xTableRows(xColumnRowRange->getRows());
2312                     uno::Reference<beans::XPropertySet> xRowProperties(xTableRows->getByIndex( aPos.Row() ), uno::UNO_QUERY);
2313 
2314                     sal_Int32 nIndex(-1);
2315                     AddStyleFromRow( xRowProperties, &rRowEntry.maName, nIndex );
2316                 }
2317             }
2318 
2319             // stored table styles
2320             const std::vector<ScCellStyleEntry>& rTableEntries = pSheetData->GetTableStyles();
2321             for (const auto& rTableEntry : rTableEntries)
2322             {
2323                 ScAddress aPos = rTableEntry.maCellPos;
2324                 sal_Int32 nTable = aPos.Tab();
2325                 bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2326                 if (bCopySheet)
2327                 {
2328                     //! separate method AddStyleFromTable needed?
2329                     uno::Reference<beans::XPropertySet> xTableProperties(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2330                     if (xTableProperties.is())
2331                     {
2332                         std::vector<XMLPropertyState> aPropStates(xTableStylesExportPropertySetMapper->Filter(xTableProperties));
2333                         OUString sName( rTableEntry.maName );
2334                         GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TABLE_TABLE, OUString(), aPropStates);
2335                         GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_TABLE, sName);
2336                     }
2337                 }
2338             }
2339 
2340             // stored styles for notes
2341 
2342             rtl::Reference<SvXMLExportPropertyMapper> xShapeMapper = XMLShapeExport::CreateShapePropMapper( *this );
2343             GetShapeExport(); // make sure the graphics styles family is added
2344 
2345             const std::vector<ScNoteStyleEntry>& rNoteEntries = pSheetData->GetNoteStyles();
2346             for (const auto& rNoteEntry : rNoteEntries)
2347             {
2348                 ScAddress aPos = rNoteEntry.maCellPos;
2349                 SCTAB nTable = aPos.Tab();
2350                 bool bCopySheet = pDoc->IsStreamValid( nTable );
2351                 if (bCopySheet)
2352                 {
2353                     //! separate method AddStyleFromNote needed?
2354 
2355                     ScPostIt* pNote = pDoc->GetNote(aPos);
2356                     OSL_ENSURE( pNote, "note not found" );
2357                     if (pNote)
2358                     {
2359                         SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
2360                         // all uno shapes are created anyway in CollectSharedData
2361                         uno::Reference<beans::XPropertySet> xShapeProperties( pDrawObj->getUnoShape(), uno::UNO_QUERY );
2362                         if (xShapeProperties.is())
2363                         {
2364                             if ( !rNoteEntry.maStyleName.isEmpty() )
2365                             {
2366                                 std::vector<XMLPropertyState> aPropStates(xShapeMapper->Filter(xShapeProperties));
2367                                 OUString sName( rNoteEntry.maStyleName );
2368                                 GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_SD_GRAPHICS_ID, OUString(), aPropStates);
2369                                 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_SD_GRAPHICS_ID, sName);
2370                             }
2371                             if ( !rNoteEntry.maTextStyle.isEmpty() )
2372                             {
2373                                 std::vector<XMLPropertyState> aPropStates(
2374                                     GetTextParagraphExport()->GetParagraphPropertyMapper()->Filter(xShapeProperties));
2375                                 OUString sName( rNoteEntry.maTextStyle );
2376                                 GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_PARAGRAPH, OUString(), aPropStates);
2377                                 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_PARAGRAPH, sName);
2378                             }
2379                         }
2380                     }
2381                 }
2382             }
2383 
2384             // note paragraph styles
2385 
2386             rtl::Reference<SvXMLExportPropertyMapper> xParaPropMapper = GetTextParagraphExport()->GetParagraphPropertyMapper();
2387 
2388             const std::vector<ScTextStyleEntry>& rNoteParaEntries = pSheetData->GetNoteParaStyles();
2389             for (const auto& rNoteParaEntry : rNoteParaEntries)
2390             {
2391                 ScAddress aPos = rNoteParaEntry.maCellPos;
2392                 SCTAB nTable = aPos.Tab();
2393                 bool bCopySheet = pDoc->IsStreamValid( nTable );
2394                 if (bCopySheet)
2395                 {
2396                     ScPostIt* pNote = pDoc->GetNote( aPos );
2397                     OSL_ENSURE( pNote, "note not found" );
2398                     if (pNote)
2399                     {
2400                         SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
2401                         uno::Reference<container::XEnumerationAccess> xCellText(pDrawObj->getUnoShape(), uno::UNO_QUERY);
2402                         uno::Reference<beans::XPropertySet> xParaProp(
2403                             lcl_GetEnumerated( xCellText, rNoteParaEntry.maSelection.nStartPara ), uno::UNO_QUERY );
2404                         if ( xParaProp.is() )
2405                         {
2406                             std::vector<XMLPropertyState> aPropStates(xParaPropMapper->Filter(xParaProp));
2407                             OUString sName( rNoteParaEntry.maName );
2408                             GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_PARAGRAPH, OUString(), aPropStates);
2409                             GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_PARAGRAPH, sName);
2410                         }
2411                     }
2412                 }
2413             }
2414 
2415             // note text styles
2416 
2417             rtl::Reference<SvXMLExportPropertyMapper> xTextPropMapper = XMLTextParagraphExport::CreateCharExtPropMapper( *this );
2418 
2419             const std::vector<ScTextStyleEntry>& rNoteTextEntries = pSheetData->GetNoteTextStyles();
2420             for (const auto& rNoteTextEntry : rNoteTextEntries)
2421             {
2422                 ScAddress aPos = rNoteTextEntry.maCellPos;
2423                 SCTAB nTable = aPos.Tab();
2424                 bool bCopySheet = pDoc->IsStreamValid( nTable );
2425                 if (bCopySheet)
2426                 {
2427                     ScPostIt* pNote = pDoc->GetNote( aPos );
2428                     OSL_ENSURE( pNote, "note not found" );
2429                     if (pNote)
2430                     {
2431                         SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
2432                         uno::Reference<text::XSimpleText> xCellText(pDrawObj->getUnoShape(), uno::UNO_QUERY);
2433                         uno::Reference<beans::XPropertySet> xCursorProp(xCellText->createTextCursor(), uno::UNO_QUERY);
2434                         ScDrawTextCursor* pCursor = comphelper::getUnoTunnelImplementation<ScDrawTextCursor>( xCursorProp );
2435                         if (pCursor)
2436                         {
2437                             pCursor->SetSelection( rNoteTextEntry.maSelection );
2438 
2439                             std::vector<XMLPropertyState> aPropStates(xTextPropMapper->Filter(xCursorProp));
2440                             OUString sName( rNoteTextEntry.maName );
2441                             GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_TEXT, OUString(), aPropStates);
2442                             GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_TEXT, sName);
2443                         }
2444                     }
2445                 }
2446             }
2447 
2448             // stored text styles
2449 
2450             // Calling createTextCursor fires up editeng, which is very slow, and often subsequent style entries
2451             // refer to the same cell, so cache it.
2452             ScAddress aPrevPos;
2453             uno::Reference<beans::XPropertySet> xPrevCursorProp;
2454             const std::vector<ScTextStyleEntry>& rTextEntries = pSheetData->GetTextStyles();
2455             for (const auto& rTextEntry : rTextEntries)
2456             {
2457                 ScAddress aPos = rTextEntry.maCellPos;
2458                 sal_Int32 nTable = aPos.Tab();
2459                 bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2460                 if (!bCopySheet)
2461                     continue;
2462 
2463                 //! separate method AddStyleFromText needed?
2464                 //! cache sheet object
2465 
2466                 uno::Reference<beans::XPropertySet> xCursorProp;
2467                 if (xPrevCursorProp && aPrevPos == aPos)
2468                     xCursorProp = xPrevCursorProp;
2469                 else
2470                 {
2471                     uno::Reference<table::XCellRange> xCellRange(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2472                     uno::Reference<text::XSimpleText> xCellText(xCellRange->getCellByPosition(aPos.Col(), aPos.Row()), uno::UNO_QUERY);
2473                     xCursorProp.set(xCellText->createTextCursor(), uno::UNO_QUERY);
2474                 }
2475                 ScCellTextCursor* pCursor = comphelper::getUnoTunnelImplementation<ScCellTextCursor>( xCursorProp );
2476                 if (!pCursor)
2477                     continue;
2478                 pCursor->SetSelection( rTextEntry.maSelection );
2479 
2480                 std::vector<XMLPropertyState> aPropStates(xTextPropMapper->Filter(xCursorProp));
2481                 OUString sName( rTextEntry.maName );
2482                 GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_TEXT, OUString(), aPropStates);
2483                 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_TEXT, sName);
2484                 xPrevCursorProp = xCursorProp;
2485                 aPrevPos = aPos;
2486             }
2487         }
2488 
2489         ExportExternalRefCacheStyles();
2490 
2491         if (!pSharedData)
2492         {
2493             SCTAB nTableCount(0);
2494             sal_Int32 nShapesCount(0);
2495             CollectSharedData(nTableCount, nShapesCount);
2496         }
2497         sal_Int32 nTableCount(xIndex->getCount());
2498         pCellStyles->AddNewTable(nTableCount - 1);
2499         CollectShapesAutoStyles(nTableCount);
2500         for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable, IncrementProgressBar(false))
2501         {
2502             uno::Reference <sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2503             if (!xTable.is())
2504                 continue;
2505 
2506             // table styles array must be complete, including copied tables - Add should find the stored style
2507             uno::Reference<beans::XPropertySet> xTableProperties(xTable, uno::UNO_QUERY);
2508             if (xTableProperties.is())
2509             {
2510                 std::vector<XMLPropertyState> aPropStates(xTableStylesExportPropertySetMapper->Filter(xTableProperties));
2511                 if(!aPropStates.empty())
2512                 {
2513                     OUString sName;
2514                     GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_TABLE, OUString(), aPropStates);
2515                     aTableStyles.push_back(sName);
2516                 }
2517             }
2518 
2519             // collect other auto-styles only for non-copied sheets
2520             uno::Reference<sheet::XUniqueCellFormatRangesSupplier> xCellFormatRanges ( xTable, uno::UNO_QUERY );
2521             if ( xCellFormatRanges.is() )
2522             {
2523                 uno::Reference<container::XIndexAccess> xFormatRangesIndex(xCellFormatRanges->getUniqueCellFormatRanges());
2524                 if (xFormatRangesIndex.is())
2525                 {
2526                     sal_Int32 nFormatRangesCount(xFormatRangesIndex->getCount());
2527                     GetProgressBarHelper()->ChangeReference(GetProgressBarHelper()->GetReference() + nFormatRangesCount);
2528                     for (sal_Int32 nFormatRange = 0; nFormatRange < nFormatRangesCount; ++nFormatRange)
2529                     {
2530                         uno::Reference< sheet::XSheetCellRanges> xCellRanges(xFormatRangesIndex->getByIndex(nFormatRange), uno::UNO_QUERY);
2531                         if (xCellRanges.is())
2532                         {
2533                             uno::Reference <beans::XPropertySet> xProperties (xCellRanges, uno::UNO_QUERY);
2534                             if (xProperties.is())
2535                             {
2536                                 AddStyleFromCells(xProperties, xTable, nTable, nullptr);
2537                                 IncrementProgressBar(false);
2538                             }
2539                         }
2540                     }
2541                 }
2542             }
2543             uno::Reference<table::XColumnRowRange> xColumnRowRange (xTable, uno::UNO_QUERY);
2544             if (xColumnRowRange.is() && pDoc)
2545             {
2546                 pDoc->SyncColRowFlags();
2547                 uno::Reference<table::XTableColumns> xTableColumns(xColumnRowRange->getColumns());
2548                 if (xTableColumns.is())
2549                 {
2550                     sal_Int32 nColumns(pDoc->GetLastChangedCol(sal::static_int_cast<SCTAB>(nTable)));
2551                     pSharedData->SetLastColumn(nTable, nColumns);
2552                     table::CellRangeAddress aCellAddress(GetEndAddress(xTable));
2553                     if (aCellAddress.EndColumn > nColumns)
2554                     {
2555                         ++nColumns;
2556                         pColumnStyles->AddNewTable(nTable, aCellAddress.EndColumn);
2557                     }
2558                     else
2559                         pColumnStyles->AddNewTable(nTable, nColumns);
2560                     sal_Int32 nColumn = 0;
2561                     while (nColumn <= MAXCOL)
2562                     {
2563                         sal_Int32 nIndex(-1);
2564                         bool bIsVisible(true);
2565                         uno::Reference <beans::XPropertySet> xColumnProperties(xTableColumns->getByIndex(nColumn), uno::UNO_QUERY);
2566                         if (xColumnProperties.is())
2567                         {
2568                             AddStyleFromColumn( xColumnProperties, nullptr, nIndex, bIsVisible );
2569                             pColumnStyles->AddFieldStyleName(nTable, nColumn, nIndex, bIsVisible);
2570                         }
2571                         sal_Int32 nOld(nColumn);
2572                         nColumn = pDoc->GetNextDifferentChangedCol(sal::static_int_cast<SCTAB>(nTable), static_cast<SCCOL>(nColumn));
2573                         for (sal_Int32 i = nOld + 1; i < nColumn; ++i)
2574                             pColumnStyles->AddFieldStyleName(nTable, i, nIndex, bIsVisible);
2575                     }
2576                     if (aCellAddress.EndColumn > nColumns)
2577                     {
2578                         bool bIsVisible(true);
2579                         sal_Int32 nIndex(pColumnStyles->GetStyleNameIndex(nTable, nColumns, bIsVisible));
2580                         for (sal_Int32 i = nColumns + 1; i <= aCellAddress.EndColumn; ++i)
2581                             pColumnStyles->AddFieldStyleName(nTable, i, nIndex, bIsVisible);
2582                     }
2583                 }
2584                 uno::Reference<table::XTableRows> xTableRows(xColumnRowRange->getRows());
2585                 if (xTableRows.is())
2586                 {
2587                     sal_Int32 nRows(pDoc->GetLastChangedRow(sal::static_int_cast<SCTAB>(nTable)));
2588                     pSharedData->SetLastRow(nTable, nRows);
2589 
2590                     pRowStyles->AddNewTable(nTable, MAXROW);
2591                     sal_Int32 nRow = 0;
2592                     while (nRow <= MAXROW)
2593                     {
2594                         sal_Int32 nIndex = 0;
2595                         uno::Reference <beans::XPropertySet> xRowProperties(xTableRows->getByIndex(nRow), uno::UNO_QUERY);
2596                         if(xRowProperties.is())
2597                         {
2598                             AddStyleFromRow( xRowProperties, nullptr, nIndex );
2599                             pRowStyles->AddFieldStyleName(nTable, nRow, nIndex);
2600                         }
2601                         sal_Int32 nOld(nRow);
2602                         nRow = pDoc->GetNextDifferentChangedRow(sal::static_int_cast<SCTAB>(nTable), static_cast<SCROW>(nRow));
2603                         if (nRow > nOld + 1)
2604                             pRowStyles->AddFieldStyleName(nTable, nOld + 1, nIndex, nRow - 1);
2605                     }
2606                 }
2607             }
2608             ExportCellTextAutoStyles(nTable);
2609         }
2610 
2611         pChangeTrackingExportHelper->CollectAutoStyles();
2612     }
2613 
2614     if (getExportFlags() & SvXMLExportFlags::MASTERSTYLES)
2615         GetPageExport()->collectAutoStyles(true);
2616 
2617     mbAutoStylesCollected = true;
2618 }
2619 
2620 void ScXMLExport::ExportAutoStyles_()
2621 {
2622     if (!GetModel().is())
2623         return;
2624 
2625     uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
2626     if (!xSpreadDoc.is())
2627         return;
2628 
2629     uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
2630     if (!xIndex.is())
2631         return;
2632 
2633     collectAutoStyles();
2634 
2635     if (getExportFlags() & SvXMLExportFlags::CONTENT)
2636     {
2637         GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_COLUMN);
2638         GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_ROW);
2639         GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_TABLE);
2640         exportAutoDataStyles();
2641         GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_CELL);
2642 
2643         GetShapeExport()->exportAutoStyles();
2644         GetFormExport()->exportAutoStyles( );
2645 
2646         if (pDoc)
2647         {
2648             ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
2649             // #i100879# write the table style for cached tables only if there are cached tables
2650             // (same logic as in ExportExternalRefCacheStyles)
2651             if (pRefMgr->hasExternalData())
2652             {
2653                 // Special table style for the external ref cache tables.
2654                 AddAttribute(XML_NAMESPACE_STYLE, XML_NAME, sExternalRefTabStyleName);
2655                 AddAttribute(XML_NAMESPACE_STYLE, XML_FAMILY, XML_TABLE);
2656                 SvXMLElementExport aElemStyle(*this, XML_NAMESPACE_STYLE, XML_STYLE, true, true);
2657                 AddAttribute(XML_NAMESPACE_TABLE,  XML_DISPLAY, XML_FALSE);
2658                 SvXMLElementExport aElemStyleTabProps(*this, XML_NAMESPACE_STYLE, XML_TABLE_PROPERTIES, true, true);
2659             }
2660         }
2661     }
2662 
2663     if (getExportFlags() & SvXMLExportFlags::MASTERSTYLES)
2664     {
2665         GetPageExport()->exportAutoStyles();
2666     }
2667 
2668     // #i30251#; only write Text Styles once
2669 
2670     if ((getExportFlags() & SvXMLExportFlags::CONTENT) || (getExportFlags() & SvXMLExportFlags::MASTERSTYLES))
2671         GetTextParagraphExport()->exportTextAutoStyles();
2672 }
2673 
2674 void ScXMLExport::ExportMasterStyles_()
2675 {
2676     GetPageExport()->exportMasterStyles( true );
2677 }
2678 
2679 void ScXMLExport::CollectInternalShape( uno::Reference< drawing::XShape > const & xShape )
2680 {
2681     // detective objects and notes
2682     if( SvxShape* pShapeImp = comphelper::getUnoTunnelImplementation<SvxShape>( xShape ) )
2683     {
2684         if( SdrObject* pObject = pShapeImp->GetSdrObject() )
2685         {
2686             // collect note caption objects from all layers (internal or hidden)
2687             if( ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( pObject, static_cast< SCTAB >( nCurrentTable ) ) )
2688             {
2689                 if(pDoc->GetNote(pCaptData->maStart))
2690                 {
2691                     pSharedData->AddNoteObj( xShape, pCaptData->maStart );
2692 
2693                     // #i60851# When the file is saved while editing a new note,
2694                     // the cell is still empty -> last column/row must be updated
2695                     OSL_ENSURE( pCaptData->maStart.Tab() == nCurrentTable, "invalid table in object data" );
2696                     pSharedData->SetLastColumn( nCurrentTable, pCaptData->maStart.Col() );
2697                     pSharedData->SetLastRow( nCurrentTable, pCaptData->maStart.Row() );
2698                 }
2699             }
2700             // other objects from internal layer only (detective)
2701             else if( pObject->GetLayer() == SC_LAYER_INTERN )
2702             {
2703                 ScDetectiveFunc aDetFunc( pDoc, static_cast<SCTAB>(nCurrentTable) );
2704                 ScAddress       aPosition;
2705                 ScRange         aSourceRange;
2706                 bool            bRedLine;
2707                 ScDetectiveObjType eObjType = aDetFunc.GetDetectiveObjectType(
2708                     pObject, nCurrentTable, aPosition, aSourceRange, bRedLine );
2709                 pSharedData->GetDetectiveObjContainer()->AddObject( eObjType, static_cast<SCTAB>(nCurrentTable), aPosition, aSourceRange, bRedLine );
2710             }
2711         }
2712     }
2713 }
2714 
2715 bool ScXMLExport::GetMerged (const table::CellRangeAddress* pCellAddress,
2716                             const uno::Reference <sheet::XSpreadsheet>& xTable)
2717 {
2718     bool bReady(false);
2719     sal_Int32 nRow(pCellAddress->StartRow);
2720     sal_Int32 nCol(pCellAddress->StartColumn);
2721     sal_Int32 nEndRow(pCellAddress->EndRow);
2722     sal_Int32 nEndCol(pCellAddress->EndColumn);
2723     bool bRowInc(nEndRow > nRow);
2724     while(!bReady && nRow <= nEndRow && nCol <= nEndCol)
2725     {
2726         uno::Reference<sheet::XSheetCellRange> xSheetCellRange(xTable->getCellRangeByPosition(nCol, nRow, nCol, nRow), uno::UNO_QUERY);
2727         if (xSheetCellRange.is())
2728         {
2729             uno::Reference<sheet::XSheetCellCursor> xCursor(xTable->createCursorByRange(xSheetCellRange));
2730             if(xCursor.is())
2731             {
2732                 uno::Reference<sheet::XCellRangeAddressable> xCellAddress (xCursor, uno::UNO_QUERY);
2733                 xCursor->collapseToMergedArea();
2734                 table::CellRangeAddress aCellAddress2(xCellAddress->getRangeAddress());
2735                 ScRange aScRange( aCellAddress2.StartColumn, aCellAddress2.StartRow, aCellAddress2.Sheet,
2736                                   aCellAddress2.EndColumn, aCellAddress2.EndRow, aCellAddress2.Sheet );
2737 
2738                 if ((aScRange.aEnd.Row() > nRow ||
2739                     aScRange.aEnd.Col() > nCol) &&
2740                     aScRange.aStart.Row() == nRow &&
2741                     aScRange.aStart.Col() == nCol)
2742                 {
2743                     pMergedRangesContainer->AddRange(aScRange);
2744                     pSharedData->SetLastColumn(aScRange.aEnd.Tab(), aScRange.aEnd.Col());
2745                     pSharedData->SetLastRow(aScRange.aEnd.Tab(), aScRange.aEnd.Row());
2746                 }
2747                 else
2748                     bReady = true;
2749             }
2750         }
2751         if (!bReady)
2752         {
2753             if (bRowInc)
2754                 ++nRow;
2755             else
2756                 ++nCol;
2757         }
2758     }
2759     OSL_ENSURE(!(!bReady && nEndRow > nRow && nEndCol > nCol), "should not be possible");
2760     return !bReady;
2761 }
2762 
2763 bool ScXMLExport::IsMatrix (const ScAddress& aCell,
2764                             ScRange& aCellAddress, bool& bIsFirst) const
2765 {
2766     bIsFirst = false;
2767 
2768     ScRange aMatrixRange;
2769 
2770     if (pDoc && pDoc->GetMatrixFormulaRange(aCell, aMatrixRange))
2771     {
2772         aCellAddress = aMatrixRange;
2773         if ((aCellAddress.aStart.Col() == aCell.Col() && aCellAddress.aStart.Row() == aCell.Row()) &&
2774             (aCellAddress.aEnd.Col() > aCell.Col() || aCellAddress.aEnd.Row() > aCell.Row()))
2775         {
2776             bIsFirst = true;
2777             return true;
2778         }
2779         else if (aCellAddress.aStart.Col() != aCell.Col() || aCellAddress.aStart.Row() != aCell.Row() ||
2780             aCellAddress.aEnd.Col() != aCell.Col() || aCellAddress.aEnd.Row()!= aCell.Row())
2781             return true;
2782         else
2783         {
2784             bIsFirst = true;
2785             return true;
2786         }
2787     }
2788 
2789     return false;
2790 }
2791 
2792 void ScXMLExport::WriteTable(sal_Int32 nTable, const uno::Reference<sheet::XSpreadsheet>& xTable)
2793 {
2794     if (!xTable.is())
2795         return;
2796 
2797     xCurrentTable.set(xTable);
2798     uno::Reference<container::XNamed> xName (xTable, uno::UNO_QUERY );
2799     if (!xName.is())
2800         return;
2801 
2802     nCurrentTable = sal::static_int_cast<sal_uInt16>( nTable );
2803     OUString sOUTableName(xName->getName());
2804     AddAttribute(sAttrName, sOUTableName);
2805     AddAttribute(sAttrStyleName, aTableStyles[nTable]);
2806 
2807     uno::Reference<util::XProtectable> xProtectable (xTable, uno::UNO_QUERY);
2808     ScTableProtection* pProtect = nullptr;
2809     if (xProtectable.is() && xProtectable->isProtected())
2810     {
2811         AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE);
2812         if (pDoc)
2813         {
2814             pProtect = pDoc->GetTabProtection(nTable);
2815             if (pProtect)
2816             {
2817                 OUStringBuffer aBuffer;
2818                 ScPasswordHash eHashUsed = PASSHASH_UNSPECIFIED;
2819                 if (pProtect->hasPasswordHash(PASSHASH_SHA1))
2820                 {
2821                     ::comphelper::Base64::encode(aBuffer,
2822                         pProtect->getPasswordHash(PASSHASH_SHA1));
2823                     eHashUsed = PASSHASH_SHA1;
2824                 }
2825                 else if (pProtect->hasPasswordHash(PASSHASH_SHA256))
2826                 {
2827                     ::comphelper::Base64::encode(aBuffer,
2828                         pProtect->getPasswordHash(PASSHASH_SHA256));
2829                     eHashUsed = PASSHASH_SHA256;
2830                 }
2831                 else if (pProtect->hasPasswordHash(PASSHASH_XL, PASSHASH_SHA1))
2832                 {
2833                     // Double-hash this by SHA1 on top of the legacy xls hash.
2834                     uno::Sequence<sal_Int8> aHash = pProtect->getPasswordHash(PASSHASH_XL, PASSHASH_SHA1);
2835                     ::comphelper::Base64::encode(aBuffer, aHash);
2836                     eHashUsed = PASSHASH_XL;
2837                 }
2838                 if (!aBuffer.isEmpty())
2839                 {
2840                     AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
2841                     if ( getDefaultVersion() >= SvtSaveOptions::ODFVER_012 )
2842                     {
2843                         if (eHashUsed == PASSHASH_XL)
2844                         {
2845                             AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
2846                                          ScPassHashHelper::getHashURI(PASSHASH_XL));
2847                             if (getDefaultVersion() > SvtSaveOptions::ODFVER_012)
2848                                 AddAttribute(XML_NAMESPACE_LO_EXT, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2,
2849                                         ScPassHashHelper::getHashURI(PASSHASH_SHA1));
2850                         }
2851                         else if (eHashUsed == PASSHASH_SHA1)
2852                         {
2853                             AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
2854                                          ScPassHashHelper::getHashURI(PASSHASH_SHA1));
2855                         }
2856                         else if (eHashUsed == PASSHASH_SHA256)
2857                         {
2858                             AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
2859                                          ScPassHashHelper::getHashURI(PASSHASH_SHA256));
2860                         }
2861                     }
2862                 }
2863             }
2864         }
2865     }
2866     OUString sPrintRanges;
2867     ScRange aColumnHeaderRange;
2868     bool bHasColumnHeader;
2869     GetColumnRowHeader(bHasColumnHeader, aColumnHeaderRange, bHasRowHeader, aRowHeaderRange, sPrintRanges);
2870     if( !sPrintRanges.isEmpty() )
2871         AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT_RANGES, sPrintRanges );
2872     else if (pDoc && !pDoc->IsPrintEntireSheet(static_cast<SCTAB>(nTable)))
2873         AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT, XML_FALSE);
2874     SvXMLElementExport aElemT(*this, sElemTab, true, true);
2875 
2876     if (pProtect && pProtect->isProtected() && getDefaultVersion() > SvtSaveOptions::ODFVER_012)
2877     {
2878         if (pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS))
2879             AddAttribute(XML_NAMESPACE_LO_EXT, XML_SELECT_PROTECTED_CELLS, XML_TRUE);
2880         if (pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS))
2881             AddAttribute(XML_NAMESPACE_LO_EXT, XML_SELECT_UNPROTECTED_CELLS, XML_TRUE);
2882 
2883         if (pProtect->isOptionEnabled(ScTableProtection::INSERT_COLUMNS))
2884             AddAttribute(XML_NAMESPACE_LO_EXT, XML_INSERT_COLUMNS, XML_TRUE);
2885         if (pProtect->isOptionEnabled(ScTableProtection::INSERT_ROWS))
2886             AddAttribute(XML_NAMESPACE_LO_EXT, XML_INSERT_ROWS, XML_TRUE);
2887 
2888         if (pProtect->isOptionEnabled(ScTableProtection::DELETE_COLUMNS))
2889             AddAttribute(XML_NAMESPACE_LO_EXT, XML_DELETE_COLUMNS, XML_TRUE);
2890         if (pProtect->isOptionEnabled(ScTableProtection::DELETE_ROWS))
2891             AddAttribute(XML_NAMESPACE_LO_EXT, XML_DELETE_ROWS, XML_TRUE);
2892 
2893         OUString aElemName = GetNamespaceMap().GetQNameByKey(
2894             XML_NAMESPACE_LO_EXT, GetXMLToken(XML_TABLE_PROTECTION));
2895 
2896         SvXMLElementExport aElemProtected(*this, aElemName, true, true);
2897     }
2898 
2899     CheckAttrList();
2900 
2901     if ( pDoc && pDoc->GetSheetEvents( static_cast<SCTAB>(nTable) ) &&
2902          getDefaultVersion() >= SvtSaveOptions::ODFVER_012 )
2903     {
2904         // store sheet events
2905         uno::Reference<document::XEventsSupplier> xSupplier(xTable, uno::UNO_QUERY);
2906         uno::Reference<container::XNameAccess> xEvents = xSupplier->getEvents();
2907         GetEventExport().ExportExt( xEvents );
2908     }
2909 
2910     WriteTableSource();
2911     WriteScenario();
2912     uno::Reference<drawing::XDrawPage> xDrawPage;
2913     if (pSharedData->HasForm(nTable, xDrawPage) && xDrawPage.is())
2914     {
2915         ::xmloff::OOfficeFormsExport aForms(*this);
2916         GetFormExport()->exportForms( xDrawPage );
2917         bool bRet(GetFormExport()->seekPage( xDrawPage ));
2918         OSL_ENSURE( bRet, "OFormLayerXMLExport::seekPage failed!" );
2919     }
2920     if (pSharedData->HasDrawPage())
2921     {
2922         GetShapeExport()->seekShapes(pSharedData->GetDrawPage(nTable));
2923         WriteTableShapes();
2924     }
2925     table::CellRangeAddress aRange(GetEndAddress(xTable));
2926     pSharedData->SetLastColumn(nTable, aRange.EndColumn);
2927     pSharedData->SetLastRow(nTable, aRange.EndRow);
2928     mpCellsItr->SetCurrentTable(static_cast<SCTAB>(nTable), xCurrentTable);
2929     pGroupColumns->NewTable();
2930     pGroupRows->NewTable();
2931     FillColumnRowGroups();
2932     if (bHasColumnHeader)
2933         pSharedData->SetLastColumn(nTable, aColumnHeaderRange.aEnd.Col());
2934     bRowHeaderOpen = false;
2935     if (bHasRowHeader)
2936         pSharedData->SetLastRow(nTable, aRowHeaderRange.aEnd.Row());
2937     pDefaults->FillDefaultStyles(nTable, pSharedData->GetLastRow(nTable),
2938         pSharedData->GetLastColumn(nTable), pCellStyles.get(), pDoc);
2939     pRowFormatRanges->SetColDefaults(&pDefaults->GetColDefaults());
2940     pCellStyles->SetColDefaults(&pDefaults->GetColDefaults());
2941     ExportColumns(nTable, aColumnHeaderRange, bHasColumnHeader);
2942     bool bIsFirst(true);
2943     sal_Int32 nEqualCells(0);
2944     ScMyCell aCell;
2945     ScMyCell aPrevCell;
2946     while (mpCellsItr->GetNext(aCell, pCellStyles.get()))
2947     {
2948         if (bIsFirst)
2949         {
2950             ExportFormatRanges(0, 0, aCell.maCellAddress.Col()-1, aCell.maCellAddress.Row(), nTable);
2951             aPrevCell = aCell;
2952             bIsFirst = false;
2953         }
2954         else
2955         {
2956             if ((aPrevCell.maCellAddress.Row() == aCell.maCellAddress.Row()) &&
2957                 (aPrevCell.maCellAddress.Col() + nEqualCells + 1 == aCell.maCellAddress.Col()))
2958             {
2959                 if(IsCellEqual(aPrevCell, aCell))
2960                     ++nEqualCells;
2961                 else
2962                 {
2963                     WriteCell(aPrevCell, nEqualCells);
2964                     nEqualCells = 0;
2965                     aPrevCell = aCell;
2966                 }
2967             }
2968             else
2969             {
2970                 WriteCell(aPrevCell, nEqualCells);
2971                 ExportFormatRanges(aPrevCell.maCellAddress.Col() + nEqualCells + 1, aPrevCell.maCellAddress.Row(),
2972                     aCell.maCellAddress.Col()-1, aCell.maCellAddress.Row(), nTable);
2973                 nEqualCells = 0;
2974                 aPrevCell = aCell;
2975             }
2976         }
2977     }
2978     if (!bIsFirst)
2979     {
2980         WriteCell(aPrevCell, nEqualCells);
2981         ExportFormatRanges(aPrevCell.maCellAddress.Col() + nEqualCells + 1, aPrevCell.maCellAddress.Row(),
2982             pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
2983     }
2984     else
2985         ExportFormatRanges(0, 0, pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
2986 
2987     CloseRow(pSharedData->GetLastRow(nTable));
2988 
2989     if (pDoc)
2990     {
2991         // Export sheet-local named ranges.
2992         ScRangeName* pRangeName = pDoc->GetRangeName(nTable);
2993         if (pRangeName && !pRangeName->empty())
2994         {
2995             WriteNamedRange(pRangeName);
2996         }
2997 
2998         if(getDefaultVersion() > SvtSaveOptions::ODFVER_012)
2999         {
3000             //export new conditional format information
3001             ExportConditionalFormat(nTable);
3002         }
3003 
3004     }
3005 }
3006 
3007 namespace {
3008 
3009 void writeContent(
3010     ScXMLExport& rExport, const OUString& rStyleName, const OUString& rContent, const SvxFieldData* pField )
3011 {
3012     std::unique_ptr<SvXMLElementExport> pElem;
3013     if (!rStyleName.isEmpty())
3014     {
3015         // Formatted section with automatic style.
3016         rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME, rStyleName);
3017         OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3018             XML_NAMESPACE_TEXT, GetXMLToken(XML_SPAN));
3019         pElem.reset(new SvXMLElementExport(rExport, aElemName, false, false));
3020     }
3021 
3022     if (pField)
3023     {
3024         // Write a field item.
3025         OUString aFieldVal = ScEditUtil::GetCellFieldValue(*pField, rExport.GetDocument(), nullptr);
3026         switch (pField->GetClassId())
3027         {
3028             case text::textfield::Type::URL:
3029             {
3030                 // <text:a xlink:href="url" xlink:type="simple">value</text:a>
3031 
3032                 const SvxURLField* pURLField = static_cast<const SvxURLField*>(pField);
3033                 const OUString& aURL = pURLField->GetURL();
3034                 rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, rExport.GetRelativeReference(aURL));
3035                 rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, "simple");
3036                 const OUString& aTargetFrame = pURLField->GetTargetFrame();
3037                 if (!aTargetFrame.isEmpty())
3038                     rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_TARGET_FRAME_NAME, aTargetFrame);
3039 
3040                 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3041                     XML_NAMESPACE_TEXT, GetXMLToken(XML_A));
3042                 SvXMLElementExport aElem(rExport, aElemName, false, false);
3043                 rExport.Characters(aFieldVal);
3044             }
3045             break;
3046             case text::textfield::Type::DATE:
3047             {
3048                 // <text:date style:data-style-name="N2" text:date-value="YYYY-MM-DD">value</text:date>
3049 
3050                 Date aDate(Date::SYSTEM);
3051                 OUStringBuffer aBuf;
3052                 sal_Int32 nVal = aDate.GetYear();
3053                 aBuf.append(nVal);
3054                 aBuf.append('-');
3055                 nVal = aDate.GetMonth();
3056                 if (nVal < 10)
3057                     aBuf.append('0');
3058                 aBuf.append(nVal);
3059                 aBuf.append('-');
3060                 nVal = aDate.GetDay();
3061                 if (nVal < 10)
3062                     aBuf.append('0');
3063                 aBuf.append(nVal);
3064                 rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_DATA_STYLE_NAME, "N2");
3065                 rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_DATE_VALUE, aBuf.makeStringAndClear());
3066 
3067                 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3068                     XML_NAMESPACE_TEXT, GetXMLToken(XML_DATE));
3069                 SvXMLElementExport aElem(rExport, aElemName, false, false);
3070                 rExport.Characters(aFieldVal);
3071             }
3072             break;
3073             case text::textfield::Type::DOCINFO_TITLE:
3074             {
3075                 // <text:title>value</text:title>
3076 
3077                 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3078                     XML_NAMESPACE_TEXT, GetXMLToken(XML_TITLE));
3079                 SvXMLElementExport aElem(rExport, aElemName, false, false);
3080                 rExport.Characters(aFieldVal);
3081             }
3082             break;
3083             case text::textfield::Type::TABLE:
3084             {
3085                 // <text:sheet-name>value</text:sheet-name>
3086 
3087                 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3088                     XML_NAMESPACE_TEXT, GetXMLToken(XML_SHEET_NAME));
3089                 SvXMLElementExport aElem(rExport, aElemName, false, false);
3090                 rExport.Characters(aFieldVal);
3091             }
3092             break;
3093             default:
3094                 rExport.Characters(aFieldVal);
3095         }
3096     }
3097     else
3098         rExport.Characters(rContent);
3099 }
3100 
3101 void flushParagraph(
3102     ScXMLExport& rExport, const OUString& rParaText,
3103     rtl::Reference<XMLPropertySetMapper> const & xMapper, rtl::Reference<SvXMLAutoStylePoolP> const & xStylePool,
3104     const ScXMLEditAttributeMap& rAttrMap,
3105     std::vector<editeng::Section>::const_iterator it, std::vector<editeng::Section>::const_iterator const & itEnd )
3106 {
3107     OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3108         XML_NAMESPACE_TEXT, GetXMLToken(XML_P));
3109     SvXMLElementExport aElemP(rExport, aElemName, false, false);
3110 
3111     for (; it != itEnd; ++it)
3112     {
3113         const editeng::Section& rSec = *it;
3114 
3115         OUString aContent(rParaText.copy(rSec.mnStart, rSec.mnEnd - rSec.mnStart));
3116 
3117         std::vector<XMLPropertyState> aPropStates;
3118         const SvxFieldData* pField = toXMLPropertyStates(aPropStates, rSec.maAttributes, xMapper, rAttrMap);
3119         OUString aStyleName = xStylePool->Find(XML_STYLE_FAMILY_TEXT_TEXT, OUString(), aPropStates);
3120         writeContent(rExport, aStyleName, aContent, pField);
3121     }
3122 }
3123 
3124 }
3125 
3126 void ScXMLExport::WriteCell(ScMyCell& aCell, sal_Int32 nEqualCellCount)
3127 {
3128     // nEqualCellCount is the number of additional cells
3129     SetRepeatAttribute(nEqualCellCount, (aCell.nType != table::CellContentType_EMPTY));
3130 
3131     if (aCell.nStyleIndex != -1)
3132         AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(aCell.nStyleIndex, aCell.bIsAutoStyle));
3133     if (aCell.nValidationIndex > -1)
3134         AddAttribute(XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, pValidationsContainer->GetValidationName(aCell.nValidationIndex));
3135     const bool bIsFirstMatrixCell(aCell.bIsMatrixBase);
3136     if (bIsFirstMatrixCell)
3137     {
3138         SCCOL nColumns( aCell.aMatrixRange.aEnd.Col() - aCell.aMatrixRange.aStart.Col() + 1 );
3139         SCROW nRows( aCell.aMatrixRange.aEnd.Row() - aCell.aMatrixRange.aStart.Row() + 1 );
3140         AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_COLUMNS_SPANNED, OUString::number(nColumns));
3141         AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_ROWS_SPANNED, OUString::number(nRows));
3142     }
3143     bool bIsEmpty(false);
3144     switch (aCell.nType)
3145     {
3146         case table::CellContentType_EMPTY :
3147             {
3148                 bIsEmpty = true;
3149             }
3150             break;
3151         case table::CellContentType_VALUE :
3152             {
3153                 GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3154                     aCell.nNumberFormat, aCell.maBaseCell.mfValue);
3155                 if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3156                     GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3157                             aCell.nNumberFormat, aCell.maBaseCell.mfValue, false, XML_NAMESPACE_CALC_EXT, false);
3158             }
3159             break;
3160         case table::CellContentType_TEXT :
3161             {
3162                 OUString sFormattedString(lcl_GetFormattedString(pDoc, aCell.maBaseCell, aCell.maCellAddress));
3163                 OUString sCellString = aCell.maBaseCell.getString(pDoc);
3164                 GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3165                         sCellString, sFormattedString);
3166                 if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3167                     GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3168                             sCellString, sFormattedString, false, XML_NAMESPACE_CALC_EXT);
3169             }
3170             break;
3171         case table::CellContentType_FORMULA :
3172             {
3173                 if (aCell.maBaseCell.meType == CELLTYPE_FORMULA)
3174                 {
3175                     const bool bIsMatrix(bIsFirstMatrixCell || aCell.bIsMatrixCovered);
3176                     ScFormulaCell* pFormulaCell = aCell.maBaseCell.mpFormula;
3177                     if (!bIsMatrix || bIsFirstMatrixCell)
3178                     {
3179                         if (!mpCompileFormulaCxt)
3180                         {
3181                             const formula::FormulaGrammar::Grammar eGrammar = pDoc->GetStorageGrammar();
3182                             mpCompileFormulaCxt.reset(new sc::CompileFormulaContext(pDoc, eGrammar));
3183                         }
3184 
3185                         OUString aFormula = pFormulaCell->GetFormula(*mpCompileFormulaCxt);
3186                         sal_uInt16 nNamespacePrefix =
3187                             (mpCompileFormulaCxt->getGrammar() == formula::FormulaGrammar::GRAM_ODFF ? XML_NAMESPACE_OF : XML_NAMESPACE_OOOC);
3188 
3189                         if (!bIsMatrix)
3190                         {
3191                             AddAttribute(sAttrFormula, GetNamespaceMap().GetQNameByKey(nNamespacePrefix, aFormula, false));
3192                         }
3193                         else
3194                         {
3195                             AddAttribute(sAttrFormula, GetNamespaceMap().GetQNameByKey(nNamespacePrefix, aFormula.copy(1, aFormula.getLength()-2), false));
3196                         }
3197                     }
3198                     if (pFormulaCell->GetErrCode() != FormulaError::NONE)
3199                     {
3200                         AddAttribute(sAttrValueType, XML_STRING);
3201                         AddAttribute(sAttrStringValue, aCell.maBaseCell.getString(pDoc));
3202                         if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3203                         {
3204                             //export calcext:value-type="error"
3205                             AddAttribute(XML_NAMESPACE_CALC_EXT,XML_VALUE_TYPE, OUString("error"));
3206                         }
3207                     }
3208                     else if (pFormulaCell->IsValue())
3209                     {
3210                         bool bIsStandard;
3211                         OUString sCurrency;
3212                         GetNumberFormatAttributesExportHelper()->GetCellType(aCell.nNumberFormat, sCurrency, bIsStandard);
3213                         if (pDoc)
3214                         {
3215                             GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3216                                     aCell.nNumberFormat, pDoc->GetValue(aCell.maCellAddress));
3217                             if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3218                             {
3219                                 GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3220                                         aCell.nNumberFormat, pDoc->GetValue(aCell.maCellAddress), false, XML_NAMESPACE_CALC_EXT, false );
3221                             }
3222                         }
3223                     }
3224                     else
3225                     {
3226                         if (!aCell.maBaseCell.getString(pDoc).isEmpty())
3227                         {
3228                             AddAttribute(sAttrValueType, XML_STRING);
3229                             AddAttribute(sAttrStringValue, aCell.maBaseCell.getString(pDoc));
3230                             if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3231                             {
3232                                 AddAttribute(XML_NAMESPACE_CALC_EXT,XML_VALUE_TYPE, XML_STRING);
3233                             }
3234                         }
3235                     }
3236                 }
3237             }
3238             break;
3239         default:
3240             break;
3241     }
3242     OUString* pCellString(&sElemCell);
3243     if (aCell.bIsCovered)
3244     {
3245         pCellString = &sElemCoveredCell;
3246     }
3247     else
3248     {
3249         if (aCell.bIsMergedBase)
3250         {
3251             SCCOL nColumns( aCell.aMergeRange.aEnd.Col() - aCell.aMergeRange.aStart.Col() + 1 );
3252             SCROW nRows( aCell.aMergeRange.aEnd.Row() - aCell.aMergeRange.aStart.Row() + 1 );
3253             AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED, OUString::number(nColumns));
3254             AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED, OUString::number(nRows));
3255         }
3256     }
3257     SvXMLElementExport aElemC(*this, *pCellString, true, true);
3258     CheckAttrList();
3259     WriteAreaLink(aCell);
3260     WriteAnnotation(aCell);
3261     WriteDetective(aCell);
3262 
3263     if (!bIsEmpty)
3264     {
3265         if (aCell.maBaseCell.meType == CELLTYPE_EDIT)
3266         {
3267             WriteEditCell(aCell.maBaseCell.mpEditText);
3268         }
3269         else if (aCell.maBaseCell.meType == CELLTYPE_FORMULA && aCell.maBaseCell.mpFormula->IsMultilineResult())
3270         {
3271             WriteMultiLineFormulaResult(aCell.maBaseCell.mpFormula);
3272         }
3273         else
3274         {
3275             SvXMLElementExport aElemP(*this, sElemP, true, false);
3276 
3277             OUString aParaStr =
3278                 ScCellFormat::GetOutputString(*pDoc, aCell.maCellAddress, aCell.maBaseCell);
3279 
3280             bool bPrevCharWasSpace = true;
3281             GetTextParagraphExport()->exportCharacterData(aParaStr, bPrevCharWasSpace);
3282         }
3283     }
3284     WriteShapes(aCell);
3285     if (!bIsEmpty)
3286         IncrementProgressBar(false);
3287 }
3288 
3289 void ScXMLExport::WriteEditCell(const EditTextObject* pText)
3290 {
3291     rtl::Reference<XMLPropertySetMapper> xMapper = GetTextParagraphExport()->GetTextPropMapper()->getPropertySetMapper();
3292     rtl::Reference<SvXMLAutoStylePoolP> xStylePool = GetAutoStylePool();
3293     const ScXMLEditAttributeMap& rAttrMap = GetEditAttributeMap();
3294 
3295     // Get raw paragraph texts first.
3296     std::vector<OUString> aParaTexts;
3297     sal_Int32 nParaCount = pText->GetParagraphCount();
3298     aParaTexts.reserve(nParaCount);
3299     for (sal_Int32 i = 0; i < nParaCount; ++i)
3300         aParaTexts.push_back(pText->GetText(i));
3301 
3302     // Get all section data and iterate through them.
3303     std::vector<editeng::Section> aAttrs;
3304     pText->GetAllSections(aAttrs);
3305     std::vector<editeng::Section>::const_iterator itSec = aAttrs.begin(), itSecEnd = aAttrs.end();
3306     std::vector<editeng::Section>::const_iterator itPara = itSec;
3307     sal_Int32 nCurPara = 0; // current paragraph
3308     for (; itSec != itSecEnd; ++itSec)
3309     {
3310         const editeng::Section& rSec = *itSec;
3311         if (nCurPara == rSec.mnParagraph)
3312             // Still in the same paragraph.
3313             continue;
3314 
3315         // Start of a new paragraph. Flush the old paragraph.
3316         flushParagraph(*this, aParaTexts[nCurPara], xMapper, xStylePool, rAttrMap, itPara, itSec);
3317         nCurPara = rSec.mnParagraph;
3318         itPara = itSec;
3319     }
3320 
3321     flushParagraph(*this, aParaTexts[nCurPara], xMapper, xStylePool, rAttrMap, itPara, itSecEnd);
3322 }
3323 
3324 void ScXMLExport::WriteMultiLineFormulaResult(const ScFormulaCell* pCell)
3325 {
3326     OUString aElemName = GetNamespaceMap().GetQNameByKey(XML_NAMESPACE_TEXT, GetXMLToken(XML_P));
3327 
3328     OUString aResStr = pCell->GetResultString().getString();
3329     const sal_Unicode* p = aResStr.getStr();
3330     const sal_Unicode* pEnd = p + static_cast<size_t>(aResStr.getLength());
3331     const sal_Unicode* pPara = p; // paragraph head.
3332     for (; p != pEnd; ++p)
3333     {
3334         if (*p != '\n')
3335             continue;
3336 
3337         // flush the paragraph.
3338         OUString aContent;
3339         if (*pPara == '\n')
3340             ++pPara;
3341         if (p > pPara)
3342             aContent = OUString(pPara, p-pPara);
3343 
3344         SvXMLElementExport aElem(*this, aElemName, false, false);
3345         Characters(aContent);
3346 
3347         pPara = p;
3348     }
3349 
3350     OUString aContent;
3351     if (*pPara == '\n')
3352         ++pPara;
3353     if (pEnd > pPara)
3354         aContent = OUString(pPara, pEnd-pPara);
3355 
3356     SvXMLElementExport aElem(*this, aElemName, false, false);
3357     Characters(aContent);
3358 }
3359 
3360 void ScXMLExport::ExportShape(const uno::Reference < drawing::XShape >& xShape, awt::Point* pPoint)
3361 {
3362     uno::Reference < beans::XPropertySet > xShapeProps ( xShape, uno::UNO_QUERY );
3363     bool bIsChart( false );
3364     OUString sPropCLSID ("CLSID");
3365     if (xShapeProps.is())
3366     {
3367         sal_Int32 nZOrder = 0;
3368         if (xShapeProps->getPropertyValue("ZOrder") >>= nZOrder)
3369         {
3370             AddAttribute(XML_NAMESPACE_DRAW, XML_ZINDEX, OUString::number(nZOrder));
3371         }
3372         uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xShapeProps->getPropertySetInfo();
3373         if( xPropSetInfo->hasPropertyByName( sPropCLSID ) )
3374         {
3375             OUString sCLSID;
3376             if (xShapeProps->getPropertyValue( sPropCLSID ) >>= sCLSID)
3377             {
3378                 if ( sCLSID.equalsIgnoreAsciiCase(GetChartExport()->getChartCLSID()) )
3379                 {
3380                     // we have a chart
3381                     OUString sRanges;
3382                     if ( pDoc )
3383                     {
3384                         OUString aChartName;
3385                         xShapeProps->getPropertyValue( "PersistName" ) >>= aChartName;
3386                         ScChartListenerCollection* pCollection = pDoc->GetChartListenerCollection();
3387                         if (pCollection)
3388                         {
3389                             ScChartListener* pListener = pCollection->findByName(aChartName);
3390                             if (pListener)
3391                             {
3392                                 const ScRangeListRef& rRangeList = pListener->GetRangeList();
3393                                 if ( rRangeList.is() )
3394                                 {
3395                                     ScRangeStringConverter::GetStringFromRangeList( sRanges, rRangeList.get(), pDoc, FormulaGrammar::CONV_OOO );
3396                                     if ( !sRanges.isEmpty() )
3397                                     {
3398                                         bIsChart = true;
3399                                         SvXMLAttributeList* pAttrList = new SvXMLAttributeList();
3400                                         pAttrList->AddAttribute(
3401                                             GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_DRAW, GetXMLToken( XML_NOTIFY_ON_UPDATE_OF_RANGES ) ), sRanges );
3402                                         GetShapeExport()->exportShape( xShape, SEF_DEFAULT, pPoint, pAttrList );
3403                                     }
3404                                 }
3405                             }
3406                         }
3407                     }
3408 
3409                     if ( sRanges.isEmpty() )
3410                     {
3411                         uno::Reference< frame::XModel > xChartModel;
3412                         if( ( xShapeProps->getPropertyValue( "Model" ) >>= xChartModel ) &&
3413                             xChartModel.is())
3414                         {
3415                             uno::Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY );
3416                             uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartModel, uno::UNO_QUERY );
3417                             if( xChartDoc.is() && xReceiver.is() &&
3418                                 ! xChartDoc->hasInternalDataProvider())
3419                             {
3420                                 // we have a chart that gets its data from Calc
3421                                 bIsChart = true;
3422                                 uno::Sequence< OUString > aRepresentations(
3423                                     xReceiver->getUsedRangeRepresentations());
3424                                 SvXMLAttributeList* pAttrList = nullptr;
3425                                 if(aRepresentations.hasElements())
3426                                 {
3427                                     // add the ranges used by the chart to the shape
3428                                     // element to be able to start listening after
3429                                     // load (when the chart is not yet loaded)
3430                                     uno::Reference< chart2::data::XRangeXMLConversion > xRangeConverter( xChartDoc->getDataProvider(), uno::UNO_QUERY );
3431                                     sRanges = lcl_RangeSequenceToString( aRepresentations, xRangeConverter );
3432                                     pAttrList = new SvXMLAttributeList();
3433                                     pAttrList->AddAttribute(
3434                                         GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_DRAW, GetXMLToken(XML_NOTIFY_ON_UPDATE_OF_RANGES) ), sRanges );
3435                                 }
3436                                 GetShapeExport()->exportShape(xShape, SEF_DEFAULT, pPoint, pAttrList);
3437                             }
3438                         }
3439                     }
3440                 }
3441             }
3442         }
3443     }
3444     if (!bIsChart)
3445     {
3446         OUString sHlink;
3447         try
3448         {
3449             uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );
3450             if ( xProps.is() )
3451                 xProps->getPropertyValue( SC_UNONAME_HYPERLINK ) >>= sHlink;
3452         }
3453         catch ( const beans::UnknownPropertyException& )
3454         {
3455             // no hyperlink property
3456         }
3457 
3458         std::unique_ptr< SvXMLElementExport > pDrawA;
3459         // enclose shapes with <draw:a> element only if sHlink contains something
3460         if ( !sHlink.isEmpty() )
3461         {
3462             // need to get delete the attributes that are pre-loaded
3463             // for the shape export ( otherwise they will become
3464             // attributes of the draw:a element ) This *shouldn't*
3465             // affect performance adversely as there are only a
3466             // couple of attributes involved
3467             uno::Reference< xml::sax::XAttributeList > xSaveAttribs( new  SvXMLAttributeList( GetAttrList() ) );
3468             ClearAttrList();
3469             // Add Hlink
3470             AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
3471             AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sHlink);
3472             pDrawA.reset( new SvXMLElementExport( *this, XML_NAMESPACE_DRAW, XML_A, false, false ) );
3473             // Attribute list has been cleared by previous operation
3474             // re-add pre-loaded attributes
3475             AddAttributeList( xSaveAttribs );
3476         }
3477         GetShapeExport()->exportShape(xShape, SEF_DEFAULT, pPoint);
3478     }
3479     IncrementProgressBar(false);
3480 }
3481 
3482 void ScXMLExport::WriteShapes(const ScMyCell& rMyCell)
3483 {
3484     if( rMyCell.bHasShape && !rMyCell.aShapeList.empty() && pDoc )
3485     {
3486         awt::Point aPoint;
3487         tools::Rectangle aRect = pDoc->GetMMRect(rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(),
3488             rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(), rMyCell.maCellAddress.Tab());
3489         bool bNegativePage = pDoc->IsNegativePage(rMyCell.maCellAddress.Tab());
3490         if (bNegativePage)
3491             aPoint.X = aRect.Right();
3492         else
3493             aPoint.X = aRect.Left();
3494         aPoint.Y = aRect.Top();
3495         for (const auto& rShape : rMyCell.aShapeList)
3496         {
3497             if (rShape.xShape.is())
3498             {
3499                 if (bNegativePage)
3500                     aPoint.X = 2 * rShape.xShape->getPosition().X + rShape.xShape->getSize().Width - aPoint.X;
3501 
3502                 // We only write the end address if we want the shape to resize with the cell
3503                 if ( rShape.bResizeWithCell &&
3504                     rShape.xShape->getShapeType() != "com.sun.star.drawing.CaptionShape" )
3505                 {
3506                     OUString sEndAddress;
3507                     ScRangeStringConverter::GetStringFromAddress(sEndAddress, rShape.aEndAddress, pDoc, FormulaGrammar::CONV_OOO);
3508                     AddAttribute(XML_NAMESPACE_TABLE, XML_END_CELL_ADDRESS, sEndAddress);
3509                     OUStringBuffer sBuffer;
3510                     GetMM100UnitConverter().convertMeasureToXML(
3511                             sBuffer, rShape.nEndX);
3512                     AddAttribute(XML_NAMESPACE_TABLE, XML_END_X, sBuffer.makeStringAndClear());
3513                     GetMM100UnitConverter().convertMeasureToXML(
3514                             sBuffer, rShape.nEndY);
3515                     AddAttribute(XML_NAMESPACE_TABLE, XML_END_Y, sBuffer.makeStringAndClear());
3516                 }
3517                 ExportShape(rShape.xShape, &aPoint);
3518             }
3519         }
3520     }
3521 }
3522 
3523 void ScXMLExport::WriteTableShapes()
3524 {
3525     ScMyTableShapes* pTableShapes(pSharedData->GetTableShapes());
3526     if (pTableShapes && !(*pTableShapes)[nCurrentTable].empty())
3527     {
3528         OSL_ENSURE(pTableShapes->size() > static_cast<size_t>(nCurrentTable), "wrong Table");
3529         SvXMLElementExport aShapesElem(*this, XML_NAMESPACE_TABLE, XML_SHAPES, true, false);
3530         for (const auto& rxShape : (*pTableShapes)[nCurrentTable])
3531         {
3532             if (rxShape.is())
3533             {
3534                 if (pDoc->IsNegativePage(static_cast<SCTAB>(nCurrentTable)))
3535                 {
3536                     awt::Point aPoint(rxShape->getPosition());
3537                     awt::Size aSize(rxShape->getSize());
3538                     aPoint.X += aPoint.X + aSize.Width;
3539                     aPoint.Y = 0;
3540                     ExportShape(rxShape, &aPoint);
3541                 }
3542                 else
3543                     ExportShape(rxShape, nullptr);
3544             }
3545         }
3546         (*pTableShapes)[nCurrentTable].clear();
3547     }
3548 }
3549 
3550 void ScXMLExport::WriteAreaLink( const ScMyCell& rMyCell )
3551 {
3552     if( rMyCell.bHasAreaLink )
3553     {
3554         const ScMyAreaLink& rAreaLink = rMyCell.aAreaLink;
3555         AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, rAreaLink.sSourceStr );
3556         AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
3557         AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, GetRelativeReference(rAreaLink.sURL) );
3558         AddAttribute( XML_NAMESPACE_TABLE, XML_FILTER_NAME, rAreaLink.sFilter );
3559         if( !rAreaLink.sFilterOptions.isEmpty() )
3560             AddAttribute( XML_NAMESPACE_TABLE, XML_FILTER_OPTIONS, rAreaLink.sFilterOptions );
3561         OUStringBuffer sValue;
3562         AddAttribute( XML_NAMESPACE_TABLE, XML_LAST_COLUMN_SPANNED, OUString::number(rAreaLink.GetColCount()) );
3563         AddAttribute( XML_NAMESPACE_TABLE, XML_LAST_ROW_SPANNED, OUString::number(rAreaLink.GetRowCount()) );
3564         if( rAreaLink.nRefresh )
3565         {
3566             ::sax::Converter::convertDuration( sValue,
3567                     static_cast<double>(rAreaLink.nRefresh) / 86400 );
3568             AddAttribute( XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, sValue.makeStringAndClear() );
3569         }
3570         SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_CELL_RANGE_SOURCE, true, true );
3571     }
3572 }
3573 
3574 void ScXMLExport::exportAnnotationMeta( const uno::Reference < drawing::XShape >& xShape)
3575 {
3576     ScPostIt* pNote = pCurrentCell->pNote;
3577 
3578     if (pNote)
3579     {
3580         // TODO : notes
3581         //is it still useful, as this call back is only called from ScXMLExport::WriteAnnotation
3582         // and should be in sync with pCurrentCell
3583         SdrCaptionObj* pNoteCaption = pNote->GetOrCreateCaption(pCurrentCell->maCellAddress);
3584         uno::Reference<drawing::XShape> xCurrentShape( pNoteCaption->getUnoShape(), uno::UNO_QUERY );
3585         if (xCurrentShape.get()!=xShape.get())
3586             return;
3587 
3588         const OUString& sAuthor(pNote->GetAuthor());
3589         if (!sAuthor.isEmpty())
3590         {
3591             SvXMLElementExport aCreatorElem( *this, XML_NAMESPACE_DC,
3592                                                 XML_CREATOR, true,
3593                                                 false );
3594             Characters(sAuthor);
3595         }
3596 
3597         const OUString& aDate(pNote->GetDate());
3598         if (pDoc)
3599         {
3600             SvNumberFormatter* pNumForm = pDoc->GetFormatTable();
3601             double fDate;
3602             sal_uInt32 nfIndex = pNumForm->GetFormatIndex(NF_DATE_SYS_DDMMYYYY, LANGUAGE_SYSTEM);
3603             if (pNumForm->IsNumberFormat(aDate, nfIndex, fDate))
3604             {
3605                 OUStringBuffer sBuf;
3606                 GetMM100UnitConverter().convertDateTime(sBuf, fDate,true);
3607                 SvXMLElementExport aDateElem( *this, XML_NAMESPACE_DC,
3608                                                 XML_DATE, true,
3609                                                 false );
3610                 Characters(sBuf.makeStringAndClear());
3611             }
3612             else
3613             {
3614                 SvXMLElementExport aDateElem( *this, XML_NAMESPACE_META,
3615                                                 XML_DATE_STRING, true,
3616                                                 false );
3617                 Characters(aDate);
3618             }
3619         }
3620         else
3621         {
3622             SvXMLElementExport aDateElem( *this, XML_NAMESPACE_META,
3623                                             XML_DATE_STRING, true,
3624                                             false );
3625             Characters(aDate);
3626         }
3627     }
3628 }
3629 
3630 void ScXMLExport::WriteAnnotation(ScMyCell& rMyCell)
3631 {
3632     ScPostIt* pNote = pDoc->GetNote(rMyCell.maCellAddress);
3633     if (pNote)
3634     {
3635         if (pNote->IsCaptionShown())
3636             AddAttribute(XML_NAMESPACE_OFFICE, XML_DISPLAY, XML_TRUE);
3637 
3638         pCurrentCell = &rMyCell;
3639 
3640         SdrCaptionObj* pNoteCaption = pNote->GetOrCreateCaption(rMyCell.maCellAddress);
3641         if (pNoteCaption)
3642         {
3643             uno::Reference<drawing::XShape> xShape( pNoteCaption->getUnoShape(), uno::UNO_QUERY );
3644             if (xShape.is())
3645                 GetShapeExport()->exportShape(xShape, SEF_DEFAULT|XMLShapeExportFlags::ANNOTATION);
3646         }
3647 
3648         pCurrentCell = nullptr;
3649 
3650     }
3651 }
3652 
3653 void ScXMLExport::WriteDetective( const ScMyCell& rMyCell )
3654 {
3655     if( rMyCell.bHasDetectiveObj || rMyCell.bHasDetectiveOp )
3656     {
3657         const ScMyDetectiveObjVec& rObjVec = rMyCell.aDetectiveObjVec;
3658         const ScMyDetectiveOpVec& rOpVec = rMyCell.aDetectiveOpVec;
3659         sal_Int32 nObjCount(rObjVec.size());
3660         sal_Int32 nOpCount(rOpVec.size());
3661         if( nObjCount || nOpCount )
3662         {
3663             SvXMLElementExport aDetElem( *this, XML_NAMESPACE_TABLE, XML_DETECTIVE, true, true );
3664             OUString sString;
3665             for(const auto& rObj : rObjVec)
3666             {
3667                 if (rObj.eObjType != SC_DETOBJ_CIRCLE)
3668                 {
3669                     if( (rObj.eObjType == SC_DETOBJ_ARROW) || (rObj.eObjType == SC_DETOBJ_TOOTHERTAB))
3670                     {
3671                         ScRangeStringConverter::GetStringFromRange( sString, rObj.aSourceRange, pDoc, FormulaGrammar::CONV_OOO );
3672                         AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, sString );
3673                     }
3674                     ScXMLConverter::GetStringFromDetObjType( sString, rObj.eObjType );
3675                     AddAttribute( XML_NAMESPACE_TABLE, XML_DIRECTION, sString );
3676                     if( rObj.bHasError )
3677                         AddAttribute( XML_NAMESPACE_TABLE, XML_CONTAINS_ERROR, XML_TRUE );
3678                 }
3679                 else
3680                     AddAttribute( XML_NAMESPACE_TABLE, XML_MARKED_INVALID, XML_TRUE );
3681                 SvXMLElementExport aRangeElem( *this, XML_NAMESPACE_TABLE, XML_HIGHLIGHTED_RANGE, true, true );
3682             }
3683             for(const auto& rOp : rOpVec)
3684             {
3685                 OUString sOpString;
3686                 ScXMLConverter::GetStringFromDetOpType( sOpString, rOp.eOpType );
3687                 AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, sOpString );
3688                 AddAttribute( XML_NAMESPACE_TABLE, XML_INDEX, OUString::number(rOp.nIndex) );
3689                 SvXMLElementExport aRangeElem( *this, XML_NAMESPACE_TABLE, XML_OPERATION, true, true );
3690             }
3691         }
3692     }
3693 }
3694 
3695 void ScXMLExport::SetRepeatAttribute(sal_Int32 nEqualCellCount, bool bIncProgress)
3696 {
3697     // nEqualCellCount is additional cells, so the attribute value is nEqualCellCount+1
3698     if (nEqualCellCount > 0)
3699     {
3700         sal_Int32 nTemp(nEqualCellCount + 1);
3701         OUString sOUEqualCellCount(OUString::number(nTemp));
3702         AddAttribute(sAttrColumnsRepeated, sOUEqualCellCount);
3703         if (bIncProgress)
3704             IncrementProgressBar(false, nEqualCellCount);
3705     }
3706 }
3707 
3708 bool ScXMLExport::IsEditCell(const ScMyCell& rCell)
3709 {
3710     return rCell.maBaseCell.meType == CELLTYPE_EDIT;
3711 }
3712 
3713 bool ScXMLExport::IsCellEqual (ScMyCell& aCell1, ScMyCell& aCell2)
3714 {
3715     bool bIsEqual = false;
3716     if( !aCell1.bIsMergedBase && !aCell2.bIsMergedBase &&
3717         aCell1.bIsCovered == aCell2.bIsCovered &&
3718         !aCell1.bIsMatrixBase && !aCell2.bIsMatrixBase &&
3719         aCell1.bIsMatrixCovered == aCell2.bIsMatrixCovered &&
3720         aCell1.bHasAnnotation == aCell2.bHasAnnotation &&
3721         !aCell1.bHasShape && !aCell2.bHasShape &&
3722         aCell1.bHasAreaLink == aCell2.bHasAreaLink &&
3723         !aCell1.bHasDetectiveObj && !aCell2.bHasDetectiveObj)
3724     {
3725         if( (aCell1.bHasAreaLink &&
3726             (aCell1.aAreaLink.GetColCount() == 1) &&
3727             (aCell2.aAreaLink.GetColCount() == 1) &&
3728             aCell1.aAreaLink.Compare( aCell2.aAreaLink ) ) ||
3729             !aCell1.bHasAreaLink )
3730         {
3731             if (!aCell1.bHasAnnotation)
3732             {
3733                 if ((((aCell1.nStyleIndex == aCell2.nStyleIndex) && (aCell1.bIsAutoStyle == aCell2.bIsAutoStyle)) ||
3734                      ((aCell1.nStyleIndex == aCell2.nStyleIndex) && (aCell1.nStyleIndex == -1))) &&
3735                     aCell1.nValidationIndex == aCell2.nValidationIndex &&
3736                     aCell1.nType == aCell2.nType)
3737                 {
3738                     switch ( aCell1.nType )
3739                     {
3740                     case table::CellContentType_EMPTY :
3741                         {
3742                             bIsEqual = true;
3743                         }
3744                         break;
3745                     case table::CellContentType_VALUE :
3746                         {
3747                             // #i29101# number format may be different from column default styles,
3748                             // but can lead to different value types, so it must also be compared
3749                             bIsEqual = (aCell1.nNumberFormat == aCell2.nNumberFormat) &&
3750                                        (aCell1.maBaseCell.mfValue == aCell2.maBaseCell.mfValue);
3751                         }
3752                         break;
3753                     case table::CellContentType_TEXT :
3754                         {
3755                             if (IsEditCell(aCell1) || IsEditCell(aCell2))
3756                                 bIsEqual = false;
3757                             else
3758                             {
3759                                 bIsEqual = (aCell1.maBaseCell.getString(pDoc) == aCell2.maBaseCell.getString(pDoc));
3760                             }
3761                         }
3762                         break;
3763                     case table::CellContentType_FORMULA :
3764                         {
3765                             bIsEqual = false;
3766                         }
3767                         break;
3768                     default :
3769                         {
3770                             bIsEqual = false;
3771                         }
3772                         break;
3773                     }
3774                 }
3775             }
3776         }
3777     }
3778     return bIsEqual;
3779 }
3780 
3781 void ScXMLExport::WriteCalculationSettings(const uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc)
3782 {
3783     uno::Reference<beans::XPropertySet> xPropertySet(xSpreadDoc, uno::UNO_QUERY);
3784     if (xPropertySet.is())
3785     {
3786         bool bCalcAsShown (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_CALCASSHOWN) ));
3787         bool bIgnoreCase (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_IGNORECASE) ));
3788         bool bLookUpLabels (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_LOOKUPLABELS) ));
3789         bool bMatchWholeCell (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_MATCHWHOLE) ));
3790         bool bUseRegularExpressions (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_REGEXENABLED) ));
3791         bool bUseWildcards (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_WILDCARDSENABLED) ));
3792         if (bUseWildcards && bUseRegularExpressions)
3793             bUseRegularExpressions = false;     // mutually exclusive, wildcards take precedence
3794         bool bIsIterationEnabled (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_ITERENABLED) ));
3795         sal_uInt16 nYear2000 (pDoc ? pDoc->GetDocOptions().GetYear2000() : 0);
3796         sal_Int32 nIterationCount(100);
3797         xPropertySet->getPropertyValue( SC_UNO_ITERCOUNT ) >>= nIterationCount;
3798         double fIterationEpsilon = 0;
3799         xPropertySet->getPropertyValue( SC_UNO_ITEREPSILON ) >>= fIterationEpsilon;
3800         util::Date aNullDate;
3801         xPropertySet->getPropertyValue( SC_UNO_NULLDATE ) >>= aNullDate;
3802         if (bCalcAsShown || bIgnoreCase || !bLookUpLabels || !bMatchWholeCell || !bUseRegularExpressions ||
3803                 bUseWildcards ||
3804                 bIsIterationEnabled || nIterationCount != 100 || !::rtl::math::approxEqual(fIterationEpsilon, 0.001) ||
3805                 aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899 || nYear2000 != 1930)
3806         {
3807             if (bIgnoreCase)
3808                 AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_FALSE);
3809             if (bCalcAsShown)
3810                 AddAttribute(XML_NAMESPACE_TABLE, XML_PRECISION_AS_SHOWN, XML_TRUE);
3811             if (!bMatchWholeCell)
3812                 AddAttribute(XML_NAMESPACE_TABLE, XML_SEARCH_CRITERIA_MUST_APPLY_TO_WHOLE_CELL, XML_FALSE);
3813             if (!bLookUpLabels)
3814                 AddAttribute(XML_NAMESPACE_TABLE, XML_AUTOMATIC_FIND_LABELS, XML_FALSE);
3815             if (!bUseRegularExpressions)
3816                 AddAttribute(XML_NAMESPACE_TABLE, XML_USE_REGULAR_EXPRESSIONS, XML_FALSE);
3817             if (bUseWildcards)
3818                 AddAttribute(XML_NAMESPACE_TABLE, XML_USE_WILDCARDS, XML_TRUE);
3819             if (nYear2000 != 1930)
3820             {
3821                 AddAttribute(XML_NAMESPACE_TABLE, XML_NULL_YEAR, OUString::number(nYear2000));
3822             }
3823             SvXMLElementExport aCalcSettings(*this, XML_NAMESPACE_TABLE, XML_CALCULATION_SETTINGS, true, true);
3824             {
3825                 if (aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899)
3826                 {
3827                     OUStringBuffer sDate;
3828                     SvXMLUnitConverter::convertDateTime(sDate, 0.0, aNullDate);
3829                     AddAttribute(XML_NAMESPACE_TABLE, XML_DATE_VALUE, sDate.makeStringAndClear());
3830                     SvXMLElementExport aElemNullDate(*this, XML_NAMESPACE_TABLE, XML_NULL_DATE, true, true);
3831                 }
3832                 if (bIsIterationEnabled || nIterationCount != 100 || !::rtl::math::approxEqual(fIterationEpsilon, 0.001))
3833                 {
3834                     OUStringBuffer sBuffer;
3835                     if (bIsIterationEnabled)
3836                         AddAttribute(XML_NAMESPACE_TABLE, XML_STATUS, XML_ENABLE);
3837                     if (nIterationCount != 100)
3838                     {
3839                         AddAttribute(XML_NAMESPACE_TABLE, XML_STEPS, OUString::number(nIterationCount));
3840                     }
3841                     if (!::rtl::math::approxEqual(fIterationEpsilon, 0.001))
3842                     {
3843                         ::sax::Converter::convertDouble(sBuffer,
3844                                 fIterationEpsilon);
3845                         AddAttribute(XML_NAMESPACE_TABLE, XML_MAXIMUM_DIFFERENCE, sBuffer.makeStringAndClear());
3846                     }
3847                     SvXMLElementExport aElemIteration(*this, XML_NAMESPACE_TABLE, XML_ITERATION, true, true);
3848                 }
3849             }
3850         }
3851     }
3852 }
3853 
3854 void ScXMLExport::WriteTableSource()
3855 {
3856     uno::Reference <sheet::XSheetLinkable> xLinkable (xCurrentTable, uno::UNO_QUERY);
3857     if (xLinkable.is() && GetModel().is())
3858     {
3859         sheet::SheetLinkMode nMode (xLinkable->getLinkMode());
3860         if (nMode != sheet::SheetLinkMode_NONE)
3861         {
3862             OUString sLink (xLinkable->getLinkUrl());
3863             uno::Reference <beans::XPropertySet> xProps (GetModel(), uno::UNO_QUERY);
3864             if (xProps.is())
3865             {
3866                 uno::Reference <container::XIndexAccess> xIndex(xProps->getPropertyValue(SC_UNO_SHEETLINKS), uno::UNO_QUERY);
3867                 if (xIndex.is())
3868                 {
3869                     sal_Int32 nCount(xIndex->getCount());
3870                     if (nCount)
3871                     {
3872                         bool bFound(false);
3873                         uno::Reference <beans::XPropertySet> xLinkProps;
3874                         for (sal_Int32 i = 0; (i < nCount) && !bFound; ++i)
3875                         {
3876                             xLinkProps.set(xIndex->getByIndex(i), uno::UNO_QUERY);
3877                             if (xLinkProps.is())
3878                             {
3879                                 OUString sNewLink;
3880                                 if (xLinkProps->getPropertyValue(SC_UNONAME_LINKURL) >>= sNewLink)
3881                                     bFound = sLink == sNewLink;
3882                             }
3883                         }
3884                         if (bFound && xLinkProps.is())
3885                         {
3886                             OUString sFilter;
3887                             OUString sFilterOptions;
3888                             OUString sTableName (xLinkable->getLinkSheetName());
3889                             sal_Int32 nRefresh(0);
3890                             xLinkProps->getPropertyValue(SC_UNONAME_FILTER) >>= sFilter;
3891                             xLinkProps->getPropertyValue(SC_UNONAME_FILTOPT) >>= sFilterOptions;
3892                             xLinkProps->getPropertyValue(SC_UNONAME_REFDELAY) >>= nRefresh;
3893                             if (!sLink.isEmpty())
3894                             {
3895                                 AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
3896                                 AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetRelativeReference(sLink));
3897                                 if (!sTableName.isEmpty())
3898                                     AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_NAME, sTableName);
3899                                 if (!sFilter.isEmpty())
3900                                     AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_NAME, sFilter);
3901                                 if (!sFilterOptions.isEmpty())
3902                                     AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_OPTIONS, sFilterOptions);
3903                                 if (nMode != sheet::SheetLinkMode_NORMAL)
3904                                     AddAttribute(XML_NAMESPACE_TABLE, XML_MODE, XML_COPY_RESULTS_ONLY);
3905                                 if( nRefresh )
3906                                 {
3907                                     OUStringBuffer sBuffer;
3908                                     ::sax::Converter::convertDuration( sBuffer,
3909                                             static_cast<double>(nRefresh) / 86400 );
3910                                     AddAttribute( XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, sBuffer.makeStringAndClear() );
3911                                 }
3912                                 SvXMLElementExport aSourceElem(*this, XML_NAMESPACE_TABLE, XML_TABLE_SOURCE, true, true);
3913                             }
3914                         }
3915                     }
3916                 }
3917             }
3918         }
3919     }
3920 }
3921 
3922 // core implementation
3923 void ScXMLExport::WriteScenario()
3924 {
3925     if (pDoc && pDoc->IsScenario(static_cast<SCTAB>(nCurrentTable)))
3926     {
3927         OUString sComment;
3928         Color       aColor;
3929         ScScenarioFlags nFlags;
3930         pDoc->GetScenarioData(static_cast<SCTAB>(nCurrentTable), sComment, aColor, nFlags);
3931         if (!(nFlags & ScScenarioFlags::ShowFrame))
3932             AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_BORDER, XML_FALSE);
3933         OUStringBuffer aBuffer;
3934         ::sax::Converter::convertColor(aBuffer, aColor);
3935         AddAttribute(XML_NAMESPACE_TABLE, XML_BORDER_COLOR, aBuffer.makeStringAndClear());
3936         if (!(nFlags & ScScenarioFlags::TwoWay))
3937             AddAttribute(XML_NAMESPACE_TABLE, XML_COPY_BACK, XML_FALSE);
3938         if (!(nFlags & ScScenarioFlags::Attrib))
3939             AddAttribute(XML_NAMESPACE_TABLE, XML_COPY_STYLES, XML_FALSE);
3940         if (nFlags & ScScenarioFlags::Value)
3941             AddAttribute(XML_NAMESPACE_TABLE, XML_COPY_FORMULAS, XML_FALSE);
3942         if (nFlags & ScScenarioFlags::Protected)
3943             AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE);
3944         ::sax::Converter::convertBool(aBuffer,
3945                 pDoc->IsActiveScenario(static_cast<SCTAB>(nCurrentTable)));
3946         AddAttribute(XML_NAMESPACE_TABLE, XML_IS_ACTIVE, aBuffer.makeStringAndClear());
3947         const ScRangeList* pRangeList = pDoc->GetScenarioRanges(static_cast<SCTAB>(nCurrentTable));
3948         OUString sRangeListStr;
3949         ScRangeStringConverter::GetStringFromRangeList( sRangeListStr, pRangeList, pDoc, FormulaGrammar::CONV_OOO );
3950         AddAttribute(XML_NAMESPACE_TABLE, XML_SCENARIO_RANGES, sRangeListStr);
3951         if (!sComment.isEmpty())
3952             AddAttribute(XML_NAMESPACE_TABLE, XML_COMMENT, sComment);
3953         SvXMLElementExport aElem(*this, XML_NAMESPACE_TABLE, XML_SCENARIO, true, true);
3954     }
3955 }
3956 
3957 void ScXMLExport::WriteTheLabelRanges( const uno::Reference< sheet::XSpreadsheetDocument >& xSpreadDoc )
3958 {
3959     uno::Reference< beans::XPropertySet > xDocProp( xSpreadDoc, uno::UNO_QUERY );
3960     if( !xDocProp.is() ) return;
3961 
3962     sal_Int32 nCount(0);
3963     uno::Reference< container::XIndexAccess > xColRangesIAccess(xDocProp->getPropertyValue( SC_UNO_COLLABELRNG ), uno::UNO_QUERY);
3964     if( xColRangesIAccess.is() )
3965         nCount += xColRangesIAccess->getCount();
3966 
3967     uno::Reference< container::XIndexAccess > xRowRangesIAccess(xDocProp->getPropertyValue( SC_UNO_ROWLABELRNG ), uno::UNO_QUERY);
3968     if( xRowRangesIAccess.is() )
3969         nCount += xRowRangesIAccess->getCount();
3970 
3971     if( nCount )
3972     {
3973         SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_LABEL_RANGES, true, true );
3974         WriteLabelRanges( xColRangesIAccess, true );
3975         WriteLabelRanges( xRowRangesIAccess, false );
3976     }
3977 }
3978 
3979 void ScXMLExport::WriteLabelRanges( const uno::Reference< container::XIndexAccess >& xRangesIAccess, bool bColumn )
3980 {
3981     if( !xRangesIAccess.is() ) return;
3982 
3983     sal_Int32 nCount(xRangesIAccess->getCount());
3984     for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
3985     {
3986         uno::Reference< sheet::XLabelRange > xRange(xRangesIAccess->getByIndex( nIndex ), uno::UNO_QUERY);
3987         if( xRange.is() )
3988         {
3989             OUString sRangeStr;
3990             table::CellRangeAddress aCellRange( xRange->getLabelArea() );
3991             ScRangeStringConverter::GetStringFromRange( sRangeStr, aCellRange, pDoc, FormulaGrammar::CONV_OOO );
3992             AddAttribute( XML_NAMESPACE_TABLE, XML_LABEL_CELL_RANGE_ADDRESS, sRangeStr );
3993             aCellRange = xRange->getDataArea();
3994             ScRangeStringConverter::GetStringFromRange( sRangeStr, aCellRange, pDoc, FormulaGrammar::CONV_OOO );
3995             AddAttribute( XML_NAMESPACE_TABLE, XML_DATA_CELL_RANGE_ADDRESS, sRangeStr );
3996             AddAttribute( XML_NAMESPACE_TABLE, XML_ORIENTATION, bColumn ? XML_COLUMN : XML_ROW );
3997             SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_LABEL_RANGE, true, true );
3998         }
3999     }
4000 }
4001 
4002 void ScXMLExport::WriteNamedExpressions()
4003 {
4004     if (!pDoc)
4005         return;
4006     ScRangeName* pNamedRanges = pDoc->GetRangeName();
4007     WriteNamedRange(pNamedRanges);
4008 }
4009 
4010 void ScXMLExport::WriteExternalDataMapping()
4011 {
4012     if (!pDoc)
4013         return;
4014 
4015     if (getDefaultVersion() <= SvtSaveOptions::ODFVER_012)
4016         // Export this only for 1.2 extended and above.
4017         return;
4018 
4019     sc::ExternalDataMapper& rDataMapper = pDoc->GetExternalDataMapper();
4020     auto& rDataSources = rDataMapper.getDataSources();
4021 
4022     if (!rDataSources.empty())
4023     {
4024         SvXMLElementExport aMappings(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_MAPPINGS, true, true);
4025         for (const auto& itr : rDataSources)
4026         {
4027             AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, itr.getURL());
4028             AddAttribute(XML_NAMESPACE_CALC_EXT, XML_PROVIDER, itr.getProvider());
4029             AddAttribute(XML_NAMESPACE_CALC_EXT, XML_DATA_FREQUENCY, OUString::number(sc::ExternalDataSource::getUpdateFrequency()));
4030             AddAttribute(XML_NAMESPACE_CALC_EXT, XML_ID, itr.getID());
4031             AddAttribute(XML_NAMESPACE_CALC_EXT, XML_DATABASE_NAME, itr.getDBName());
4032 
4033             SvXMLElementExport aMapping(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_MAPPING, true, true);
4034             // Add the data transformations
4035             WriteExternalDataTransformations(itr.getDataTransformation());
4036         }
4037     }
4038 }
4039 
4040 void ScXMLExport::WriteExternalDataTransformations(const std::vector<std::shared_ptr<sc::DataTransformation>>& aDataTransformations)
4041 {
4042     SvXMLElementExport aTransformations(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_TRANSFORMATIONS, true, true);
4043     for (auto& itr : aDataTransformations)
4044     {
4045         sc::TransformationType aTransformationType = itr->getTransformationType();
4046 
4047         switch(aTransformationType)
4048         {
4049             case sc::TransformationType::DELETE_TRANSFORMATION:
4050             {
4051                 // Delete Columns Transformation
4052                 std::shared_ptr<sc::ColumnRemoveTransformation> aDeleteTransformation = std::dynamic_pointer_cast<sc::ColumnRemoveTransformation>(itr);
4053                 std::set<SCCOL> aColumns = aDeleteTransformation->getColumns();
4054                 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_REMOVE_TRANSFORMATION, true, true);
4055                 for(auto& col : aColumns)
4056                 {
4057                     // Add Columns
4058                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4059                     SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4060                 }
4061             }
4062             break;
4063             case sc::TransformationType::SPLIT_TRANSFORMATION:
4064             {
4065                 std::shared_ptr<sc::SplitColumnTransformation> aSplitTransformation = std::dynamic_pointer_cast<sc::SplitColumnTransformation>(itr);
4066 
4067                 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(aSplitTransformation->getColumn()));
4068                 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_SEPARATOR, OUString::number(aSplitTransformation->getSeparator()));
4069                 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_SPLIT_TRANSFORMATION, true, true);
4070             }
4071             break;
4072             case sc::TransformationType::MERGE_TRANSFORMATION:
4073             {
4074                 // Merge Transformation
4075                 std::shared_ptr<sc::MergeColumnTransformation> aMergeTransformation = std::dynamic_pointer_cast<sc::MergeColumnTransformation>(itr);
4076                 std::set<SCCOL> aColumns = aMergeTransformation->getColumns();
4077 
4078                 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MERGE_STRING, aMergeTransformation->getMergeString());
4079                 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_MERGE_TRANSFORMATION, true, true);
4080 
4081                 for(auto& col : aColumns)
4082                 {
4083                     // Columns
4084                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4085                     SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4086                 }
4087             }
4088             break;
4089             case sc::TransformationType::SORT_TRANSFORMATION:
4090             {
4091                 // Sort Transformation
4092                 std::shared_ptr<sc::SortTransformation> aSortTransformation = std::dynamic_pointer_cast<sc::SortTransformation>(itr);
4093                 ScSortParam aSortParam = aSortTransformation->getSortParam();
4094                 const sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
4095                 const sc::DataStream* pStrm = rMgr.getDataStream();
4096                 if (!pStrm)
4097                     // No data stream.
4098                     return;
4099 
4100                 // Streamed range
4101                 ScRange aRange = pStrm->GetRange();
4102 
4103                 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_SORT_TRANSFORMATION, true, true);
4104 
4105                 writeSort(*this, aSortParam, aRange, pDoc);
4106             }
4107             break;
4108             case sc::TransformationType::TEXT_TRANSFORMATION:
4109             {
4110                 // Text Transformation
4111                 std::shared_ptr<sc::TextTransformation> aTextTransformation = std::dynamic_pointer_cast<sc::TextTransformation>(itr);
4112 
4113                 sc::TEXT_TRANSFORM_TYPE aTextTransformType = aTextTransformation->getTextTransformationType();
4114 
4115                 switch ( aTextTransformType )
4116                 {
4117                     case sc::TEXT_TRANSFORM_TYPE::TO_LOWER:
4118                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_CASEMAP_LOWERCASE);
4119                     break;
4120                     case sc::TEXT_TRANSFORM_TYPE::TO_UPPER:
4121                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_CASEMAP_UPPERCASE);
4122                     break;
4123                     case sc::TEXT_TRANSFORM_TYPE::CAPITALIZE:
4124                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_CASEMAP_CAPITALIZE);
4125                     break;
4126                     case sc::TEXT_TRANSFORM_TYPE::TRIM:
4127                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_TRIM);
4128                     break;
4129                 }
4130 
4131                 std::set<SCCOL> aColumns = aTextTransformation->getColumns();
4132 
4133                 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_TEXT_TRANSFORMATION, true, true);
4134 
4135                 for(auto& col : aColumns)
4136                 {
4137                     // Columns
4138                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4139                     SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4140                 }
4141             }
4142             break;
4143             case sc::TransformationType::AGGREGATE_FUNCTION:
4144             {
4145                 // Aggregate Transformation
4146                 std::shared_ptr<sc::AggregateFunction> aAggregateFunction = std::dynamic_pointer_cast<sc::AggregateFunction>(itr);
4147                 std::set<SCCOL> aColumns = aAggregateFunction->getColumns();
4148 
4149                 sc::AGGREGATE_FUNCTION aAggregateType = aAggregateFunction->getAggregateType();
4150 
4151                 switch (aAggregateType)
4152                 {
4153                     case sc::AGGREGATE_FUNCTION::SUM:
4154                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_SUM);
4155                     break;
4156                     case sc::AGGREGATE_FUNCTION::AVERAGE:
4157                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_AVERAGE);
4158                     break;
4159                     case sc::AGGREGATE_FUNCTION::MIN:
4160                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_MIN);
4161                     break;
4162                     case sc::AGGREGATE_FUNCTION::MAX:
4163                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_MAX);
4164                     break;
4165                 }
4166 
4167                 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT,XML_COLUMN_AGGREGATE_TRANSFORMATION, true, true);
4168 
4169                 for(auto& col : aColumns)
4170                 {
4171                     // Columns
4172                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4173                     SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4174                 }
4175             }
4176             break;
4177             case sc::TransformationType::NUMBER_TRANSFORMATION:
4178             {
4179                 // Number Transformation
4180                 std::shared_ptr<sc::NumberTransformation> aNumberTransformation = std::dynamic_pointer_cast<sc::NumberTransformation>(itr);
4181 
4182                 sc::NUMBER_TRANSFORM_TYPE aNumberTransformType = aNumberTransformation->getNumberTransformationType();
4183 
4184                 switch ( aNumberTransformType )
4185                 {
4186                     case sc::NUMBER_TRANSFORM_TYPE::ROUND:
4187                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_ROUND);
4188                     break;
4189                     case sc::NUMBER_TRANSFORM_TYPE::ROUND_UP:
4190                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_ROUND_UP);
4191                     break;
4192                     case sc::NUMBER_TRANSFORM_TYPE::ROUND_DOWN:
4193                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_ROUND_DOWN);
4194                     break;
4195                     case sc::NUMBER_TRANSFORM_TYPE::ABSOLUTE:
4196                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_ABS);
4197                     break;
4198                     case sc::NUMBER_TRANSFORM_TYPE::LOG_E:
4199                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_LOG);
4200                     break;
4201                     case sc::NUMBER_TRANSFORM_TYPE::LOG_10:
4202                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_LOG_10);
4203                     break;
4204                     case sc::NUMBER_TRANSFORM_TYPE::CUBE:
4205                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_CUBE);
4206                     break;
4207                     case sc::NUMBER_TRANSFORM_TYPE::SQUARE:
4208                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_SQUARE);
4209                     break;
4210                     case sc::NUMBER_TRANSFORM_TYPE::SQUARE_ROOT:
4211                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_SQUARE_ROOT);
4212                     break;
4213                     case sc::NUMBER_TRANSFORM_TYPE::EXPONENT:
4214                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_EXPONENTIAL);
4215                     break;
4216                     case sc::NUMBER_TRANSFORM_TYPE::IS_EVEN:
4217                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_EVEN);
4218                     break;
4219                     case sc::NUMBER_TRANSFORM_TYPE::IS_ODD:
4220                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_ODD);
4221                     break;
4222                     case sc::NUMBER_TRANSFORM_TYPE::SIGN:
4223                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_SIGN);
4224                     break;
4225                 }
4226 
4227                 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_PRECISION, OUString::number(aNumberTransformation->getPrecision()));
4228                 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_NUMBER_TRANSFORMATION, true, true);
4229 
4230                 std::set<SCCOL> aColumns = aNumberTransformation->getColumn();
4231                 for(auto& col : aColumns)
4232                 {
4233                     // Columns
4234                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4235                     SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4236                 }
4237             }
4238             break;
4239             case sc::TransformationType::REMOVE_NULL_TRANSFORMATION:
4240             {
4241                 // Replace Null Transformation
4242                 std::shared_ptr<sc::ReplaceNullTransformation> aReplaceNullTransformation = std::dynamic_pointer_cast<sc::ReplaceNullTransformation>(itr);
4243                 std::set<SCCOL> aColumns = aReplaceNullTransformation->getColumn();
4244 
4245                 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_REPLACE_STRING, aReplaceNullTransformation->getReplaceString());
4246                 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_REPLACENULL_TRANSFORMATION, true, true);
4247 
4248                 for(auto& col : aColumns)
4249                 {
4250                     // Columns
4251                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4252                     SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4253                 }
4254             }
4255             break;
4256             case sc::TransformationType::DATETIME_TRANSFORMATION:
4257             {
4258                 // Number Transformation
4259                 std::shared_ptr<sc::DateTimeTransformation> aDateTimeTransformation = std::dynamic_pointer_cast<sc::DateTimeTransformation>(itr);
4260 
4261                 sc::DATETIME_TRANSFORMATION_TYPE aDateTimeTransformationType = aDateTimeTransformation->getDateTimeTransformationType();
4262 
4263                 switch ( aDateTimeTransformationType )
4264                 {
4265                     case sc::DATETIME_TRANSFORMATION_TYPE::DATE_STRING:
4266                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_DATE_STRING);
4267                     break;
4268                     case sc::DATETIME_TRANSFORMATION_TYPE::YEAR:
4269                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_YEAR);
4270                     break;
4271                     case sc::DATETIME_TRANSFORMATION_TYPE::START_OF_YEAR:
4272                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_START_OF_YEAR);
4273                     break;
4274                     case sc::DATETIME_TRANSFORMATION_TYPE::END_OF_YEAR:
4275                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_END_OF_YEAR);
4276                     break;
4277                     case sc::DATETIME_TRANSFORMATION_TYPE::MONTH:
4278                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_MONTH);
4279                     break;
4280                     case sc::DATETIME_TRANSFORMATION_TYPE::MONTH_NAME:
4281                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_MONTH_NAME);
4282                     break;
4283                     case sc::DATETIME_TRANSFORMATION_TYPE::START_OF_MONTH:
4284                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_START_OF_MONTH);
4285                     break;
4286                     case sc::DATETIME_TRANSFORMATION_TYPE::END_OF_MONTH:
4287                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_END_OF_MONTH);
4288                     break;
4289                     case sc::DATETIME_TRANSFORMATION_TYPE::DAY:
4290                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_DAY);
4291                     break;
4292                     case sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_WEEK:
4293                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_DAY_OF_WEEK);
4294                     break;
4295                     case sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_YEAR:
4296                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_DAY_OF_YEAR);
4297                     break;
4298                     case sc::DATETIME_TRANSFORMATION_TYPE::QUARTER:
4299                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_QUARTER);
4300                     break;
4301                     case sc::DATETIME_TRANSFORMATION_TYPE::START_OF_QUARTER:
4302                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_START_OF_QUARTER);
4303                     break;
4304                     case sc::DATETIME_TRANSFORMATION_TYPE::END_OF_QUARTER:
4305                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_END_OF_QUARTER);
4306                     break;
4307                     case sc::DATETIME_TRANSFORMATION_TYPE::TIME:
4308                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_TIME);
4309                     break;
4310                     case sc::DATETIME_TRANSFORMATION_TYPE::HOUR:
4311                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_HOUR);
4312                     break;
4313                     case sc::DATETIME_TRANSFORMATION_TYPE::MINUTE:
4314                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_MINUTE);
4315                     break;
4316                     case sc::DATETIME_TRANSFORMATION_TYPE::SECOND:
4317                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_SECONDS);
4318                     break;
4319                 }
4320 
4321                 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_DATETIME_TRANSFORMATION, true, true);
4322 
4323                 std::set<SCCOL> aColumns = aDateTimeTransformation->getColumn();
4324                 for(auto& col : aColumns)
4325                 {
4326                     // Columns
4327                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4328                     SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4329                 }
4330             }
4331             break;
4332             default:
4333             break;
4334         }
4335     }
4336 }
4337 
4338 void ScXMLExport::WriteDataStream()
4339 {
4340     if (!pDoc)
4341         return;
4342 
4343     SvtMiscOptions aMiscOptions;
4344     if (!aMiscOptions.IsExperimentalMode())
4345         // Export this only in experimental mode.
4346         return;
4347 
4348     if (getDefaultVersion() <= SvtSaveOptions::ODFVER_012)
4349         // Export this only for 1.2 extended and above.
4350         return;
4351 
4352     const sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
4353     const sc::DataStream* pStrm = rMgr.getDataStream();
4354     if (!pStrm)
4355         // No data stream.
4356         return;
4357 
4358     // Source URL
4359     AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetRelativeReference(pStrm->GetURL()));
4360 
4361     // Streamed range
4362     ScRange aRange = pStrm->GetRange();
4363     OUString aRangeStr;
4364     ScRangeStringConverter::GetStringFromRange(
4365         aRangeStr, aRange, pDoc, formula::FormulaGrammar::CONV_OOO);
4366     AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, aRangeStr);
4367 
4368     // Empty line refresh option.
4369     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_EMPTY_LINE_REFRESH, pStrm->IsRefreshOnEmptyLine() ? XML_TRUE : XML_FALSE);
4370 
4371     // New data insertion position. Either top of bottom. Default to bottom.
4372     xmloff::token::XMLTokenEnum eInsertPosition = XML_BOTTOM;
4373     if (pStrm->GetMove() == sc::DataStream::MOVE_DOWN)
4374         eInsertPosition = XML_TOP;
4375 
4376     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_INSERTION_POSITION, eInsertPosition);
4377 
4378     SvXMLElementExport aElem(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_STREAM_SOURCE, true, true);
4379 }
4380 
4381 void ScXMLExport::WriteNamedRange(ScRangeName* pRangeName)
4382 {
4383     //write a global or local ScRangeName
4384     SvXMLElementExport aElemNEs(*this, XML_NAMESPACE_TABLE, XML_NAMED_EXPRESSIONS, true, true);
4385     for (const auto& rxEntry : *pRangeName)
4386     {
4387         AddAttribute(sAttrName, rxEntry.second->GetName());
4388 
4389         OUString sBaseCellAddress;
4390         rxEntry.second->ValidateTabRefs();
4391         ScRangeStringConverter::GetStringFromAddress( sBaseCellAddress, rxEntry.second->GetPos(), pDoc,
4392                             FormulaGrammar::CONV_OOO, ' ', false, ScRefFlags::ADDR_ABS_3D);
4393         AddAttribute(XML_NAMESPACE_TABLE, XML_BASE_CELL_ADDRESS, sBaseCellAddress);
4394 
4395         OUString sSymbol;
4396         rxEntry.second->GetSymbol(sSymbol, pDoc->GetStorageGrammar());
4397         OUString sTempSymbol(sSymbol);
4398         ScRange aRange;
4399         if (rxEntry.second->IsReference(aRange))
4400         {
4401 
4402             OUString sContent(sTempSymbol.copy(1, sTempSymbol.getLength() -2 ));
4403             AddAttribute(XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, sContent);
4404 
4405             sal_Int32 nRangeType = rxEntry.second->GetUnoType();
4406             OUStringBuffer sBufferRangeType;
4407             if ((nRangeType & sheet::NamedRangeFlag::COLUMN_HEADER) == sheet::NamedRangeFlag::COLUMN_HEADER)
4408                 sBufferRangeType.append(GetXMLToken(XML_REPEAT_COLUMN));
4409             if ((nRangeType & sheet::NamedRangeFlag::ROW_HEADER) == sheet::NamedRangeFlag::ROW_HEADER)
4410             {
4411                 if (!sBufferRangeType.isEmpty())
4412                     sBufferRangeType.append(" ");
4413                 sBufferRangeType.append(GetXMLToken(XML_REPEAT_ROW));
4414             }
4415             if ((nRangeType & sheet::NamedRangeFlag::FILTER_CRITERIA) == sheet::NamedRangeFlag::FILTER_CRITERIA)
4416             {
4417                 if (!sBufferRangeType.isEmpty())
4418                     sBufferRangeType.append(" ");
4419                 sBufferRangeType.append(GetXMLToken(XML_FILTER));
4420             }
4421             if ((nRangeType & sheet::NamedRangeFlag::PRINT_AREA) == sheet::NamedRangeFlag::PRINT_AREA)
4422             {
4423                 if (!sBufferRangeType.isEmpty())
4424                     sBufferRangeType.append(" ");
4425                 sBufferRangeType.append(GetXMLToken(XML_PRINT_RANGE));
4426             }
4427             OUString sRangeType = sBufferRangeType.makeStringAndClear();
4428             if (!sRangeType.isEmpty())
4429                 AddAttribute(XML_NAMESPACE_TABLE, XML_RANGE_USABLE_AS, sRangeType);
4430             SvXMLElementExport aElemNR(*this, XML_NAMESPACE_TABLE, XML_NAMED_RANGE, true, true);
4431 
4432         }
4433         else
4434         {
4435             AddAttribute(XML_NAMESPACE_TABLE, XML_EXPRESSION, sTempSymbol);
4436             SvXMLElementExport aElemNE(*this, XML_NAMESPACE_TABLE, XML_NAMED_EXPRESSION, true, true);
4437         }
4438     }
4439 }
4440 
4441 namespace {
4442 
4443 OUString getCondFormatEntryType(const ScColorScaleEntry& rEntry, bool bFirst = true)
4444 {
4445     switch(rEntry.GetType())
4446     {
4447         case COLORSCALE_MIN:
4448             return "minimum";
4449         case COLORSCALE_MAX:
4450             return "maximum";
4451         case COLORSCALE_PERCENT:
4452             return "percent";
4453         case COLORSCALE_PERCENTILE:
4454             return "percentile";
4455         case COLORSCALE_FORMULA:
4456             return "formula";
4457         case COLORSCALE_VALUE:
4458             return "number";
4459         case COLORSCALE_AUTO:
4460             // only important for data bars
4461             if(bFirst)
4462                 return "auto-minimum";
4463             else
4464                 return "auto-maximum";
4465     }
4466     return OUString();
4467 }
4468 
4469 OUString getDateStringForType(condformat::ScCondFormatDateType eType)
4470 {
4471     switch(eType)
4472     {
4473         case condformat::TODAY:
4474             return "today";
4475         case condformat::YESTERDAY:
4476             return "yesterday";
4477         case condformat::TOMORROW:
4478             return "tomorrow";
4479         case condformat::LAST7DAYS:
4480             return "last-7-days";
4481         case condformat::THISWEEK:
4482             return "this-week";
4483         case condformat::LASTWEEK:
4484             return "last-week";
4485         case condformat::NEXTWEEK:
4486             return "next-week";
4487         case condformat::THISMONTH:
4488             return "this-month";
4489         case condformat::LASTMONTH:
4490             return "last-month";
4491         case condformat::NEXTMONTH:
4492             return "next-month";
4493         case condformat::THISYEAR:
4494             return "this-year";
4495         case condformat::LASTYEAR:
4496             return "last-year";
4497         case condformat::NEXTYEAR:
4498             return "next-year";
4499     }
4500 
4501     return OUString();
4502 }
4503 
4504 }
4505 
4506 void ScXMLExport::ExportConditionalFormat(SCTAB nTab)
4507 {
4508     ScConditionalFormatList* pCondFormatList = pDoc->GetCondFormList(nTab);
4509     if(!pCondFormatList)
4510         return;
4511 
4512     if (pCondFormatList->empty())
4513         return;
4514 
4515     SvXMLElementExport aElementCondFormats(*this, XML_NAMESPACE_CALC_EXT, XML_CONDITIONAL_FORMATS, true, true);
4516 
4517     for(const auto& rxCondFormat : *pCondFormatList)
4518     {
4519         OUString sRanges;
4520         const ScRangeList& rRangeList = rxCondFormat->GetRange();
4521         ScRangeStringConverter::GetStringFromRangeList( sRanges, &rRangeList, pDoc, formula::FormulaGrammar::CONV_OOO );
4522         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TARGET_RANGE_ADDRESS, sRanges);
4523         SvXMLElementExport aElementCondFormat(*this, XML_NAMESPACE_CALC_EXT, XML_CONDITIONAL_FORMAT, true, true);
4524         size_t nEntries = rxCondFormat->size();
4525         for(size_t i = 0; i < nEntries; ++i)
4526         {
4527             const ScFormatEntry* pFormatEntry = rxCondFormat->GetEntry(i);
4528             if(pFormatEntry->GetType()==ScFormatEntry::Type::Condition)
4529             {
4530                 const ScCondFormatEntry* pEntry = static_cast<const ScCondFormatEntry*>(pFormatEntry);
4531                 OUStringBuffer aCond;
4532                 ScAddress aPos = pEntry->GetSrcPos();
4533                 switch(pEntry->GetOperation())
4534                 {
4535                     case ScConditionMode::Equal:
4536                         aCond.append('=');
4537                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4538                         break;
4539                     case ScConditionMode::Less:
4540                         aCond.append('<');
4541                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4542                         break;
4543                     case ScConditionMode::Greater:
4544                         aCond.append('>');
4545                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4546                         break;
4547                     case ScConditionMode::EqLess:
4548                         aCond.append("<=");
4549                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4550                         break;
4551                     case ScConditionMode::EqGreater:
4552                         aCond.append(">=");
4553                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4554                         break;
4555                     case ScConditionMode::NotEqual:
4556                         aCond.append("!=");
4557                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4558                         break;
4559                     case ScConditionMode::Between:
4560                         aCond.append("between(");
4561                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4562                         aCond.append(',');
4563                         aCond.append(pEntry->GetExpression(aPos, 1, 0, formula::FormulaGrammar::GRAM_ODFF));
4564                         aCond.append(')');
4565                         break;
4566                     case ScConditionMode::NotBetween:
4567                         aCond.append("not-between(");
4568                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4569                         aCond.append(',');
4570                         aCond.append(pEntry->GetExpression(aPos, 1, 0, formula::FormulaGrammar::GRAM_ODFF));
4571                         aCond.append(')');
4572                         break;
4573                     case ScConditionMode::Duplicate:
4574                         aCond.append("duplicate");
4575                         break;
4576                     case ScConditionMode::NotDuplicate:
4577                         aCond.append("unique");
4578                         break;
4579                     case ScConditionMode::Direct:
4580                         aCond.append("formula-is(");
4581                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4582                         aCond.append(')');
4583                         break;
4584                     case ScConditionMode::Top10:
4585                         aCond.append("top-elements(");
4586                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4587                         aCond.append(")");
4588                         break;
4589                     case ScConditionMode::Bottom10:
4590                         aCond.append("bottom-elements(");
4591                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4592                         aCond.append(")");
4593                         break;
4594                     case ScConditionMode::TopPercent:
4595                         aCond.append("top-percent(");
4596                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4597                         aCond.append(")");
4598                         break;
4599                     case ScConditionMode::BottomPercent:
4600                         aCond.append("bottom-percent(");
4601                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4602                         aCond.append(")");
4603                         break;
4604                     case ScConditionMode::AboveAverage:
4605                         aCond.append("above-average");
4606                         break;
4607                     case ScConditionMode::BelowAverage:
4608                         aCond.append("below-average");
4609                         break;
4610                     case ScConditionMode::AboveEqualAverage:
4611                         aCond.append("above-equal-average");
4612                         break;
4613                     case ScConditionMode::BelowEqualAverage:
4614                         aCond.append("below-equal-average");
4615                         break;
4616                     case ScConditionMode::Error:
4617                         aCond.append("is-error");
4618                         break;
4619                     case ScConditionMode::NoError:
4620                         aCond.append("is-no-error");
4621                         break;
4622                     case ScConditionMode::BeginsWith:
4623                         aCond.append("begins-with(");
4624                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4625                         aCond.append(")");
4626                         break;
4627                     case ScConditionMode::EndsWith:
4628                         aCond.append("ends-with(");
4629                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4630                         aCond.append(")");
4631                         break;
4632                     case ScConditionMode::ContainsText:
4633                         aCond.append("contains-text(");
4634                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4635                         aCond.append(")");
4636                         break;
4637                     case ScConditionMode::NotContainsText:
4638                         aCond.append("not-contains-text(");
4639                         aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4640                         aCond.append(")");
4641                         break;
4642                     case ScConditionMode::NONE:
4643                         continue;
4644                     default:
4645                         SAL_WARN("sc", "unimplemented conditional format export");
4646                 }
4647                 OUString sStyle = ScStyleNameConversion::DisplayToProgrammaticName(pEntry->GetStyle(), SfxStyleFamily::Para);
4648                 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_APPLY_STYLE_NAME, sStyle);
4649                 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, aCond.makeStringAndClear());
4650 
4651                 OUString sBaseAddress;
4652                 ScRangeStringConverter::GetStringFromAddress( sBaseAddress, aPos, pDoc,formula::FormulaGrammar::CONV_ODF );
4653                 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_BASE_CELL_ADDRESS, sBaseAddress);
4654                 SvXMLElementExport aElementCondEntry(*this, XML_NAMESPACE_CALC_EXT, XML_CONDITION, true, true);
4655             }
4656             else if(pFormatEntry->GetType() == ScFormatEntry::Type::Colorscale)
4657             {
4658                 SvXMLElementExport aElementColorScale(*this, XML_NAMESPACE_CALC_EXT, XML_COLOR_SCALE, true, true);
4659                 const ScColorScaleFormat& rColorScale = static_cast<const ScColorScaleFormat&>(*pFormatEntry);
4660                 for(const auto& rxItem : rColorScale)
4661                 {
4662                     if(rxItem->GetType() == COLORSCALE_FORMULA)
4663                     {
4664                         OUString sFormula = rxItem->GetFormula(formula::FormulaGrammar::GRAM_ODFF);
4665                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, sFormula);
4666                     }
4667                     else
4668                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, OUString::number(rxItem->GetValue()));
4669 
4670                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, getCondFormatEntryType(*rxItem));
4671                     OUStringBuffer aBuffer;
4672                     ::sax::Converter::convertColor(aBuffer, rxItem->GetColor());
4673                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLOR, aBuffer.makeStringAndClear());
4674                     SvXMLElementExport aElementColorScaleEntry(*this, XML_NAMESPACE_CALC_EXT, XML_COLOR_SCALE_ENTRY, true, true);
4675                 }
4676             }
4677             else if(pFormatEntry->GetType() == ScFormatEntry::Type::Databar)
4678             {
4679                 const ScDataBarFormatData* pFormatData = static_cast<const ScDataBarFormat&>(*pFormatEntry).GetDataBarData();
4680                 if(!pFormatData->mbGradient)
4681                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_GRADIENT, XML_FALSE);
4682                 if(pFormatData->mbOnlyBar)
4683                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_SHOW_VALUE, XML_FALSE);
4684 
4685                 if (pFormatData->mnMinLength != 0.0)
4686                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MIN_LENGTH, OUString::number(pFormatData->mnMinLength));
4687 
4688                 if (pFormatData->mnMaxLength != 0.0)
4689                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MAX_LENGTH, OUString::number(pFormatData->mnMaxLength));
4690 
4691                 if(pFormatData->mbNeg)
4692                 {
4693                     if(pFormatData->mpNegativeColor)
4694                     {
4695                         OUStringBuffer aBuffer;
4696                         ::sax::Converter::convertColor(aBuffer, *pFormatData->mpNegativeColor);
4697                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_NEGATIVE_COLOR, aBuffer.makeStringAndClear());
4698                     }
4699                     else
4700                     {
4701                         OUStringBuffer aBuffer;
4702                         ::sax::Converter::convertColor(aBuffer, COL_LIGHTRED);
4703                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_NEGATIVE_COLOR, aBuffer.makeStringAndClear());
4704                     }
4705                 }
4706 
4707                 if(pFormatData->meAxisPosition != databar::AUTOMATIC)
4708                 {
4709                     if(pFormatData->meAxisPosition == databar::NONE)
4710                     {
4711                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_AXIS_POSITION, OUString("none"));
4712                     }
4713                     else
4714                     {
4715                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_AXIS_POSITION, OUString("middle"));
4716                     }
4717                 }
4718 
4719                 OUStringBuffer aBuffer;
4720                 ::sax::Converter::convertColor(aBuffer, pFormatData->maPositiveColor);
4721                 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_POSITIVE_COLOR, aBuffer.makeStringAndClear());
4722 
4723                 aBuffer.truncate();
4724                 ::sax::Converter::convertColor(aBuffer, pFormatData->maAxisColor);
4725                 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_AXIS_COLOR, aBuffer.makeStringAndClear());
4726                 SvXMLElementExport aElementDataBar(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_BAR, true, true);
4727 
4728                 {
4729                     if(pFormatData->mpLowerLimit->GetType() == COLORSCALE_FORMULA)
4730                     {
4731                         OUString sFormula = pFormatData->mpLowerLimit->GetFormula(formula::FormulaGrammar::GRAM_ODFF);
4732                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, sFormula);
4733                     }
4734                     else
4735                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, OUString::number(pFormatData->mpLowerLimit->GetValue()));
4736                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, getCondFormatEntryType(*pFormatData->mpLowerLimit));
4737                     SvXMLElementExport aElementDataBarEntryLower(*this, XML_NAMESPACE_CALC_EXT, XML_FORMATTING_ENTRY, true, true);
4738                 }
4739 
4740                 {
4741                     if(pFormatData->mpUpperLimit->GetType() == COLORSCALE_FORMULA)
4742                     {
4743                         OUString sFormula = pFormatData->mpUpperLimit->GetFormula(formula::FormulaGrammar::GRAM_ODFF);
4744                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, sFormula);
4745                     }
4746                     else
4747                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, OUString::number(pFormatData->mpUpperLimit->GetValue()));
4748                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, getCondFormatEntryType(*pFormatData->mpUpperLimit, false));
4749                     SvXMLElementExport aElementDataBarEntryUpper(*this, XML_NAMESPACE_CALC_EXT, XML_FORMATTING_ENTRY, true, true);
4750                 }
4751             }
4752             else if(pFormatEntry->GetType() == ScFormatEntry::Type::Iconset)
4753             {
4754                 const ScIconSetFormat& rIconSet = static_cast<const ScIconSetFormat&>(*pFormatEntry);
4755                 OUString aIconSetName = OUString::createFromAscii(ScIconSetFormat::getIconSetName(rIconSet.GetIconSetData()->eIconSetType));
4756                 AddAttribute( XML_NAMESPACE_CALC_EXT, XML_ICON_SET_TYPE, aIconSetName );
4757                 if (rIconSet.GetIconSetData()->mbCustom)
4758                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_CUSTOM, OUString::boolean(true));
4759 
4760                 SvXMLElementExport aElementColorScale(*this, XML_NAMESPACE_CALC_EXT, XML_ICON_SET, true, true);
4761 
4762                 if (rIconSet.GetIconSetData()->mbCustom)
4763                 {
4764                     for (const auto& [rType, rIndex] : rIconSet.GetIconSetData()->maCustomVector)
4765                     {
4766                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_CUSTOM_ICONSET_NAME, OUString::createFromAscii(ScIconSetFormat::getIconSetName(rType)));
4767                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_CUSTOM_ICONSET_INDEX, OUString::number(rIndex));
4768                         SvXMLElementExport aCustomIcon(*this, XML_NAMESPACE_CALC_EXT, XML_CUSTOM_ICONSET, true, true);
4769                     }
4770 
4771                 }
4772 
4773                 if(!rIconSet.GetIconSetData()->mbShowValue)
4774                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_SHOW_VALUE, XML_FALSE);
4775                 for (auto const& it : rIconSet)
4776                 {
4777                     if(it->GetType() == COLORSCALE_FORMULA)
4778                     {
4779                         OUString sFormula = it->GetFormula(formula::FormulaGrammar::GRAM_ODFF);
4780                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, sFormula);
4781                     }
4782                     else
4783                         AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, OUString::number(it->GetValue()));
4784 
4785                     AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, getCondFormatEntryType(*it));
4786                     SvXMLElementExport aElementColorScaleEntry(*this, XML_NAMESPACE_CALC_EXT, XML_FORMATTING_ENTRY, true, true);
4787                 }
4788             }
4789             else if(pFormatEntry->GetType() == ScFormatEntry::Type::Date)
4790             {
4791                 const ScCondDateFormatEntry& rDateFormat = static_cast<const ScCondDateFormatEntry&>(*pFormatEntry);
4792                 OUString aDateType = getDateStringForType(rDateFormat.GetDateType());
4793                 OUString aStyleName = ScStyleNameConversion::DisplayToProgrammaticName(rDateFormat.GetStyleName(), SfxStyleFamily::Para );
4794                 AddAttribute( XML_NAMESPACE_CALC_EXT, XML_STYLE, aStyleName);
4795                 AddAttribute( XML_NAMESPACE_CALC_EXT, XML_DATE, aDateType);
4796                 SvXMLElementExport aElementDateFormat(*this, XML_NAMESPACE_CALC_EXT, XML_DATE_IS, true, true);
4797             }
4798         }
4799     }
4800 }
4801 
4802 void ScXMLExport::WriteExternalRefCaches()
4803 {
4804     if (!pDoc)
4805         return;
4806 
4807     ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
4808     pRefMgr->resetSrcFileData(GetOrigFileName());
4809     sal_uInt16 nCount = pRefMgr->getExternalFileCount();
4810     for (sal_uInt16 nFileId = 0; nFileId < nCount; ++nFileId)
4811     {
4812         const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
4813         if (!pUrl)
4814             continue;
4815 
4816         vector<OUString> aTabNames;
4817         pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
4818         if (aTabNames.empty())
4819             continue;
4820 
4821         for (const auto& rTabName : aTabNames)
4822         {
4823             ScExternalRefCache::TableTypeRef pTable = pRefMgr->getCacheTable(nFileId, rTabName, false);
4824             if (!pTable.get() || !pTable->isReferenced())
4825                 continue;
4826 
4827             AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, "'" + *pUrl + "'#" + rTabName);
4828             AddAttribute(XML_NAMESPACE_TABLE, XML_PRINT, GetXMLToken(XML_FALSE));
4829             AddAttribute(XML_NAMESPACE_TABLE, XML_STYLE_NAME, sExternalRefTabStyleName);
4830             SvXMLElementExport aElemTable(*this, XML_NAMESPACE_TABLE, XML_TABLE, true, true);
4831             {
4832                 const ScExternalRefManager::SrcFileData* pExtFileData = pRefMgr->getExternalFileData(nFileId);
4833                 if (pExtFileData)
4834                 {
4835                     OUString aRelUrl;
4836                     if (!pExtFileData->maRelativeName.isEmpty())
4837                         aRelUrl = pExtFileData->maRelativeName;
4838                     else
4839                         aRelUrl = GetRelativeReference(pExtFileData->maRelativeName);
4840                     AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
4841                     AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, aRelUrl);
4842                     AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_NAME, rTabName);
4843                     if (!pExtFileData->maFilterName.isEmpty())
4844                         AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_NAME, pExtFileData->maFilterName);
4845                     if (!pExtFileData->maFilterOptions.isEmpty())
4846                         AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_OPTIONS, pExtFileData->maFilterOptions);
4847                     AddAttribute(XML_NAMESPACE_TABLE, XML_MODE, XML_COPY_RESULTS_ONLY);
4848                 }
4849                 SvXMLElementExport aElemTableSource(*this, XML_NAMESPACE_TABLE, XML_TABLE_SOURCE, true, true);
4850             }
4851 
4852             // Determine maximum column count of used area, for repeated cells.
4853             SCCOL nMaxColsUsed = 1;     // assume that there is at least one cell somewhere...
4854             vector<SCROW> aRows;
4855             pTable->getAllRows(aRows);
4856             for (SCROW nRow : aRows)
4857             {
4858                 vector<SCCOL> aCols;
4859                 pTable->getAllCols(nRow, aCols);
4860                 if (!aCols.empty())
4861                 {
4862                     SCCOL nCol = aCols.back();
4863                     if (nMaxColsUsed <= nCol)
4864                         nMaxColsUsed = nCol + 1;
4865                 }
4866             }
4867 
4868             // Column definitions have to be present to make a valid file
4869             {
4870                 if (nMaxColsUsed > 1)
4871                     AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
4872                                     OUString::number(nMaxColsUsed));
4873                 SvXMLElementExport aElemColumn(*this, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true);
4874             }
4875 
4876             // Write cache content for this table.
4877             SCROW nLastRow = 0;
4878             bool bFirstRow = true;
4879             for (SCROW nRow : aRows)
4880             {
4881                 if (bFirstRow)
4882                 {
4883                     if (nRow > 0)
4884                     {
4885                         if (nRow > 1)
4886                         {
4887                             OUStringBuffer aVal;
4888                             aVal.append(nRow);
4889                             AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, aVal.makeStringAndClear());
4890                         }
4891                         SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true);
4892                         OUStringBuffer aVal;
4893                         aVal.append(static_cast<sal_Int32>(nMaxColsUsed));
4894                         AddAttribute(XML_NAMESPACE_TABLE,  XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
4895                         SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
4896                     }
4897                 }
4898                 else
4899                 {
4900                     SCROW nRowGap = nRow - nLastRow;
4901                     if (nRowGap > 1)
4902                     {
4903                         if (nRowGap > 2)
4904                         {
4905                             OUStringBuffer aVal;
4906                             aVal.append(static_cast<sal_Int32>(nRowGap-1));
4907                             AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, aVal.makeStringAndClear());
4908                         }
4909                         SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true);
4910                         OUStringBuffer aVal;
4911                         aVal.append(static_cast<sal_Int32>(nMaxColsUsed));
4912                         AddAttribute(XML_NAMESPACE_TABLE,  XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
4913                         SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
4914                     }
4915                 }
4916                 SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true);
4917 
4918                 vector<SCCOL> aCols;
4919                 pTable->getAllCols(nRow, aCols);
4920                 SCCOL nLastCol = 0;
4921                 bool bFirstCol = true;
4922                 for (SCCOL nCol : aCols)
4923                 {
4924                     if (bFirstCol)
4925                     {
4926                         if (nCol > 0)
4927                         {
4928                             if (nCol > 1)
4929                             {
4930                                 OUStringBuffer aVal;
4931                                 aVal.append(static_cast<sal_Int32>(nCol));
4932                                 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
4933                             }
4934                             SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
4935                         }
4936                     }
4937                     else
4938                     {
4939                         SCCOL nColGap = nCol - nLastCol;
4940                         if (nColGap > 1)
4941                         {
4942                             if (nColGap > 2)
4943                             {
4944                                 OUStringBuffer aVal;
4945                                 aVal.append(static_cast<sal_Int32>(nColGap-1));
4946                                 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
4947                             }
4948                             SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
4949                         }
4950                     }
4951 
4952                     // Write out this cell.
4953                     sal_uInt32 nNumFmt = 0;
4954                     ScExternalRefCache::TokenRef pToken = pTable->getCell(nCol, nRow, &nNumFmt);
4955                     OUString aStrVal;
4956                     if (pToken.get())
4957                     {
4958                         sal_Int32 nIndex = GetNumberFormatStyleIndex(nNumFmt);
4959                         if (nIndex >= 0)
4960                         {
4961                             const OUString & aStyleName = pCellStyles->GetStyleNameByIndex(nIndex, true);
4962                             AddAttribute(XML_NAMESPACE_TABLE, XML_STYLE_NAME, aStyleName);
4963                         }
4964 
4965                         switch(pToken->GetType())
4966                         {
4967                             case svDouble:
4968                             {
4969                                 AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT);
4970                                 OUStringBuffer aVal;
4971                                 aVal.append(pToken->GetDouble());
4972                                 aStrVal = aVal.makeStringAndClear();
4973                                 AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE, aStrVal);
4974                             }
4975                             break;
4976                             case svString:
4977                             {
4978                                 AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING);
4979                                 aStrVal = pToken->GetString().getString();
4980                             }
4981                             break;
4982                             default:
4983                                 ;
4984                         }
4985                     }
4986                     SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
4987                     SvXMLElementExport aElemText(*this, XML_NAMESPACE_TEXT, XML_P, true, false);
4988                     Characters(aStrVal);
4989 
4990                     nLastCol = nCol;
4991                     bFirstCol = false;
4992                 }
4993                 nLastRow = nRow;
4994                 bFirstRow = false;
4995             }
4996         }
4997     }
4998 }
4999 
5000 // core implementation
5001 void ScXMLExport::WriteConsolidation()
5002 {
5003     if (pDoc)
5004     {
5005         const ScConsolidateParam* pCons(pDoc->GetConsolidateDlgData());
5006         if( pCons )
5007         {
5008             OUString sStrData;
5009 
5010             ScXMLConverter::GetStringFromFunction( sStrData, pCons->eFunction );
5011             AddAttribute( XML_NAMESPACE_TABLE, XML_FUNCTION, sStrData );
5012 
5013             sStrData.clear();
5014             for( sal_Int32 nIndex = 0; nIndex < pCons->nDataAreaCount; ++nIndex )
5015                 ScRangeStringConverter::GetStringFromArea( sStrData, pCons->pDataAreas[ nIndex ], pDoc, FormulaGrammar::CONV_OOO, ' ', true );
5016             AddAttribute( XML_NAMESPACE_TABLE, XML_SOURCE_CELL_RANGE_ADDRESSES, sStrData );
5017 
5018             ScRangeStringConverter::GetStringFromAddress( sStrData, ScAddress( pCons->nCol, pCons->nRow, pCons->nTab ), pDoc, FormulaGrammar::CONV_OOO );
5019             AddAttribute( XML_NAMESPACE_TABLE, XML_TARGET_CELL_ADDRESS, sStrData );
5020 
5021             if( pCons->bByCol && !pCons->bByRow )
5022                 AddAttribute( XML_NAMESPACE_TABLE, XML_USE_LABEL, XML_COLUMN );
5023             else if( !pCons->bByCol && pCons->bByRow )
5024                 AddAttribute( XML_NAMESPACE_TABLE, XML_USE_LABEL, XML_ROW );
5025             else if( pCons->bByCol && pCons->bByRow )
5026                 AddAttribute( XML_NAMESPACE_TABLE, XML_USE_LABEL, XML_BOTH );
5027 
5028             if( pCons->bReferenceData )
5029                 AddAttribute( XML_NAMESPACE_TABLE, XML_LINK_TO_SOURCE_DATA, XML_TRUE );
5030 
5031             SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_CONSOLIDATION, true, true );
5032         }
5033     }
5034 }
5035 
5036 SvXMLAutoStylePoolP* ScXMLExport::CreateAutoStylePool()
5037 {
5038     return new ScXMLAutoStylePoolP(*this);
5039 }
5040 
5041 XMLPageExport* ScXMLExport::CreatePageExport()
5042 {
5043     return new XMLTableMasterPageExport( *this );
5044 }
5045 
5046 void ScXMLExport::GetChangeTrackViewSettings(uno::Sequence<beans::PropertyValue>& rProps)
5047 {
5048     ScChangeViewSettings* pViewSettings(GetDocument() ? GetDocument()->GetChangeViewSettings() : nullptr);
5049     if (pViewSettings)
5050     {
5051         sal_Int32 nChangePos(rProps.getLength());
5052         rProps.realloc(nChangePos + 1);
5053         beans::PropertyValue* pProps(rProps.getArray());
5054 
5055         uno::Sequence<beans::PropertyValue> aChangeProps(SC_VIEWCHANGES_COUNT);
5056         beans::PropertyValue* pChangeProps(aChangeProps.getArray());
5057         pChangeProps[SC_SHOW_CHANGES].Name = "ShowChanges";
5058         pChangeProps[SC_SHOW_CHANGES].Value <<= pViewSettings->ShowChanges();
5059         pChangeProps[SC_SHOW_ACCEPTED_CHANGES].Name = "ShowAcceptedChanges";
5060         pChangeProps[SC_SHOW_ACCEPTED_CHANGES].Value <<= pViewSettings->IsShowAccepted();
5061         pChangeProps[SC_SHOW_REJECTED_CHANGES].Name = "ShowRejectedChanges";
5062         pChangeProps[SC_SHOW_REJECTED_CHANGES].Value <<= pViewSettings->IsShowRejected();
5063         pChangeProps[SC_SHOW_CHANGES_BY_DATETIME].Name = "ShowChangesByDatetime";
5064         pChangeProps[SC_SHOW_CHANGES_BY_DATETIME].Value <<= pViewSettings->HasDate();
5065         pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_MODE].Name = "ShowChangesByDatetimeMode";
5066         pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_MODE].Value <<= static_cast<sal_Int16>(pViewSettings->GetTheDateMode());
5067         pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_FIRST_DATETIME].Name = "ShowChangesByDatetimeFirstDatetime";
5068         pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_FIRST_DATETIME].Value <<= pViewSettings->GetTheFirstDateTime().GetUNODateTime();
5069         pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_SECOND_DATETIME].Name = "ShowChangesByDatetimeSecondDatetime";
5070         pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_SECOND_DATETIME].Value <<= pViewSettings->GetTheLastDateTime().GetUNODateTime();
5071         pChangeProps[SC_SHOW_CHANGES_BY_AUTHOR].Name = "ShowChangesByAuthor";
5072         pChangeProps[SC_SHOW_CHANGES_BY_AUTHOR].Value <<= pViewSettings->HasAuthor();
5073         pChangeProps[SC_SHOW_CHANGES_BY_AUTHOR_NAME].Name = "ShowChangesByAuthorName";
5074         pChangeProps[SC_SHOW_CHANGES_BY_AUTHOR_NAME].Value <<= pViewSettings->GetTheAuthorToShow();
5075         pChangeProps[SC_SHOW_CHANGES_BY_COMMENT].Name = "ShowChangesByComment";
5076         pChangeProps[SC_SHOW_CHANGES_BY_COMMENT].Value <<= pViewSettings->HasComment();
5077         pChangeProps[SC_SHOW_CHANGES_BY_COMMENT_TEXT].Name = "ShowChangesByCommentText";
5078         pChangeProps[SC_SHOW_CHANGES_BY_COMMENT_TEXT].Value <<= pViewSettings->GetTheComment();
5079         pChangeProps[SC_SHOW_CHANGES_BY_RANGES].Name = "ShowChangesByRanges";
5080         pChangeProps[SC_SHOW_CHANGES_BY_RANGES].Value <<= pViewSettings->HasRange();
5081         OUString sRangeList;
5082         ScRangeStringConverter::GetStringFromRangeList(sRangeList, &(pViewSettings->GetTheRangeList()), GetDocument(), FormulaGrammar::CONV_OOO);
5083         pChangeProps[SC_SHOW_CHANGES_BY_RANGES_LIST].Name = "ShowChangesByRangesList";
5084         pChangeProps[SC_SHOW_CHANGES_BY_RANGES_LIST].Value <<= sRangeList;
5085 
5086         pProps[nChangePos].Name = "TrackedChangesViewSettings";
5087         pProps[nChangePos].Value <<= aChangeProps;
5088     }
5089 }
5090 
5091 void ScXMLExport::GetViewSettings(uno::Sequence<beans::PropertyValue>& rProps)
5092 {
5093     if (GetModel().is())
5094     {
5095         rProps.realloc(4);
5096         beans::PropertyValue* pProps(rProps.getArray());
5097         ScModelObj* pDocObj(comphelper::getUnoTunnelImplementation<ScModelObj>( GetModel() ));
5098         if (pDocObj)
5099         {
5100             SfxObjectShell* pEmbeddedObj = pDocObj->GetEmbeddedObject();
5101             if (pEmbeddedObj)
5102             {
5103                 tools::Rectangle aRect(pEmbeddedObj->GetVisArea());
5104                 sal_uInt16 i(0);
5105                 pProps[i].Name = "VisibleAreaTop";
5106                 pProps[i].Value <<= static_cast<sal_Int32>(aRect.getY());
5107                 pProps[++i].Name = "VisibleAreaLeft";
5108                 pProps[i].Value <<= static_cast<sal_Int32>(aRect.getX());
5109                 pProps[++i].Name = "VisibleAreaWidth";
5110                 pProps[i].Value <<= static_cast<sal_Int32>(aRect.getWidth());
5111                 pProps[++i].Name = "VisibleAreaHeight";
5112                 pProps[i].Value <<= static_cast<sal_Int32>(aRect.getHeight());
5113             }
5114         }
5115     }
5116     GetChangeTrackViewSettings(rProps);
5117 }
5118 
5119 void ScXMLExport::GetConfigurationSettings(uno::Sequence<beans::PropertyValue>& rProps)
5120 {
5121     if (GetModel().is())
5122     {
5123         uno::Reference <lang::XMultiServiceFactory> xMultiServiceFactory(GetModel(), uno::UNO_QUERY);
5124         if (xMultiServiceFactory.is())
5125         {
5126             uno::Reference <beans::XPropertySet> xProperties(xMultiServiceFactory->createInstance("com.sun.star.comp.SpreadsheetSettings"), uno::UNO_QUERY);
5127             if (xProperties.is())
5128                 SvXMLUnitConverter::convertPropertySet(rProps, xProperties);
5129 
5130             sal_Int32 nPropsToAdd = 0;
5131             OUStringBuffer aTrackedChangesKey;
5132             if (GetDocument() && GetDocument()->GetChangeTrack() && GetDocument()->GetChangeTrack()->IsProtected())
5133             {
5134                 ::comphelper::Base64::encode(aTrackedChangesKey,
5135                         GetDocument()->GetChangeTrack()->GetProtection());
5136                 if (!aTrackedChangesKey.isEmpty())
5137                     ++nPropsToAdd;
5138             }
5139 
5140             bool bVBACompat = false;
5141             uno::Reference <container::XNameAccess> xCodeNameAccess;
5142             OSL_ENSURE( pDoc, "ScXMLExport::GetConfigurationSettings - no ScDocument!" );
5143             if( pDoc && pDoc->IsInVBAMode() )
5144             {
5145                 // VBA compatibility mode
5146                 bVBACompat = true;
5147                 ++nPropsToAdd;
5148                 // code names
5149                 xCodeNameAccess = new XMLCodeNameProvider( pDoc );
5150                 if( xCodeNameAccess->hasElements() )
5151                     ++nPropsToAdd;
5152                 else
5153                     xCodeNameAccess.clear();
5154             }
5155 
5156             if( nPropsToAdd > 0 )
5157             {
5158                 sal_Int32 nCount(rProps.getLength());
5159                 rProps.realloc(nCount + nPropsToAdd);
5160                 if (!aTrackedChangesKey.isEmpty())
5161                 {
5162                     rProps[nCount].Name = "TrackedChangesProtectionKey";
5163                     rProps[nCount].Value <<= aTrackedChangesKey.makeStringAndClear();
5164                     ++nCount;
5165                 }
5166                 if( bVBACompat )
5167                 {
5168                     rProps[nCount].Name = "VBACompatibilityMode";
5169                     rProps[nCount].Value <<= bVBACompat;
5170                     ++nCount;
5171                 }
5172                 if( xCodeNameAccess.is() )
5173                 {
5174                     rProps[nCount].Name = "ScriptConfiguration";
5175                     rProps[nCount].Value <<= xCodeNameAccess;
5176                     ++nCount;
5177                 }
5178             }
5179         }
5180     }
5181 }
5182 
5183 XMLShapeExport* ScXMLExport::CreateShapeExport()
5184 {
5185     return new ScXMLShapeExport(*this);
5186 }
5187 
5188 XMLNumberFormatAttributesExportHelper* ScXMLExport::GetNumberFormatAttributesExportHelper()
5189 {
5190     if (!pNumberFormatAttributesExportHelper)
5191         pNumberFormatAttributesExportHelper.reset(new XMLNumberFormatAttributesExportHelper(GetNumberFormatsSupplier(), *this ));
5192     return pNumberFormatAttributesExportHelper.get();
5193 }
5194 
5195 void ScXMLExport::CollectUserDefinedNamespaces(const SfxItemPool* pPool, sal_uInt16 nAttrib)
5196 {
5197     for (const SfxPoolItem* pItem : pPool->GetItemSurrogates(nAttrib))
5198     {
5199         const SvXMLAttrContainerItem *pUnknown(static_cast<const SvXMLAttrContainerItem *>(pItem));
5200         if( pUnknown->GetAttrCount() > 0 )
5201         {
5202             sal_uInt16 nIdx(pUnknown->GetFirstNamespaceIndex());
5203             while( USHRT_MAX != nIdx )
5204             {
5205                 if( (XML_NAMESPACE_UNKNOWN_FLAG & nIdx) != 0 )
5206                 {
5207                     const OUString& rPrefix = pUnknown->GetPrefix( nIdx );
5208                     // Add namespace declaration for unknown attributes if
5209                     // there aren't existing ones for the prefix used by the
5210                     // attributes
5211                     GetNamespaceMap_().Add( rPrefix,
5212                                             pUnknown->GetNamespace( nIdx ) );
5213                 }
5214                 nIdx = pUnknown->GetNextNamespaceIndex( nIdx );
5215             }
5216         }
5217     }
5218 
5219     // #i66550# needed for 'presentation:event-listener' element for URLs in shapes
5220     GetNamespaceMap_().Add(
5221         GetXMLToken( XML_NP_PRESENTATION ),
5222         GetXMLToken( XML_N_PRESENTATION ),
5223         XML_NAMESPACE_PRESENTATION );
5224 }
5225 
5226 void ScXMLExport::IncrementProgressBar(bool bFlush, sal_Int32 nInc)
5227 {
5228     nProgressCount += nInc;
5229     if (bFlush || nProgressCount > 100)
5230     {
5231         GetProgressBarHelper()->Increment(nProgressCount);
5232         nProgressCount = 0;
5233     }
5234 }
5235 
5236 ErrCode ScXMLExport::exportDoc( enum XMLTokenEnum eClass )
5237 {
5238     if( getExportFlags() & (SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::STYLES|
5239                              SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
5240     {
5241         if (GetDocument())
5242         {
5243             // if source doc was Excel then
5244             uno::Reference< frame::XModel > xModel = GetModel();
5245             if ( xModel.is() )
5246             {
5247                 uno::Reference< lang::XUnoTunnel >  xObjShellTunnel( xModel, uno::UNO_QUERY );
5248                 SfxObjectShell* pFoundShell = reinterpret_cast<SfxObjectShell*>( xObjShellTunnel.is() ? xObjShellTunnel->getSomething(SfxObjectShell::getUnoTunnelId()) : 0 );
5249                 if ( pFoundShell && ooo::vba::isAlienExcelDoc( *pFoundShell ) )
5250                 {
5251                     xRowStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScFromXLSRowStylesProperties, xScPropHdlFactory, true);
5252                     xRowStylesExportPropertySetMapper = new ScXMLRowExportPropertyMapper(xRowStylesPropertySetMapper);
5253                     GetAutoStylePool()->SetFamilyPropSetMapper( XML_STYLE_FAMILY_TABLE_ROW,
5254                         xRowStylesExportPropertySetMapper );
5255                 }
5256             }
5257             CollectUserDefinedNamespaces(GetDocument()->GetPool(), ATTR_USERDEF);
5258             CollectUserDefinedNamespaces(GetDocument()->GetEditPool(), EE_PARA_XMLATTRIBS);
5259             CollectUserDefinedNamespaces(GetDocument()->GetEditPool(), EE_CHAR_XMLATTRIBS);
5260             ScDrawLayer* pDrawLayer = GetDocument()->GetDrawLayer();
5261             if (pDrawLayer)
5262             {
5263                 CollectUserDefinedNamespaces(&pDrawLayer->GetItemPool(), EE_PARA_XMLATTRIBS);
5264                 CollectUserDefinedNamespaces(&pDrawLayer->GetItemPool(), EE_CHAR_XMLATTRIBS);
5265                 CollectUserDefinedNamespaces(&pDrawLayer->GetItemPool(), SDRATTR_XMLATTRIBUTES);
5266             }
5267 
5268             // sheet events use officeooo namespace
5269             if( (getExportFlags() & SvXMLExportFlags::CONTENT) &&
5270                 getDefaultVersion() >= SvtSaveOptions::ODFVER_012 )
5271             {
5272                 bool bAnySheetEvents = false;
5273                 SCTAB nTabCount = pDoc->GetTableCount();
5274                 for (SCTAB nTab=0; nTab<nTabCount; ++nTab)
5275                     if (pDoc->GetSheetEvents(nTab))
5276                         bAnySheetEvents = true;
5277                 if (bAnySheetEvents)
5278                     GetNamespaceMap_().Add(
5279                         GetXMLToken( XML_NP_OFFICE_EXT ),
5280                         GetXMLToken( XML_N_OFFICE_EXT ),
5281                         XML_NAMESPACE_OFFICE_EXT );
5282             }
5283         }
5284     }
5285     return SvXMLExport::exportDoc( eClass );
5286 }
5287 
5288 // XExporter
5289 void SAL_CALL ScXMLExport::setSourceDocument( const uno::Reference<lang::XComponent>& xComponent )
5290 {
5291     SolarMutexGuard aGuard;
5292     SvXMLExport::setSourceDocument( xComponent );
5293 
5294     pDoc = ScXMLConverter::GetScDocument( GetModel() );
5295     OSL_ENSURE( pDoc, "ScXMLExport::setSourceDocument - no ScDocument!" );
5296     if (!pDoc)
5297         throw lang::IllegalArgumentException();
5298 
5299     // create ScChangeTrackingExportHelper after document is known
5300     pChangeTrackingExportHelper.reset(new ScChangeTrackingExportHelper(*this));
5301 
5302     // Set the document's storage grammar corresponding to the ODF version that
5303     // is to be written.
5304     SvtSaveOptions::ODFDefaultVersion meODFDefaultVersion = getDefaultVersion();
5305     switch (meODFDefaultVersion)
5306     {
5307         // ODF 1.0 and 1.1 use GRAM_PODF, everything later or unspecified GRAM_ODFF
5308         case SvtSaveOptions::ODFVER_010:
5309         case SvtSaveOptions::ODFVER_011:
5310             pDoc->SetStorageGrammar( formula::FormulaGrammar::GRAM_PODF);
5311             break;
5312         default:
5313             pDoc->SetStorageGrammar( formula::FormulaGrammar::GRAM_ODFF);
5314     }
5315 }
5316 
5317 // XFilter
5318 sal_Bool SAL_CALL ScXMLExport::filter( const css::uno::Sequence< css::beans::PropertyValue >& aDescriptor )
5319 {
5320     SolarMutexGuard aGuard;
5321     if (pDoc)
5322         pDoc->EnableIdle(false);
5323     bool bReturn(SvXMLExport::filter(aDescriptor));
5324     if (pDoc)
5325         pDoc->EnableIdle(true);
5326     return bReturn;
5327 }
5328 
5329 void SAL_CALL ScXMLExport::cancel()
5330 {
5331     SolarMutexGuard aGuard;
5332     if (pDoc)
5333         pDoc->EnableIdle(true);
5334     SvXMLExport::cancel();
5335 }
5336 
5337 // XInitialization
5338 void SAL_CALL ScXMLExport::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
5339 {
5340     SolarMutexGuard aGuard;
5341     SvXMLExport::initialize(aArguments);
5342 }
5343 
5344 // XUnoTunnel
5345 sal_Int64 SAL_CALL ScXMLExport::getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier )
5346 {
5347     SolarMutexGuard aGuard;
5348     return SvXMLExport::getSomething(aIdentifier);
5349 }
5350 
5351 void ScXMLExport::DisposingModel()
5352 {
5353     SvXMLExport::DisposingModel();
5354     pDoc = nullptr;
5355     xCurrentTable = nullptr;
5356 }
5357 
5358 void ScXMLExport::SetSharedData(std::unique_ptr<ScMySharedData> pTemp) { pSharedData = std::move(pTemp); }
5359 
5360 std::unique_ptr<ScMySharedData> ScXMLExport::ReleaseSharedData() { return std::move(pSharedData); }
5361 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
5362