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