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