Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / xml / xmlexprt.cxx
bloba1fdf72f53b1375cbc8579d9c4b52c29cb988dc3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
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>
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>
105 #include <sax/tools/converter.hxx>
106 #include <tools/fldunit.hxx>
108 #include <rtl/ustring.hxx>
110 #include <tools/color.hxx>
111 #include <rtl/math.hxx>
112 #include <svl/zforlist.hxx>
113 #include <svx/unoshape.hxx>
114 #include <comphelper/base64.hxx>
115 #include <comphelper/extract.hxx>
116 #include <svx/svdobj.hxx>
117 #include <svx/svdocapt.hxx>
118 #include <svtools/miscopt.hxx>
119 #include <vcl/svapp.hxx>
121 #include <comphelper/processfactory.hxx>
122 #include <com/sun/star/beans/XPropertySet.hpp>
123 #include <com/sun/star/container/XNamed.hpp>
124 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
125 #include <com/sun/star/form/XFormsSupplier2.hpp>
126 #include <com/sun/star/io/XActiveDataSource.hpp>
127 #include <com/sun/star/io/XSeekable.hpp>
128 #include <com/sun/star/sheet/XUsedAreaCursor.hpp>
129 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
130 #include <com/sun/star/sheet/XPrintAreas.hpp>
131 #include <com/sun/star/sheet/XUniqueCellFormatRangesSupplier.hpp>
132 #include <com/sun/star/sheet/XLabelRange.hpp>
133 #include <com/sun/star/sheet/NamedRangeFlag.hpp>
134 #include <com/sun/star/sheet/XSheetCellCursor.hpp>
135 #include <com/sun/star/sheet/XSheetCellRanges.hpp>
136 #include <com/sun/star/sheet/XSheetLinkable.hpp>
137 #include <com/sun/star/sheet/GlobalSheetSettings.hpp>
138 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
139 #include <com/sun/star/table/XColumnRowRange.hpp>
140 #include <com/sun/star/util/XProtectable.hpp>
142 #include <com/sun/star/chart2/XChartDocument.hpp>
143 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
144 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
146 #include <com/sun/star/document/XDocumentProperties.hpp>
147 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
149 #include "XMLCodeNameProvider.hxx"
151 #include <sfx2/linkmgr.hxx>
152 #include <sfx2/objsh.hxx>
154 #include <memory>
155 #include <vector>
156 #include <vbahelper/vbaaccesshelper.hxx>
158 namespace com { namespace sun { namespace star { namespace uno { class XComponentContext; } } } }
162 //! not found in unonames.hxx
163 #define SC_LAYERID "LayerID"
165 #define SC_VIEWCHANGES_COUNT 13
166 #define SC_SHOW_CHANGES 0
167 #define SC_SHOW_ACCEPTED_CHANGES 1
168 #define SC_SHOW_REJECTED_CHANGES 2
169 #define SC_SHOW_CHANGES_BY_DATETIME 3
170 #define SC_SHOW_CHANGES_BY_DATETIME_MODE 4
171 #define SC_SHOW_CHANGES_BY_DATETIME_FIRST_DATETIME 5
172 #define SC_SHOW_CHANGES_BY_DATETIME_SECOND_DATETIME 6
173 #define SC_SHOW_CHANGES_BY_AUTHOR 7
174 #define SC_SHOW_CHANGES_BY_AUTHOR_NAME 8
175 #define SC_SHOW_CHANGES_BY_COMMENT 9
176 #define SC_SHOW_CHANGES_BY_COMMENT_TEXT 10
177 #define SC_SHOW_CHANGES_BY_RANGES 11
178 #define SC_SHOW_CHANGES_BY_RANGES_LIST 12
180 using namespace formula;
181 using namespace com::sun::star;
182 using namespace xmloff::token;
183 using ::std::vector;
184 using ::com::sun::star::uno::UNO_QUERY;
186 namespace
188 OUString lcl_RangeSequenceToString(
189 const uno::Sequence< OUString > & rRanges,
190 const uno::Reference< chart2::data::XRangeXMLConversion > & xFormatConverter )
192 OUStringBuffer aResult;
193 const sal_Int32 nMaxIndex( rRanges.getLength() - 1 );
194 const sal_Unicode cSep(' ');
195 for( sal_Int32 i=0; i<=nMaxIndex; ++i )
197 OUString aRange( rRanges[i] );
198 if( xFormatConverter.is())
199 aRange = xFormatConverter->convertRangeToXML( aRange );
200 aResult.append( aRange );
201 if( i < nMaxIndex )
202 aResult.append( cSep );
204 return aResult.makeStringAndClear();
207 OUString lcl_GetFormattedString(ScDocument* pDoc, const ScRefCellValue& rCell, const ScAddress& rAddr)
209 // return text/edit cell string content, with line feeds in edit cells
211 if (!pDoc)
212 return EMPTY_OUSTRING;
214 switch (rCell.meType)
216 case CELLTYPE_STRING:
218 OUString aStr;
219 Color* pColor;
220 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
222 sal_uInt32 nFormat = pDoc->GetNumberFormat(rAddr);
223 ScCellFormat::GetString(rCell, nFormat, aStr, &pColor, *pFormatter, pDoc);
224 return aStr;
226 case CELLTYPE_EDIT:
228 const EditTextObject* pData = rCell.mpEditText;
229 if (!pData)
230 return EMPTY_OUSTRING;
232 EditEngine& rEngine = pDoc->GetEditEngine();
233 rEngine.SetText(*pData);
234 return rEngine.GetText();
236 break;
237 default:
241 return EMPTY_OUSTRING;
244 } // anonymous namespace
246 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
247 Calc_XMLExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
249 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLExporter", SvXMLExportFlags::ALL));
252 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
253 Calc_XMLMetaExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
255 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLMetaExporter", SvXMLExportFlags::META));
258 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
259 Calc_XMLStylesExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
261 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLStylesExporter", SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS));
264 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
265 Calc_XMLContentExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
267 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLContentExporter", SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::FONTDECLS));
270 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
271 Calc_XMLSettingsExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
273 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLSettingsExporter", SvXMLExportFlags::SETTINGS));
276 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
277 Calc_XMLOasisExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
279 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisExporter", SvXMLExportFlags::ALL|SvXMLExportFlags::OASIS));
282 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
283 Calc_XMLOasisMetaExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
285 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisMetaExporter", SvXMLExportFlags::META|SvXMLExportFlags::OASIS));
288 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
289 Calc_XMLOasisStylesExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
291 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisStylesExporter", SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::OASIS));
294 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
295 Calc_XMLOasisContentExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
297 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisContentExporter", SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::OASIS));
300 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
301 Calc_XMLOasisSettingsExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
303 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisSettingsExporter", SvXMLExportFlags::SETTINGS|SvXMLExportFlags::OASIS));
306 class ScXMLShapeExport : public XMLShapeExport
308 public:
309 explicit ScXMLShapeExport(SvXMLExport& rExp) : XMLShapeExport(rExp) {}
311 /** is called before a shape element for the given XShape is exported */
312 virtual void onExport( const uno::Reference < drawing::XShape >& xShape ) override;
315 void ScXMLShapeExport::onExport( const uno::Reference < drawing::XShape >& xShape )
317 uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
318 if( xShapeProp.is() )
320 sal_Int16 nLayerID = 0;
321 if( (xShapeProp->getPropertyValue( SC_LAYERID ) >>= nLayerID) && (SdrLayerID(nLayerID) == SC_LAYER_BACK) )
322 GetExport().AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_BACKGROUND, XML_TRUE);
326 sal_Int16 ScXMLExport::GetMeasureUnit()
328 css::uno::Reference<css::sheet::XGlobalSheetSettings> xProperties =
329 css::sheet::GlobalSheetSettings::create( comphelper::getProcessComponentContext() );
330 const FieldUnit eFieldUnit = static_cast<FieldUnit>(xProperties->getMetric());
331 return SvXMLUnitConverter::GetMeasureUnit(eFieldUnit);
334 static const OUStringLiteral gsLayerID( SC_LAYERID );
336 ScXMLExport::ScXMLExport(
337 const css::uno::Reference< css::uno::XComponentContext >& rContext,
338 OUString const & implementationName, SvXMLExportFlags nExportFlag)
339 : SvXMLExport( GetMeasureUnit(),
340 rContext, implementationName, XML_SPREADSHEET, nExportFlag ),
341 pDoc(nullptr),
342 nSourceStreamPos(0),
343 aTableStyles(),
344 pCurrentCell(nullptr),
345 nOpenRow(-1),
346 nProgressCount(0),
347 nCurrentTable(0),
348 bHasRowHeader(false),
349 bRowHeaderOpen(false)
351 if (getExportFlags() & SvXMLExportFlags::CONTENT)
353 pGroupColumns.reset( new ScMyOpenCloseColumnRowGroup(*this, XML_TABLE_COLUMN_GROUP) );
354 pGroupRows.reset( new ScMyOpenCloseColumnRowGroup(*this, XML_TABLE_ROW_GROUP) );
355 pColumnStyles.reset( new ScColumnStyles() );
356 pRowStyles.reset( new ScRowStyles() );
357 pRowFormatRanges.reset( new ScRowFormatRanges() );
358 pMergedRangesContainer.reset( new ScMyMergedRangesContainer() );
359 pValidationsContainer.reset( new ScMyValidationsContainer() );
360 mpCellsItr.reset(new ScMyNotEmptyCellsIterator(*this));
361 pDefaults.reset( new ScMyDefaultStyles );
363 pCellStyles.reset( new ScFormatRangeStyles() );
365 // document is not set here - create ScChangeTrackingExportHelper later
367 xScPropHdlFactory = new XMLScPropHdlFactory;
368 xCellStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScCellStylesProperties, xScPropHdlFactory, true);
369 xColumnStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScColumnStylesProperties, xScPropHdlFactory, true);
370 xRowStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScRowStylesProperties, xScPropHdlFactory, true);
371 xTableStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScTableStylesProperties, xScPropHdlFactory, true);
372 xCellStylesExportPropertySetMapper = new ScXMLCellExportPropertyMapper(xCellStylesPropertySetMapper);
373 xCellStylesExportPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaExtPropMapper(*this));
374 xColumnStylesExportPropertySetMapper = new ScXMLColumnExportPropertyMapper(xColumnStylesPropertySetMapper);
375 xRowStylesExportPropertySetMapper = new ScXMLRowExportPropertyMapper(xRowStylesPropertySetMapper);
376 xTableStylesExportPropertySetMapper = new ScXMLTableExportPropertyMapper(xTableStylesPropertySetMapper);
378 GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_CELL, XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME,
379 xCellStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX);
380 GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_COLUMN, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_NAME,
381 xColumnStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_PREFIX);
382 GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_ROW, XML_STYLE_FAMILY_TABLE_ROW_STYLES_NAME,
383 xRowStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_ROW_STYLES_PREFIX);
384 GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_TABLE, XML_STYLE_FAMILY_TABLE_TABLE_STYLES_NAME,
385 xTableStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_TABLE_STYLES_PREFIX);
387 if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
389 // This name is reserved for the external ref cache tables. This
390 // should not conflict with user-defined styles since this name is
391 // used for a table style which is not available in the UI.
392 sExternalRefTabStyleName = "ta_extref";
393 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_TABLE, sExternalRefTabStyleName);
395 sAttrName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_NAME));
396 sAttrStyleName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_STYLE_NAME));
397 sAttrColumnsRepeated = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_NUMBER_COLUMNS_REPEATED));
398 sAttrFormula = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_FORMULA));
399 sAttrStringValue = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_STRING_VALUE));
400 sAttrValueType = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_VALUE_TYPE));
401 sElemCell = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_TABLE_CELL));
402 sElemCoveredCell = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_COVERED_TABLE_CELL));
403 sElemCol = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_TABLE_COLUMN));
404 sElemRow = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_TABLE_ROW));
405 sElemTab = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_TABLE));
406 sElemP = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TEXT, GetXMLToken(XML_P));
410 ScXMLExport::~ScXMLExport()
412 pGroupColumns.reset();
413 pGroupRows.reset();
414 pColumnStyles.reset();
415 pRowStyles.reset();
416 pCellStyles.reset();
417 pRowFormatRanges.reset();
418 pMergedRangesContainer.reset();
419 pValidationsContainer.reset();
420 pChangeTrackingExportHelper.reset();
421 pDefaults.reset();
422 pNumberFormatAttributesExportHelper.reset();
425 void ScXMLExport::SetSourceStream( const uno::Reference<io::XInputStream>& xNewStream )
427 xSourceStream = xNewStream;
429 if ( xSourceStream.is() )
431 // make sure it's a plain UTF-8 stream as written by OOo itself
433 const sal_Char pXmlHeader[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
434 sal_Int32 nLen = strlen(pXmlHeader);
436 uno::Sequence<sal_Int8> aFileStart(nLen);
437 sal_Int32 nRead = xSourceStream->readBytes( aFileStart, nLen );
439 if ( nRead != nLen || memcmp( aFileStart.getConstArray(), pXmlHeader, nLen ) != 0 )
441 // invalid - ignore stream, save normally
442 xSourceStream.clear();
444 else
446 // keep track of the bytes already read
447 nSourceStreamPos = nRead;
449 const ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(GetModel())->GetSheetSaveData();
450 if (pSheetData)
452 // add the loaded namespaces to the name space map
454 if ( !pSheetData->AddLoadedNamespaces( GetNamespaceMap_() ) )
456 // conflicts in the namespaces - ignore the stream, save normally
457 xSourceStream.clear();
464 sal_Int32 ScXMLExport::GetNumberFormatStyleIndex(sal_Int32 nNumFmt) const
466 NumberFormatIndexMap::const_iterator itr = aNumFmtIndexMap.find(nNumFmt);
467 if (itr == aNumFmtIndexMap.end())
468 return -1;
470 return itr->second;
473 void ScXMLExport::CollectSharedData(SCTAB& nTableCount, sal_Int32& nShapesCount)
475 if (!GetModel().is())
476 return;
478 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc(GetModel(), uno::UNO_QUERY);
479 if (!xSpreadDoc.is())
480 return;
482 uno::Reference<container::XIndexAccess> xIndex(xSpreadDoc->getSheets(), uno::UNO_QUERY);
483 if (!xIndex.is())
484 return;
486 nTableCount = xIndex->getCount();
487 if (!pSharedData)
488 pSharedData.reset(new ScMySharedData(nTableCount));
490 pCellStyles->AddNewTable(nTableCount - 1);
492 for (SCTAB nTable = 0; nTable < nTableCount; ++nTable)
494 nCurrentTable = sal::static_int_cast<sal_uInt16>(nTable);
495 uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xIndex->getByIndex(nTable), uno::UNO_QUERY);
496 if (!xDrawPageSupplier.is())
497 continue;
499 uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage());
500 ScMyDrawPage aDrawPage;
501 aDrawPage.bHasForms = false;
502 aDrawPage.xDrawPage.set(xDrawPage);
503 pSharedData->AddDrawPage(aDrawPage, nTable);
504 if (!xDrawPage.is())
505 continue;
507 sal_Int32 nShapes = xDrawPage->getCount();
508 for (sal_Int32 nShape = 0; nShape < nShapes; ++nShape)
510 uno::Reference<drawing::XShape> xShape(xDrawPage->getByIndex(nShape), uno::UNO_QUERY);
511 if (!xShape.is())
512 continue;
514 uno::Reference<beans::XPropertySet> xShapeProp(xShape, uno::UNO_QUERY);
515 if (!xShapeProp.is())
516 continue;
518 sal_Int16 nLayerID = 0;
519 bool bExtracted = xShapeProp->getPropertyValue(gsLayerID) >>= nLayerID;
520 if (!bExtracted)
521 continue;
523 if ((SdrLayerID(nLayerID) == SC_LAYER_INTERN) || (SdrLayerID(nLayerID) == SC_LAYER_HIDDEN))
525 CollectInternalShape(xShape);
526 continue;
529 ++nShapesCount;
531 SvxShape* pShapeImp = comphelper::getUnoTunnelImplementation<SvxShape>(xShape);
532 if (!pShapeImp)
533 continue;
535 SdrObject* pSdrObj = pShapeImp->GetSdrObject();
536 if (!pSdrObj)
537 continue;
539 if (ScDrawObjData *pAnchor = ScDrawLayer::GetNonRotatedObjData(pSdrObj))
541 ScMyShape aMyShape;
542 aMyShape.aAddress = pAnchor->maStart;
543 SAL_WARN_IF(aMyShape.aAddress.Tab() != nTable, "sc", "not anchored to current sheet!");
544 aMyShape.aAddress.SetTab(nTable);
545 aMyShape.aEndAddress = pAnchor->maEnd;
546 aMyShape.aEndAddress.SetTab( nTable );
547 aMyShape.nEndX = pAnchor->maEndOffset.X();
548 aMyShape.nEndY = pAnchor->maEndOffset.Y();
549 aMyShape.xShape = xShape;
550 aMyShape.bResizeWithCell = ScDrawLayer::IsResizeWithCell(*pSdrObj);
551 pSharedData->AddNewShape(aMyShape);
552 pSharedData->SetLastColumn(nTable, pAnchor->maStart.Col());
553 pSharedData->SetLastRow(nTable, pAnchor->maStart.Row());
555 else
556 pSharedData->AddTableShape(nTable, xShape);
561 void ScXMLExport::CollectShapesAutoStyles(SCTAB nTableCount)
563 // #i84077# To avoid compiler warnings about uninitialized aShapeItr,
564 // it's initialized using this dummy list. The iterator contains shapes
565 // from all sheets, so it can't be declared inside the nTable loop where
566 // it is used.
567 ScMyShapeList aDummyInitList;
569 pSharedData->SortShapesContainer();
570 pSharedData->SortNoteShapes();
571 const ScMyShapeList* pShapeList(nullptr);
572 ScMyShapeList::const_iterator aShapeItr = aDummyInitList.end();
573 if (pSharedData->GetShapesContainer())
575 pShapeList = &pSharedData->GetShapesContainer()->GetShapes();
576 aShapeItr = pShapeList->begin();
578 if (pSharedData->HasDrawPage())
580 for (SCTAB nTable = 0; nTable < nTableCount; ++nTable)
582 uno::Reference<drawing::XDrawPage> xDrawPage(pSharedData->GetDrawPage(nTable));
584 if (xDrawPage.is())
586 GetShapeExport()->seekShapes(xDrawPage);
587 uno::Reference< form::XFormsSupplier2 > xFormsSupplier( xDrawPage, uno::UNO_QUERY );
588 if( xFormsSupplier.is() && xFormsSupplier->hasForms() )
590 GetFormExport()->examineForms(xDrawPage);
591 pSharedData->SetDrawPageHasForms(nTable, true);
593 ScMyTableShapes* pTableShapes(pSharedData->GetTableShapes());
594 if (pTableShapes)
596 for (const auto& rxShape : (*pTableShapes)[nTable])
598 GetShapeExport()->collectShapeAutoStyles(rxShape);
599 IncrementProgressBar(false);
602 if (pShapeList)
604 ScMyShapeList::const_iterator aEndItr(pShapeList->end());
605 while ( aShapeItr != aEndItr && ( aShapeItr->aAddress.Tab() == nTable ) )
607 GetShapeExport()->collectShapeAutoStyles(aShapeItr->xShape);
608 IncrementProgressBar(false);
609 ++aShapeItr;
612 if (pSharedData->GetNoteShapes())
614 const ScMyNoteShapeList& rNoteShapes = pSharedData->GetNoteShapes()->GetNotes();
615 for (const auto& rNoteShape : rNoteShapes)
617 if ( rNoteShape.aPos.Tab() == nTable )
618 GetShapeExport()->collectShapeAutoStyles(rNoteShape.xShape);
624 pSharedData->SortNoteShapes(); // sort twice, because some more shapes are added
627 void ScXMLExport::ExportMeta_()
629 sal_Int32 nCellCount(pDoc ? pDoc->GetCellCount() : 0);
630 SCTAB nTableCount(0);
631 sal_Int32 nShapesCount(0);
632 GetAutoStylePool()->ClearEntries();
633 CollectSharedData(nTableCount, nShapesCount);
635 uno::Sequence<beans::NamedValue> stats
637 { "TableCount", uno::makeAny(static_cast<sal_Int32>(nTableCount)) },
638 { "CellCount", uno::makeAny(nCellCount) },
639 { "ObjectCount", uno::makeAny(nShapesCount) }
642 // update document statistics at the model
643 uno::Reference<document::XDocumentPropertiesSupplier> xPropSup(GetModel(),
644 uno::UNO_QUERY_THROW);
645 uno::Reference<document::XDocumentProperties> xDocProps(
646 xPropSup->getDocumentProperties());
647 if (xDocProps.is()) {
648 xDocProps->setDocumentStatistics(stats);
651 // export document properties
652 SvXMLExport::ExportMeta_();
655 void ScXMLExport::ExportFontDecls_()
657 GetFontAutoStylePool(); // make sure the pool is created
658 SvXMLExport::ExportFontDecls_();
661 table::CellRangeAddress ScXMLExport::GetEndAddress(const uno::Reference<sheet::XSpreadsheet>& xTable)
663 table::CellRangeAddress aCellAddress;
664 uno::Reference<sheet::XSheetCellCursor> xCursor(xTable->createCursor());
665 uno::Reference<sheet::XUsedAreaCursor> xUsedArea (xCursor, uno::UNO_QUERY);
666 uno::Reference<sheet::XCellRangeAddressable> xCellAddress (xCursor, uno::UNO_QUERY);
667 if (xUsedArea.is() && xCellAddress.is())
669 xUsedArea->gotoEndOfUsedArea(true);
670 aCellAddress = xCellAddress->getRangeAddress();
672 return aCellAddress;
675 void ScXMLExport::GetAreaLinks( ScMyAreaLinksContainer& rAreaLinks )
677 if (pDoc->GetLinkManager())
679 const sfx2::SvBaseLinks& rLinks = pDoc->GetLinkManager()->GetLinks();
680 for (const auto & rLink : rLinks)
682 ScAreaLink *pLink = dynamic_cast<ScAreaLink*>(rLink.get());
683 if (pLink)
685 ScMyAreaLink aAreaLink;
686 aAreaLink.aDestRange = pLink->GetDestArea();
687 aAreaLink.sSourceStr = pLink->GetSource();
688 aAreaLink.sFilter = pLink->GetFilter();
689 aAreaLink.sFilterOptions = pLink->GetOptions();
690 aAreaLink.sURL = pLink->GetFile();
691 aAreaLink.nRefresh = pLink->GetRefreshDelay();
692 rAreaLinks.AddNewAreaLink( aAreaLink );
696 rAreaLinks.Sort();
699 // core implementation
700 void ScXMLExport::GetDetectiveOpList( ScMyDetectiveOpContainer& rDetOp )
702 if (pDoc)
704 ScDetOpList* pOpList(pDoc->GetDetOpList());
705 if( pOpList )
707 size_t nCount = pOpList->Count();
708 for (size_t nIndex = 0; nIndex < nCount; ++nIndex )
710 const ScDetOpData& rDetData = pOpList->GetObject( nIndex);
711 const ScAddress& rDetPos = rDetData.GetPos();
712 SCTAB nTab = rDetPos.Tab();
713 if ( nTab < pDoc->GetTableCount() )
715 rDetOp.AddOperation( rDetData.GetOperation(), rDetPos, static_cast<sal_uInt32>( nIndex) );
717 // cells with detective operations are written even if empty
718 pSharedData->SetLastColumn( nTab, rDetPos.Col() );
719 pSharedData->SetLastRow( nTab, rDetPos.Row() );
722 rDetOp.Sort();
727 void ScXMLExport::WriteSingleColumn(const sal_Int32 nRepeatColumns, const sal_Int32 nStyleIndex,
728 const sal_Int32 nIndex, const bool bIsAutoStyle, const bool bIsVisible)
730 CheckAttrList();
731 AddAttribute(sAttrStyleName, pColumnStyles->GetStyleNameByIndex(nStyleIndex));
732 if (!bIsVisible)
733 AddAttribute(XML_NAMESPACE_TABLE, XML_VISIBILITY, XML_COLLAPSE);
734 if (nRepeatColumns > 1)
736 OUString sOUEndCol(OUString::number(nRepeatColumns));
737 AddAttribute(sAttrColumnsRepeated, sOUEndCol);
739 if (nIndex != -1)
740 AddAttribute(XML_NAMESPACE_TABLE, XML_DEFAULT_CELL_STYLE_NAME, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
741 SvXMLElementExport aElemC(*this, sElemCol, true, true);
744 void ScXMLExport::WriteColumn(const sal_Int32 nColumn, const sal_Int32 nRepeatColumns,
745 const sal_Int32 nStyleIndex, const bool bIsVisible)
747 sal_Int32 nRepeat(1);
748 sal_Int32 nPrevIndex(pDefaults->GetColDefaults()[nColumn].nIndex);
749 bool bPrevAutoStyle(pDefaults->GetColDefaults()[nColumn].bIsAutoStyle);
750 for (sal_Int32 i = nColumn + 1; i < nColumn + nRepeatColumns; ++i)
752 if ((pDefaults->GetColDefaults()[i].nIndex != nPrevIndex) ||
753 (pDefaults->GetColDefaults()[i].bIsAutoStyle != bPrevAutoStyle))
755 WriteSingleColumn(nRepeat, nStyleIndex, nPrevIndex, bPrevAutoStyle, bIsVisible);
756 nPrevIndex = pDefaults->GetColDefaults()[i].nIndex;
757 bPrevAutoStyle = pDefaults->GetColDefaults()[i].bIsAutoStyle;
758 nRepeat = 1;
760 else
761 ++nRepeat;
763 WriteSingleColumn(nRepeat, nStyleIndex, nPrevIndex, bPrevAutoStyle, bIsVisible);
766 void ScXMLExport::OpenHeaderColumn()
768 StartElement( XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS, true );
771 void ScXMLExport::CloseHeaderColumn()
773 EndElement(XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS, true);
776 void ScXMLExport::ExportColumns(const sal_Int32 nTable, const ScRange& aColumnHeaderRange, const bool bHasColumnHeader)
778 sal_Int32 nColsRepeated (1);
779 sal_Int32 nIndex;
780 sal_Int32 nPrevColumn(0);
781 bool bPrevIsVisible (true);
782 bool bWasHeader (false);
783 bool bIsClosed (true);
784 sal_Int32 nPrevIndex (-1);
785 sal_Int32 nColumn;
786 for (nColumn = 0; nColumn <= pSharedData->GetLastColumn(nTable); ++nColumn)
788 CheckAttrList();
789 bool bIsVisible(true);
790 nIndex = pColumnStyles->GetStyleNameIndex(nTable, nColumn, bIsVisible);
792 const bool bIsHeader = bHasColumnHeader && (aColumnHeaderRange.aStart.Col() <= nColumn) && (nColumn <= aColumnHeaderRange.aEnd.Col());
793 if (bIsHeader != bWasHeader)
795 if (bIsHeader)
797 if (nColumn > 0)
799 WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
800 if (pGroupColumns->IsGroupEnd(nColumn - 1))
801 pGroupColumns->CloseGroups(nColumn - 1);
803 bPrevIsVisible = bIsVisible;
804 nPrevIndex = nIndex;
805 nPrevColumn = nColumn;
806 nColsRepeated = 1;
807 if(pGroupColumns->IsGroupStart(nColumn))
808 pGroupColumns->OpenGroups(nColumn);
809 OpenHeaderColumn();
810 bWasHeader = true;
811 bIsClosed = false;
813 else
815 WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
816 CloseHeaderColumn();
817 if (pGroupColumns->IsGroupEnd(nColumn - 1))
818 pGroupColumns->CloseGroups(nColumn - 1);
819 if(pGroupColumns->IsGroupStart(nColumn))
820 pGroupColumns->OpenGroups(nColumn);
821 bPrevIsVisible = bIsVisible;
822 nPrevIndex = nIndex;
823 nPrevColumn = nColumn;
824 nColsRepeated = 1;
825 bWasHeader = false;
826 bIsClosed = true;
829 else if (nColumn == 0)
831 if (pGroupColumns->IsGroupStart(nColumn))
832 pGroupColumns->OpenGroups(nColumn);
833 bPrevIsVisible = bIsVisible;
834 nPrevIndex = nIndex;
836 else if ((bIsVisible == bPrevIsVisible) && (nIndex == nPrevIndex) &&
837 !pGroupColumns->IsGroupStart(nColumn) && !pGroupColumns->IsGroupEnd(nColumn - 1))
838 ++nColsRepeated;
839 else
841 WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
842 if (pGroupColumns->IsGroupEnd(nColumn - 1))
844 if (bIsHeader)
845 CloseHeaderColumn();
846 pGroupColumns->CloseGroups(nColumn - 1);
847 if (bIsHeader)
848 OpenHeaderColumn();
850 if (pGroupColumns->IsGroupStart(nColumn))
852 if (bIsHeader)
853 CloseHeaderColumn();
854 pGroupColumns->OpenGroups(nColumn);
855 if (bIsHeader)
856 OpenHeaderColumn();
858 bPrevIsVisible = bIsVisible;
859 nPrevIndex = nIndex;
860 nPrevColumn = nColumn;
861 nColsRepeated = 1;
864 assert(nPrevIndex >= 0 && "coverity#1438402");
865 WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
866 if (!bIsClosed)
867 CloseHeaderColumn();
868 if (pGroupColumns->IsGroupEnd(nColumn - 1))
869 pGroupColumns->CloseGroups(nColumn - 1);
872 void ScXMLExport::ExportExternalRefCacheStyles()
874 sal_Int32 nEntryIndex = GetCellStylesPropertySetMapper()->FindEntryIndex(
875 "NumberFormat", XML_NAMESPACE_STYLE, "data-style-name");
877 if (nEntryIndex < 0)
878 // No entry index for the number format is found.
879 return;
881 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
882 if (!pRefMgr->hasExternalData())
883 // No external reference data cached.
884 return;
886 // Export each unique number format used in the external ref cache.
887 vector<sal_uInt32> aNumFmts;
888 pRefMgr->getAllCachedNumberFormats(aNumFmts);
889 const OUString aDefaultStyle = OUString("Default").intern();
890 for (const auto& rNumFmt : aNumFmts)
892 sal_Int32 nNumFmt = static_cast<sal_Int32>(rNumFmt);
894 addDataStyle(nNumFmt);
896 uno::Any aVal;
897 aVal <<= nNumFmt;
898 vector<XMLPropertyState> aProps;
899 aVal <<= aDefaultStyle;
900 aProps.emplace_back(nEntryIndex, aVal);
902 OUString aName;
903 sal_Int32 nIndex;
904 if (GetAutoStylePool()->Add(aName, XML_STYLE_FAMILY_TABLE_CELL, aDefaultStyle, aProps))
906 pCellStyles->AddStyleName(aName, nIndex);
908 else
910 bool bIsAuto;
911 nIndex = pCellStyles->GetIndexOfStyleName(
912 aName, XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX, bIsAuto);
915 // store the number format to index mapping for later use.
916 aNumFmtIndexMap.emplace(nNumFmt, nIndex);
920 namespace {
922 void handleFont(
923 std::vector<XMLPropertyState>& rPropStates,
924 const SfxPoolItem* p, const rtl::Reference<XMLPropertySetMapper>& xMapper, const OUString& rXMLName )
926 sal_Int32 nEntryCount = xMapper->GetEntryCount();
928 // Apparently font info needs special handling.
929 const SvxFontItem* pItem = static_cast<const SvxFontItem*>(p);
931 sal_Int32 nIndexFontName = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, rXMLName, 0);
933 if (nIndexFontName == -1 || nIndexFontName >= nEntryCount)
934 return;
936 uno::Any aAny;
937 if (!pItem->QueryValue(aAny, MID_FONT_FAMILY_NAME))
938 return;
940 rPropStates.emplace_back(nIndexFontName, aAny);
943 const SvxFieldData* toXMLPropertyStates(
944 std::vector<XMLPropertyState>& rPropStates, const std::vector<const SfxPoolItem*>& rSecAttrs,
945 const rtl::Reference<XMLPropertySetMapper>& xMapper, const ScXMLEditAttributeMap& rAttrMap )
947 const SvxFieldData* pField = nullptr;
948 sal_Int32 nEntryCount = xMapper->GetEntryCount();
949 rPropStates.reserve(rSecAttrs.size());
950 for (const SfxPoolItem* p : rSecAttrs)
952 if (p->Which() == EE_FEATURE_FIELD)
954 pField = static_cast<const SvxFieldItem*>(p)->GetField();
955 continue;
958 const ScXMLEditAttributeMap::Entry* pEntry = rAttrMap.getEntryByItemID(p->Which());
959 if (!pEntry)
960 continue;
962 sal_Int32 nIndex = xMapper->GetEntryIndex(
963 pEntry->nmXMLNS, OUString::createFromAscii(pEntry->mpXMLName), 0);
965 if (nIndex == -1 || nIndex >= nEntryCount)
966 continue;
968 uno::Any aAny;
969 switch (p->Which())
971 case EE_CHAR_FONTINFO:
972 handleFont(rPropStates, p, xMapper, "font-name");
973 break;
974 case EE_CHAR_FONTINFO_CJK:
975 handleFont(rPropStates, p, xMapper, "font-name-asian");
976 break;
977 case EE_CHAR_FONTINFO_CTL:
978 handleFont(rPropStates, p, xMapper, "font-name-complex");
979 break;
980 case EE_CHAR_WEIGHT:
981 case EE_CHAR_WEIGHT_CJK:
982 case EE_CHAR_WEIGHT_CTL:
984 if (!static_cast<const SvxWeightItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
985 continue;
987 rPropStates.emplace_back(nIndex, aAny);
989 break;
990 case EE_CHAR_FONTHEIGHT:
991 case EE_CHAR_FONTHEIGHT_CJK:
992 case EE_CHAR_FONTHEIGHT_CTL:
994 if (!static_cast<const SvxFontHeightItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
995 continue;
997 rPropStates.emplace_back(nIndex, aAny);
999 break;
1000 case EE_CHAR_ITALIC:
1001 case EE_CHAR_ITALIC_CJK:
1002 case EE_CHAR_ITALIC_CTL:
1004 if (!static_cast<const SvxPostureItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1005 continue;
1007 rPropStates.emplace_back(nIndex, aAny);
1009 break;
1010 case EE_CHAR_UNDERLINE:
1012 // Underline attribute needs to export multiple entries.
1013 sal_Int32 nIndexStyle = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-underline-style", 0);
1014 if (nIndexStyle == -1 || nIndexStyle > nEntryCount)
1015 break;
1017 sal_Int32 nIndexWidth = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-underline-width", 0);
1018 if (nIndexWidth == -1 || nIndexWidth > nEntryCount)
1019 break;
1021 sal_Int32 nIndexType = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-underline-type", 0);
1022 if (nIndexType == -1 || nIndexType > nEntryCount)
1023 break;
1025 sal_Int32 nIndexColor = xMapper->FindEntryIndex("CharUnderlineColor", XML_NAMESPACE_STYLE, "text-underline-color");
1026 if (nIndexColor == -1 || nIndexColor > nEntryCount)
1027 break;
1029 sal_Int32 nIndexHasColor = xMapper->FindEntryIndex("CharUnderlineHasColor", XML_NAMESPACE_STYLE, "text-underline-color");
1030 if (nIndexHasColor == -1 || nIndexHasColor > nEntryCount)
1031 break;
1033 const SvxUnderlineItem* pUL = static_cast<const SvxUnderlineItem*>(p);
1034 pUL->QueryValue(aAny, MID_TL_STYLE);
1035 rPropStates.emplace_back(nIndexStyle, aAny);
1036 rPropStates.emplace_back(nIndexType, aAny);
1037 rPropStates.emplace_back(nIndexWidth, aAny);
1039 pUL->QueryValue(aAny, MID_TL_COLOR);
1040 rPropStates.emplace_back(nIndexColor, aAny);
1042 pUL->QueryValue(aAny, MID_TL_HASCOLOR);
1043 rPropStates.emplace_back(nIndexHasColor, aAny);
1045 break;
1046 case EE_CHAR_OVERLINE:
1048 // Same with overline. Do just as we do with underline attributes.
1049 sal_Int32 nIndexStyle = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-overline-style", 0);
1050 if (nIndexStyle == -1 || nIndexStyle > nEntryCount)
1051 break;
1053 sal_Int32 nIndexWidth = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-overline-width", 0);
1054 if (nIndexWidth == -1 || nIndexWidth > nEntryCount)
1055 break;
1057 sal_Int32 nIndexType = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-overline-type", 0);
1058 if (nIndexType == -1 || nIndexType > nEntryCount)
1059 break;
1061 sal_Int32 nIndexColor = xMapper->FindEntryIndex("CharOverlineColor", XML_NAMESPACE_STYLE, "text-overline-color");
1062 if (nIndexColor == -1 || nIndexColor > nEntryCount)
1063 break;
1065 sal_Int32 nIndexHasColor = xMapper->FindEntryIndex("CharOverlineHasColor", XML_NAMESPACE_STYLE, "text-overline-color");
1066 if (nIndexHasColor == -1 || nIndexHasColor > nEntryCount)
1067 break;
1069 const SvxOverlineItem* pOL = static_cast<const SvxOverlineItem*>(p);
1070 pOL->QueryValue(aAny, MID_TL_STYLE);
1071 rPropStates.emplace_back(nIndexStyle, aAny);
1072 rPropStates.emplace_back(nIndexType, aAny);
1073 rPropStates.emplace_back(nIndexWidth, aAny);
1075 pOL->QueryValue(aAny, MID_TL_COLOR);
1076 rPropStates.emplace_back(nIndexColor, aAny);
1078 pOL->QueryValue(aAny, MID_TL_HASCOLOR);
1079 rPropStates.emplace_back(nIndexHasColor, aAny);
1081 break;
1082 case EE_CHAR_COLOR:
1084 if (!static_cast<const SvxColorItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1085 continue;
1087 ::Color nColor;
1088 if ( aAny >>= nColor )
1090 sal_Int32 nIndexColor = ( nColor == COL_AUTO ) ? xMapper->GetEntryIndex(
1091 XML_NAMESPACE_STYLE, GetXMLToken( XML_USE_WINDOW_FONT_COLOR ), 0 ) : nIndex;
1092 rPropStates.emplace_back( nIndexColor, aAny );
1095 break;
1096 case EE_CHAR_WLM:
1098 if (!static_cast<const SvxWordLineModeItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1099 continue;
1101 rPropStates.emplace_back(nIndex, aAny);
1103 break;
1104 case EE_CHAR_STRIKEOUT:
1106 if (!static_cast<const SvxCrossedOutItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1107 continue;
1109 rPropStates.emplace_back(nIndex, aAny);
1111 break;
1112 case EE_CHAR_RELIEF:
1114 if (!static_cast<const SvxCharReliefItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1115 continue;
1117 rPropStates.emplace_back(nIndex, aAny);
1119 break;
1120 case EE_CHAR_OUTLINE:
1122 if (!static_cast<const SvxContourItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1123 continue;
1125 rPropStates.emplace_back(nIndex, aAny);
1127 break;
1128 case EE_CHAR_SHADOW:
1130 if (!static_cast<const SvxShadowedItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1131 continue;
1133 rPropStates.emplace_back(nIndex, aAny);
1135 break;
1136 case EE_CHAR_KERNING:
1138 if (!static_cast<const SvxKerningItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1139 continue;
1141 rPropStates.emplace_back(nIndex, aAny);
1143 break;
1144 case EE_CHAR_PAIRKERNING:
1146 if (!static_cast<const SvxAutoKernItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1147 continue;
1149 rPropStates.emplace_back(nIndex, aAny);
1151 break;
1152 case EE_CHAR_FONTWIDTH:
1154 if (!static_cast<const SvxCharScaleWidthItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1155 continue;
1157 rPropStates.emplace_back(nIndex, aAny);
1159 break;
1160 case EE_CHAR_ESCAPEMENT:
1162 sal_Int32 nIndexEsc = xMapper->FindEntryIndex("CharEscapement", XML_NAMESPACE_STYLE, "text-position");
1163 if (nIndexEsc == -1 || nIndexEsc > nEntryCount)
1164 break;
1166 sal_Int32 nIndexEscHeight = xMapper->FindEntryIndex("CharEscapementHeight", XML_NAMESPACE_STYLE, "text-position");
1167 if (nIndexEscHeight == -1 || nIndexEscHeight > nEntryCount)
1168 break;
1170 const SvxEscapementItem* pEsc = static_cast<const SvxEscapementItem*>(p);
1172 pEsc->QueryValue(aAny);
1173 rPropStates.emplace_back(nIndexEsc, aAny);
1175 pEsc->QueryValue(aAny, MID_ESC_HEIGHT);
1176 rPropStates.emplace_back(nIndexEscHeight, aAny);
1179 break;
1180 case EE_CHAR_EMPHASISMARK:
1182 if (!static_cast<const SvxEmphasisMarkItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1183 continue;
1185 rPropStates.emplace_back(nIndex, aAny);
1187 break;
1188 case EE_CHAR_LANGUAGE:
1189 case EE_CHAR_LANGUAGE_CJK:
1190 case EE_CHAR_LANGUAGE_CTL:
1192 if (!static_cast<const SvxLanguageItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1193 continue;
1195 // Export multiple entries.
1196 sal_Int32 nIndexLanguage, nIndexCountry, nIndexScript, nIndexTag;
1197 switch (p->Which())
1199 case EE_CHAR_LANGUAGE:
1200 nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_FO, "language", 0);
1201 nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_FO, "country", 0);
1202 nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_FO, "script", 0);
1203 nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "rfc-language-tag", 0);
1204 break;
1205 case EE_CHAR_LANGUAGE_CJK:
1206 nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "language-asian", 0);
1207 nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "country-asian", 0);
1208 nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "script-asian", 0);
1209 nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "rfc-language-tag-asian", 0);
1210 break;
1211 case EE_CHAR_LANGUAGE_CTL:
1212 nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "language-complex", 0);
1213 nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "country-complex", 0);
1214 nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "script-complex", 0);
1215 nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "rfc-language-tag-complex", 0);
1216 break;
1217 default:
1218 nIndexLanguage = nIndexCountry = nIndexScript = nIndexTag = -1;
1220 assert( nIndexLanguage >= 0 && nIndexCountry >= 0 && nIndexScript >= 0 && nIndexTag >= 0);
1221 rPropStates.emplace_back( nIndexLanguage, aAny);
1222 rPropStates.emplace_back( nIndexCountry, aAny);
1223 rPropStates.emplace_back( nIndexScript, aAny);
1224 rPropStates.emplace_back( nIndexTag, aAny);
1226 break;
1227 default:
1228 continue;
1232 return pField;
1237 void ScXMLExport::ExportCellTextAutoStyles(sal_Int32 nTable)
1239 if (!ValidTab(nTable))
1240 return;
1242 rtl::Reference<XMLPropertySetMapper> xMapper = GetTextParagraphExport()->GetTextPropMapper()->getPropertySetMapper();
1243 rtl::Reference<SvXMLAutoStylePoolP> xStylePool = GetAutoStylePool();
1244 const ScXMLEditAttributeMap& rAttrMap = GetEditAttributeMap();
1246 sc::EditTextIterator aIter(*pDoc, nTable);
1247 sal_Int32 nCellCount = 0;
1248 for (const EditTextObject* pEdit = aIter.first(); pEdit; pEdit = aIter.next(), ++nCellCount)
1250 std::vector<editeng::Section> aAttrs;
1251 pEdit->GetAllSections(aAttrs);
1252 if (aAttrs.empty())
1253 continue;
1255 for (const auto& rSec : aAttrs)
1257 const std::vector<const SfxPoolItem*>& rSecAttrs = rSec.maAttributes;
1258 if (rSecAttrs.empty())
1259 // No formats applied to this section. Skip it.
1260 continue;
1262 std::vector<XMLPropertyState> aPropStates;
1263 toXMLPropertyStates(aPropStates, rSecAttrs, xMapper, rAttrMap);
1264 if (!aPropStates.empty())
1265 xStylePool->Add(XML_STYLE_FAMILY_TEXT_TEXT, OUString(), aPropStates);
1269 GetProgressBarHelper()->ChangeReference(GetProgressBarHelper()->GetReference() + nCellCount);
1272 void ScXMLExport::WriteRowContent()
1274 ScMyRowFormatRange aRange;
1275 sal_Int32 nIndex(-1);
1276 #if OSL_DEBUG_LEVEL > 0
1277 sal_Int32 nPrevCol(0);
1278 #endif
1279 sal_Int32 nCols(0);
1280 sal_Int32 nPrevValidationIndex(-1);
1281 bool bIsAutoStyle(true);
1282 bool bIsFirst(true);
1283 while (pRowFormatRanges->GetNext(aRange))
1285 #if OSL_DEBUG_LEVEL > 0
1286 OSL_ENSURE(bIsFirst || (!bIsFirst && (nPrevCol + nCols == aRange.nStartColumn)), "here are some columns missing");
1287 #endif
1288 if (bIsFirst)
1290 nIndex = aRange.nIndex;
1291 nPrevValidationIndex = aRange.nValidationIndex;
1292 bIsAutoStyle = aRange.bIsAutoStyle;
1293 nCols = aRange.nRepeatColumns;
1294 bIsFirst = false;
1295 #if OSL_DEBUG_LEVEL > 0
1296 nPrevCol = aRange.nStartColumn;
1297 #endif
1299 else
1301 if (((aRange.nIndex == nIndex && aRange.bIsAutoStyle == bIsAutoStyle) ||
1302 (aRange.nIndex == nIndex && nIndex == -1)) &&
1303 nPrevValidationIndex == aRange.nValidationIndex)
1304 nCols += aRange.nRepeatColumns;
1305 else
1307 if (nIndex != -1)
1308 AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
1309 if (nPrevValidationIndex > -1)
1310 AddAttribute(XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, pValidationsContainer->GetValidationName(nPrevValidationIndex));
1311 if (nCols > 1)
1313 AddAttribute(sAttrColumnsRepeated, OUString::number(nCols));
1315 SvXMLElementExport aElemC(*this, sElemCell, true, true);
1316 nIndex = aRange.nIndex;
1317 bIsAutoStyle = aRange.bIsAutoStyle;
1318 nCols = aRange.nRepeatColumns;
1319 nPrevValidationIndex = aRange.nValidationIndex;
1320 #if OSL_DEBUG_LEVEL > 0
1321 nPrevCol = aRange.nStartColumn;
1322 #endif
1326 if (!bIsFirst)
1328 if (nIndex != -1)
1329 AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
1330 if (nPrevValidationIndex > -1)
1331 AddAttribute(XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, pValidationsContainer->GetValidationName(nPrevValidationIndex));
1332 if (nCols > 1)
1334 AddAttribute(sAttrColumnsRepeated, OUString::number(nCols));
1336 SvXMLElementExport aElemC(*this, sElemCell, true, true);
1340 void ScXMLExport::WriteRowStartTag(
1341 const sal_Int32 nIndex, const sal_Int32 nEqualRows,
1342 bool bHidden, bool bFiltered)
1344 AddAttribute(sAttrStyleName, pRowStyles->GetStyleNameByIndex(nIndex));
1345 if (bHidden)
1347 if (bFiltered)
1348 AddAttribute(XML_NAMESPACE_TABLE, XML_VISIBILITY, XML_FILTER);
1349 else
1350 AddAttribute(XML_NAMESPACE_TABLE, XML_VISIBILITY, XML_COLLAPSE);
1352 if (nEqualRows > 1)
1354 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, OUString::number(nEqualRows));
1357 StartElement( sElemRow, true);
1360 void ScXMLExport::OpenHeaderRows()
1362 StartElement( XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, true);
1363 bRowHeaderOpen = true;
1366 void ScXMLExport::CloseHeaderRows()
1368 EndElement(XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, true);
1371 void ScXMLExport::OpenNewRow(
1372 const sal_Int32 nIndex, const sal_Int32 nStartRow, const sal_Int32 nEqualRows,
1373 bool bHidden, bool bFiltered)
1375 nOpenRow = nStartRow;
1376 if (pGroupRows->IsGroupStart(nStartRow))
1378 if (bHasRowHeader && bRowHeaderOpen)
1379 CloseHeaderRows();
1380 pGroupRows->OpenGroups(nStartRow);
1381 if (bHasRowHeader && bRowHeaderOpen)
1382 OpenHeaderRows();
1384 if (bHasRowHeader && !bRowHeaderOpen && nStartRow >= aRowHeaderRange.aStart.Row() && nStartRow <= aRowHeaderRange.aEnd.Row())
1386 if (nStartRow == aRowHeaderRange.aStart.Row())
1387 OpenHeaderRows();
1388 sal_Int32 nEquals;
1389 if (aRowHeaderRange.aEnd.Row() < nStartRow + nEqualRows - 1)
1390 nEquals = aRowHeaderRange.aEnd.Row() - nStartRow + 1;
1391 else
1392 nEquals = nEqualRows;
1393 WriteRowStartTag(nIndex, nEquals, bHidden, bFiltered);
1394 nOpenRow = nStartRow + nEquals - 1;
1395 if (nEquals < nEqualRows)
1397 CloseRow(nStartRow + nEquals - 1);
1398 WriteRowStartTag(nIndex, nEqualRows - nEquals, bHidden, bFiltered);
1399 nOpenRow = nStartRow + nEqualRows - 1;
1402 else
1403 WriteRowStartTag(nIndex, nEqualRows, bHidden, bFiltered);
1406 void ScXMLExport::OpenAndCloseRow(
1407 const sal_Int32 nIndex, const sal_Int32 nStartRow, const sal_Int32 nEqualRows,
1408 bool bHidden, bool bFiltered)
1410 OpenNewRow(nIndex, nStartRow, nEqualRows, bHidden, bFiltered);
1411 WriteRowContent();
1412 CloseRow(nStartRow + nEqualRows - 1);
1413 pRowFormatRanges->Clear();
1416 void ScXMLExport::OpenRow(const sal_Int32 nTable, const sal_Int32 nStartRow, const sal_Int32 nRepeatRow, ScXMLCachedRowAttrAccess& rRowAttr)
1418 if (nRepeatRow > 1)
1420 sal_Int32 nPrevIndex(0), nIndex;
1421 bool bPrevHidden = false;
1422 bool bPrevFiltered = false;
1423 bool bHidden = false;
1424 bool bFiltered = false;
1425 sal_Int32 nEqualRows(1);
1426 sal_Int32 nEndRow(nStartRow + nRepeatRow);
1427 sal_Int32 nEndRowHidden = nStartRow - 1;
1428 sal_Int32 nEndRowFiltered = nStartRow - 1;
1429 sal_Int32 nRow;
1430 for (nRow = nStartRow; nRow < nEndRow; ++nRow)
1432 if (nRow == nStartRow)
1434 nPrevIndex = pRowStyles->GetStyleNameIndex(nTable, nRow);
1435 if (pDoc)
1437 if (nRow > nEndRowHidden)
1439 bPrevHidden = rRowAttr.rowHidden(nTable, nRow, nEndRowHidden);
1440 bHidden = bPrevHidden;
1442 if (nRow > nEndRowFiltered)
1444 bPrevFiltered = rRowAttr.rowFiltered(nTable, nRow, nEndRowFiltered);
1445 bFiltered = bPrevFiltered;
1450 else
1452 nIndex = pRowStyles->GetStyleNameIndex(nTable, nRow);
1453 if (pDoc)
1455 if (nRow > nEndRowHidden)
1456 bHidden = rRowAttr.rowHidden(nTable, nRow, nEndRowHidden);
1457 if (nRow > nEndRowFiltered)
1458 bFiltered = rRowAttr.rowFiltered(nTable, nRow, nEndRowFiltered);
1460 if (nIndex == nPrevIndex && bHidden == bPrevHidden && bFiltered == bPrevFiltered &&
1461 !(bHasRowHeader && ((nRow == aRowHeaderRange.aStart.Row()) || (nRow - 1 == aRowHeaderRange.aEnd.Row()))) &&
1462 !(pGroupRows->IsGroupStart(nRow)) &&
1463 !(pGroupRows->IsGroupEnd(nRow - 1)))
1464 ++nEqualRows;
1465 else
1467 assert(nPrevIndex >= 0 && "coverity#1438402");
1468 ScRowFormatRanges* pTempRowFormatRanges = new ScRowFormatRanges(pRowFormatRanges.get());
1469 OpenAndCloseRow(nPrevIndex, nRow - nEqualRows, nEqualRows, bPrevHidden, bPrevFiltered);
1470 pRowFormatRanges.reset(pTempRowFormatRanges);
1471 nEqualRows = 1;
1472 nPrevIndex = nIndex;
1473 bPrevHidden = bHidden;
1474 bPrevFiltered = bFiltered;
1478 assert(nPrevIndex >= 0 && "coverity#1438402");
1479 OpenNewRow(nPrevIndex, nRow - nEqualRows, nEqualRows, bPrevHidden, bPrevFiltered);
1481 else
1483 sal_Int32 nIndex = pRowStyles->GetStyleNameIndex(nTable, nStartRow);
1484 bool bHidden = false;
1485 bool bFiltered = false;
1486 if (pDoc)
1488 sal_Int32 nEndRowHidden;
1489 sal_Int32 nEndRowFiltered;
1490 bHidden = rRowAttr.rowHidden(nTable, nStartRow, nEndRowHidden);
1491 bFiltered = rRowAttr.rowFiltered(nTable, nStartRow, nEndRowFiltered);
1493 assert(nIndex >= 0 && "coverity#1438402");
1494 OpenNewRow(nIndex, nStartRow, 1, bHidden, bFiltered);
1496 nOpenRow = nStartRow + nRepeatRow - 1;
1499 void ScXMLExport::CloseRow(const sal_Int32 nRow)
1501 if (nOpenRow > -1)
1503 EndElement(sElemRow, true);
1504 if (bHasRowHeader && nRow == aRowHeaderRange.aEnd.Row())
1506 CloseHeaderRows();
1507 bRowHeaderOpen = false;
1509 if (pGroupRows->IsGroupEnd(nRow))
1511 if (bHasRowHeader && bRowHeaderOpen)
1512 CloseHeaderRows();
1513 pGroupRows->CloseGroups(nRow);
1514 if (bHasRowHeader && bRowHeaderOpen)
1515 OpenHeaderRows();
1518 nOpenRow = -1;
1521 void ScXMLExport::ExportFormatRanges(const sal_Int32 nStartCol, const sal_Int32 nStartRow,
1522 const sal_Int32 nEndCol, const sal_Int32 nEndRow, const sal_Int32 nSheet)
1524 pRowFormatRanges->Clear();
1525 ScXMLCachedRowAttrAccess aRowAttr(pDoc);
1526 if (nStartRow == nEndRow)
1528 pCellStyles->GetFormatRanges(nStartCol, nEndCol, nStartRow, nSheet, pRowFormatRanges.get());
1529 if (nOpenRow == - 1)
1530 OpenRow(nSheet, nStartRow, 1, aRowAttr);
1531 WriteRowContent();
1532 pRowFormatRanges->Clear();
1534 else
1536 if (nOpenRow > -1)
1538 pCellStyles->GetFormatRanges(nStartCol, pSharedData->GetLastColumn(nSheet), nStartRow, nSheet, pRowFormatRanges.get());
1539 WriteRowContent();
1540 CloseRow(nStartRow);
1541 sal_Int32 nRows(1);
1542 sal_Int32 nTotalRows(nEndRow - nStartRow + 1 - 1);
1543 while (nRows < nTotalRows)
1545 pRowFormatRanges->Clear();
1546 pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1547 sal_Int32 nMaxRows = pRowFormatRanges->GetMaxRows();
1548 OSL_ENSURE(nMaxRows, "something went wrong");
1549 if (nMaxRows >= nTotalRows - nRows)
1551 OpenRow(nSheet, nStartRow + nRows, nTotalRows - nRows, aRowAttr);
1552 nRows += nTotalRows - nRows;
1554 else
1556 OpenRow(nSheet, nStartRow + nRows, nMaxRows, aRowAttr);
1557 nRows += nMaxRows;
1559 if (!pRowFormatRanges->GetSize())
1560 pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1561 WriteRowContent();
1562 CloseRow(nStartRow + nRows - 1);
1564 if (nTotalRows == 1)
1565 CloseRow(nStartRow);
1566 OpenRow(nSheet, nEndRow, 1, aRowAttr);
1567 pRowFormatRanges->Clear();
1568 pCellStyles->GetFormatRanges(0, nEndCol, nEndRow, nSheet, pRowFormatRanges.get());
1569 WriteRowContent();
1571 else
1573 sal_Int32 nRows(0);
1574 sal_Int32 nTotalRows(nEndRow - nStartRow + 1 - 1);
1575 while (nRows < nTotalRows)
1577 pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1578 sal_Int32 nMaxRows = pRowFormatRanges->GetMaxRows();
1579 OSL_ENSURE(nMaxRows, "something went wrong");
1580 if (nMaxRows >= nTotalRows - nRows)
1582 OpenRow(nSheet, nStartRow + nRows, nTotalRows - nRows, aRowAttr);
1583 nRows += nTotalRows - nRows;
1585 else
1587 OpenRow(nSheet, nStartRow + nRows, nMaxRows, aRowAttr);
1588 nRows += nMaxRows;
1590 if (!pRowFormatRanges->GetSize())
1591 pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1592 WriteRowContent();
1593 CloseRow(nStartRow + nRows - 1);
1595 OpenRow(nSheet, nEndRow, 1, aRowAttr);
1596 pRowFormatRanges->Clear();
1597 pCellStyles->GetFormatRanges(0, nEndCol, nEndRow, nSheet, pRowFormatRanges.get());
1598 WriteRowContent();
1603 void ScXMLExport::GetColumnRowHeader(bool& rHasColumnHeader, ScRange& rColumnHeaderRange,
1604 bool& rHasRowHeader, ScRange& rRowHeaderRange,
1605 OUString& rPrintRanges) const
1607 uno::Reference <sheet::XPrintAreas> xPrintAreas (xCurrentTable, uno::UNO_QUERY);
1608 if (xPrintAreas.is())
1610 rHasRowHeader = xPrintAreas->getPrintTitleRows();
1611 rHasColumnHeader = xPrintAreas->getPrintTitleColumns();
1612 table::CellRangeAddress rTempRowHeaderRange = xPrintAreas->getTitleRows();
1613 rRowHeaderRange = ScRange(rTempRowHeaderRange.StartColumn,
1614 rTempRowHeaderRange.StartRow,
1615 rTempRowHeaderRange.Sheet,
1616 rTempRowHeaderRange.EndColumn,
1617 rTempRowHeaderRange.EndRow,
1618 rTempRowHeaderRange.Sheet);
1619 table::CellRangeAddress rTempColumnHeaderRange = xPrintAreas->getTitleColumns();
1620 rColumnHeaderRange = ScRange(rTempColumnHeaderRange.StartColumn,
1621 rTempColumnHeaderRange.StartRow,
1622 rTempColumnHeaderRange.Sheet,
1623 rTempColumnHeaderRange.EndColumn,
1624 rTempColumnHeaderRange.EndRow,
1625 rTempColumnHeaderRange.Sheet);
1626 uno::Sequence< table::CellRangeAddress > aRangeList( xPrintAreas->getPrintAreas() );
1627 ScRangeStringConverter::GetStringFromRangeList( rPrintRanges, aRangeList, pDoc, FormulaGrammar::CONV_OOO );
1631 void ScXMLExport::FillFieldGroup(ScOutlineArray* pFields, ScMyOpenCloseColumnRowGroup* pGroups)
1633 size_t nDepth = pFields->GetDepth();
1634 for (size_t i = 0; i < nDepth; ++i)
1636 size_t nFields = pFields->GetCount(i);
1637 for (size_t j = 0; j < nFields; ++j)
1639 ScMyColumnRowGroup aGroup;
1640 const ScOutlineEntry* pEntry = pFields->GetEntry(i, j);
1641 aGroup.nField = pEntry->GetStart();
1642 aGroup.nLevel = static_cast<sal_Int16>(i);
1643 aGroup.bDisplay = !(pEntry->IsHidden());
1644 pGroups->AddGroup(aGroup, pEntry->GetEnd());
1647 if (nDepth)
1648 pGroups->Sort();
1651 void ScXMLExport::FillColumnRowGroups()
1653 if (pDoc)
1655 ScOutlineTable* pOutlineTable = pDoc->GetOutlineTable( static_cast<SCTAB>(nCurrentTable) );
1656 if(pOutlineTable)
1658 ScOutlineArray& rCols(pOutlineTable->GetColArray());
1659 ScOutlineArray& rRows(pOutlineTable->GetRowArray());
1660 FillFieldGroup(&rCols, pGroupColumns.get());
1661 FillFieldGroup(&rRows, pGroupRows.get());
1662 pSharedData->SetLastColumn(nCurrentTable, pGroupColumns->GetLast());
1663 pSharedData->SetLastRow(nCurrentTable, pGroupRows->GetLast());
1668 void ScXMLExport::SetBodyAttributes()
1670 if (pDoc && pDoc->IsDocProtected())
1672 AddAttribute(XML_NAMESPACE_TABLE, XML_STRUCTURE_PROTECTED, XML_TRUE);
1673 OUStringBuffer aBuffer;
1674 uno::Sequence<sal_Int8> aPassHash;
1675 ScPasswordHash eHashUsed = PASSHASH_UNSPECIFIED;
1676 const ScDocProtection* p = pDoc->GetDocProtection();
1677 if (p)
1679 if (p->hasPasswordHash(PASSHASH_SHA1))
1681 aPassHash = p->getPasswordHash(PASSHASH_SHA1);
1682 eHashUsed = PASSHASH_SHA1;
1684 else if (p->hasPasswordHash(PASSHASH_SHA256))
1686 aPassHash = p->getPasswordHash(PASSHASH_SHA256);
1687 eHashUsed = PASSHASH_SHA256;
1689 else if (p->hasPasswordHash(PASSHASH_XL, PASSHASH_SHA1))
1691 aPassHash = p->getPasswordHash(PASSHASH_XL, PASSHASH_SHA1);
1692 eHashUsed = PASSHASH_XL;
1695 ::comphelper::Base64::encode(aBuffer, aPassHash);
1696 if (!aBuffer.isEmpty())
1698 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
1699 if ( getDefaultVersion() >= SvtSaveOptions::ODFVER_012 )
1701 if (eHashUsed == PASSHASH_XL)
1703 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
1704 ScPassHashHelper::getHashURI(PASSHASH_XL));
1705 if (getDefaultVersion() > SvtSaveOptions::ODFVER_012)
1706 AddAttribute(XML_NAMESPACE_LO_EXT, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2,
1707 ScPassHashHelper::getHashURI(PASSHASH_SHA1));
1709 else if (eHashUsed == PASSHASH_SHA1)
1711 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
1712 ScPassHashHelper::getHashURI(PASSHASH_SHA1));
1714 else if (eHashUsed == PASSHASH_SHA256)
1716 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
1717 ScPassHashHelper::getHashURI(PASSHASH_SHA256));
1724 static bool lcl_CopyStreamElement( const uno::Reference< io::XInputStream >& xInput,
1725 const uno::Reference< io::XOutputStream >& xOutput,
1726 sal_Int32 nCount )
1728 const sal_Int32 nBufSize = 16*1024;
1729 uno::Sequence<sal_Int8> aSequence(nBufSize);
1731 sal_Int32 nRemaining = nCount;
1732 bool bFirst = true;
1734 while ( nRemaining > 0 )
1736 sal_Int32 nRead = xInput->readBytes( aSequence, std::min( nRemaining, nBufSize ) );
1737 if (bFirst)
1739 // safety check: Make sure the copied part actually points to the start of an element
1740 if ( nRead < 1 || aSequence[0] != static_cast<sal_Int8>('<') )
1742 return false; // abort and set an error
1744 bFirst = false;
1746 if (nRead == nRemaining)
1748 // safety check: Make sure the copied part also ends at the end of an element
1749 if ( aSequence[nRead-1] != static_cast<sal_Int8>('>') )
1751 return false; // abort and set an error
1755 if ( nRead == nBufSize )
1757 xOutput->writeBytes( aSequence );
1758 nRemaining -= nRead;
1760 else
1762 if ( nRead > 0 )
1764 uno::Sequence<sal_Int8> aTempBuf( aSequence.getConstArray(), nRead );
1765 xOutput->writeBytes( aTempBuf );
1767 nRemaining = 0;
1770 return true; // successful
1773 static void lcl_SkipBytesInBlocks( const uno::Reference< io::XInputStream >& xInput, sal_Int32 nBytesToSkip )
1775 // skipBytes in zip stream is implemented as reading.
1776 // For now, split into several calls to avoid allocating a large buffer.
1777 // Later, skipBytes should be changed.
1779 const sal_Int32 nMaxSize = 32*1024;
1781 if ( nBytesToSkip > 0 )
1783 sal_Int32 nRemaining = nBytesToSkip;
1784 while ( nRemaining > 0 )
1786 sal_Int32 nSkip = std::min( nRemaining, nMaxSize );
1787 xInput->skipBytes( nSkip );
1788 nRemaining -= nSkip;
1793 void ScXMLExport::CopySourceStream( sal_Int32 nStartOffset, sal_Int32 nEndOffset, sal_Int32& rNewStart, sal_Int32& rNewEnd )
1795 uno::Reference<xml::sax::XDocumentHandler> xHandler = GetDocHandler();
1796 uno::Reference<io::XActiveDataSource> xDestSource( xHandler, uno::UNO_QUERY );
1797 if ( xDestSource.is() )
1799 uno::Reference<io::XOutputStream> xDestStream = xDestSource->getOutputStream();
1800 uno::Reference<io::XSeekable> xDestSeek( xDestStream, uno::UNO_QUERY );
1801 if ( xDestSeek.is() )
1803 // temporary: set same stream again to clear buffer
1804 xDestSource->setOutputStream( xDestStream );
1806 if ( getExportFlags() & SvXMLExportFlags::PRETTY )
1808 const OString aOutStr("\n ");
1809 uno::Sequence<sal_Int8> aOutSeq( reinterpret_cast<sal_Int8 const *>(aOutStr.getStr()), aOutStr.getLength() );
1810 xDestStream->writeBytes( aOutSeq );
1813 rNewStart = static_cast<sal_Int32>(xDestSeek->getPosition());
1815 if ( nStartOffset > nSourceStreamPos )
1816 lcl_SkipBytesInBlocks( xSourceStream, nStartOffset - nSourceStreamPos );
1818 if ( !lcl_CopyStreamElement( xSourceStream, xDestStream, nEndOffset - nStartOffset ) )
1820 // If copying went wrong, set an error.
1821 // ScXMLImportWrapper then resets all stream flags, so the next save attempt will use normal saving.
1823 uno::Sequence<OUString> aEmptySeq;
1824 SetError(XMLERROR_CANCEL|XMLERROR_FLAG_SEVERE, aEmptySeq);
1826 nSourceStreamPos = nEndOffset;
1828 rNewEnd = static_cast<sal_Int32>(xDestSeek->getPosition());
1833 const ScXMLEditAttributeMap& ScXMLExport::GetEditAttributeMap() const
1835 if (!mpEditAttrMap)
1836 mpEditAttrMap.reset(new ScXMLEditAttributeMap);
1837 return *mpEditAttrMap;
1840 void ScXMLExport::RegisterDefinedStyleNames( const uno::Reference< css::sheet::XSpreadsheetDocument > & xSpreadDoc )
1842 ScFormatSaveData* pFormatData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetFormatSaveData();
1843 auto xAutoStylePool = GetAutoStylePool();
1844 for (const auto& rFormatInfo : pFormatData->maIDToName)
1846 xAutoStylePool->RegisterDefinedName(XML_STYLE_FAMILY_TABLE_CELL, rFormatInfo.second);
1850 void ScXMLExport::ExportContent_()
1852 nCurrentTable = 0;
1853 if (!pSharedData)
1855 SCTAB nTableCount(0);
1856 sal_Int32 nShapesCount(0);
1857 CollectSharedData(nTableCount, nShapesCount);
1858 OSL_FAIL("no shared data set");
1859 if (!pSharedData)
1860 return;
1862 ScXMLExportDatabaseRanges aExportDatabaseRanges(*this);
1863 if (!GetModel().is())
1864 return;
1866 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
1867 if ( !xSpreadDoc.is() )
1868 return;
1870 ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetSheetSaveData();
1871 if (pSheetData)
1872 pSheetData->ResetSaveEntries();
1874 uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
1875 if ( xIndex.is() )
1877 //_GetNamespaceMap().ClearQNamesCache();
1878 pChangeTrackingExportHelper->CollectAndWriteChanges();
1879 WriteCalculationSettings(xSpreadDoc);
1880 sal_Int32 nTableCount(xIndex->getCount());
1881 ScMyAreaLinksContainer aAreaLinks;
1882 GetAreaLinks( aAreaLinks );
1883 ScMyEmptyDatabaseRangesContainer aEmptyRanges(aExportDatabaseRanges.GetEmptyDatabaseRanges());
1884 ScMyDetectiveOpContainer aDetectiveOpContainer;
1885 GetDetectiveOpList( aDetectiveOpContainer );
1887 pCellStyles->Sort();
1888 pMergedRangesContainer->Sort();
1889 pSharedData->GetDetectiveObjContainer()->Sort();
1891 mpCellsItr->Clear();
1892 mpCellsItr->SetShapes( pSharedData->GetShapesContainer() );
1893 mpCellsItr->SetNoteShapes( pSharedData->GetNoteShapes() );
1894 mpCellsItr->SetMergedRanges( pMergedRangesContainer.get() );
1895 mpCellsItr->SetAreaLinks( &aAreaLinks );
1896 mpCellsItr->SetEmptyDatabaseRanges( &aEmptyRanges );
1897 mpCellsItr->SetDetectiveObj( pSharedData->GetDetectiveObjContainer() );
1898 mpCellsItr->SetDetectiveOp( &aDetectiveOpContainer );
1900 if (nTableCount > 0)
1901 pValidationsContainer->WriteValidations(*this);
1902 WriteTheLabelRanges( xSpreadDoc );
1903 for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable)
1905 sal_Int32 nStartOffset = -1;
1906 sal_Int32 nEndOffset = -1;
1907 if (pSheetData && pDoc && pDoc->IsStreamValid(static_cast<SCTAB>(nTable)) && !pDoc->GetChangeTrack())
1908 pSheetData->GetStreamPos( nTable, nStartOffset, nEndOffset );
1910 if ( nStartOffset >= 0 && nEndOffset >= 0 && xSourceStream.is() )
1912 sal_Int32 nNewStart = -1;
1913 sal_Int32 nNewEnd = -1;
1914 CopySourceStream( nStartOffset, nEndOffset, nNewStart, nNewEnd );
1916 // store position of copied sheet in output
1917 pSheetData->AddSavePos( nTable, nNewStart, nNewEnd );
1919 // skip iterator entries for this sheet
1920 mpCellsItr->SkipTable(static_cast<SCTAB>(nTable));
1922 else
1924 uno::Reference<sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
1925 WriteTable(nTable, xTable);
1927 IncrementProgressBar(false);
1930 WriteExternalRefCaches();
1931 WriteNamedExpressions();
1932 WriteDataStream();
1933 aExportDatabaseRanges.WriteDatabaseRanges();
1934 WriteExternalDataMapping();
1935 ScXMLExportDataPilot aExportDataPilot(*this);
1936 aExportDataPilot.WriteDataPilots();
1937 WriteConsolidation();
1938 ScXMLExportDDELinks aExportDDELinks(*this);
1939 aExportDDELinks.WriteDDELinks(xSpreadDoc);
1940 IncrementProgressBar(true, 0);
1941 GetProgressBarHelper()->SetValue(GetProgressBarHelper()->GetReference());
1944 void ScXMLExport::ExportStyles_( bool bUsed )
1946 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
1947 if (xSpreadDoc.is())
1948 RegisterDefinedStyleNames( xSpreadDoc);
1950 if (!pSharedData)
1952 SCTAB nTableCount(0);
1953 sal_Int32 nShapesCount(0);
1954 CollectSharedData(nTableCount, nShapesCount);
1956 rtl::Reference<ScXMLStyleExport> aStylesExp(new ScXMLStyleExport(*this, GetAutoStylePool().get()));
1957 if (GetModel().is())
1959 uno::Reference <lang::XMultiServiceFactory> xMultiServiceFactory(GetModel(), uno::UNO_QUERY);
1960 if (xMultiServiceFactory.is())
1962 uno::Reference <beans::XPropertySet> xProperties(xMultiServiceFactory->createInstance("com.sun.star.sheet.Defaults"), uno::UNO_QUERY);
1963 if (xProperties.is())
1964 aStylesExp->exportDefaultStyle(xProperties, XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME, xCellStylesExportPropertySetMapper);
1965 if (pSharedData->HasShapes())
1967 GetShapeExport()->ExportGraphicDefaults();
1970 uno::Reference <style::XStyleFamiliesSupplier> xStyleFamiliesSupplier (GetModel(), uno::UNO_QUERY);
1971 if (xStyleFamiliesSupplier.is())
1973 uno::Reference <container::XNameAccess> xStylesFamilies(xStyleFamiliesSupplier->getStyleFamilies());
1974 if (xStylesFamilies.is())
1976 uno::Reference <container::XIndexAccess> xCellStyles(xStylesFamilies->getByName("CellStyles"), uno::UNO_QUERY);
1977 if (xCellStyles.is())
1979 sal_Int32 nCount(xCellStyles->getCount());
1980 for (sal_Int32 i = 0; i < nCount; ++i)
1982 uno::Reference <beans::XPropertySet> xCellProperties(xCellStyles->getByIndex(i), uno::UNO_QUERY);
1983 if (xCellProperties.is())
1985 sal_Int32 nNumberFormat = 0;
1986 if (xCellProperties->getPropertyValue(SC_UNONAME_NUMFMT) >>= nNumberFormat)
1987 addDataStyle(nNumberFormat);
1994 exportDataStyles();
1996 aStylesExp->exportStyleFamily(OUString("CellStyles"),
1997 OUString(XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME), xCellStylesExportPropertySetMapper, false, XML_STYLE_FAMILY_TABLE_CELL);
1999 SvXMLExport::ExportStyles_(bUsed);
2002 void ScXMLExport::AddStyleFromCells(const uno::Reference<beans::XPropertySet>& xProperties,
2003 const uno::Reference<sheet::XSpreadsheet>& xTable,
2004 sal_Int32 nTable, const OUString* pOldName)
2006 css::uno::Any aAny = xProperties->getPropertyValue("FormatID");
2007 sal_uInt64 nKey = 0;
2008 aAny >>= nKey;
2010 //! pass xCellRanges instead
2011 uno::Reference<sheet::XSheetCellRanges> xCellRanges( xProperties, uno::UNO_QUERY );
2013 OUString sStyleName;
2014 sal_Int32 nNumberFormat(-1);
2015 sal_Int32 nValidationIndex(-1);
2016 std::vector< XMLPropertyState > aPropStates(xCellStylesExportPropertySetMapper->Filter( xProperties ));
2017 std::vector< XMLPropertyState >::iterator aItr(aPropStates.begin());
2018 std::vector< XMLPropertyState >::iterator aEndItr(aPropStates.end());
2019 sal_Int32 nCount(0);
2020 while (aItr != aEndItr)
2022 if (aItr->mnIndex != -1)
2024 switch (xCellStylesPropertySetMapper->GetEntryContextId(aItr->mnIndex))
2026 case CTF_SC_VALIDATION :
2028 pValidationsContainer->AddValidation(aItr->maValue, nValidationIndex);
2029 // this is not very slow, because it is most the last property or
2030 // if it is not the last property it is the property before the last property,
2031 // so in the worst case only one property has to be copied, but in the best case no
2032 // property has to be copied
2033 aItr = aPropStates.erase(aItr);
2034 aEndItr = aPropStates.end(); // old aEndItr is invalidated!
2036 break;
2037 case CTF_SC_CELLSTYLE :
2039 aItr->maValue >>= sStyleName;
2040 aItr->mnIndex = -1;
2041 ++aItr;
2042 ++nCount;
2044 break;
2045 case CTF_SC_NUMBERFORMAT :
2047 if (aItr->maValue >>= nNumberFormat)
2048 addDataStyle(nNumberFormat);
2049 ++aItr;
2050 ++nCount;
2052 break;
2053 default:
2055 ++aItr;
2056 ++nCount;
2058 break;
2061 else
2063 ++aItr;
2064 ++nCount;
2067 if (nCount == 1) // this is the CellStyle and should be removed if alone
2068 aPropStates.clear();
2069 if (nNumberFormat == -1)
2070 xProperties->getPropertyValue(SC_UNONAME_NUMFMT) >>= nNumberFormat;
2071 if (!sStyleName.isEmpty())
2073 if (!aPropStates.empty())
2075 sal_Int32 nIndex;
2076 if (pOldName)
2078 if (GetAutoStylePool()->AddNamed(*pOldName, XML_STYLE_FAMILY_TABLE_CELL, sStyleName, aPropStates))
2080 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_CELL, *pOldName);
2081 // add to pCellStyles, so the name is found for normal sheets
2082 pCellStyles->AddStyleName(*pOldName, nIndex);
2085 else
2087 OUString sName;
2088 bool bAdded = false;
2089 if (nKey)
2091 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
2092 ScFormatSaveData* pFormatData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetFormatSaveData();
2093 auto itr = pFormatData->maIDToName.find(nKey);
2094 if (itr != pFormatData->maIDToName.end())
2096 sName = itr->second;
2097 bAdded = GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TABLE_CELL, sStyleName, aPropStates);
2098 if (bAdded)
2099 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_CELL, sName);
2102 bool bIsAutoStyle(true);
2103 if (bAdded || GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_CELL, sStyleName, aPropStates))
2105 pCellStyles->AddStyleName(sName, nIndex);
2107 else
2108 nIndex = pCellStyles->GetIndexOfStyleName(sName, XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX, bIsAutoStyle);
2110 const uno::Sequence<table::CellRangeAddress> aAddresses(xCellRanges->getRangeAddresses());
2111 bool bGetMerge(true);
2112 for (table::CellRangeAddress const & address : aAddresses)
2114 pSharedData->SetLastColumn(nTable, address.EndColumn);
2115 pSharedData->SetLastRow(nTable, address.EndRow);
2116 pCellStyles->AddRangeStyleName(address, nIndex, bIsAutoStyle, nValidationIndex, nNumberFormat);
2117 if (bGetMerge)
2118 bGetMerge = GetMerged(&address, xTable);
2122 else
2124 OUString sEncodedStyleName(EncodeStyleName(sStyleName));
2125 sal_Int32 nIndex(0);
2126 pCellStyles->AddStyleName(sEncodedStyleName, nIndex, false);
2127 if ( !pOldName )
2129 const uno::Sequence<table::CellRangeAddress> aAddresses(xCellRanges->getRangeAddresses());
2130 bool bGetMerge(true);
2131 for (table::CellRangeAddress const & address : aAddresses)
2133 if (bGetMerge)
2134 bGetMerge = GetMerged(&address, xTable);
2135 pCellStyles->AddRangeStyleName(address, nIndex, false, nValidationIndex, nNumberFormat);
2136 if( sStyleName != "Default" || nValidationIndex != -1 )
2138 pSharedData->SetLastColumn(nTable, address.EndColumn);
2139 pSharedData->SetLastRow(nTable, address.EndRow);
2147 void ScXMLExport::AddStyleFromColumn(const uno::Reference<beans::XPropertySet>& xColumnProperties,
2148 const OUString* pOldName, sal_Int32& rIndex, bool& rIsVisible)
2150 std::vector<XMLPropertyState> aPropStates(xColumnStylesExportPropertySetMapper->Filter(xColumnProperties));
2151 if(!aPropStates.empty())
2153 auto aItr = std::find_if(aPropStates.begin(), aPropStates.end(),
2154 [this](const XMLPropertyState& rPropState) {
2155 return xColumnStylesPropertySetMapper->GetEntryContextId(rPropState.mnIndex) == CTF_SC_ISVISIBLE; });
2156 if (aItr != aPropStates.end())
2158 aItr->maValue >>= rIsVisible;
2161 OUString sParent;
2162 if (pOldName)
2164 if (GetAutoStylePool()->AddNamed(*pOldName, XML_STYLE_FAMILY_TABLE_COLUMN, sParent, aPropStates))
2166 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_COLUMN, *pOldName);
2167 // add to pColumnStyles, so the name is found for normal sheets
2168 rIndex = pColumnStyles->AddStyleName(*pOldName);
2171 else
2173 OUString sName;
2174 if (GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_COLUMN, sParent, aPropStates))
2176 rIndex = pColumnStyles->AddStyleName(sName);
2178 else
2179 rIndex = pColumnStyles->GetIndexOfStyleName(sName, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_PREFIX);
2184 void ScXMLExport::AddStyleFromRow(const uno::Reference<beans::XPropertySet>& xRowProperties,
2185 const OUString* pOldName, sal_Int32& rIndex)
2187 std::vector<XMLPropertyState> aPropStates(xRowStylesExportPropertySetMapper->Filter(xRowProperties));
2188 if(!aPropStates.empty())
2190 OUString sParent;
2191 if (pOldName)
2193 if (GetAutoStylePool()->AddNamed(*pOldName, XML_STYLE_FAMILY_TABLE_ROW, sParent, aPropStates))
2195 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_ROW, *pOldName);
2196 // add to pRowStyles, so the name is found for normal sheets
2197 rIndex = pRowStyles->AddStyleName(*pOldName);
2200 else
2202 OUString sName;
2203 if (GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_ROW, sParent, aPropStates))
2205 rIndex = pRowStyles->AddStyleName(sName);
2207 else
2208 rIndex = pRowStyles->GetIndexOfStyleName(sName, XML_STYLE_FAMILY_TABLE_ROW_STYLES_PREFIX);
2213 static uno::Any lcl_GetEnumerated( uno::Reference<container::XEnumerationAccess> const & xEnumAccess, sal_Int32 nIndex )
2215 uno::Any aRet;
2216 uno::Reference<container::XEnumeration> xEnum( xEnumAccess->createEnumeration() );
2219 sal_Int32 nSkip = nIndex;
2220 while ( nSkip > 0 )
2222 (void) xEnum->nextElement();
2223 --nSkip;
2225 aRet = xEnum->nextElement();
2227 catch (container::NoSuchElementException&)
2229 // leave aRet empty
2231 return aRet;
2234 void ScXMLExport::collectAutoStyles()
2236 SvXMLExport::collectAutoStyles();
2238 if (mbAutoStylesCollected)
2239 return;
2241 if (!GetModel().is())
2242 return;
2244 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
2245 if (!xSpreadDoc.is())
2246 return;
2248 uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
2249 if (!xIndex.is())
2250 return;
2252 if (getExportFlags() & SvXMLExportFlags::CONTENT)
2254 // Reserve the loaded cell style names.
2255 RegisterDefinedStyleNames( xSpreadDoc);
2257 // re-create automatic styles with old names from stored data
2258 ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetSheetSaveData();
2259 if (pSheetData && pDoc)
2261 // formulas have to be calculated now, to detect changed results
2262 // (during normal save, they will be calculated anyway)
2263 SCTAB nTabCount = pDoc->GetTableCount();
2264 for (SCTAB nTab=0; nTab<nTabCount; ++nTab)
2265 if (pDoc->IsStreamValid(nTab))
2266 pDoc->InterpretDirtyCells(ScRange(0, 0, nTab, pDoc->MaxCol(), pDoc->MaxRow(), nTab));
2268 // stored cell styles
2269 const std::vector<ScCellStyleEntry>& rCellEntries = pSheetData->GetCellStyles();
2270 for (const auto& rCellEntry : rCellEntries)
2272 ScAddress aPos = rCellEntry.maCellPos;
2273 sal_Int32 nTable = aPos.Tab();
2274 bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2275 if (bCopySheet)
2277 uno::Reference <sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2278 uno::Reference <beans::XPropertySet> xProperties(
2279 xTable->getCellByPosition( aPos.Col(), aPos.Row() ), uno::UNO_QUERY );
2281 AddStyleFromCells(xProperties, xTable, nTable, &rCellEntry.maName);
2285 // stored column styles
2286 const std::vector<ScCellStyleEntry>& rColumnEntries = pSheetData->GetColumnStyles();
2287 for (const auto& rColumnEntry : rColumnEntries)
2289 ScAddress aPos = rColumnEntry.maCellPos;
2290 sal_Int32 nTable = aPos.Tab();
2291 bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2292 if (bCopySheet)
2294 uno::Reference<table::XColumnRowRange> xColumnRowRange(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2295 uno::Reference<table::XTableColumns> xTableColumns(xColumnRowRange->getColumns());
2296 uno::Reference<beans::XPropertySet> xColumnProperties(xTableColumns->getByIndex( aPos.Col() ), uno::UNO_QUERY);
2298 sal_Int32 nIndex(-1);
2299 bool bIsVisible(true);
2300 AddStyleFromColumn( xColumnProperties, &rColumnEntry.maName, nIndex, bIsVisible );
2304 // stored row styles
2305 const std::vector<ScCellStyleEntry>& rRowEntries = pSheetData->GetRowStyles();
2306 for (const auto& rRowEntry : rRowEntries)
2308 ScAddress aPos = rRowEntry.maCellPos;
2309 sal_Int32 nTable = aPos.Tab();
2310 bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2311 if (bCopySheet)
2313 uno::Reference<table::XColumnRowRange> xColumnRowRange(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2314 uno::Reference<table::XTableRows> xTableRows(xColumnRowRange->getRows());
2315 uno::Reference<beans::XPropertySet> xRowProperties(xTableRows->getByIndex( aPos.Row() ), uno::UNO_QUERY);
2317 sal_Int32 nIndex(-1);
2318 AddStyleFromRow( xRowProperties, &rRowEntry.maName, nIndex );
2322 // stored table styles
2323 const std::vector<ScCellStyleEntry>& rTableEntries = pSheetData->GetTableStyles();
2324 for (const auto& rTableEntry : rTableEntries)
2326 ScAddress aPos = rTableEntry.maCellPos;
2327 sal_Int32 nTable = aPos.Tab();
2328 bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2329 if (bCopySheet)
2331 //! separate method AddStyleFromTable needed?
2332 uno::Reference<beans::XPropertySet> xTableProperties(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2333 if (xTableProperties.is())
2335 std::vector<XMLPropertyState> aPropStates(xTableStylesExportPropertySetMapper->Filter(xTableProperties));
2336 OUString sName( rTableEntry.maName );
2337 GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TABLE_TABLE, OUString(), aPropStates);
2338 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_TABLE, sName);
2343 // stored styles for notes
2345 rtl::Reference<SvXMLExportPropertyMapper> xShapeMapper = XMLShapeExport::CreateShapePropMapper( *this );
2346 GetShapeExport(); // make sure the graphics styles family is added
2348 const std::vector<ScNoteStyleEntry>& rNoteEntries = pSheetData->GetNoteStyles();
2349 for (const auto& rNoteEntry : rNoteEntries)
2351 ScAddress aPos = rNoteEntry.maCellPos;
2352 SCTAB nTable = aPos.Tab();
2353 bool bCopySheet = pDoc->IsStreamValid( nTable );
2354 if (bCopySheet)
2356 //! separate method AddStyleFromNote needed?
2358 ScPostIt* pNote = pDoc->GetNote(aPos);
2359 OSL_ENSURE( pNote, "note not found" );
2360 if (pNote)
2362 SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
2363 // all uno shapes are created anyway in CollectSharedData
2364 uno::Reference<beans::XPropertySet> xShapeProperties( pDrawObj->getUnoShape(), uno::UNO_QUERY );
2365 if (xShapeProperties.is())
2367 if ( !rNoteEntry.maStyleName.isEmpty() )
2369 std::vector<XMLPropertyState> aPropStates(xShapeMapper->Filter(xShapeProperties));
2370 OUString sName( rNoteEntry.maStyleName );
2371 GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_SD_GRAPHICS_ID, OUString(), aPropStates);
2372 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_SD_GRAPHICS_ID, sName);
2374 if ( !rNoteEntry.maTextStyle.isEmpty() )
2376 std::vector<XMLPropertyState> aPropStates(
2377 GetTextParagraphExport()->GetParagraphPropertyMapper()->Filter(xShapeProperties));
2378 OUString sName( rNoteEntry.maTextStyle );
2379 GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_PARAGRAPH, OUString(), aPropStates);
2380 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_PARAGRAPH, sName);
2387 // note paragraph styles
2389 rtl::Reference<SvXMLExportPropertyMapper> xParaPropMapper = GetTextParagraphExport()->GetParagraphPropertyMapper();
2391 const std::vector<ScTextStyleEntry>& rNoteParaEntries = pSheetData->GetNoteParaStyles();
2392 for (const auto& rNoteParaEntry : rNoteParaEntries)
2394 ScAddress aPos = rNoteParaEntry.maCellPos;
2395 SCTAB nTable = aPos.Tab();
2396 bool bCopySheet = pDoc->IsStreamValid( nTable );
2397 if (bCopySheet)
2399 ScPostIt* pNote = pDoc->GetNote( aPos );
2400 OSL_ENSURE( pNote, "note not found" );
2401 if (pNote)
2403 SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
2404 uno::Reference<container::XEnumerationAccess> xCellText(pDrawObj->getUnoShape(), uno::UNO_QUERY);
2405 uno::Reference<beans::XPropertySet> xParaProp(
2406 lcl_GetEnumerated( xCellText, rNoteParaEntry.maSelection.nStartPara ), uno::UNO_QUERY );
2407 if ( xParaProp.is() )
2409 std::vector<XMLPropertyState> aPropStates(xParaPropMapper->Filter(xParaProp));
2410 OUString sName( rNoteParaEntry.maName );
2411 GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_PARAGRAPH, OUString(), aPropStates);
2412 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_PARAGRAPH, sName);
2418 // note text styles
2420 rtl::Reference<SvXMLExportPropertyMapper> xTextPropMapper = XMLTextParagraphExport::CreateCharExtPropMapper( *this );
2422 const std::vector<ScTextStyleEntry>& rNoteTextEntries = pSheetData->GetNoteTextStyles();
2423 for (const auto& rNoteTextEntry : rNoteTextEntries)
2425 ScAddress aPos = rNoteTextEntry.maCellPos;
2426 SCTAB nTable = aPos.Tab();
2427 bool bCopySheet = pDoc->IsStreamValid( nTable );
2428 if (bCopySheet)
2430 ScPostIt* pNote = pDoc->GetNote( aPos );
2431 OSL_ENSURE( pNote, "note not found" );
2432 if (pNote)
2434 SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
2435 uno::Reference<text::XSimpleText> xCellText(pDrawObj->getUnoShape(), uno::UNO_QUERY);
2436 uno::Reference<beans::XPropertySet> xCursorProp(xCellText->createTextCursor(), uno::UNO_QUERY);
2437 ScDrawTextCursor* pCursor = comphelper::getUnoTunnelImplementation<ScDrawTextCursor>( xCursorProp );
2438 if (pCursor)
2440 pCursor->SetSelection( rNoteTextEntry.maSelection );
2442 std::vector<XMLPropertyState> aPropStates(xTextPropMapper->Filter(xCursorProp));
2443 OUString sName( rNoteTextEntry.maName );
2444 GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_TEXT, OUString(), aPropStates);
2445 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_TEXT, sName);
2451 // stored text styles
2453 // Calling createTextCursor fires up editeng, which is very slow, and often subsequent style entries
2454 // refer to the same cell, so cache it.
2455 ScAddress aPrevPos;
2456 uno::Reference<beans::XPropertySet> xPrevCursorProp;
2457 const std::vector<ScTextStyleEntry>& rTextEntries = pSheetData->GetTextStyles();
2458 for (const auto& rTextEntry : rTextEntries)
2460 ScAddress aPos = rTextEntry.maCellPos;
2461 sal_Int32 nTable = aPos.Tab();
2462 bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2463 if (!bCopySheet)
2464 continue;
2466 //! separate method AddStyleFromText needed?
2467 //! cache sheet object
2469 uno::Reference<beans::XPropertySet> xCursorProp;
2470 if (xPrevCursorProp && aPrevPos == aPos)
2471 xCursorProp = xPrevCursorProp;
2472 else
2474 uno::Reference<table::XCellRange> xCellRange(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2475 uno::Reference<text::XSimpleText> xCellText(xCellRange->getCellByPosition(aPos.Col(), aPos.Row()), uno::UNO_QUERY);
2476 xCursorProp.set(xCellText->createTextCursor(), uno::UNO_QUERY);
2478 ScCellTextCursor* pCursor = comphelper::getUnoTunnelImplementation<ScCellTextCursor>( xCursorProp );
2479 if (!pCursor)
2480 continue;
2481 pCursor->SetSelection( rTextEntry.maSelection );
2483 std::vector<XMLPropertyState> aPropStates(xTextPropMapper->Filter(xCursorProp));
2484 OUString sName( rTextEntry.maName );
2485 GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_TEXT, OUString(), aPropStates);
2486 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_TEXT, sName);
2487 xPrevCursorProp = xCursorProp;
2488 aPrevPos = aPos;
2492 ExportExternalRefCacheStyles();
2494 if (!pSharedData)
2496 SCTAB nTableCount(0);
2497 sal_Int32 nShapesCount(0);
2498 CollectSharedData(nTableCount, nShapesCount);
2500 sal_Int32 nTableCount(xIndex->getCount());
2501 pCellStyles->AddNewTable(nTableCount - 1);
2502 CollectShapesAutoStyles(nTableCount);
2503 for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable, IncrementProgressBar(false))
2505 uno::Reference <sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2506 if (!xTable.is())
2507 continue;
2509 // table styles array must be complete, including copied tables - Add should find the stored style
2510 uno::Reference<beans::XPropertySet> xTableProperties(xTable, uno::UNO_QUERY);
2511 if (xTableProperties.is())
2513 std::vector<XMLPropertyState> aPropStates(xTableStylesExportPropertySetMapper->Filter(xTableProperties));
2514 if(!aPropStates.empty())
2516 OUString sName;
2517 GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_TABLE, OUString(), aPropStates);
2518 aTableStyles.push_back(sName);
2522 // collect other auto-styles only for non-copied sheets
2523 uno::Reference<sheet::XUniqueCellFormatRangesSupplier> xCellFormatRanges ( xTable, uno::UNO_QUERY );
2524 if ( xCellFormatRanges.is() )
2526 uno::Reference<container::XIndexAccess> xFormatRangesIndex(xCellFormatRanges->getUniqueCellFormatRanges());
2527 if (xFormatRangesIndex.is())
2529 sal_Int32 nFormatRangesCount(xFormatRangesIndex->getCount());
2530 GetProgressBarHelper()->ChangeReference(GetProgressBarHelper()->GetReference() + nFormatRangesCount);
2531 for (sal_Int32 nFormatRange = 0; nFormatRange < nFormatRangesCount; ++nFormatRange)
2533 uno::Reference< sheet::XSheetCellRanges> xCellRanges(xFormatRangesIndex->getByIndex(nFormatRange), uno::UNO_QUERY);
2534 if (xCellRanges.is())
2536 uno::Reference <beans::XPropertySet> xProperties (xCellRanges, uno::UNO_QUERY);
2537 if (xProperties.is())
2539 AddStyleFromCells(xProperties, xTable, nTable, nullptr);
2540 IncrementProgressBar(false);
2546 uno::Reference<table::XColumnRowRange> xColumnRowRange (xTable, uno::UNO_QUERY);
2547 if (xColumnRowRange.is() && pDoc)
2549 pDoc->SyncColRowFlags();
2550 uno::Reference<table::XTableColumns> xTableColumns(xColumnRowRange->getColumns());
2551 if (xTableColumns.is())
2553 sal_Int32 nColumns(pDoc->GetLastChangedCol(sal::static_int_cast<SCTAB>(nTable)));
2554 pSharedData->SetLastColumn(nTable, nColumns);
2555 table::CellRangeAddress aCellAddress(GetEndAddress(xTable));
2556 if (aCellAddress.EndColumn > nColumns)
2558 ++nColumns;
2559 pColumnStyles->AddNewTable(nTable, aCellAddress.EndColumn);
2561 else
2562 pColumnStyles->AddNewTable(nTable, nColumns);
2563 sal_Int32 nColumn = 0;
2564 while (nColumn <= pDoc->MaxCol())
2566 sal_Int32 nIndex(-1);
2567 bool bIsVisible(true);
2568 uno::Reference <beans::XPropertySet> xColumnProperties(xTableColumns->getByIndex(nColumn), uno::UNO_QUERY);
2569 if (xColumnProperties.is())
2571 AddStyleFromColumn( xColumnProperties, nullptr, nIndex, bIsVisible );
2572 pColumnStyles->AddFieldStyleName(nTable, nColumn, nIndex, bIsVisible);
2574 sal_Int32 nOld(nColumn);
2575 nColumn = pDoc->GetNextDifferentChangedCol(sal::static_int_cast<SCTAB>(nTable), static_cast<SCCOL>(nColumn));
2576 for (sal_Int32 i = nOld + 1; i < nColumn; ++i)
2577 pColumnStyles->AddFieldStyleName(nTable, i, nIndex, bIsVisible);
2579 if (aCellAddress.EndColumn > nColumns)
2581 bool bIsVisible(true);
2582 sal_Int32 nIndex(pColumnStyles->GetStyleNameIndex(nTable, nColumns, bIsVisible));
2583 for (sal_Int32 i = nColumns + 1; i <= aCellAddress.EndColumn; ++i)
2584 pColumnStyles->AddFieldStyleName(nTable, i, nIndex, bIsVisible);
2587 uno::Reference<table::XTableRows> xTableRows(xColumnRowRange->getRows());
2588 if (xTableRows.is())
2590 sal_Int32 nRows(pDoc->GetLastChangedRow(sal::static_int_cast<SCTAB>(nTable)));
2591 pSharedData->SetLastRow(nTable, nRows);
2593 pRowStyles->AddNewTable(nTable, pDoc->MaxRow());
2594 sal_Int32 nRow = 0;
2595 while (nRow <= pDoc->MaxRow())
2597 sal_Int32 nIndex = 0;
2598 uno::Reference <beans::XPropertySet> xRowProperties(xTableRows->getByIndex(nRow), uno::UNO_QUERY);
2599 if(xRowProperties.is())
2601 AddStyleFromRow( xRowProperties, nullptr, nIndex );
2602 pRowStyles->AddFieldStyleName(nTable, nRow, nIndex);
2604 sal_Int32 nOld(nRow);
2605 nRow = pDoc->GetNextDifferentChangedRow(sal::static_int_cast<SCTAB>(nTable), static_cast<SCROW>(nRow));
2606 if (nRow > nOld + 1)
2607 pRowStyles->AddFieldStyleName(nTable, nOld + 1, nIndex, nRow - 1);
2611 ExportCellTextAutoStyles(nTable);
2614 pChangeTrackingExportHelper->CollectAutoStyles();
2617 if (getExportFlags() & SvXMLExportFlags::MASTERSTYLES)
2618 GetPageExport()->collectAutoStyles(true);
2620 mbAutoStylesCollected = true;
2623 void ScXMLExport::ExportAutoStyles_()
2625 if (!GetModel().is())
2626 return;
2628 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
2629 if (!xSpreadDoc.is())
2630 return;
2632 uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
2633 if (!xIndex.is())
2634 return;
2636 collectAutoStyles();
2638 if (getExportFlags() & SvXMLExportFlags::CONTENT)
2640 GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_COLUMN);
2641 GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_ROW);
2642 GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_TABLE);
2643 exportAutoDataStyles();
2644 GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_CELL);
2646 GetShapeExport()->exportAutoStyles();
2647 GetFormExport()->exportAutoStyles( );
2649 if (pDoc)
2651 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
2652 // #i100879# write the table style for cached tables only if there are cached tables
2653 // (same logic as in ExportExternalRefCacheStyles)
2654 if (pRefMgr->hasExternalData())
2656 // Special table style for the external ref cache tables.
2657 AddAttribute(XML_NAMESPACE_STYLE, XML_NAME, sExternalRefTabStyleName);
2658 AddAttribute(XML_NAMESPACE_STYLE, XML_FAMILY, XML_TABLE);
2659 SvXMLElementExport aElemStyle(*this, XML_NAMESPACE_STYLE, XML_STYLE, true, true);
2660 AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY, XML_FALSE);
2661 SvXMLElementExport aElemStyleTabProps(*this, XML_NAMESPACE_STYLE, XML_TABLE_PROPERTIES, true, true);
2666 if (getExportFlags() & SvXMLExportFlags::MASTERSTYLES)
2668 GetPageExport()->exportAutoStyles();
2671 // #i30251#; only write Text Styles once
2673 if ((getExportFlags() & SvXMLExportFlags::CONTENT) || (getExportFlags() & SvXMLExportFlags::MASTERSTYLES))
2674 GetTextParagraphExport()->exportTextAutoStyles();
2677 void ScXMLExport::ExportMasterStyles_()
2679 GetPageExport()->exportMasterStyles( true );
2682 void ScXMLExport::CollectInternalShape( uno::Reference< drawing::XShape > const & xShape )
2684 // detective objects and notes
2685 if( SvxShape* pShapeImp = comphelper::getUnoTunnelImplementation<SvxShape>( xShape ) )
2687 if( SdrObject* pObject = pShapeImp->GetSdrObject() )
2689 // collect note caption objects from all layers (internal or hidden)
2690 if( ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( pObject, static_cast< SCTAB >( nCurrentTable ) ) )
2692 if(pDoc->GetNote(pCaptData->maStart))
2694 pSharedData->AddNoteObj( xShape, pCaptData->maStart );
2696 // #i60851# When the file is saved while editing a new note,
2697 // the cell is still empty -> last column/row must be updated
2698 OSL_ENSURE( pCaptData->maStart.Tab() == nCurrentTable, "invalid table in object data" );
2699 pSharedData->SetLastColumn( nCurrentTable, pCaptData->maStart.Col() );
2700 pSharedData->SetLastRow( nCurrentTable, pCaptData->maStart.Row() );
2703 // other objects from internal layer only (detective)
2704 else if( pObject->GetLayer() == SC_LAYER_INTERN )
2706 ScDetectiveFunc aDetFunc( pDoc, static_cast<SCTAB>(nCurrentTable) );
2707 ScAddress aPosition;
2708 ScRange aSourceRange;
2709 bool bRedLine;
2710 ScDetectiveObjType eObjType = aDetFunc.GetDetectiveObjectType(
2711 pObject, nCurrentTable, aPosition, aSourceRange, bRedLine );
2712 pSharedData->GetDetectiveObjContainer()->AddObject( eObjType, static_cast<SCTAB>(nCurrentTable), aPosition, aSourceRange, bRedLine );
2718 bool ScXMLExport::GetMerged (const table::CellRangeAddress* pCellAddress,
2719 const uno::Reference <sheet::XSpreadsheet>& xTable)
2721 bool bReady(false);
2722 sal_Int32 nRow(pCellAddress->StartRow);
2723 sal_Int32 nCol(pCellAddress->StartColumn);
2724 sal_Int32 nEndRow(pCellAddress->EndRow);
2725 sal_Int32 nEndCol(pCellAddress->EndColumn);
2726 bool bRowInc(nEndRow > nRow);
2727 while(!bReady && nRow <= nEndRow && nCol <= nEndCol)
2729 uno::Reference<sheet::XSheetCellRange> xSheetCellRange(xTable->getCellRangeByPosition(nCol, nRow, nCol, nRow), uno::UNO_QUERY);
2730 if (xSheetCellRange.is())
2732 uno::Reference<sheet::XSheetCellCursor> xCursor(xTable->createCursorByRange(xSheetCellRange));
2733 if(xCursor.is())
2735 uno::Reference<sheet::XCellRangeAddressable> xCellAddress (xCursor, uno::UNO_QUERY);
2736 xCursor->collapseToMergedArea();
2737 table::CellRangeAddress aCellAddress2(xCellAddress->getRangeAddress());
2738 ScRange aScRange( aCellAddress2.StartColumn, aCellAddress2.StartRow, aCellAddress2.Sheet,
2739 aCellAddress2.EndColumn, aCellAddress2.EndRow, aCellAddress2.Sheet );
2741 if ((aScRange.aEnd.Row() > nRow ||
2742 aScRange.aEnd.Col() > nCol) &&
2743 aScRange.aStart.Row() == nRow &&
2744 aScRange.aStart.Col() == nCol)
2746 pMergedRangesContainer->AddRange(aScRange);
2747 pSharedData->SetLastColumn(aScRange.aEnd.Tab(), aScRange.aEnd.Col());
2748 pSharedData->SetLastRow(aScRange.aEnd.Tab(), aScRange.aEnd.Row());
2750 else
2751 bReady = true;
2754 if (!bReady)
2756 if (bRowInc)
2757 ++nRow;
2758 else
2759 ++nCol;
2762 OSL_ENSURE(!(!bReady && nEndRow > nRow && nEndCol > nCol), "should not be possible");
2763 return !bReady;
2766 bool ScXMLExport::IsMatrix (const ScAddress& aCell,
2767 ScRange& aCellAddress, bool& bIsFirst) const
2769 bIsFirst = false;
2771 ScRange aMatrixRange;
2773 if (pDoc && pDoc->GetMatrixFormulaRange(aCell, aMatrixRange))
2775 aCellAddress = aMatrixRange;
2776 if ((aCellAddress.aStart.Col() == aCell.Col() && aCellAddress.aStart.Row() == aCell.Row()) &&
2777 (aCellAddress.aEnd.Col() > aCell.Col() || aCellAddress.aEnd.Row() > aCell.Row()))
2779 bIsFirst = true;
2780 return true;
2782 else if (aCellAddress.aStart.Col() != aCell.Col() || aCellAddress.aStart.Row() != aCell.Row() ||
2783 aCellAddress.aEnd.Col() != aCell.Col() || aCellAddress.aEnd.Row()!= aCell.Row())
2784 return true;
2785 else
2787 bIsFirst = true;
2788 return true;
2792 return false;
2795 void ScXMLExport::WriteTable(sal_Int32 nTable, const uno::Reference<sheet::XSpreadsheet>& xTable)
2797 if (!xTable.is())
2798 return;
2800 xCurrentTable.set(xTable);
2801 uno::Reference<container::XNamed> xName (xTable, uno::UNO_QUERY );
2802 if (!xName.is())
2803 return;
2805 nCurrentTable = sal::static_int_cast<sal_uInt16>( nTable );
2806 OUString sOUTableName(xName->getName());
2807 AddAttribute(sAttrName, sOUTableName);
2808 AddAttribute(sAttrStyleName, aTableStyles[nTable]);
2810 uno::Reference<util::XProtectable> xProtectable (xTable, uno::UNO_QUERY);
2811 ScTableProtection* pProtect = nullptr;
2812 if (xProtectable.is() && xProtectable->isProtected())
2814 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE);
2815 if (pDoc)
2817 pProtect = pDoc->GetTabProtection(nTable);
2818 if (pProtect)
2820 OUStringBuffer aBuffer;
2821 ScPasswordHash eHashUsed = PASSHASH_UNSPECIFIED;
2822 if (pProtect->hasPasswordHash(PASSHASH_SHA1))
2824 ::comphelper::Base64::encode(aBuffer,
2825 pProtect->getPasswordHash(PASSHASH_SHA1));
2826 eHashUsed = PASSHASH_SHA1;
2828 else if (pProtect->hasPasswordHash(PASSHASH_SHA256))
2830 ::comphelper::Base64::encode(aBuffer,
2831 pProtect->getPasswordHash(PASSHASH_SHA256));
2832 eHashUsed = PASSHASH_SHA256;
2834 else if (pProtect->hasPasswordHash(PASSHASH_XL, PASSHASH_SHA1))
2836 // Double-hash this by SHA1 on top of the legacy xls hash.
2837 uno::Sequence<sal_Int8> aHash = pProtect->getPasswordHash(PASSHASH_XL, PASSHASH_SHA1);
2838 ::comphelper::Base64::encode(aBuffer, aHash);
2839 eHashUsed = PASSHASH_XL;
2841 if (!aBuffer.isEmpty())
2843 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
2844 if ( getDefaultVersion() >= SvtSaveOptions::ODFVER_012 )
2846 if (eHashUsed == PASSHASH_XL)
2848 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
2849 ScPassHashHelper::getHashURI(PASSHASH_XL));
2850 if (getDefaultVersion() > SvtSaveOptions::ODFVER_012)
2851 AddAttribute(XML_NAMESPACE_LO_EXT, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2,
2852 ScPassHashHelper::getHashURI(PASSHASH_SHA1));
2854 else if (eHashUsed == PASSHASH_SHA1)
2856 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
2857 ScPassHashHelper::getHashURI(PASSHASH_SHA1));
2859 else if (eHashUsed == PASSHASH_SHA256)
2861 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
2862 ScPassHashHelper::getHashURI(PASSHASH_SHA256));
2869 OUString sPrintRanges;
2870 ScRange aColumnHeaderRange;
2871 bool bHasColumnHeader;
2872 GetColumnRowHeader(bHasColumnHeader, aColumnHeaderRange, bHasRowHeader, aRowHeaderRange, sPrintRanges);
2873 if( !sPrintRanges.isEmpty() )
2874 AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT_RANGES, sPrintRanges );
2875 else if (pDoc && !pDoc->IsPrintEntireSheet(static_cast<SCTAB>(nTable)))
2876 AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT, XML_FALSE);
2877 SvXMLElementExport aElemT(*this, sElemTab, true, true);
2879 if (pProtect && pProtect->isProtected() && getDefaultVersion() > SvtSaveOptions::ODFVER_012)
2881 if (pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS))
2882 AddAttribute(XML_NAMESPACE_LO_EXT, XML_SELECT_PROTECTED_CELLS, XML_TRUE);
2883 if (pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS))
2884 AddAttribute(XML_NAMESPACE_LO_EXT, XML_SELECT_UNPROTECTED_CELLS, XML_TRUE);
2886 if (pProtect->isOptionEnabled(ScTableProtection::INSERT_COLUMNS))
2887 AddAttribute(XML_NAMESPACE_LO_EXT, XML_INSERT_COLUMNS, XML_TRUE);
2888 if (pProtect->isOptionEnabled(ScTableProtection::INSERT_ROWS))
2889 AddAttribute(XML_NAMESPACE_LO_EXT, XML_INSERT_ROWS, XML_TRUE);
2891 if (pProtect->isOptionEnabled(ScTableProtection::DELETE_COLUMNS))
2892 AddAttribute(XML_NAMESPACE_LO_EXT, XML_DELETE_COLUMNS, XML_TRUE);
2893 if (pProtect->isOptionEnabled(ScTableProtection::DELETE_ROWS))
2894 AddAttribute(XML_NAMESPACE_LO_EXT, XML_DELETE_ROWS, XML_TRUE);
2896 OUString aElemName = GetNamespaceMap().GetQNameByKey(
2897 XML_NAMESPACE_LO_EXT, GetXMLToken(XML_TABLE_PROTECTION));
2899 SvXMLElementExport aElemProtected(*this, aElemName, true, true);
2902 CheckAttrList();
2904 if ( pDoc && pDoc->GetSheetEvents( static_cast<SCTAB>(nTable) ) &&
2905 getDefaultVersion() >= SvtSaveOptions::ODFVER_012 )
2907 // store sheet events
2908 uno::Reference<document::XEventsSupplier> xSupplier(xTable, uno::UNO_QUERY);
2909 uno::Reference<container::XNameAccess> xEvents = xSupplier->getEvents();
2910 GetEventExport().ExportExt( xEvents );
2913 WriteTableSource();
2914 WriteScenario();
2915 uno::Reference<drawing::XDrawPage> xDrawPage;
2916 if (pSharedData->HasForm(nTable, xDrawPage) && xDrawPage.is())
2918 ::xmloff::OOfficeFormsExport aForms(*this);
2919 GetFormExport()->exportForms( xDrawPage );
2920 bool bRet(GetFormExport()->seekPage( xDrawPage ));
2921 OSL_ENSURE( bRet, "OFormLayerXMLExport::seekPage failed!" );
2923 if (pSharedData->HasDrawPage())
2925 GetShapeExport()->seekShapes(pSharedData->GetDrawPage(nTable));
2926 WriteTableShapes();
2928 table::CellRangeAddress aRange(GetEndAddress(xTable));
2929 pSharedData->SetLastColumn(nTable, aRange.EndColumn);
2930 pSharedData->SetLastRow(nTable, aRange.EndRow);
2931 mpCellsItr->SetCurrentTable(static_cast<SCTAB>(nTable), xCurrentTable);
2932 pGroupColumns->NewTable();
2933 pGroupRows->NewTable();
2934 FillColumnRowGroups();
2935 if (bHasColumnHeader)
2936 pSharedData->SetLastColumn(nTable, aColumnHeaderRange.aEnd.Col());
2937 bRowHeaderOpen = false;
2938 if (bHasRowHeader)
2939 pSharedData->SetLastRow(nTable, aRowHeaderRange.aEnd.Row());
2940 pDefaults->FillDefaultStyles(nTable, pSharedData->GetLastRow(nTable),
2941 pSharedData->GetLastColumn(nTable), pCellStyles.get(), pDoc);
2942 pRowFormatRanges->SetColDefaults(&pDefaults->GetColDefaults());
2943 pCellStyles->SetColDefaults(&pDefaults->GetColDefaults());
2944 ExportColumns(nTable, aColumnHeaderRange, bHasColumnHeader);
2945 bool bIsFirst(true);
2946 sal_Int32 nEqualCells(0);
2947 ScMyCell aCell;
2948 ScMyCell aPrevCell;
2949 while (mpCellsItr->GetNext(aCell, pCellStyles.get()))
2951 if (bIsFirst)
2953 ExportFormatRanges(0, 0, aCell.maCellAddress.Col()-1, aCell.maCellAddress.Row(), nTable);
2954 aPrevCell = aCell;
2955 bIsFirst = false;
2957 else
2959 if ((aPrevCell.maCellAddress.Row() == aCell.maCellAddress.Row()) &&
2960 (aPrevCell.maCellAddress.Col() + nEqualCells + 1 == aCell.maCellAddress.Col()))
2962 if(IsCellEqual(aPrevCell, aCell))
2963 ++nEqualCells;
2964 else
2966 WriteCell(aPrevCell, nEqualCells);
2967 nEqualCells = 0;
2968 aPrevCell = aCell;
2971 else
2973 WriteCell(aPrevCell, nEqualCells);
2974 ExportFormatRanges(aPrevCell.maCellAddress.Col() + nEqualCells + 1, aPrevCell.maCellAddress.Row(),
2975 aCell.maCellAddress.Col()-1, aCell.maCellAddress.Row(), nTable);
2976 nEqualCells = 0;
2977 aPrevCell = aCell;
2981 if (!bIsFirst)
2983 WriteCell(aPrevCell, nEqualCells);
2984 ExportFormatRanges(aPrevCell.maCellAddress.Col() + nEqualCells + 1, aPrevCell.maCellAddress.Row(),
2985 pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
2987 else
2988 ExportFormatRanges(0, 0, pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
2990 CloseRow(pSharedData->GetLastRow(nTable));
2992 if (pDoc)
2994 // Export sheet-local named ranges.
2995 ScRangeName* pRangeName = pDoc->GetRangeName(nTable);
2996 if (pRangeName && !pRangeName->empty())
2998 WriteNamedRange(pRangeName);
3001 if(getDefaultVersion() > SvtSaveOptions::ODFVER_012)
3003 //export new conditional format information
3004 ExportConditionalFormat(nTable);
3010 namespace {
3012 void writeContent(
3013 ScXMLExport& rExport, const OUString& rStyleName, const OUString& rContent, const SvxFieldData* pField )
3015 std::unique_ptr<SvXMLElementExport> pElem;
3016 if (!rStyleName.isEmpty())
3018 // Formatted section with automatic style.
3019 rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME, rStyleName);
3020 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3021 XML_NAMESPACE_TEXT, GetXMLToken(XML_SPAN));
3022 pElem.reset(new SvXMLElementExport(rExport, aElemName, false, false));
3025 if (pField)
3027 // Write a field item.
3028 OUString aFieldVal = ScEditUtil::GetCellFieldValue(*pField, rExport.GetDocument(), nullptr);
3029 switch (pField->GetClassId())
3031 case text::textfield::Type::URL:
3033 // <text:a xlink:href="url" xlink:type="simple">value</text:a>
3035 const SvxURLField* pURLField = static_cast<const SvxURLField*>(pField);
3036 const OUString& aURL = pURLField->GetURL();
3037 rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, rExport.GetRelativeReference(aURL));
3038 rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, "simple");
3039 const OUString& aTargetFrame = pURLField->GetTargetFrame();
3040 if (!aTargetFrame.isEmpty())
3041 rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_TARGET_FRAME_NAME, aTargetFrame);
3043 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3044 XML_NAMESPACE_TEXT, GetXMLToken(XML_A));
3045 SvXMLElementExport aElem(rExport, aElemName, false, false);
3046 rExport.Characters(aFieldVal);
3048 break;
3049 case text::textfield::Type::DATE:
3051 // <text:date style:data-style-name="N2" text:date-value="YYYY-MM-DD">value</text:date>
3053 Date aDate(Date::SYSTEM);
3054 OUStringBuffer aBuf;
3055 sal_Int32 nVal = aDate.GetYear();
3056 aBuf.append(nVal);
3057 aBuf.append('-');
3058 nVal = aDate.GetMonth();
3059 if (nVal < 10)
3060 aBuf.append('0');
3061 aBuf.append(nVal);
3062 aBuf.append('-');
3063 nVal = aDate.GetDay();
3064 if (nVal < 10)
3065 aBuf.append('0');
3066 aBuf.append(nVal);
3067 rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_DATA_STYLE_NAME, "N2");
3068 rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_DATE_VALUE, aBuf.makeStringAndClear());
3070 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3071 XML_NAMESPACE_TEXT, GetXMLToken(XML_DATE));
3072 SvXMLElementExport aElem(rExport, aElemName, false, false);
3073 rExport.Characters(aFieldVal);
3075 break;
3076 case text::textfield::Type::DOCINFO_TITLE:
3078 // <text:title>value</text:title>
3080 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3081 XML_NAMESPACE_TEXT, GetXMLToken(XML_TITLE));
3082 SvXMLElementExport aElem(rExport, aElemName, false, false);
3083 rExport.Characters(aFieldVal);
3085 break;
3086 case text::textfield::Type::TABLE:
3088 // <text:sheet-name>value</text:sheet-name>
3090 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3091 XML_NAMESPACE_TEXT, GetXMLToken(XML_SHEET_NAME));
3092 SvXMLElementExport aElem(rExport, aElemName, false, false);
3093 rExport.Characters(aFieldVal);
3095 break;
3096 default:
3097 rExport.Characters(aFieldVal);
3100 else
3101 rExport.Characters(rContent);
3104 void flushParagraph(
3105 ScXMLExport& rExport, const OUString& rParaText,
3106 rtl::Reference<XMLPropertySetMapper> const & xMapper, rtl::Reference<SvXMLAutoStylePoolP> const & xStylePool,
3107 const ScXMLEditAttributeMap& rAttrMap,
3108 std::vector<editeng::Section>::const_iterator it, std::vector<editeng::Section>::const_iterator const & itEnd )
3110 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3111 XML_NAMESPACE_TEXT, GetXMLToken(XML_P));
3112 SvXMLElementExport aElemP(rExport, aElemName, false, false);
3114 for (; it != itEnd; ++it)
3116 const editeng::Section& rSec = *it;
3118 OUString aContent(rParaText.copy(rSec.mnStart, rSec.mnEnd - rSec.mnStart));
3120 std::vector<XMLPropertyState> aPropStates;
3121 const SvxFieldData* pField = toXMLPropertyStates(aPropStates, rSec.maAttributes, xMapper, rAttrMap);
3122 OUString aStyleName = xStylePool->Find(XML_STYLE_FAMILY_TEXT_TEXT, OUString(), aPropStates);
3123 writeContent(rExport, aStyleName, aContent, pField);
3129 void ScXMLExport::WriteCell(ScMyCell& aCell, sal_Int32 nEqualCellCount)
3131 // nEqualCellCount is the number of additional cells
3132 SetRepeatAttribute(nEqualCellCount, (aCell.nType != table::CellContentType_EMPTY));
3134 if (aCell.nStyleIndex != -1)
3135 AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(aCell.nStyleIndex, aCell.bIsAutoStyle));
3136 if (aCell.nValidationIndex > -1)
3137 AddAttribute(XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, pValidationsContainer->GetValidationName(aCell.nValidationIndex));
3138 const bool bIsFirstMatrixCell(aCell.bIsMatrixBase);
3139 if (bIsFirstMatrixCell)
3141 SCCOL nColumns( aCell.aMatrixRange.aEnd.Col() - aCell.aMatrixRange.aStart.Col() + 1 );
3142 SCROW nRows( aCell.aMatrixRange.aEnd.Row() - aCell.aMatrixRange.aStart.Row() + 1 );
3143 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_COLUMNS_SPANNED, OUString::number(nColumns));
3144 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_ROWS_SPANNED, OUString::number(nRows));
3146 bool bIsEmpty(false);
3147 switch (aCell.nType)
3149 case table::CellContentType_EMPTY :
3151 bIsEmpty = true;
3153 break;
3154 case table::CellContentType_VALUE :
3156 GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3157 aCell.nNumberFormat, aCell.maBaseCell.mfValue);
3158 if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3159 GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3160 aCell.nNumberFormat, aCell.maBaseCell.mfValue, false, XML_NAMESPACE_CALC_EXT, false);
3162 break;
3163 case table::CellContentType_TEXT :
3165 OUString sFormattedString(lcl_GetFormattedString(pDoc, aCell.maBaseCell, aCell.maCellAddress));
3166 OUString sCellString = aCell.maBaseCell.getString(pDoc);
3167 GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3168 sCellString, sFormattedString);
3169 if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3170 GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3171 sCellString, sFormattedString, false, XML_NAMESPACE_CALC_EXT);
3173 break;
3174 case table::CellContentType_FORMULA :
3176 if (aCell.maBaseCell.meType == CELLTYPE_FORMULA)
3178 const bool bIsMatrix(bIsFirstMatrixCell || aCell.bIsMatrixCovered);
3179 ScFormulaCell* pFormulaCell = aCell.maBaseCell.mpFormula;
3180 if (!bIsMatrix || bIsFirstMatrixCell)
3182 if (!mpCompileFormulaCxt)
3184 const formula::FormulaGrammar::Grammar eGrammar = pDoc->GetStorageGrammar();
3185 mpCompileFormulaCxt.reset(new sc::CompileFormulaContext(pDoc, eGrammar));
3188 OUString aFormula = pFormulaCell->GetFormula(*mpCompileFormulaCxt);
3189 sal_uInt16 nNamespacePrefix =
3190 (mpCompileFormulaCxt->getGrammar() == formula::FormulaGrammar::GRAM_ODFF ? XML_NAMESPACE_OF : XML_NAMESPACE_OOOC);
3192 if (!bIsMatrix)
3194 AddAttribute(sAttrFormula, GetNamespaceMap().GetQNameByKey(nNamespacePrefix, aFormula, false));
3196 else
3198 AddAttribute(sAttrFormula, GetNamespaceMap().GetQNameByKey(nNamespacePrefix, aFormula.copy(1, aFormula.getLength()-2), false));
3201 if (pFormulaCell->GetErrCode() != FormulaError::NONE)
3203 AddAttribute(sAttrValueType, XML_STRING);
3204 AddAttribute(sAttrStringValue, aCell.maBaseCell.getString(pDoc));
3205 if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3207 //export calcext:value-type="error"
3208 AddAttribute(XML_NAMESPACE_CALC_EXT,XML_VALUE_TYPE, OUString("error"));
3211 else if (pFormulaCell->IsValue())
3213 bool bIsStandard;
3214 OUString sCurrency;
3215 GetNumberFormatAttributesExportHelper()->GetCellType(aCell.nNumberFormat, sCurrency, bIsStandard);
3216 if (pDoc)
3218 GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3219 aCell.nNumberFormat, pDoc->GetValue(aCell.maCellAddress));
3220 if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3222 GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3223 aCell.nNumberFormat, pDoc->GetValue(aCell.maCellAddress), false, XML_NAMESPACE_CALC_EXT, false );
3227 else
3229 if (!aCell.maBaseCell.getString(pDoc).isEmpty())
3231 AddAttribute(sAttrValueType, XML_STRING);
3232 AddAttribute(sAttrStringValue, aCell.maBaseCell.getString(pDoc));
3233 if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3235 AddAttribute(XML_NAMESPACE_CALC_EXT,XML_VALUE_TYPE, XML_STRING);
3241 break;
3242 default:
3243 break;
3245 OUString* pCellString(&sElemCell);
3246 if (aCell.bIsCovered)
3248 pCellString = &sElemCoveredCell;
3250 else
3252 if (aCell.bIsMergedBase)
3254 SCCOL nColumns( aCell.aMergeRange.aEnd.Col() - aCell.aMergeRange.aStart.Col() + 1 );
3255 SCROW nRows( aCell.aMergeRange.aEnd.Row() - aCell.aMergeRange.aStart.Row() + 1 );
3256 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED, OUString::number(nColumns));
3257 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED, OUString::number(nRows));
3260 SvXMLElementExport aElemC(*this, *pCellString, true, true);
3261 CheckAttrList();
3262 WriteAreaLink(aCell);
3263 WriteAnnotation(aCell);
3264 WriteDetective(aCell);
3266 if (!bIsEmpty)
3268 if (aCell.maBaseCell.meType == CELLTYPE_EDIT)
3270 WriteEditCell(aCell.maBaseCell.mpEditText);
3272 else if (aCell.maBaseCell.meType == CELLTYPE_FORMULA && aCell.maBaseCell.mpFormula->IsMultilineResult())
3274 WriteMultiLineFormulaResult(aCell.maBaseCell.mpFormula);
3276 else
3278 SvXMLElementExport aElemP(*this, sElemP, true, false);
3280 OUString aParaStr =
3281 ScCellFormat::GetOutputString(*pDoc, aCell.maCellAddress, aCell.maBaseCell);
3283 bool bPrevCharWasSpace = true;
3284 GetTextParagraphExport()->exportCharacterData(aParaStr, bPrevCharWasSpace);
3287 WriteShapes(aCell);
3288 if (!bIsEmpty)
3289 IncrementProgressBar(false);
3292 void ScXMLExport::WriteEditCell(const EditTextObject* pText)
3294 rtl::Reference<XMLPropertySetMapper> xMapper = GetTextParagraphExport()->GetTextPropMapper()->getPropertySetMapper();
3295 rtl::Reference<SvXMLAutoStylePoolP> xStylePool = GetAutoStylePool();
3296 const ScXMLEditAttributeMap& rAttrMap = GetEditAttributeMap();
3298 // Get raw paragraph texts first.
3299 std::vector<OUString> aParaTexts;
3300 sal_Int32 nParaCount = pText->GetParagraphCount();
3301 aParaTexts.reserve(nParaCount);
3302 for (sal_Int32 i = 0; i < nParaCount; ++i)
3303 aParaTexts.push_back(pText->GetText(i));
3305 // Get all section data and iterate through them.
3306 std::vector<editeng::Section> aAttrs;
3307 pText->GetAllSections(aAttrs);
3308 std::vector<editeng::Section>::const_iterator itSec = aAttrs.begin(), itSecEnd = aAttrs.end();
3309 std::vector<editeng::Section>::const_iterator itPara = itSec;
3310 sal_Int32 nCurPara = 0; // current paragraph
3311 for (; itSec != itSecEnd; ++itSec)
3313 const editeng::Section& rSec = *itSec;
3314 if (nCurPara == rSec.mnParagraph)
3315 // Still in the same paragraph.
3316 continue;
3318 // Start of a new paragraph. Flush the old paragraph.
3319 flushParagraph(*this, aParaTexts[nCurPara], xMapper, xStylePool, rAttrMap, itPara, itSec);
3320 nCurPara = rSec.mnParagraph;
3321 itPara = itSec;
3324 flushParagraph(*this, aParaTexts[nCurPara], xMapper, xStylePool, rAttrMap, itPara, itSecEnd);
3327 void ScXMLExport::WriteMultiLineFormulaResult(const ScFormulaCell* pCell)
3329 OUString aElemName = GetNamespaceMap().GetQNameByKey(XML_NAMESPACE_TEXT, GetXMLToken(XML_P));
3331 OUString aResStr = pCell->GetResultString().getString();
3332 const sal_Unicode* p = aResStr.getStr();
3333 const sal_Unicode* pEnd = p + static_cast<size_t>(aResStr.getLength());
3334 const sal_Unicode* pPara = p; // paragraph head.
3335 for (; p != pEnd; ++p)
3337 if (*p != '\n')
3338 continue;
3340 // flush the paragraph.
3341 OUString aContent;
3342 if (*pPara == '\n')
3343 ++pPara;
3344 if (p > pPara)
3345 aContent = OUString(pPara, p-pPara);
3347 SvXMLElementExport aElem(*this, aElemName, false, false);
3348 Characters(aContent);
3350 pPara = p;
3353 OUString aContent;
3354 if (*pPara == '\n')
3355 ++pPara;
3356 if (pEnd > pPara)
3357 aContent = OUString(pPara, pEnd-pPara);
3359 SvXMLElementExport aElem(*this, aElemName, false, false);
3360 Characters(aContent);
3363 void ScXMLExport::ExportShape(const uno::Reference < drawing::XShape >& xShape, awt::Point* pPoint)
3365 uno::Reference < beans::XPropertySet > xShapeProps ( xShape, uno::UNO_QUERY );
3366 bool bIsChart( false );
3367 OUString sPropCLSID ("CLSID");
3368 if (xShapeProps.is())
3370 sal_Int32 nZOrder = 0;
3371 if (xShapeProps->getPropertyValue("ZOrder") >>= nZOrder)
3373 AddAttribute(XML_NAMESPACE_DRAW, XML_ZINDEX, OUString::number(nZOrder));
3375 uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xShapeProps->getPropertySetInfo();
3376 if( xPropSetInfo->hasPropertyByName( sPropCLSID ) )
3378 OUString sCLSID;
3379 if (xShapeProps->getPropertyValue( sPropCLSID ) >>= sCLSID)
3381 if ( sCLSID.equalsIgnoreAsciiCase(GetChartExport()->getChartCLSID()) )
3383 // we have a chart
3384 OUString sRanges;
3385 if ( pDoc )
3387 OUString aChartName;
3388 xShapeProps->getPropertyValue( "PersistName" ) >>= aChartName;
3389 ScChartListenerCollection* pCollection = pDoc->GetChartListenerCollection();
3390 if (pCollection)
3392 ScChartListener* pListener = pCollection->findByName(aChartName);
3393 if (pListener)
3395 const ScRangeListRef& rRangeList = pListener->GetRangeList();
3396 if ( rRangeList.is() )
3398 ScRangeStringConverter::GetStringFromRangeList( sRanges, rRangeList.get(), pDoc, FormulaGrammar::CONV_OOO );
3399 if ( !sRanges.isEmpty() )
3401 bIsChart = true;
3402 SvXMLAttributeList* pAttrList = new SvXMLAttributeList();
3403 pAttrList->AddAttribute(
3404 GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_DRAW, GetXMLToken( XML_NOTIFY_ON_UPDATE_OF_RANGES ) ), sRanges );
3405 GetShapeExport()->exportShape( xShape, SEF_DEFAULT, pPoint, pAttrList );
3412 if ( sRanges.isEmpty() )
3414 uno::Reference< frame::XModel > xChartModel;
3415 if( ( xShapeProps->getPropertyValue( "Model" ) >>= xChartModel ) &&
3416 xChartModel.is())
3418 uno::Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY );
3419 uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartModel, uno::UNO_QUERY );
3420 if( xChartDoc.is() && xReceiver.is() &&
3421 ! xChartDoc->hasInternalDataProvider())
3423 // we have a chart that gets its data from Calc
3424 bIsChart = true;
3425 uno::Sequence< OUString > aRepresentations(
3426 xReceiver->getUsedRangeRepresentations());
3427 SvXMLAttributeList* pAttrList = nullptr;
3428 if(aRepresentations.hasElements())
3430 // add the ranges used by the chart to the shape
3431 // element to be able to start listening after
3432 // load (when the chart is not yet loaded)
3433 uno::Reference< chart2::data::XRangeXMLConversion > xRangeConverter( xChartDoc->getDataProvider(), uno::UNO_QUERY );
3434 sRanges = lcl_RangeSequenceToString( aRepresentations, xRangeConverter );
3435 pAttrList = new SvXMLAttributeList();
3436 pAttrList->AddAttribute(
3437 GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_DRAW, GetXMLToken(XML_NOTIFY_ON_UPDATE_OF_RANGES) ), sRanges );
3439 GetShapeExport()->exportShape(xShape, SEF_DEFAULT, pPoint, pAttrList);
3447 if (!bIsChart)
3449 OUString sHlink;
3452 uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );
3453 if ( xProps.is() )
3454 xProps->getPropertyValue( SC_UNONAME_HYPERLINK ) >>= sHlink;
3456 catch ( const beans::UnknownPropertyException& )
3458 // no hyperlink property
3461 std::unique_ptr< SvXMLElementExport > pDrawA;
3462 // enclose shapes with <draw:a> element only if sHlink contains something
3463 if ( !sHlink.isEmpty() )
3465 // need to get delete the attributes that are pre-loaded
3466 // for the shape export ( otherwise they will become
3467 // attributes of the draw:a element ) This *shouldn't*
3468 // affect performance adversely as there are only a
3469 // couple of attributes involved
3470 uno::Reference< xml::sax::XAttributeList > xSaveAttribs( new SvXMLAttributeList( GetAttrList() ) );
3471 ClearAttrList();
3472 // Add Hlink
3473 AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
3474 AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sHlink);
3475 pDrawA.reset( new SvXMLElementExport( *this, XML_NAMESPACE_DRAW, XML_A, false, false ) );
3476 // Attribute list has been cleared by previous operation
3477 // re-add pre-loaded attributes
3478 AddAttributeList( xSaveAttribs );
3480 GetShapeExport()->exportShape(xShape, SEF_DEFAULT, pPoint);
3482 IncrementProgressBar(false);
3485 void ScXMLExport::WriteShapes(const ScMyCell& rMyCell)
3487 if( rMyCell.bHasShape && !rMyCell.aShapeList.empty() && pDoc )
3489 awt::Point aPoint;
3490 tools::Rectangle aRect = pDoc->GetMMRect(rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(),
3491 rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(), rMyCell.maCellAddress.Tab());
3492 bool bNegativePage = pDoc->IsNegativePage(rMyCell.maCellAddress.Tab());
3493 if (bNegativePage)
3494 aPoint.X = aRect.Right();
3495 else
3496 aPoint.X = aRect.Left();
3497 aPoint.Y = aRect.Top();
3498 for (const auto& rShape : rMyCell.aShapeList)
3500 if (rShape.xShape.is())
3502 if (bNegativePage)
3503 aPoint.X = 2 * rShape.xShape->getPosition().X + rShape.xShape->getSize().Width - aPoint.X;
3505 // We only write the end address if we want the shape to resize with the cell
3506 if ( rShape.bResizeWithCell &&
3507 rShape.xShape->getShapeType() != "com.sun.star.drawing.CaptionShape" )
3509 OUString sEndAddress;
3510 ScRangeStringConverter::GetStringFromAddress(sEndAddress, rShape.aEndAddress, pDoc, FormulaGrammar::CONV_OOO);
3511 AddAttribute(XML_NAMESPACE_TABLE, XML_END_CELL_ADDRESS, sEndAddress);
3512 OUStringBuffer sBuffer;
3513 GetMM100UnitConverter().convertMeasureToXML(
3514 sBuffer, rShape.nEndX);
3515 AddAttribute(XML_NAMESPACE_TABLE, XML_END_X, sBuffer.makeStringAndClear());
3516 GetMM100UnitConverter().convertMeasureToXML(
3517 sBuffer, rShape.nEndY);
3518 AddAttribute(XML_NAMESPACE_TABLE, XML_END_Y, sBuffer.makeStringAndClear());
3520 ExportShape(rShape.xShape, &aPoint);
3526 void ScXMLExport::WriteTableShapes()
3528 ScMyTableShapes* pTableShapes(pSharedData->GetTableShapes());
3529 if (pTableShapes && !(*pTableShapes)[nCurrentTable].empty())
3531 OSL_ENSURE(pTableShapes->size() > static_cast<size_t>(nCurrentTable), "wrong Table");
3532 SvXMLElementExport aShapesElem(*this, XML_NAMESPACE_TABLE, XML_SHAPES, true, false);
3533 for (const auto& rxShape : (*pTableShapes)[nCurrentTable])
3535 if (rxShape.is())
3537 if (pDoc->IsNegativePage(static_cast<SCTAB>(nCurrentTable)))
3539 awt::Point aPoint(rxShape->getPosition());
3540 awt::Size aSize(rxShape->getSize());
3541 aPoint.X += aPoint.X + aSize.Width;
3542 aPoint.Y = 0;
3543 ExportShape(rxShape, &aPoint);
3545 else
3546 ExportShape(rxShape, nullptr);
3549 (*pTableShapes)[nCurrentTable].clear();
3553 void ScXMLExport::WriteAreaLink( const ScMyCell& rMyCell )
3555 if( rMyCell.bHasAreaLink )
3557 const ScMyAreaLink& rAreaLink = rMyCell.aAreaLink;
3558 AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, rAreaLink.sSourceStr );
3559 AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
3560 AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, GetRelativeReference(rAreaLink.sURL) );
3561 AddAttribute( XML_NAMESPACE_TABLE, XML_FILTER_NAME, rAreaLink.sFilter );
3562 if( !rAreaLink.sFilterOptions.isEmpty() )
3563 AddAttribute( XML_NAMESPACE_TABLE, XML_FILTER_OPTIONS, rAreaLink.sFilterOptions );
3564 OUStringBuffer sValue;
3565 AddAttribute( XML_NAMESPACE_TABLE, XML_LAST_COLUMN_SPANNED, OUString::number(rAreaLink.GetColCount()) );
3566 AddAttribute( XML_NAMESPACE_TABLE, XML_LAST_ROW_SPANNED, OUString::number(rAreaLink.GetRowCount()) );
3567 if( rAreaLink.nRefresh )
3569 ::sax::Converter::convertDuration( sValue,
3570 static_cast<double>(rAreaLink.nRefresh) / 86400 );
3571 AddAttribute( XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, sValue.makeStringAndClear() );
3573 SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_CELL_RANGE_SOURCE, true, true );
3577 void ScXMLExport::exportAnnotationMeta( const uno::Reference < drawing::XShape >& xShape)
3579 ScPostIt* pNote = pCurrentCell->pNote;
3581 if (pNote)
3583 // TODO : notes
3584 //is it still useful, as this call back is only called from ScXMLExport::WriteAnnotation
3585 // and should be in sync with pCurrentCell
3586 SdrCaptionObj* pNoteCaption = pNote->GetOrCreateCaption(pCurrentCell->maCellAddress);
3587 uno::Reference<drawing::XShape> xCurrentShape( pNoteCaption->getUnoShape(), uno::UNO_QUERY );
3588 if (xCurrentShape.get()!=xShape.get())
3589 return;
3591 const OUString& sAuthor(pNote->GetAuthor());
3592 if (!sAuthor.isEmpty())
3594 SvXMLElementExport aCreatorElem( *this, XML_NAMESPACE_DC,
3595 XML_CREATOR, true,
3596 false );
3597 Characters(sAuthor);
3600 const OUString& aDate(pNote->GetDate());
3601 if (pDoc)
3603 SvNumberFormatter* pNumForm = pDoc->GetFormatTable();
3604 double fDate;
3605 sal_uInt32 nfIndex = pNumForm->GetFormatIndex(NF_DATE_SYS_DDMMYYYY, LANGUAGE_SYSTEM);
3606 if (pNumForm->IsNumberFormat(aDate, nfIndex, fDate))
3608 OUStringBuffer sBuf;
3609 GetMM100UnitConverter().convertDateTime(sBuf, fDate,true);
3610 SvXMLElementExport aDateElem( *this, XML_NAMESPACE_DC,
3611 XML_DATE, true,
3612 false );
3613 Characters(sBuf.makeStringAndClear());
3615 else
3617 SvXMLElementExport aDateElem( *this, XML_NAMESPACE_META,
3618 XML_DATE_STRING, true,
3619 false );
3620 Characters(aDate);
3623 else
3625 SvXMLElementExport aDateElem( *this, XML_NAMESPACE_META,
3626 XML_DATE_STRING, true,
3627 false );
3628 Characters(aDate);
3633 void ScXMLExport::WriteAnnotation(ScMyCell& rMyCell)
3635 ScPostIt* pNote = pDoc->GetNote(rMyCell.maCellAddress);
3636 if (pNote)
3638 if (pNote->IsCaptionShown())
3639 AddAttribute(XML_NAMESPACE_OFFICE, XML_DISPLAY, XML_TRUE);
3641 pCurrentCell = &rMyCell;
3643 SdrCaptionObj* pNoteCaption = pNote->GetOrCreateCaption(rMyCell.maCellAddress);
3644 if (pNoteCaption)
3646 uno::Reference<drawing::XShape> xShape( pNoteCaption->getUnoShape(), uno::UNO_QUERY );
3647 if (xShape.is())
3648 GetShapeExport()->exportShape(xShape, SEF_DEFAULT|XMLShapeExportFlags::ANNOTATION);
3651 pCurrentCell = nullptr;
3656 void ScXMLExport::WriteDetective( const ScMyCell& rMyCell )
3658 if( rMyCell.bHasDetectiveObj || rMyCell.bHasDetectiveOp )
3660 const ScMyDetectiveObjVec& rObjVec = rMyCell.aDetectiveObjVec;
3661 const ScMyDetectiveOpVec& rOpVec = rMyCell.aDetectiveOpVec;
3662 sal_Int32 nObjCount(rObjVec.size());
3663 sal_Int32 nOpCount(rOpVec.size());
3664 if( nObjCount || nOpCount )
3666 SvXMLElementExport aDetElem( *this, XML_NAMESPACE_TABLE, XML_DETECTIVE, true, true );
3667 OUString sString;
3668 for(const auto& rObj : rObjVec)
3670 if (rObj.eObjType != SC_DETOBJ_CIRCLE)
3672 if( (rObj.eObjType == SC_DETOBJ_ARROW) || (rObj.eObjType == SC_DETOBJ_TOOTHERTAB))
3674 ScRangeStringConverter::GetStringFromRange( sString, rObj.aSourceRange, pDoc, FormulaGrammar::CONV_OOO );
3675 AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, sString );
3677 ScXMLConverter::GetStringFromDetObjType( sString, rObj.eObjType );
3678 AddAttribute( XML_NAMESPACE_TABLE, XML_DIRECTION, sString );
3679 if( rObj.bHasError )
3680 AddAttribute( XML_NAMESPACE_TABLE, XML_CONTAINS_ERROR, XML_TRUE );
3682 else
3683 AddAttribute( XML_NAMESPACE_TABLE, XML_MARKED_INVALID, XML_TRUE );
3684 SvXMLElementExport aRangeElem( *this, XML_NAMESPACE_TABLE, XML_HIGHLIGHTED_RANGE, true, true );
3686 for(const auto& rOp : rOpVec)
3688 OUString sOpString;
3689 ScXMLConverter::GetStringFromDetOpType( sOpString, rOp.eOpType );
3690 AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, sOpString );
3691 AddAttribute( XML_NAMESPACE_TABLE, XML_INDEX, OUString::number(rOp.nIndex) );
3692 SvXMLElementExport aRangeElem( *this, XML_NAMESPACE_TABLE, XML_OPERATION, true, true );
3698 void ScXMLExport::SetRepeatAttribute(sal_Int32 nEqualCellCount, bool bIncProgress)
3700 // nEqualCellCount is additional cells, so the attribute value is nEqualCellCount+1
3701 if (nEqualCellCount > 0)
3703 sal_Int32 nTemp(nEqualCellCount + 1);
3704 OUString sOUEqualCellCount(OUString::number(nTemp));
3705 AddAttribute(sAttrColumnsRepeated, sOUEqualCellCount);
3706 if (bIncProgress)
3707 IncrementProgressBar(false, nEqualCellCount);
3711 bool ScXMLExport::IsEditCell(const ScMyCell& rCell)
3713 return rCell.maBaseCell.meType == CELLTYPE_EDIT;
3716 bool ScXMLExport::IsCellEqual (const ScMyCell& aCell1, const ScMyCell& aCell2)
3718 bool bIsEqual = false;
3719 if( !aCell1.bIsMergedBase && !aCell2.bIsMergedBase &&
3720 aCell1.bIsCovered == aCell2.bIsCovered &&
3721 !aCell1.bIsMatrixBase && !aCell2.bIsMatrixBase &&
3722 aCell1.bIsMatrixCovered == aCell2.bIsMatrixCovered &&
3723 aCell1.bHasAnnotation == aCell2.bHasAnnotation &&
3724 !aCell1.bHasShape && !aCell2.bHasShape &&
3725 aCell1.bHasAreaLink == aCell2.bHasAreaLink &&
3726 !aCell1.bHasDetectiveObj && !aCell2.bHasDetectiveObj)
3728 if( (aCell1.bHasAreaLink &&
3729 (aCell1.aAreaLink.GetColCount() == 1) &&
3730 (aCell2.aAreaLink.GetColCount() == 1) &&
3731 aCell1.aAreaLink.Compare( aCell2.aAreaLink ) ) ||
3732 !aCell1.bHasAreaLink )
3734 if (!aCell1.bHasAnnotation)
3736 if ((((aCell1.nStyleIndex == aCell2.nStyleIndex) && (aCell1.bIsAutoStyle == aCell2.bIsAutoStyle)) ||
3737 ((aCell1.nStyleIndex == aCell2.nStyleIndex) && (aCell1.nStyleIndex == -1))) &&
3738 aCell1.nValidationIndex == aCell2.nValidationIndex &&
3739 aCell1.nType == aCell2.nType)
3741 switch ( aCell1.nType )
3743 case table::CellContentType_EMPTY :
3745 bIsEqual = true;
3747 break;
3748 case table::CellContentType_VALUE :
3750 // #i29101# number format may be different from column default styles,
3751 // but can lead to different value types, so it must also be compared
3752 bIsEqual = (aCell1.nNumberFormat == aCell2.nNumberFormat) &&
3753 (aCell1.maBaseCell.mfValue == aCell2.maBaseCell.mfValue);
3755 break;
3756 case table::CellContentType_TEXT :
3758 if (IsEditCell(aCell1) || IsEditCell(aCell2))
3759 bIsEqual = false;
3760 else
3762 bIsEqual = (aCell1.maBaseCell.getString(pDoc) == aCell2.maBaseCell.getString(pDoc));
3765 break;
3766 case table::CellContentType_FORMULA :
3768 bIsEqual = false;
3770 break;
3771 default :
3773 bIsEqual = false;
3775 break;
3781 return bIsEqual;
3784 void ScXMLExport::WriteCalculationSettings(const uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc)
3786 uno::Reference<beans::XPropertySet> xPropertySet(xSpreadDoc, uno::UNO_QUERY);
3787 if (xPropertySet.is())
3789 bool bCalcAsShown (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_CALCASSHOWN) ));
3790 bool bIgnoreCase (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_IGNORECASE) ));
3791 bool bLookUpLabels (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_LOOKUPLABELS) ));
3792 bool bMatchWholeCell (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_MATCHWHOLE) ));
3793 bool bUseRegularExpressions (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_REGEXENABLED) ));
3794 bool bUseWildcards (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_WILDCARDSENABLED) ));
3795 if (bUseWildcards && bUseRegularExpressions)
3796 bUseRegularExpressions = false; // mutually exclusive, wildcards take precedence
3797 bool bIsIterationEnabled (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_ITERENABLED) ));
3798 sal_uInt16 nYear2000 (pDoc ? pDoc->GetDocOptions().GetYear2000() : 0);
3799 sal_Int32 nIterationCount(100);
3800 xPropertySet->getPropertyValue( SC_UNO_ITERCOUNT ) >>= nIterationCount;
3801 double fIterationEpsilon = 0;
3802 xPropertySet->getPropertyValue( SC_UNO_ITEREPSILON ) >>= fIterationEpsilon;
3803 util::Date aNullDate;
3804 xPropertySet->getPropertyValue( SC_UNO_NULLDATE ) >>= aNullDate;
3805 if (bCalcAsShown || bIgnoreCase || !bLookUpLabels || !bMatchWholeCell || !bUseRegularExpressions ||
3806 bUseWildcards ||
3807 bIsIterationEnabled || nIterationCount != 100 || !::rtl::math::approxEqual(fIterationEpsilon, 0.001) ||
3808 aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899 || nYear2000 != 1930)
3810 if (bIgnoreCase)
3811 AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_FALSE);
3812 if (bCalcAsShown)
3813 AddAttribute(XML_NAMESPACE_TABLE, XML_PRECISION_AS_SHOWN, XML_TRUE);
3814 if (!bMatchWholeCell)
3815 AddAttribute(XML_NAMESPACE_TABLE, XML_SEARCH_CRITERIA_MUST_APPLY_TO_WHOLE_CELL, XML_FALSE);
3816 if (!bLookUpLabels)
3817 AddAttribute(XML_NAMESPACE_TABLE, XML_AUTOMATIC_FIND_LABELS, XML_FALSE);
3818 if (!bUseRegularExpressions)
3819 AddAttribute(XML_NAMESPACE_TABLE, XML_USE_REGULAR_EXPRESSIONS, XML_FALSE);
3820 if (bUseWildcards)
3821 AddAttribute(XML_NAMESPACE_TABLE, XML_USE_WILDCARDS, XML_TRUE);
3822 if (nYear2000 != 1930)
3824 AddAttribute(XML_NAMESPACE_TABLE, XML_NULL_YEAR, OUString::number(nYear2000));
3826 SvXMLElementExport aCalcSettings(*this, XML_NAMESPACE_TABLE, XML_CALCULATION_SETTINGS, true, true);
3828 if (aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899)
3830 OUStringBuffer sDate;
3831 SvXMLUnitConverter::convertDateTime(sDate, 0.0, aNullDate);
3832 AddAttribute(XML_NAMESPACE_TABLE, XML_DATE_VALUE, sDate.makeStringAndClear());
3833 SvXMLElementExport aElemNullDate(*this, XML_NAMESPACE_TABLE, XML_NULL_DATE, true, true);
3835 if (bIsIterationEnabled || nIterationCount != 100 || !::rtl::math::approxEqual(fIterationEpsilon, 0.001))
3837 OUStringBuffer sBuffer;
3838 if (bIsIterationEnabled)
3839 AddAttribute(XML_NAMESPACE_TABLE, XML_STATUS, XML_ENABLE);
3840 if (nIterationCount != 100)
3842 AddAttribute(XML_NAMESPACE_TABLE, XML_STEPS, OUString::number(nIterationCount));
3844 if (!::rtl::math::approxEqual(fIterationEpsilon, 0.001))
3846 ::sax::Converter::convertDouble(sBuffer,
3847 fIterationEpsilon);
3848 AddAttribute(XML_NAMESPACE_TABLE, XML_MAXIMUM_DIFFERENCE, sBuffer.makeStringAndClear());
3850 SvXMLElementExport aElemIteration(*this, XML_NAMESPACE_TABLE, XML_ITERATION, true, true);
3857 void ScXMLExport::WriteTableSource()
3859 uno::Reference <sheet::XSheetLinkable> xLinkable (xCurrentTable, uno::UNO_QUERY);
3860 if (xLinkable.is() && GetModel().is())
3862 sheet::SheetLinkMode nMode (xLinkable->getLinkMode());
3863 if (nMode != sheet::SheetLinkMode_NONE)
3865 OUString sLink (xLinkable->getLinkUrl());
3866 uno::Reference <beans::XPropertySet> xProps (GetModel(), uno::UNO_QUERY);
3867 if (xProps.is())
3869 uno::Reference <container::XIndexAccess> xIndex(xProps->getPropertyValue(SC_UNO_SHEETLINKS), uno::UNO_QUERY);
3870 if (xIndex.is())
3872 sal_Int32 nCount(xIndex->getCount());
3873 if (nCount)
3875 bool bFound(false);
3876 uno::Reference <beans::XPropertySet> xLinkProps;
3877 for (sal_Int32 i = 0; (i < nCount) && !bFound; ++i)
3879 xLinkProps.set(xIndex->getByIndex(i), uno::UNO_QUERY);
3880 if (xLinkProps.is())
3882 OUString sNewLink;
3883 if (xLinkProps->getPropertyValue(SC_UNONAME_LINKURL) >>= sNewLink)
3884 bFound = sLink == sNewLink;
3887 if (bFound && xLinkProps.is())
3889 OUString sFilter;
3890 OUString sFilterOptions;
3891 OUString sTableName (xLinkable->getLinkSheetName());
3892 sal_Int32 nRefresh(0);
3893 xLinkProps->getPropertyValue(SC_UNONAME_FILTER) >>= sFilter;
3894 xLinkProps->getPropertyValue(SC_UNONAME_FILTOPT) >>= sFilterOptions;
3895 xLinkProps->getPropertyValue(SC_UNONAME_REFDELAY) >>= nRefresh;
3896 if (!sLink.isEmpty())
3898 AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
3899 AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetRelativeReference(sLink));
3900 if (!sTableName.isEmpty())
3901 AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_NAME, sTableName);
3902 if (!sFilter.isEmpty())
3903 AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_NAME, sFilter);
3904 if (!sFilterOptions.isEmpty())
3905 AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_OPTIONS, sFilterOptions);
3906 if (nMode != sheet::SheetLinkMode_NORMAL)
3907 AddAttribute(XML_NAMESPACE_TABLE, XML_MODE, XML_COPY_RESULTS_ONLY);
3908 if( nRefresh )
3910 OUStringBuffer sBuffer;
3911 ::sax::Converter::convertDuration( sBuffer,
3912 static_cast<double>(nRefresh) / 86400 );
3913 AddAttribute( XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, sBuffer.makeStringAndClear() );
3915 SvXMLElementExport aSourceElem(*this, XML_NAMESPACE_TABLE, XML_TABLE_SOURCE, true, true);
3925 // core implementation
3926 void ScXMLExport::WriteScenario()
3928 if (pDoc && pDoc->IsScenario(static_cast<SCTAB>(nCurrentTable)))
3930 OUString sComment;
3931 Color aColor;
3932 ScScenarioFlags nFlags;
3933 pDoc->GetScenarioData(static_cast<SCTAB>(nCurrentTable), sComment, aColor, nFlags);
3934 if (!(nFlags & ScScenarioFlags::ShowFrame))
3935 AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_BORDER, XML_FALSE);
3936 OUStringBuffer aBuffer;
3937 ::sax::Converter::convertColor(aBuffer, aColor);
3938 AddAttribute(XML_NAMESPACE_TABLE, XML_BORDER_COLOR, aBuffer.makeStringAndClear());
3939 if (!(nFlags & ScScenarioFlags::TwoWay))
3940 AddAttribute(XML_NAMESPACE_TABLE, XML_COPY_BACK, XML_FALSE);
3941 if (!(nFlags & ScScenarioFlags::Attrib))
3942 AddAttribute(XML_NAMESPACE_TABLE, XML_COPY_STYLES, XML_FALSE);
3943 if (nFlags & ScScenarioFlags::Value)
3944 AddAttribute(XML_NAMESPACE_TABLE, XML_COPY_FORMULAS, XML_FALSE);
3945 if (nFlags & ScScenarioFlags::Protected)
3946 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE);
3947 ::sax::Converter::convertBool(aBuffer,
3948 pDoc->IsActiveScenario(static_cast<SCTAB>(nCurrentTable)));
3949 AddAttribute(XML_NAMESPACE_TABLE, XML_IS_ACTIVE, aBuffer.makeStringAndClear());
3950 const ScRangeList* pRangeList = pDoc->GetScenarioRanges(static_cast<SCTAB>(nCurrentTable));
3951 OUString sRangeListStr;
3952 ScRangeStringConverter::GetStringFromRangeList( sRangeListStr, pRangeList, pDoc, FormulaGrammar::CONV_OOO );
3953 AddAttribute(XML_NAMESPACE_TABLE, XML_SCENARIO_RANGES, sRangeListStr);
3954 if (!sComment.isEmpty())
3955 AddAttribute(XML_NAMESPACE_TABLE, XML_COMMENT, sComment);
3956 SvXMLElementExport aElem(*this, XML_NAMESPACE_TABLE, XML_SCENARIO, true, true);
3960 void ScXMLExport::WriteTheLabelRanges( const uno::Reference< sheet::XSpreadsheetDocument >& xSpreadDoc )
3962 uno::Reference< beans::XPropertySet > xDocProp( xSpreadDoc, uno::UNO_QUERY );
3963 if( !xDocProp.is() ) return;
3965 sal_Int32 nCount(0);
3966 uno::Reference< container::XIndexAccess > xColRangesIAccess(xDocProp->getPropertyValue( SC_UNO_COLLABELRNG ), uno::UNO_QUERY);
3967 if( xColRangesIAccess.is() )
3968 nCount += xColRangesIAccess->getCount();
3970 uno::Reference< container::XIndexAccess > xRowRangesIAccess(xDocProp->getPropertyValue( SC_UNO_ROWLABELRNG ), uno::UNO_QUERY);
3971 if( xRowRangesIAccess.is() )
3972 nCount += xRowRangesIAccess->getCount();
3974 if( nCount )
3976 SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_LABEL_RANGES, true, true );
3977 WriteLabelRanges( xColRangesIAccess, true );
3978 WriteLabelRanges( xRowRangesIAccess, false );
3982 void ScXMLExport::WriteLabelRanges( const uno::Reference< container::XIndexAccess >& xRangesIAccess, bool bColumn )
3984 if( !xRangesIAccess.is() ) return;
3986 sal_Int32 nCount(xRangesIAccess->getCount());
3987 for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
3989 uno::Reference< sheet::XLabelRange > xRange(xRangesIAccess->getByIndex( nIndex ), uno::UNO_QUERY);
3990 if( xRange.is() )
3992 OUString sRangeStr;
3993 table::CellRangeAddress aCellRange( xRange->getLabelArea() );
3994 ScRangeStringConverter::GetStringFromRange( sRangeStr, aCellRange, pDoc, FormulaGrammar::CONV_OOO );
3995 AddAttribute( XML_NAMESPACE_TABLE, XML_LABEL_CELL_RANGE_ADDRESS, sRangeStr );
3996 aCellRange = xRange->getDataArea();
3997 ScRangeStringConverter::GetStringFromRange( sRangeStr, aCellRange, pDoc, FormulaGrammar::CONV_OOO );
3998 AddAttribute( XML_NAMESPACE_TABLE, XML_DATA_CELL_RANGE_ADDRESS, sRangeStr );
3999 AddAttribute( XML_NAMESPACE_TABLE, XML_ORIENTATION, bColumn ? XML_COLUMN : XML_ROW );
4000 SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_LABEL_RANGE, true, true );
4005 void ScXMLExport::WriteNamedExpressions()
4007 if (!pDoc)
4008 return;
4009 ScRangeName* pNamedRanges = pDoc->GetRangeName();
4010 WriteNamedRange(pNamedRanges);
4013 void ScXMLExport::WriteExternalDataMapping()
4015 if (!pDoc)
4016 return;
4018 if (getDefaultVersion() <= SvtSaveOptions::ODFVER_012)
4019 // Export this only for 1.2 extended and above.
4020 return;
4022 sc::ExternalDataMapper& rDataMapper = pDoc->GetExternalDataMapper();
4023 auto& rDataSources = rDataMapper.getDataSources();
4025 if (!rDataSources.empty())
4027 SvXMLElementExport aMappings(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_MAPPINGS, true, true);
4028 for (const auto& itr : rDataSources)
4030 AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, itr.getURL());
4031 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_PROVIDER, itr.getProvider());
4032 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_DATA_FREQUENCY, OUString::number(sc::ExternalDataSource::getUpdateFrequency()));
4033 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_ID, itr.getID());
4034 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_DATABASE_NAME, itr.getDBName());
4036 SvXMLElementExport aMapping(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_MAPPING, true, true);
4037 // Add the data transformations
4038 WriteExternalDataTransformations(itr.getDataTransformation());
4043 void ScXMLExport::WriteExternalDataTransformations(const std::vector<std::shared_ptr<sc::DataTransformation>>& aDataTransformations)
4045 SvXMLElementExport aTransformations(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_TRANSFORMATIONS, true, true);
4046 for (auto& itr : aDataTransformations)
4048 sc::TransformationType aTransformationType = itr->getTransformationType();
4050 switch(aTransformationType)
4052 case sc::TransformationType::DELETE_TRANSFORMATION:
4054 // Delete Columns Transformation
4055 std::shared_ptr<sc::ColumnRemoveTransformation> aDeleteTransformation = std::dynamic_pointer_cast<sc::ColumnRemoveTransformation>(itr);
4056 std::set<SCCOL> aColumns = aDeleteTransformation->getColumns();
4057 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_REMOVE_TRANSFORMATION, true, true);
4058 for(auto& col : aColumns)
4060 // Add Columns
4061 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4062 SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4065 break;
4066 case sc::TransformationType::SPLIT_TRANSFORMATION:
4068 std::shared_ptr<sc::SplitColumnTransformation> aSplitTransformation = std::dynamic_pointer_cast<sc::SplitColumnTransformation>(itr);
4070 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(aSplitTransformation->getColumn()));
4071 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_SEPARATOR, OUString::number(aSplitTransformation->getSeparator()));
4072 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_SPLIT_TRANSFORMATION, true, true);
4074 break;
4075 case sc::TransformationType::MERGE_TRANSFORMATION:
4077 // Merge Transformation
4078 std::shared_ptr<sc::MergeColumnTransformation> aMergeTransformation = std::dynamic_pointer_cast<sc::MergeColumnTransformation>(itr);
4079 std::set<SCCOL> aColumns = aMergeTransformation->getColumns();
4081 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MERGE_STRING, aMergeTransformation->getMergeString());
4082 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_MERGE_TRANSFORMATION, true, true);
4084 for(auto& col : aColumns)
4086 // Columns
4087 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4088 SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4091 break;
4092 case sc::TransformationType::SORT_TRANSFORMATION:
4094 // Sort Transformation
4095 std::shared_ptr<sc::SortTransformation> aSortTransformation = std::dynamic_pointer_cast<sc::SortTransformation>(itr);
4096 ScSortParam aSortParam = aSortTransformation->getSortParam();
4097 const sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
4098 const sc::DataStream* pStrm = rMgr.getDataStream();
4099 if (!pStrm)
4100 // No data stream.
4101 return;
4103 // Streamed range
4104 ScRange aRange = pStrm->GetRange();
4106 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_SORT_TRANSFORMATION, true, true);
4108 writeSort(*this, aSortParam, aRange, pDoc);
4110 break;
4111 case sc::TransformationType::TEXT_TRANSFORMATION:
4113 // Text Transformation
4114 std::shared_ptr<sc::TextTransformation> aTextTransformation = std::dynamic_pointer_cast<sc::TextTransformation>(itr);
4116 sc::TEXT_TRANSFORM_TYPE aTextTransformType = aTextTransformation->getTextTransformationType();
4118 switch ( aTextTransformType )
4120 case sc::TEXT_TRANSFORM_TYPE::TO_LOWER:
4121 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_CASEMAP_LOWERCASE);
4122 break;
4123 case sc::TEXT_TRANSFORM_TYPE::TO_UPPER:
4124 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_CASEMAP_UPPERCASE);
4125 break;
4126 case sc::TEXT_TRANSFORM_TYPE::CAPITALIZE:
4127 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_CASEMAP_CAPITALIZE);
4128 break;
4129 case sc::TEXT_TRANSFORM_TYPE::TRIM:
4130 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_TRIM);
4131 break;
4134 std::set<SCCOL> aColumns = aTextTransformation->getColumns();
4136 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_TEXT_TRANSFORMATION, true, true);
4138 for(auto& col : aColumns)
4140 // Columns
4141 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4142 SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4145 break;
4146 case sc::TransformationType::AGGREGATE_FUNCTION:
4148 // Aggregate Transformation
4149 std::shared_ptr<sc::AggregateFunction> aAggregateFunction = std::dynamic_pointer_cast<sc::AggregateFunction>(itr);
4150 std::set<SCCOL> aColumns = aAggregateFunction->getColumns();
4152 sc::AGGREGATE_FUNCTION aAggregateType = aAggregateFunction->getAggregateType();
4154 switch (aAggregateType)
4156 case sc::AGGREGATE_FUNCTION::SUM:
4157 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_SUM);
4158 break;
4159 case sc::AGGREGATE_FUNCTION::AVERAGE:
4160 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_AVERAGE);
4161 break;
4162 case sc::AGGREGATE_FUNCTION::MIN:
4163 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_MIN);
4164 break;
4165 case sc::AGGREGATE_FUNCTION::MAX:
4166 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_MAX);
4167 break;
4170 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT,XML_COLUMN_AGGREGATE_TRANSFORMATION, true, true);
4172 for(auto& col : aColumns)
4174 // Columns
4175 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4176 SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4179 break;
4180 case sc::TransformationType::NUMBER_TRANSFORMATION:
4182 // Number Transformation
4183 std::shared_ptr<sc::NumberTransformation> aNumberTransformation = std::dynamic_pointer_cast<sc::NumberTransformation>(itr);
4185 sc::NUMBER_TRANSFORM_TYPE aNumberTransformType = aNumberTransformation->getNumberTransformationType();
4187 switch ( aNumberTransformType )
4189 case sc::NUMBER_TRANSFORM_TYPE::ROUND:
4190 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_ROUND);
4191 break;
4192 case sc::NUMBER_TRANSFORM_TYPE::ROUND_UP:
4193 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_ROUND_UP);
4194 break;
4195 case sc::NUMBER_TRANSFORM_TYPE::ROUND_DOWN:
4196 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_ROUND_DOWN);
4197 break;
4198 case sc::NUMBER_TRANSFORM_TYPE::ABSOLUTE:
4199 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_ABS);
4200 break;
4201 case sc::NUMBER_TRANSFORM_TYPE::LOG_E:
4202 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_LOG);
4203 break;
4204 case sc::NUMBER_TRANSFORM_TYPE::LOG_10:
4205 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_LOG_10);
4206 break;
4207 case sc::NUMBER_TRANSFORM_TYPE::CUBE:
4208 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_CUBE);
4209 break;
4210 case sc::NUMBER_TRANSFORM_TYPE::SQUARE:
4211 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_SQUARE);
4212 break;
4213 case sc::NUMBER_TRANSFORM_TYPE::SQUARE_ROOT:
4214 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_SQUARE_ROOT);
4215 break;
4216 case sc::NUMBER_TRANSFORM_TYPE::EXPONENT:
4217 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_EXPONENTIAL);
4218 break;
4219 case sc::NUMBER_TRANSFORM_TYPE::IS_EVEN:
4220 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_EVEN);
4221 break;
4222 case sc::NUMBER_TRANSFORM_TYPE::IS_ODD:
4223 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_ODD);
4224 break;
4225 case sc::NUMBER_TRANSFORM_TYPE::SIGN:
4226 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_SIGN);
4227 break;
4230 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_PRECISION, OUString::number(aNumberTransformation->getPrecision()));
4231 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_NUMBER_TRANSFORMATION, true, true);
4233 std::set<SCCOL> aColumns = aNumberTransformation->getColumn();
4234 for(auto& col : aColumns)
4236 // Columns
4237 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4238 SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4241 break;
4242 case sc::TransformationType::REMOVE_NULL_TRANSFORMATION:
4244 // Replace Null Transformation
4245 std::shared_ptr<sc::ReplaceNullTransformation> aReplaceNullTransformation = std::dynamic_pointer_cast<sc::ReplaceNullTransformation>(itr);
4246 std::set<SCCOL> aColumns = aReplaceNullTransformation->getColumn();
4248 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_REPLACE_STRING, aReplaceNullTransformation->getReplaceString());
4249 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_REPLACENULL_TRANSFORMATION, true, true);
4251 for(auto& col : aColumns)
4253 // Columns
4254 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4255 SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4258 break;
4259 case sc::TransformationType::DATETIME_TRANSFORMATION:
4261 // Number Transformation
4262 std::shared_ptr<sc::DateTimeTransformation> aDateTimeTransformation = std::dynamic_pointer_cast<sc::DateTimeTransformation>(itr);
4264 sc::DATETIME_TRANSFORMATION_TYPE aDateTimeTransformationType = aDateTimeTransformation->getDateTimeTransformationType();
4266 switch ( aDateTimeTransformationType )
4268 case sc::DATETIME_TRANSFORMATION_TYPE::DATE_STRING:
4269 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_DATE_STRING);
4270 break;
4271 case sc::DATETIME_TRANSFORMATION_TYPE::YEAR:
4272 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_YEAR);
4273 break;
4274 case sc::DATETIME_TRANSFORMATION_TYPE::START_OF_YEAR:
4275 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_START_OF_YEAR);
4276 break;
4277 case sc::DATETIME_TRANSFORMATION_TYPE::END_OF_YEAR:
4278 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_END_OF_YEAR);
4279 break;
4280 case sc::DATETIME_TRANSFORMATION_TYPE::MONTH:
4281 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_MONTH);
4282 break;
4283 case sc::DATETIME_TRANSFORMATION_TYPE::MONTH_NAME:
4284 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_MONTH_NAME);
4285 break;
4286 case sc::DATETIME_TRANSFORMATION_TYPE::START_OF_MONTH:
4287 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_START_OF_MONTH);
4288 break;
4289 case sc::DATETIME_TRANSFORMATION_TYPE::END_OF_MONTH:
4290 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_END_OF_MONTH);
4291 break;
4292 case sc::DATETIME_TRANSFORMATION_TYPE::DAY:
4293 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_DAY);
4294 break;
4295 case sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_WEEK:
4296 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_DAY_OF_WEEK);
4297 break;
4298 case sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_YEAR:
4299 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_DAY_OF_YEAR);
4300 break;
4301 case sc::DATETIME_TRANSFORMATION_TYPE::QUARTER:
4302 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_QUARTER);
4303 break;
4304 case sc::DATETIME_TRANSFORMATION_TYPE::START_OF_QUARTER:
4305 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_START_OF_QUARTER);
4306 break;
4307 case sc::DATETIME_TRANSFORMATION_TYPE::END_OF_QUARTER:
4308 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_END_OF_QUARTER);
4309 break;
4310 case sc::DATETIME_TRANSFORMATION_TYPE::TIME:
4311 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_TIME);
4312 break;
4313 case sc::DATETIME_TRANSFORMATION_TYPE::HOUR:
4314 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_HOUR);
4315 break;
4316 case sc::DATETIME_TRANSFORMATION_TYPE::MINUTE:
4317 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_MINUTE);
4318 break;
4319 case sc::DATETIME_TRANSFORMATION_TYPE::SECOND:
4320 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_SECONDS);
4321 break;
4324 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_DATETIME_TRANSFORMATION, true, true);
4326 std::set<SCCOL> aColumns = aDateTimeTransformation->getColumn();
4327 for(auto& col : aColumns)
4329 // Columns
4330 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4331 SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4334 break;
4335 default:
4336 break;
4341 void ScXMLExport::WriteDataStream()
4343 if (!pDoc)
4344 return;
4346 SvtMiscOptions aMiscOptions;
4347 if (!aMiscOptions.IsExperimentalMode())
4348 // Export this only in experimental mode.
4349 return;
4351 if (getDefaultVersion() <= SvtSaveOptions::ODFVER_012)
4352 // Export this only for 1.2 extended and above.
4353 return;
4355 const sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
4356 const sc::DataStream* pStrm = rMgr.getDataStream();
4357 if (!pStrm)
4358 // No data stream.
4359 return;
4361 // Source URL
4362 AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetRelativeReference(pStrm->GetURL()));
4364 // Streamed range
4365 ScRange aRange = pStrm->GetRange();
4366 OUString aRangeStr;
4367 ScRangeStringConverter::GetStringFromRange(
4368 aRangeStr, aRange, pDoc, formula::FormulaGrammar::CONV_OOO);
4369 AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, aRangeStr);
4371 // Empty line refresh option.
4372 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_EMPTY_LINE_REFRESH, pStrm->IsRefreshOnEmptyLine() ? XML_TRUE : XML_FALSE);
4374 // New data insertion position. Either top of bottom. Default to bottom.
4375 xmloff::token::XMLTokenEnum eInsertPosition = XML_BOTTOM;
4376 if (pStrm->GetMove() == sc::DataStream::MOVE_DOWN)
4377 eInsertPosition = XML_TOP;
4379 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_INSERTION_POSITION, eInsertPosition);
4381 SvXMLElementExport aElem(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_STREAM_SOURCE, true, true);
4384 void ScXMLExport::WriteNamedRange(ScRangeName* pRangeName)
4386 //write a global or local ScRangeName
4387 SvXMLElementExport aElemNEs(*this, XML_NAMESPACE_TABLE, XML_NAMED_EXPRESSIONS, true, true);
4388 for (const auto& rxEntry : *pRangeName)
4390 AddAttribute(sAttrName, rxEntry.second->GetName());
4392 OUString sBaseCellAddress;
4393 rxEntry.second->ValidateTabRefs();
4394 ScRangeStringConverter::GetStringFromAddress( sBaseCellAddress, rxEntry.second->GetPos(), pDoc,
4395 FormulaGrammar::CONV_OOO, ' ', false, ScRefFlags::ADDR_ABS_3D);
4396 AddAttribute(XML_NAMESPACE_TABLE, XML_BASE_CELL_ADDRESS, sBaseCellAddress);
4398 OUString sSymbol;
4399 rxEntry.second->GetSymbol(sSymbol, pDoc->GetStorageGrammar());
4400 OUString sTempSymbol(sSymbol);
4401 ScRange aRange;
4402 if (rxEntry.second->IsReference(aRange))
4405 OUString sContent(sTempSymbol.copy(1, sTempSymbol.getLength() -2 ));
4406 AddAttribute(XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, sContent);
4408 sal_Int32 nRangeType = rxEntry.second->GetUnoType();
4409 OUStringBuffer sBufferRangeType;
4410 if ((nRangeType & sheet::NamedRangeFlag::COLUMN_HEADER) == sheet::NamedRangeFlag::COLUMN_HEADER)
4411 sBufferRangeType.append(GetXMLToken(XML_REPEAT_COLUMN));
4412 if ((nRangeType & sheet::NamedRangeFlag::ROW_HEADER) == sheet::NamedRangeFlag::ROW_HEADER)
4414 if (!sBufferRangeType.isEmpty())
4415 sBufferRangeType.append(" ");
4416 sBufferRangeType.append(GetXMLToken(XML_REPEAT_ROW));
4418 if ((nRangeType & sheet::NamedRangeFlag::FILTER_CRITERIA) == sheet::NamedRangeFlag::FILTER_CRITERIA)
4420 if (!sBufferRangeType.isEmpty())
4421 sBufferRangeType.append(" ");
4422 sBufferRangeType.append(GetXMLToken(XML_FILTER));
4424 if ((nRangeType & sheet::NamedRangeFlag::PRINT_AREA) == sheet::NamedRangeFlag::PRINT_AREA)
4426 if (!sBufferRangeType.isEmpty())
4427 sBufferRangeType.append(" ");
4428 sBufferRangeType.append(GetXMLToken(XML_PRINT_RANGE));
4430 OUString sRangeType = sBufferRangeType.makeStringAndClear();
4431 if (!sRangeType.isEmpty())
4432 AddAttribute(XML_NAMESPACE_TABLE, XML_RANGE_USABLE_AS, sRangeType);
4433 SvXMLElementExport aElemNR(*this, XML_NAMESPACE_TABLE, XML_NAMED_RANGE, true, true);
4436 else
4438 AddAttribute(XML_NAMESPACE_TABLE, XML_EXPRESSION, sTempSymbol);
4439 SvXMLElementExport aElemNE(*this, XML_NAMESPACE_TABLE, XML_NAMED_EXPRESSION, true, true);
4444 namespace {
4446 OUString getCondFormatEntryType(const ScColorScaleEntry& rEntry, bool bFirst = true)
4448 switch(rEntry.GetType())
4450 case COLORSCALE_MIN:
4451 return "minimum";
4452 case COLORSCALE_MAX:
4453 return "maximum";
4454 case COLORSCALE_PERCENT:
4455 return "percent";
4456 case COLORSCALE_PERCENTILE:
4457 return "percentile";
4458 case COLORSCALE_FORMULA:
4459 return "formula";
4460 case COLORSCALE_VALUE:
4461 return "number";
4462 case COLORSCALE_AUTO:
4463 // only important for data bars
4464 if(bFirst)
4465 return "auto-minimum";
4466 else
4467 return "auto-maximum";
4469 return OUString();
4472 OUString getDateStringForType(condformat::ScCondFormatDateType eType)
4474 switch(eType)
4476 case condformat::TODAY:
4477 return "today";
4478 case condformat::YESTERDAY:
4479 return "yesterday";
4480 case condformat::TOMORROW:
4481 return "tomorrow";
4482 case condformat::LAST7DAYS:
4483 return "last-7-days";
4484 case condformat::THISWEEK:
4485 return "this-week";
4486 case condformat::LASTWEEK:
4487 return "last-week";
4488 case condformat::NEXTWEEK:
4489 return "next-week";
4490 case condformat::THISMONTH:
4491 return "this-month";
4492 case condformat::LASTMONTH:
4493 return "last-month";
4494 case condformat::NEXTMONTH:
4495 return "next-month";
4496 case condformat::THISYEAR:
4497 return "this-year";
4498 case condformat::LASTYEAR:
4499 return "last-year";
4500 case condformat::NEXTYEAR:
4501 return "next-year";
4504 return OUString();
4509 void ScXMLExport::ExportConditionalFormat(SCTAB nTab)
4511 ScConditionalFormatList* pCondFormatList = pDoc->GetCondFormList(nTab);
4512 if(!pCondFormatList)
4513 return;
4515 if (pCondFormatList->empty())
4516 return;
4518 SvXMLElementExport aElementCondFormats(*this, XML_NAMESPACE_CALC_EXT, XML_CONDITIONAL_FORMATS, true, true);
4520 for(const auto& rxCondFormat : *pCondFormatList)
4522 OUString sRanges;
4523 const ScRangeList& rRangeList = rxCondFormat->GetRange();
4524 ScRangeStringConverter::GetStringFromRangeList( sRanges, &rRangeList, pDoc, formula::FormulaGrammar::CONV_OOO );
4525 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TARGET_RANGE_ADDRESS, sRanges);
4526 SvXMLElementExport aElementCondFormat(*this, XML_NAMESPACE_CALC_EXT, XML_CONDITIONAL_FORMAT, true, true);
4527 size_t nEntries = rxCondFormat->size();
4528 for(size_t i = 0; i < nEntries; ++i)
4530 const ScFormatEntry* pFormatEntry = rxCondFormat->GetEntry(i);
4531 if(pFormatEntry->GetType()==ScFormatEntry::Type::Condition)
4533 const ScCondFormatEntry* pEntry = static_cast<const ScCondFormatEntry*>(pFormatEntry);
4534 OUStringBuffer aCond;
4535 ScAddress aPos = pEntry->GetSrcPos();
4536 switch(pEntry->GetOperation())
4538 case ScConditionMode::Equal:
4539 aCond.append('=');
4540 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4541 break;
4542 case ScConditionMode::Less:
4543 aCond.append('<');
4544 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4545 break;
4546 case ScConditionMode::Greater:
4547 aCond.append('>');
4548 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4549 break;
4550 case ScConditionMode::EqLess:
4551 aCond.append("<=");
4552 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4553 break;
4554 case ScConditionMode::EqGreater:
4555 aCond.append(">=");
4556 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4557 break;
4558 case ScConditionMode::NotEqual:
4559 aCond.append("!=");
4560 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4561 break;
4562 case ScConditionMode::Between:
4563 aCond.append("between(");
4564 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4565 aCond.append(',');
4566 aCond.append(pEntry->GetExpression(aPos, 1, 0, formula::FormulaGrammar::GRAM_ODFF));
4567 aCond.append(')');
4568 break;
4569 case ScConditionMode::NotBetween:
4570 aCond.append("not-between(");
4571 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4572 aCond.append(',');
4573 aCond.append(pEntry->GetExpression(aPos, 1, 0, formula::FormulaGrammar::GRAM_ODFF));
4574 aCond.append(')');
4575 break;
4576 case ScConditionMode::Duplicate:
4577 aCond.append("duplicate");
4578 break;
4579 case ScConditionMode::NotDuplicate:
4580 aCond.append("unique");
4581 break;
4582 case ScConditionMode::Direct:
4583 aCond.append("formula-is(");
4584 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4585 aCond.append(')');
4586 break;
4587 case ScConditionMode::Top10:
4588 aCond.append("top-elements(");
4589 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4590 aCond.append(")");
4591 break;
4592 case ScConditionMode::Bottom10:
4593 aCond.append("bottom-elements(");
4594 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4595 aCond.append(")");
4596 break;
4597 case ScConditionMode::TopPercent:
4598 aCond.append("top-percent(");
4599 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4600 aCond.append(")");
4601 break;
4602 case ScConditionMode::BottomPercent:
4603 aCond.append("bottom-percent(");
4604 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4605 aCond.append(")");
4606 break;
4607 case ScConditionMode::AboveAverage:
4608 aCond.append("above-average");
4609 break;
4610 case ScConditionMode::BelowAverage:
4611 aCond.append("below-average");
4612 break;
4613 case ScConditionMode::AboveEqualAverage:
4614 aCond.append("above-equal-average");
4615 break;
4616 case ScConditionMode::BelowEqualAverage:
4617 aCond.append("below-equal-average");
4618 break;
4619 case ScConditionMode::Error:
4620 aCond.append("is-error");
4621 break;
4622 case ScConditionMode::NoError:
4623 aCond.append("is-no-error");
4624 break;
4625 case ScConditionMode::BeginsWith:
4626 aCond.append("begins-with(");
4627 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4628 aCond.append(")");
4629 break;
4630 case ScConditionMode::EndsWith:
4631 aCond.append("ends-with(");
4632 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4633 aCond.append(")");
4634 break;
4635 case ScConditionMode::ContainsText:
4636 aCond.append("contains-text(");
4637 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4638 aCond.append(")");
4639 break;
4640 case ScConditionMode::NotContainsText:
4641 aCond.append("not-contains-text(");
4642 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4643 aCond.append(")");
4644 break;
4645 case ScConditionMode::NONE:
4646 continue;
4647 default:
4648 SAL_WARN("sc", "unimplemented conditional format export");
4650 OUString sStyle = ScStyleNameConversion::DisplayToProgrammaticName(pEntry->GetStyle(), SfxStyleFamily::Para);
4651 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_APPLY_STYLE_NAME, sStyle);
4652 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, aCond.makeStringAndClear());
4654 OUString sBaseAddress;
4655 ScRangeStringConverter::GetStringFromAddress( sBaseAddress, aPos, pDoc,formula::FormulaGrammar::CONV_ODF );
4656 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_BASE_CELL_ADDRESS, sBaseAddress);
4657 SvXMLElementExport aElementCondEntry(*this, XML_NAMESPACE_CALC_EXT, XML_CONDITION, true, true);
4659 else if(pFormatEntry->GetType() == ScFormatEntry::Type::Colorscale)
4661 SvXMLElementExport aElementColorScale(*this, XML_NAMESPACE_CALC_EXT, XML_COLOR_SCALE, true, true);
4662 const ScColorScaleFormat& rColorScale = static_cast<const ScColorScaleFormat&>(*pFormatEntry);
4663 for(const auto& rxItem : rColorScale)
4665 if(rxItem->GetType() == COLORSCALE_FORMULA)
4667 OUString sFormula = rxItem->GetFormula(formula::FormulaGrammar::GRAM_ODFF);
4668 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, sFormula);
4670 else
4671 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, OUString::number(rxItem->GetValue()));
4673 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, getCondFormatEntryType(*rxItem));
4674 OUStringBuffer aBuffer;
4675 ::sax::Converter::convertColor(aBuffer, rxItem->GetColor());
4676 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLOR, aBuffer.makeStringAndClear());
4677 SvXMLElementExport aElementColorScaleEntry(*this, XML_NAMESPACE_CALC_EXT, XML_COLOR_SCALE_ENTRY, true, true);
4680 else if(pFormatEntry->GetType() == ScFormatEntry::Type::Databar)
4682 const ScDataBarFormatData* pFormatData = static_cast<const ScDataBarFormat&>(*pFormatEntry).GetDataBarData();
4683 if(!pFormatData->mbGradient)
4684 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_GRADIENT, XML_FALSE);
4685 if(pFormatData->mbOnlyBar)
4686 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_SHOW_VALUE, XML_FALSE);
4688 if (pFormatData->mnMinLength != 0.0)
4689 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MIN_LENGTH, OUString::number(pFormatData->mnMinLength));
4691 if (pFormatData->mnMaxLength != 0.0)
4692 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MAX_LENGTH, OUString::number(pFormatData->mnMaxLength));
4694 if(pFormatData->mbNeg)
4696 if(pFormatData->mpNegativeColor)
4698 OUStringBuffer aBuffer;
4699 ::sax::Converter::convertColor(aBuffer, *pFormatData->mpNegativeColor);
4700 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_NEGATIVE_COLOR, aBuffer.makeStringAndClear());
4702 else
4704 OUStringBuffer aBuffer;
4705 ::sax::Converter::convertColor(aBuffer, COL_LIGHTRED);
4706 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_NEGATIVE_COLOR, aBuffer.makeStringAndClear());
4710 if(pFormatData->meAxisPosition != databar::AUTOMATIC)
4712 if(pFormatData->meAxisPosition == databar::NONE)
4714 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_AXIS_POSITION, OUString("none"));
4716 else
4718 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_AXIS_POSITION, OUString("middle"));
4722 OUStringBuffer aBuffer;
4723 ::sax::Converter::convertColor(aBuffer, pFormatData->maPositiveColor);
4724 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_POSITIVE_COLOR, aBuffer.makeStringAndClear());
4726 aBuffer.truncate();
4727 ::sax::Converter::convertColor(aBuffer, pFormatData->maAxisColor);
4728 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_AXIS_COLOR, aBuffer.makeStringAndClear());
4729 SvXMLElementExport aElementDataBar(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_BAR, true, true);
4732 if(pFormatData->mpLowerLimit->GetType() == COLORSCALE_FORMULA)
4734 OUString sFormula = pFormatData->mpLowerLimit->GetFormula(formula::FormulaGrammar::GRAM_ODFF);
4735 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, sFormula);
4737 else
4738 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, OUString::number(pFormatData->mpLowerLimit->GetValue()));
4739 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, getCondFormatEntryType(*pFormatData->mpLowerLimit));
4740 SvXMLElementExport aElementDataBarEntryLower(*this, XML_NAMESPACE_CALC_EXT, XML_FORMATTING_ENTRY, true, true);
4744 if(pFormatData->mpUpperLimit->GetType() == COLORSCALE_FORMULA)
4746 OUString sFormula = pFormatData->mpUpperLimit->GetFormula(formula::FormulaGrammar::GRAM_ODFF);
4747 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, sFormula);
4749 else
4750 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, OUString::number(pFormatData->mpUpperLimit->GetValue()));
4751 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, getCondFormatEntryType(*pFormatData->mpUpperLimit, false));
4752 SvXMLElementExport aElementDataBarEntryUpper(*this, XML_NAMESPACE_CALC_EXT, XML_FORMATTING_ENTRY, true, true);
4755 else if(pFormatEntry->GetType() == ScFormatEntry::Type::Iconset)
4757 const ScIconSetFormat& rIconSet = static_cast<const ScIconSetFormat&>(*pFormatEntry);
4758 OUString aIconSetName = OUString::createFromAscii(ScIconSetFormat::getIconSetName(rIconSet.GetIconSetData()->eIconSetType));
4759 AddAttribute( XML_NAMESPACE_CALC_EXT, XML_ICON_SET_TYPE, aIconSetName );
4760 if (rIconSet.GetIconSetData()->mbCustom)
4761 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_CUSTOM, OUString::boolean(true));
4763 SvXMLElementExport aElementColorScale(*this, XML_NAMESPACE_CALC_EXT, XML_ICON_SET, true, true);
4765 if (rIconSet.GetIconSetData()->mbCustom)
4767 for (const auto& [rType, rIndex] : rIconSet.GetIconSetData()->maCustomVector)
4769 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_CUSTOM_ICONSET_NAME, OUString::createFromAscii(ScIconSetFormat::getIconSetName(rType)));
4770 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_CUSTOM_ICONSET_INDEX, OUString::number(rIndex));
4771 SvXMLElementExport aCustomIcon(*this, XML_NAMESPACE_CALC_EXT, XML_CUSTOM_ICONSET, true, true);
4776 if(!rIconSet.GetIconSetData()->mbShowValue)
4777 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_SHOW_VALUE, XML_FALSE);
4778 for (auto const& it : rIconSet)
4780 if(it->GetType() == COLORSCALE_FORMULA)
4782 OUString sFormula = it->GetFormula(formula::FormulaGrammar::GRAM_ODFF);
4783 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, sFormula);
4785 else
4786 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, OUString::number(it->GetValue()));
4788 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, getCondFormatEntryType(*it));
4789 SvXMLElementExport aElementColorScaleEntry(*this, XML_NAMESPACE_CALC_EXT, XML_FORMATTING_ENTRY, true, true);
4792 else if(pFormatEntry->GetType() == ScFormatEntry::Type::Date)
4794 const ScCondDateFormatEntry& rDateFormat = static_cast<const ScCondDateFormatEntry&>(*pFormatEntry);
4795 OUString aDateType = getDateStringForType(rDateFormat.GetDateType());
4796 OUString aStyleName = ScStyleNameConversion::DisplayToProgrammaticName(rDateFormat.GetStyleName(), SfxStyleFamily::Para );
4797 AddAttribute( XML_NAMESPACE_CALC_EXT, XML_STYLE, aStyleName);
4798 AddAttribute( XML_NAMESPACE_CALC_EXT, XML_DATE, aDateType);
4799 SvXMLElementExport aElementDateFormat(*this, XML_NAMESPACE_CALC_EXT, XML_DATE_IS, true, true);
4805 void ScXMLExport::WriteExternalRefCaches()
4807 if (!pDoc)
4808 return;
4810 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
4811 pRefMgr->resetSrcFileData(GetOrigFileName());
4812 sal_uInt16 nCount = pRefMgr->getExternalFileCount();
4813 for (sal_uInt16 nFileId = 0; nFileId < nCount; ++nFileId)
4815 const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
4816 if (!pUrl)
4817 continue;
4819 vector<OUString> aTabNames;
4820 pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
4821 if (aTabNames.empty())
4822 continue;
4824 for (const auto& rTabName : aTabNames)
4826 ScExternalRefCache::TableTypeRef pTable = pRefMgr->getCacheTable(nFileId, rTabName, false);
4827 if (!pTable.get() || !pTable->isReferenced())
4828 continue;
4830 AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, "'" + *pUrl + "'#" + rTabName);
4831 AddAttribute(XML_NAMESPACE_TABLE, XML_PRINT, GetXMLToken(XML_FALSE));
4832 AddAttribute(XML_NAMESPACE_TABLE, XML_STYLE_NAME, sExternalRefTabStyleName);
4833 SvXMLElementExport aElemTable(*this, XML_NAMESPACE_TABLE, XML_TABLE, true, true);
4835 const ScExternalRefManager::SrcFileData* pExtFileData = pRefMgr->getExternalFileData(nFileId);
4836 if (pExtFileData)
4838 OUString aRelUrl;
4839 if (!pExtFileData->maRelativeName.isEmpty())
4840 aRelUrl = pExtFileData->maRelativeName;
4841 else
4842 aRelUrl = GetRelativeReference(pExtFileData->maRelativeName);
4843 AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
4844 AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, aRelUrl);
4845 AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_NAME, rTabName);
4846 if (!pExtFileData->maFilterName.isEmpty())
4847 AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_NAME, pExtFileData->maFilterName);
4848 if (!pExtFileData->maFilterOptions.isEmpty())
4849 AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_OPTIONS, pExtFileData->maFilterOptions);
4850 AddAttribute(XML_NAMESPACE_TABLE, XML_MODE, XML_COPY_RESULTS_ONLY);
4852 SvXMLElementExport aElemTableSource(*this, XML_NAMESPACE_TABLE, XML_TABLE_SOURCE, true, true);
4855 // Determine maximum column count of used area, for repeated cells.
4856 SCCOL nMaxColsUsed = 1; // assume that there is at least one cell somewhere...
4857 vector<SCROW> aRows;
4858 pTable->getAllRows(aRows);
4859 for (SCROW nRow : aRows)
4861 vector<SCCOL> aCols;
4862 pTable->getAllCols(nRow, aCols);
4863 if (!aCols.empty())
4865 SCCOL nCol = aCols.back();
4866 if (nMaxColsUsed <= nCol)
4867 nMaxColsUsed = nCol + 1;
4871 // Column definitions have to be present to make a valid file
4873 if (nMaxColsUsed > 1)
4874 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
4875 OUString::number(nMaxColsUsed));
4876 SvXMLElementExport aElemColumn(*this, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true);
4879 // Write cache content for this table.
4880 SCROW nLastRow = 0;
4881 bool bFirstRow = true;
4882 for (SCROW nRow : aRows)
4884 if (bFirstRow)
4886 if (nRow > 0)
4888 if (nRow > 1)
4890 OUString aVal = OUString::number(nRow);
4891 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, aVal);
4893 SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true);
4894 OUString aVal = OUString::number(static_cast<sal_Int32>(nMaxColsUsed));
4895 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal);
4896 SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
4899 else
4901 SCROW nRowGap = nRow - nLastRow;
4902 if (nRowGap > 1)
4904 if (nRowGap > 2)
4906 OUString aVal = OUString::number(static_cast<sal_Int32>(nRowGap-1));
4907 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, aVal);
4909 SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true);
4910 OUString aVal = OUString::number(static_cast<sal_Int32>(nMaxColsUsed));
4911 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal);
4912 SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
4915 SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true);
4917 vector<SCCOL> aCols;
4918 pTable->getAllCols(nRow, aCols);
4919 SCCOL nLastCol = 0;
4920 bool bFirstCol = true;
4921 for (SCCOL nCol : aCols)
4923 if (bFirstCol)
4925 if (nCol > 0)
4927 if (nCol > 1)
4929 OUString aVal = OUString::number(static_cast<sal_Int32>(nCol));
4930 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal);
4932 SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
4935 else
4937 SCCOL nColGap = nCol - nLastCol;
4938 if (nColGap > 1)
4940 if (nColGap > 2)
4942 OUString aVal = OUString::number(static_cast<sal_Int32>(nColGap-1));
4943 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal);
4945 SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
4949 // Write out this cell.
4950 sal_uInt32 nNumFmt = 0;
4951 ScExternalRefCache::TokenRef pToken = pTable->getCell(nCol, nRow, &nNumFmt);
4952 OUString aStrVal;
4953 if (pToken.get())
4955 sal_Int32 nIndex = GetNumberFormatStyleIndex(nNumFmt);
4956 if (nIndex >= 0)
4958 const OUString & aStyleName = pCellStyles->GetStyleNameByIndex(nIndex, true);
4959 AddAttribute(XML_NAMESPACE_TABLE, XML_STYLE_NAME, aStyleName);
4962 switch(pToken->GetType())
4964 case svDouble:
4966 AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT);
4967 OUStringBuffer aVal;
4968 aVal.append(pToken->GetDouble());
4969 aStrVal = aVal.makeStringAndClear();
4970 AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE, aStrVal);
4972 break;
4973 case svString:
4975 AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING);
4976 aStrVal = pToken->GetString().getString();
4978 break;
4979 default:
4983 SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
4984 SvXMLElementExport aElemText(*this, XML_NAMESPACE_TEXT, XML_P, true, false);
4985 Characters(aStrVal);
4987 nLastCol = nCol;
4988 bFirstCol = false;
4990 nLastRow = nRow;
4991 bFirstRow = false;
4997 // core implementation
4998 void ScXMLExport::WriteConsolidation()
5000 if (pDoc)
5002 const ScConsolidateParam* pCons(pDoc->GetConsolidateDlgData());
5003 if( pCons )
5005 OUString sStrData;
5007 ScXMLConverter::GetStringFromFunction( sStrData, pCons->eFunction );
5008 AddAttribute( XML_NAMESPACE_TABLE, XML_FUNCTION, sStrData );
5010 sStrData.clear();
5011 for( sal_Int32 nIndex = 0; nIndex < pCons->nDataAreaCount; ++nIndex )
5012 ScRangeStringConverter::GetStringFromArea( sStrData, pCons->pDataAreas[ nIndex ], pDoc, FormulaGrammar::CONV_OOO, ' ', true );
5013 AddAttribute( XML_NAMESPACE_TABLE, XML_SOURCE_CELL_RANGE_ADDRESSES, sStrData );
5015 ScRangeStringConverter::GetStringFromAddress( sStrData, ScAddress( pCons->nCol, pCons->nRow, pCons->nTab ), pDoc, FormulaGrammar::CONV_OOO );
5016 AddAttribute( XML_NAMESPACE_TABLE, XML_TARGET_CELL_ADDRESS, sStrData );
5018 if( pCons->bByCol && !pCons->bByRow )
5019 AddAttribute( XML_NAMESPACE_TABLE, XML_USE_LABEL, XML_COLUMN );
5020 else if( !pCons->bByCol && pCons->bByRow )
5021 AddAttribute( XML_NAMESPACE_TABLE, XML_USE_LABEL, XML_ROW );
5022 else if( pCons->bByCol && pCons->bByRow )
5023 AddAttribute( XML_NAMESPACE_TABLE, XML_USE_LABEL, XML_BOTH );
5025 if( pCons->bReferenceData )
5026 AddAttribute( XML_NAMESPACE_TABLE, XML_LINK_TO_SOURCE_DATA, XML_TRUE );
5028 SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_CONSOLIDATION, true, true );
5033 SvXMLAutoStylePoolP* ScXMLExport::CreateAutoStylePool()
5035 return new ScXMLAutoStylePoolP(*this);
5038 XMLPageExport* ScXMLExport::CreatePageExport()
5040 return new XMLTableMasterPageExport( *this );
5043 void ScXMLExport::GetChangeTrackViewSettings(uno::Sequence<beans::PropertyValue>& rProps)
5045 ScChangeViewSettings* pViewSettings(GetDocument() ? GetDocument()->GetChangeViewSettings() : nullptr);
5046 if (pViewSettings)
5048 sal_Int32 nChangePos(rProps.getLength());
5049 rProps.realloc(nChangePos + 1);
5050 beans::PropertyValue* pProps(rProps.getArray());
5052 uno::Sequence<beans::PropertyValue> aChangeProps(SC_VIEWCHANGES_COUNT);
5053 beans::PropertyValue* pChangeProps(aChangeProps.getArray());
5054 pChangeProps[SC_SHOW_CHANGES].Name = "ShowChanges";
5055 pChangeProps[SC_SHOW_CHANGES].Value <<= pViewSettings->ShowChanges();
5056 pChangeProps[SC_SHOW_ACCEPTED_CHANGES].Name = "ShowAcceptedChanges";
5057 pChangeProps[SC_SHOW_ACCEPTED_CHANGES].Value <<= pViewSettings->IsShowAccepted();
5058 pChangeProps[SC_SHOW_REJECTED_CHANGES].Name = "ShowRejectedChanges";
5059 pChangeProps[SC_SHOW_REJECTED_CHANGES].Value <<= pViewSettings->IsShowRejected();
5060 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME].Name = "ShowChangesByDatetime";
5061 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME].Value <<= pViewSettings->HasDate();
5062 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_MODE].Name = "ShowChangesByDatetimeMode";
5063 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_MODE].Value <<= static_cast<sal_Int16>(pViewSettings->GetTheDateMode());
5064 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_FIRST_DATETIME].Name = "ShowChangesByDatetimeFirstDatetime";
5065 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_FIRST_DATETIME].Value <<= pViewSettings->GetTheFirstDateTime().GetUNODateTime();
5066 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_SECOND_DATETIME].Name = "ShowChangesByDatetimeSecondDatetime";
5067 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_SECOND_DATETIME].Value <<= pViewSettings->GetTheLastDateTime().GetUNODateTime();
5068 pChangeProps[SC_SHOW_CHANGES_BY_AUTHOR].Name = "ShowChangesByAuthor";
5069 pChangeProps[SC_SHOW_CHANGES_BY_AUTHOR].Value <<= pViewSettings->HasAuthor();
5070 pChangeProps[SC_SHOW_CHANGES_BY_AUTHOR_NAME].Name = "ShowChangesByAuthorName";
5071 pChangeProps[SC_SHOW_CHANGES_BY_AUTHOR_NAME].Value <<= pViewSettings->GetTheAuthorToShow();
5072 pChangeProps[SC_SHOW_CHANGES_BY_COMMENT].Name = "ShowChangesByComment";
5073 pChangeProps[SC_SHOW_CHANGES_BY_COMMENT].Value <<= pViewSettings->HasComment();
5074 pChangeProps[SC_SHOW_CHANGES_BY_COMMENT_TEXT].Name = "ShowChangesByCommentText";
5075 pChangeProps[SC_SHOW_CHANGES_BY_COMMENT_TEXT].Value <<= pViewSettings->GetTheComment();
5076 pChangeProps[SC_SHOW_CHANGES_BY_RANGES].Name = "ShowChangesByRanges";
5077 pChangeProps[SC_SHOW_CHANGES_BY_RANGES].Value <<= pViewSettings->HasRange();
5078 OUString sRangeList;
5079 ScRangeStringConverter::GetStringFromRangeList(sRangeList, &(pViewSettings->GetTheRangeList()), GetDocument(), FormulaGrammar::CONV_OOO);
5080 pChangeProps[SC_SHOW_CHANGES_BY_RANGES_LIST].Name = "ShowChangesByRangesList";
5081 pChangeProps[SC_SHOW_CHANGES_BY_RANGES_LIST].Value <<= sRangeList;
5083 pProps[nChangePos].Name = "TrackedChangesViewSettings";
5084 pProps[nChangePos].Value <<= aChangeProps;
5088 void ScXMLExport::GetViewSettings(uno::Sequence<beans::PropertyValue>& rProps)
5090 if (GetModel().is())
5092 rProps.realloc(4);
5093 beans::PropertyValue* pProps(rProps.getArray());
5094 ScModelObj* pDocObj(comphelper::getUnoTunnelImplementation<ScModelObj>( GetModel() ));
5095 if (pDocObj)
5097 SfxObjectShell* pEmbeddedObj = pDocObj->GetEmbeddedObject();
5098 if (pEmbeddedObj)
5100 tools::Rectangle aRect(pEmbeddedObj->GetVisArea());
5101 sal_uInt16 i(0);
5102 pProps[i].Name = "VisibleAreaTop";
5103 pProps[i].Value <<= static_cast<sal_Int32>(aRect.getY());
5104 pProps[++i].Name = "VisibleAreaLeft";
5105 pProps[i].Value <<= static_cast<sal_Int32>(aRect.getX());
5106 pProps[++i].Name = "VisibleAreaWidth";
5107 pProps[i].Value <<= static_cast<sal_Int32>(aRect.getWidth());
5108 pProps[++i].Name = "VisibleAreaHeight";
5109 pProps[i].Value <<= static_cast<sal_Int32>(aRect.getHeight());
5113 GetChangeTrackViewSettings(rProps);
5116 void ScXMLExport::GetConfigurationSettings(uno::Sequence<beans::PropertyValue>& rProps)
5118 if (GetModel().is())
5120 uno::Reference <lang::XMultiServiceFactory> xMultiServiceFactory(GetModel(), uno::UNO_QUERY);
5121 if (xMultiServiceFactory.is())
5123 uno::Reference <beans::XPropertySet> xProperties(xMultiServiceFactory->createInstance("com.sun.star.comp.SpreadsheetSettings"), uno::UNO_QUERY);
5124 if (xProperties.is())
5125 SvXMLUnitConverter::convertPropertySet(rProps, xProperties);
5127 sal_Int32 nPropsToAdd = 0;
5128 OUStringBuffer aTrackedChangesKey;
5129 if (GetDocument() && GetDocument()->GetChangeTrack() && GetDocument()->GetChangeTrack()->IsProtected())
5131 ::comphelper::Base64::encode(aTrackedChangesKey,
5132 GetDocument()->GetChangeTrack()->GetProtection());
5133 if (!aTrackedChangesKey.isEmpty())
5134 ++nPropsToAdd;
5137 bool bVBACompat = false;
5138 uno::Reference <container::XNameAccess> xCodeNameAccess;
5139 OSL_ENSURE( pDoc, "ScXMLExport::GetConfigurationSettings - no ScDocument!" );
5140 if( pDoc && pDoc->IsInVBAMode() )
5142 // VBA compatibility mode
5143 bVBACompat = true;
5144 ++nPropsToAdd;
5145 // code names
5146 xCodeNameAccess = new XMLCodeNameProvider( pDoc );
5147 if( xCodeNameAccess->hasElements() )
5148 ++nPropsToAdd;
5149 else
5150 xCodeNameAccess.clear();
5153 if( nPropsToAdd > 0 )
5155 sal_Int32 nCount(rProps.getLength());
5156 rProps.realloc(nCount + nPropsToAdd);
5157 if (!aTrackedChangesKey.isEmpty())
5159 rProps[nCount].Name = "TrackedChangesProtectionKey";
5160 rProps[nCount].Value <<= aTrackedChangesKey.makeStringAndClear();
5161 ++nCount;
5163 if( bVBACompat )
5165 rProps[nCount].Name = "VBACompatibilityMode";
5166 rProps[nCount].Value <<= bVBACompat;
5167 ++nCount;
5169 if( xCodeNameAccess.is() )
5171 rProps[nCount].Name = "ScriptConfiguration";
5172 rProps[nCount].Value <<= xCodeNameAccess;
5173 ++nCount;
5180 XMLShapeExport* ScXMLExport::CreateShapeExport()
5182 return new ScXMLShapeExport(*this);
5185 XMLNumberFormatAttributesExportHelper* ScXMLExport::GetNumberFormatAttributesExportHelper()
5187 if (!pNumberFormatAttributesExportHelper)
5188 pNumberFormatAttributesExportHelper.reset(new XMLNumberFormatAttributesExportHelper(GetNumberFormatsSupplier(), *this ));
5189 return pNumberFormatAttributesExportHelper.get();
5192 void ScXMLExport::CollectUserDefinedNamespaces(const SfxItemPool* pPool, sal_uInt16 nAttrib)
5194 for (const SfxPoolItem* pItem : pPool->GetItemSurrogates(nAttrib))
5196 const SvXMLAttrContainerItem *pUnknown(static_cast<const SvXMLAttrContainerItem *>(pItem));
5197 if( pUnknown->GetAttrCount() > 0 )
5199 sal_uInt16 nIdx(pUnknown->GetFirstNamespaceIndex());
5200 while( USHRT_MAX != nIdx )
5202 if( (XML_NAMESPACE_UNKNOWN_FLAG & nIdx) != 0 )
5204 const OUString& rPrefix = pUnknown->GetPrefix( nIdx );
5205 // Add namespace declaration for unknown attributes if
5206 // there aren't existing ones for the prefix used by the
5207 // attributes
5208 GetNamespaceMap_().Add( rPrefix,
5209 pUnknown->GetNamespace( nIdx ) );
5211 nIdx = pUnknown->GetNextNamespaceIndex( nIdx );
5216 // #i66550# needed for 'presentation:event-listener' element for URLs in shapes
5217 GetNamespaceMap_().Add(
5218 GetXMLToken( XML_NP_PRESENTATION ),
5219 GetXMLToken( XML_N_PRESENTATION ),
5220 XML_NAMESPACE_PRESENTATION );
5223 void ScXMLExport::IncrementProgressBar(bool bFlush, sal_Int32 nInc)
5225 nProgressCount += nInc;
5226 if (bFlush || nProgressCount > 100)
5228 GetProgressBarHelper()->Increment(nProgressCount);
5229 nProgressCount = 0;
5233 ErrCode ScXMLExport::exportDoc( enum XMLTokenEnum eClass )
5235 if( getExportFlags() & (SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::STYLES|
5236 SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
5238 if (GetDocument())
5240 // if source doc was Excel then
5241 uno::Reference< frame::XModel > xModel = GetModel();
5242 if ( xModel.is() )
5244 auto pFoundShell = comphelper::getUnoTunnelImplementation<SfxObjectShell>(xModel);
5245 if ( pFoundShell && ooo::vba::isAlienExcelDoc( *pFoundShell ) )
5247 xRowStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScFromXLSRowStylesProperties, xScPropHdlFactory, true);
5248 xRowStylesExportPropertySetMapper = new ScXMLRowExportPropertyMapper(xRowStylesPropertySetMapper);
5249 GetAutoStylePool()->SetFamilyPropSetMapper( XML_STYLE_FAMILY_TABLE_ROW,
5250 xRowStylesExportPropertySetMapper );
5253 CollectUserDefinedNamespaces(GetDocument()->GetPool(), ATTR_USERDEF);
5254 CollectUserDefinedNamespaces(GetDocument()->GetEditPool(), EE_PARA_XMLATTRIBS);
5255 CollectUserDefinedNamespaces(GetDocument()->GetEditPool(), EE_CHAR_XMLATTRIBS);
5256 ScDrawLayer* pDrawLayer = GetDocument()->GetDrawLayer();
5257 if (pDrawLayer)
5259 CollectUserDefinedNamespaces(&pDrawLayer->GetItemPool(), EE_PARA_XMLATTRIBS);
5260 CollectUserDefinedNamespaces(&pDrawLayer->GetItemPool(), EE_CHAR_XMLATTRIBS);
5261 CollectUserDefinedNamespaces(&pDrawLayer->GetItemPool(), SDRATTR_XMLATTRIBUTES);
5264 // sheet events use officeooo namespace
5265 if( (getExportFlags() & SvXMLExportFlags::CONTENT) &&
5266 getDefaultVersion() >= SvtSaveOptions::ODFVER_012 )
5268 bool bAnySheetEvents = false;
5269 SCTAB nTabCount = pDoc->GetTableCount();
5270 for (SCTAB nTab=0; nTab<nTabCount; ++nTab)
5271 if (pDoc->GetSheetEvents(nTab))
5272 bAnySheetEvents = true;
5273 if (bAnySheetEvents)
5274 GetNamespaceMap_().Add(
5275 GetXMLToken( XML_NP_OFFICE_EXT ),
5276 GetXMLToken( XML_N_OFFICE_EXT ),
5277 XML_NAMESPACE_OFFICE_EXT );
5281 return SvXMLExport::exportDoc( eClass );
5284 // XExporter
5285 void SAL_CALL ScXMLExport::setSourceDocument( const uno::Reference<lang::XComponent>& xComponent )
5287 SolarMutexGuard aGuard;
5288 SvXMLExport::setSourceDocument( xComponent );
5290 pDoc = ScXMLConverter::GetScDocument( GetModel() );
5291 OSL_ENSURE( pDoc, "ScXMLExport::setSourceDocument - no ScDocument!" );
5292 if (!pDoc)
5293 throw lang::IllegalArgumentException();
5295 // create ScChangeTrackingExportHelper after document is known
5296 pChangeTrackingExportHelper.reset(new ScChangeTrackingExportHelper(*this));
5298 // Set the document's storage grammar corresponding to the ODF version that
5299 // is to be written.
5300 SvtSaveOptions::ODFDefaultVersion meODFDefaultVersion = getDefaultVersion();
5301 switch (meODFDefaultVersion)
5303 // ODF 1.0 and 1.1 use GRAM_PODF, everything later or unspecified GRAM_ODFF
5304 case SvtSaveOptions::ODFVER_010:
5305 case SvtSaveOptions::ODFVER_011:
5306 pDoc->SetStorageGrammar( formula::FormulaGrammar::GRAM_PODF);
5307 break;
5308 default:
5309 pDoc->SetStorageGrammar( formula::FormulaGrammar::GRAM_ODFF);
5313 // XFilter
5314 sal_Bool SAL_CALL ScXMLExport::filter( const css::uno::Sequence< css::beans::PropertyValue >& aDescriptor )
5316 SolarMutexGuard aGuard;
5317 if (pDoc)
5318 pDoc->EnableIdle(false);
5319 bool bReturn(SvXMLExport::filter(aDescriptor));
5320 if (pDoc)
5321 pDoc->EnableIdle(true);
5322 return bReturn;
5325 void SAL_CALL ScXMLExport::cancel()
5327 SolarMutexGuard aGuard;
5328 if (pDoc)
5329 pDoc->EnableIdle(true);
5330 SvXMLExport::cancel();
5333 // XInitialization
5334 void SAL_CALL ScXMLExport::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
5336 SolarMutexGuard aGuard;
5337 SvXMLExport::initialize(aArguments);
5340 // XUnoTunnel
5341 sal_Int64 SAL_CALL ScXMLExport::getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier )
5343 SolarMutexGuard aGuard;
5344 return SvXMLExport::getSomething(aIdentifier);
5347 void ScXMLExport::DisposingModel()
5349 SvXMLExport::DisposingModel();
5350 pDoc = nullptr;
5351 xCurrentTable = nullptr;
5354 void ScXMLExport::SetSharedData(std::unique_ptr<ScMySharedData> pTemp) { pSharedData = std::move(pTemp); }
5356 std::unique_ptr<ScMySharedData> ScXMLExport::ReleaseSharedData() { return std::move(pSharedData); }
5357 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */