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