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