reintroduce ScCaptionPtr
[LibreOffice.git] / sc / source / filter / xml / xmlexprt.cxx
blob144fc4470e329fc3181ca97d307493ae88fa8b11
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>
107 #include <rtl/ustring.hxx>
109 #include <tools/color.hxx>
110 #include <rtl/math.hxx>
111 #include <svl/zforlist.hxx>
112 #include <svx/unoshape.hxx>
113 #include <comphelper/base64.hxx>
114 #include <comphelper/extract.hxx>
115 #include <svx/svdobj.hxx>
116 #include <svx/svdocapt.hxx>
117 #include <svtools/miscopt.hxx>
119 #include <comphelper/processfactory.hxx>
120 #include <com/sun/star/beans/XPropertySet.hpp>
121 #include <com/sun/star/container/XNamed.hpp>
122 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
123 #include <com/sun/star/form/XFormsSupplier2.hpp>
124 #include <com/sun/star/io/XActiveDataSource.hpp>
125 #include <com/sun/star/io/XSeekable.hpp>
126 #include <com/sun/star/sheet/XUsedAreaCursor.hpp>
127 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
128 #include <com/sun/star/sheet/XPrintAreas.hpp>
129 #include <com/sun/star/sheet/XUniqueCellFormatRangesSupplier.hpp>
130 #include <com/sun/star/sheet/XLabelRange.hpp>
131 #include <com/sun/star/sheet/NamedRangeFlag.hpp>
132 #include <com/sun/star/sheet/XSheetCellCursor.hpp>
133 #include <com/sun/star/sheet/XSheetCellRanges.hpp>
134 #include <com/sun/star/sheet/XSheetLinkable.hpp>
135 #include <com/sun/star/sheet/GlobalSheetSettings.hpp>
136 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
137 #include <com/sun/star/table/XColumnRowRange.hpp>
138 #include <com/sun/star/util/XProtectable.hpp>
140 #include <com/sun/star/chart2/XChartDocument.hpp>
141 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
142 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
144 #include <com/sun/star/document/XDocumentProperties.hpp>
145 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
147 #include "XMLCodeNameProvider.hxx"
149 #include <sfx2/linkmgr.hxx>
150 #include <sfx2/objsh.hxx>
152 #include <memory>
153 #include <vector>
154 #include <vbahelper/vbaaccesshelper.hxx>
156 namespace com { namespace sun { namespace star { namespace uno { class XComponentContext; } } } }
160 //! not found in unonames.hxx
161 #define SC_LAYERID "LayerID"
163 #define SC_VIEWCHANGES_COUNT 13
164 #define SC_SHOW_CHANGES 0
165 #define SC_SHOW_ACCEPTED_CHANGES 1
166 #define SC_SHOW_REJECTED_CHANGES 2
167 #define SC_SHOW_CHANGES_BY_DATETIME 3
168 #define SC_SHOW_CHANGES_BY_DATETIME_MODE 4
169 #define SC_SHOW_CHANGES_BY_DATETIME_FIRST_DATETIME 5
170 #define SC_SHOW_CHANGES_BY_DATETIME_SECOND_DATETIME 6
171 #define SC_SHOW_CHANGES_BY_AUTHOR 7
172 #define SC_SHOW_CHANGES_BY_AUTHOR_NAME 8
173 #define SC_SHOW_CHANGES_BY_COMMENT 9
174 #define SC_SHOW_CHANGES_BY_COMMENT_TEXT 10
175 #define SC_SHOW_CHANGES_BY_RANGES 11
176 #define SC_SHOW_CHANGES_BY_RANGES_LIST 12
178 using namespace formula;
179 using namespace com::sun::star;
180 using namespace xmloff::token;
181 using ::std::vector;
182 using ::com::sun::star::uno::UNO_QUERY;
184 namespace
186 OUString lcl_RangeSequenceToString(
187 const uno::Sequence< OUString > & rRanges,
188 const uno::Reference< chart2::data::XRangeXMLConversion > & xFormatConverter )
190 OUStringBuffer aResult;
191 const sal_Int32 nMaxIndex( rRanges.getLength() - 1 );
192 const sal_Unicode cSep(' ');
193 for( sal_Int32 i=0; i<=nMaxIndex; ++i )
195 OUString aRange( rRanges[i] );
196 if( xFormatConverter.is())
197 aRange = xFormatConverter->convertRangeToXML( aRange );
198 aResult.append( aRange );
199 if( i < nMaxIndex )
200 aResult.append( cSep );
202 return aResult.makeStringAndClear();
205 OUString lcl_GetFormattedString(ScDocument* pDoc, ScRefCellValue& rCell, const ScAddress& rAddr)
207 // return text/edit cell string content, with line feeds in edit cells
209 if (!pDoc)
210 return EMPTY_OUSTRING;
212 switch (rCell.meType)
214 case CELLTYPE_STRING:
216 OUString aStr;
217 Color* pColor;
218 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
220 sal_uInt32 nFormat = pDoc->GetNumberFormat(rAddr);
221 ScCellFormat::GetString(rCell, nFormat, aStr, &pColor, *pFormatter, pDoc);
222 return aStr;
224 case CELLTYPE_EDIT:
226 const EditTextObject* pData = rCell.mpEditText;
227 if (!pData)
228 return EMPTY_OUSTRING;
230 EditEngine& rEngine = pDoc->GetEditEngine();
231 rEngine.SetText(*pData);
232 return rEngine.GetText();
234 break;
235 default:
239 return EMPTY_OUSTRING;
242 } // anonymous namespace
244 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
245 Calc_XMLExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
247 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLExporter", SvXMLExportFlags::ALL));
250 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
251 Calc_XMLMetaExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
253 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLMetaExporter", SvXMLExportFlags::META));
256 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
257 Calc_XMLStylesExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
259 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLStylesExporter", SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS));
262 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
263 Calc_XMLContentExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
265 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLContentExporter", SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::FONTDECLS));
268 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
269 Calc_XMLSettingsExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
271 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLSettingsExporter", SvXMLExportFlags::SETTINGS));
274 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
275 Calc_XMLOasisExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
277 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisExporter", SvXMLExportFlags::ALL|SvXMLExportFlags::OASIS));
280 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
281 Calc_XMLOasisMetaExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
283 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisMetaExporter", SvXMLExportFlags::META|SvXMLExportFlags::OASIS));
286 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
287 Calc_XMLOasisStylesExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
289 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisStylesExporter", SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::OASIS));
292 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
293 Calc_XMLOasisContentExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
295 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisContentExporter", SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::OASIS));
298 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
299 Calc_XMLOasisSettingsExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
301 return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisSettingsExporter", SvXMLExportFlags::SETTINGS|SvXMLExportFlags::OASIS));
304 class ScXMLShapeExport : public XMLShapeExport
306 public:
307 explicit ScXMLShapeExport(SvXMLExport& rExp) : XMLShapeExport(rExp) {}
309 /** is called before a shape element for the given XShape is exported */
310 virtual void onExport( const uno::Reference < drawing::XShape >& xShape ) override;
313 void ScXMLShapeExport::onExport( const uno::Reference < drawing::XShape >& xShape )
315 uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
316 if( xShapeProp.is() )
318 sal_Int16 nLayerID = 0;
319 if( (xShapeProp->getPropertyValue( SC_LAYERID ) >>= nLayerID) && (SdrLayerID(nLayerID) == SC_LAYER_BACK) )
320 GetExport().AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_BACKGROUND, XML_TRUE);
324 sal_Int16 ScXMLExport::GetMeasureUnit()
326 css::uno::Reference<css::sheet::XGlobalSheetSettings> xProperties =
327 css::sheet::GlobalSheetSettings::create( comphelper::getProcessComponentContext() );
328 return xProperties->getMetric();
331 static const OUStringLiteral gsLayerID( SC_LAYERID );
333 ScXMLExport::ScXMLExport(
334 const css::uno::Reference< css::uno::XComponentContext >& rContext,
335 OUString const & implementationName, SvXMLExportFlags nExportFlag)
336 : SvXMLExport( GetMeasureUnit(),
337 rContext, implementationName, XML_SPREADSHEET, nExportFlag ),
338 pDoc(nullptr),
339 nSourceStreamPos(0),
340 aTableStyles(),
341 pCurrentCell(nullptr),
342 nOpenRow(-1),
343 nProgressCount(0),
344 nCurrentTable(0),
345 bHasRowHeader(false),
346 bRowHeaderOpen(false)
348 if (getExportFlags() & SvXMLExportFlags::CONTENT)
350 pGroupColumns.reset( new ScMyOpenCloseColumnRowGroup(*this, XML_TABLE_COLUMN_GROUP) );
351 pGroupRows.reset( new ScMyOpenCloseColumnRowGroup(*this, XML_TABLE_ROW_GROUP) );
352 pColumnStyles.reset( new ScColumnStyles() );
353 pRowStyles.reset( new ScRowStyles() );
354 pRowFormatRanges.reset( new ScRowFormatRanges() );
355 pMergedRangesContainer.reset( new ScMyMergedRangesContainer() );
356 pValidationsContainer.reset( new ScMyValidationsContainer() );
357 mpCellsItr.reset(new ScMyNotEmptyCellsIterator(*this));
358 pDefaults.reset( new ScMyDefaultStyles );
360 pCellStyles.reset( new ScFormatRangeStyles() );
362 // document is not set here - create ScChangeTrackingExportHelper later
364 xScPropHdlFactory = new XMLScPropHdlFactory;
365 xCellStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScCellStylesProperties, xScPropHdlFactory, true);
366 xColumnStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScColumnStylesProperties, xScPropHdlFactory, true);
367 xRowStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScRowStylesProperties, xScPropHdlFactory, true);
368 xTableStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScTableStylesProperties, xScPropHdlFactory, true);
369 xCellStylesExportPropertySetMapper = new ScXMLCellExportPropertyMapper(xCellStylesPropertySetMapper);
370 xCellStylesExportPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaExtPropMapper(*this));
371 xColumnStylesExportPropertySetMapper = new ScXMLColumnExportPropertyMapper(xColumnStylesPropertySetMapper);
372 xRowStylesExportPropertySetMapper = new ScXMLRowExportPropertyMapper(xRowStylesPropertySetMapper);
373 xTableStylesExportPropertySetMapper = new ScXMLTableExportPropertyMapper(xTableStylesPropertySetMapper);
375 GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_CELL, XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME,
376 xCellStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX);
377 GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_COLUMN, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_NAME,
378 xColumnStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_PREFIX);
379 GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_ROW, XML_STYLE_FAMILY_TABLE_ROW_STYLES_NAME,
380 xRowStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_ROW_STYLES_PREFIX);
381 GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_TABLE, XML_STYLE_FAMILY_TABLE_TABLE_STYLES_NAME,
382 xTableStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_TABLE_STYLES_PREFIX);
384 if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
386 // This name is reserved for the external ref cache tables. This
387 // should not conflict with user-defined styles since this name is
388 // used for a table style which is not available in the UI.
389 sExternalRefTabStyleName = "ta_extref";
390 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_TABLE, sExternalRefTabStyleName);
392 sAttrName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_NAME));
393 sAttrStyleName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_STYLE_NAME));
394 sAttrColumnsRepeated = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_NUMBER_COLUMNS_REPEATED));
395 sAttrFormula = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_FORMULA));
396 sAttrStringValue = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_STRING_VALUE));
397 sAttrValueType = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_VALUE_TYPE));
398 sElemCell = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_TABLE_CELL));
399 sElemCoveredCell = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_COVERED_TABLE_CELL));
400 sElemCol = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_TABLE_COLUMN));
401 sElemRow = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_TABLE_ROW));
402 sElemTab = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_TABLE));
403 sElemP = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TEXT, GetXMLToken(XML_P));
407 ScXMLExport::~ScXMLExport()
409 pGroupColumns.reset();
410 pGroupRows.reset();
411 pColumnStyles.reset();
412 pRowStyles.reset();
413 pCellStyles.reset();
414 pRowFormatRanges.reset();
415 pMergedRangesContainer.reset();
416 pValidationsContainer.reset();
417 pChangeTrackingExportHelper.reset();
418 pDefaults.reset();
419 pNumberFormatAttributesExportHelper.reset();
422 void ScXMLExport::SetSourceStream( const uno::Reference<io::XInputStream>& xNewStream )
424 xSourceStream = xNewStream;
426 if ( xSourceStream.is() )
428 // make sure it's a plain UTF-8 stream as written by OOo itself
430 const sal_Char pXmlHeader[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
431 sal_Int32 nLen = strlen(pXmlHeader);
433 uno::Sequence<sal_Int8> aFileStart(nLen);
434 sal_Int32 nRead = xSourceStream->readBytes( aFileStart, nLen );
436 if ( nRead != nLen || memcmp( aFileStart.getConstArray(), pXmlHeader, nLen ) != 0 )
438 // invalid - ignore stream, save normally
439 xSourceStream.clear();
441 else
443 // keep track of the bytes already read
444 nSourceStreamPos = nRead;
446 const ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetModel())->GetSheetSaveData();
447 if (pSheetData)
449 // add the loaded namespaces to the name space map
451 if ( !pSheetData->AddLoadedNamespaces( GetNamespaceMap_() ) )
453 // conflicts in the namespaces - ignore the stream, save normally
454 xSourceStream.clear();
461 sal_Int32 ScXMLExport::GetNumberFormatStyleIndex(sal_Int32 nNumFmt) const
463 NumberFormatIndexMap::const_iterator itr = aNumFmtIndexMap.find(nNumFmt);
464 if (itr == aNumFmtIndexMap.end())
465 return -1;
467 return itr->second;
470 void ScXMLExport::CollectSharedData(SCTAB& nTableCount, sal_Int32& nShapesCount)
472 if (!GetModel().is())
473 return;
475 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc(GetModel(), uno::UNO_QUERY);
476 if (!xSpreadDoc.is())
477 return;
479 uno::Reference<container::XIndexAccess> xIndex(xSpreadDoc->getSheets(), uno::UNO_QUERY);
480 if (!xIndex.is())
481 return;
483 nTableCount = xIndex->getCount();
484 if (!pSharedData)
485 pSharedData.reset(new ScMySharedData(nTableCount));
487 pCellStyles->AddNewTable(nTableCount - 1);
489 for (SCTAB nTable = 0; nTable < nTableCount; ++nTable)
491 nCurrentTable = sal::static_int_cast<sal_uInt16>(nTable);
492 uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xIndex->getByIndex(nTable), uno::UNO_QUERY);
493 if (!xDrawPageSupplier.is())
494 continue;
496 uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage());
497 ScMyDrawPage aDrawPage;
498 aDrawPage.bHasForms = false;
499 aDrawPage.xDrawPage.set(xDrawPage);
500 pSharedData->AddDrawPage(aDrawPage, nTable);
501 uno::Reference<container::XIndexAccess> xShapesIndex(xDrawPage, uno::UNO_QUERY);
502 if (!xShapesIndex.is())
503 continue;
505 sal_Int32 nShapes = xShapesIndex->getCount();
506 for (sal_Int32 nShape = 0; nShape < nShapes; ++nShape)
508 uno::Reference<drawing::XShape> xShape(xShapesIndex->getByIndex(nShape), uno::UNO_QUERY);
509 if (!xShape.is())
510 continue;
512 uno::Reference<beans::XPropertySet> xShapeProp(xShape, uno::UNO_QUERY);
513 if (!xShapeProp.is())
514 continue;
516 sal_Int16 nLayerID = 0;
517 bool bExtracted = xShapeProp->getPropertyValue(gsLayerID) >>= nLayerID;
518 if (!bExtracted)
519 continue;
521 if ((SdrLayerID(nLayerID) == SC_LAYER_INTERN) || (SdrLayerID(nLayerID) == SC_LAYER_HIDDEN))
523 CollectInternalShape(xShape);
524 continue;
527 ++nShapesCount;
529 SvxShape* pShapeImp = SvxShape::getImplementation(xShape);
530 if (!pShapeImp)
531 continue;
533 SdrObject* pSdrObj = pShapeImp->GetSdrObject();
534 if (!pSdrObj)
535 continue;
537 if (ScDrawObjData *pAnchor = ScDrawLayer::GetNonRotatedObjData(pSdrObj))
539 ScMyShape aMyShape;
540 aMyShape.aAddress = pAnchor->maStart;
541 SAL_WARN_IF(aMyShape.aAddress.Tab() != nTable, "sc", "not anchored to current sheet!");
542 aMyShape.aAddress.SetTab(nTable);
543 aMyShape.aEndAddress = pAnchor->maEnd;
544 aMyShape.aEndAddress.SetTab( nTable );
545 aMyShape.nEndX = pAnchor->maEndOffset.X();
546 aMyShape.nEndY = pAnchor->maEndOffset.Y();
547 aMyShape.xShape = xShape;
548 aMyShape.bResizeWithCell = ScDrawLayer::IsResizeWithCell(*pSdrObj);
549 pSharedData->AddNewShape(aMyShape);
550 pSharedData->SetLastColumn(nTable, pAnchor->maStart.Col());
551 pSharedData->SetLastRow(nTable, pAnchor->maStart.Row());
553 else
554 pSharedData->AddTableShape(nTable, xShape);
559 void ScXMLExport::CollectShapesAutoStyles(SCTAB nTableCount)
561 // #i84077# To avoid compiler warnings about uninitialized aShapeItr,
562 // it's initialized using this dummy list. The iterator contains shapes
563 // from all sheets, so it can't be declared inside the nTable loop where
564 // it is used.
565 ScMyShapeList aDummyInitList;
567 pSharedData->SortShapesContainer();
568 pSharedData->SortNoteShapes();
569 const ScMyShapeList* pShapeList(nullptr);
570 ScMyShapeList::const_iterator aShapeItr = aDummyInitList.end();
571 if (pSharedData->GetShapesContainer())
573 pShapeList = &pSharedData->GetShapesContainer()->GetShapes();
574 aShapeItr = pShapeList->begin();
576 if (pSharedData->HasDrawPage())
578 for (SCTAB nTable = 0; nTable < nTableCount; ++nTable)
580 uno::Reference<drawing::XDrawPage> xDrawPage(pSharedData->GetDrawPage(nTable));
581 uno::Reference<drawing::XShapes> xShapes (xDrawPage, uno::UNO_QUERY);
583 if (xShapes.is())
585 GetShapeExport()->seekShapes(xShapes);
586 uno::Reference< form::XFormsSupplier2 > xFormsSupplier( xDrawPage, uno::UNO_QUERY );
587 if( xFormsSupplier.is() && xFormsSupplier->hasForms() )
589 GetFormExport()->examineForms(xDrawPage);
590 pSharedData->SetDrawPageHasForms(nTable, true);
592 ScMyTableShapes* pTableShapes(pSharedData->GetTableShapes());
593 if (pTableShapes)
595 for (const auto& rxShape : (*pTableShapes)[nTable])
597 GetShapeExport()->collectShapeAutoStyles(rxShape);
598 IncrementProgressBar(false);
601 if (pShapeList)
603 ScMyShapeList::const_iterator aEndItr(pShapeList->end());
604 while ( aShapeItr != aEndItr && ( aShapeItr->aAddress.Tab() == nTable ) )
606 GetShapeExport()->collectShapeAutoStyles(aShapeItr->xShape);
607 IncrementProgressBar(false);
608 ++aShapeItr;
611 if (pSharedData->GetNoteShapes())
613 const ScMyNoteShapeList& rNoteShapes = pSharedData->GetNoteShapes()->GetNotes();
614 for (const auto& rNoteShape : rNoteShapes)
616 if ( rNoteShape.aPos.Tab() == nTable )
617 GetShapeExport()->collectShapeAutoStyles(rNoteShape.xShape);
623 pSharedData->SortNoteShapes(); // sort twice, because some more shapes are added
626 void ScXMLExport::ExportMeta_()
628 sal_Int32 nCellCount(pDoc ? pDoc->GetCellCount() : 0);
629 SCTAB nTableCount(0);
630 sal_Int32 nShapesCount(0);
631 GetAutoStylePool()->ClearEntries();
632 CollectSharedData(nTableCount, nShapesCount);
634 uno::Sequence<beans::NamedValue> stats
636 { "TableCount", uno::makeAny(static_cast<sal_Int32>(nTableCount)) },
637 { "CellCount", uno::makeAny(nCellCount) },
638 { "ObjectCount", uno::makeAny(nShapesCount) }
641 // update document statistics at the model
642 uno::Reference<document::XDocumentPropertiesSupplier> xPropSup(GetModel(),
643 uno::UNO_QUERY_THROW);
644 uno::Reference<document::XDocumentProperties> xDocProps(
645 xPropSup->getDocumentProperties());
646 if (xDocProps.is()) {
647 xDocProps->setDocumentStatistics(stats);
650 // export document properties
651 SvXMLExport::ExportMeta_();
654 void ScXMLExport::ExportFontDecls_()
656 GetFontAutoStylePool(); // make sure the pool is created
657 SvXMLExport::ExportFontDecls_();
660 table::CellRangeAddress ScXMLExport::GetEndAddress(const uno::Reference<sheet::XSpreadsheet>& xTable)
662 table::CellRangeAddress aCellAddress;
663 uno::Reference<sheet::XSheetCellCursor> xCursor(xTable->createCursor());
664 uno::Reference<sheet::XUsedAreaCursor> xUsedArea (xCursor, uno::UNO_QUERY);
665 uno::Reference<sheet::XCellRangeAddressable> xCellAddress (xCursor, uno::UNO_QUERY);
666 if (xUsedArea.is() && xCellAddress.is())
668 xUsedArea->gotoEndOfUsedArea(true);
669 aCellAddress = xCellAddress->getRangeAddress();
671 return aCellAddress;
674 void ScXMLExport::GetAreaLinks( ScMyAreaLinksContainer& rAreaLinks )
676 if (pDoc->GetLinkManager())
678 const sfx2::SvBaseLinks& rLinks = pDoc->GetLinkManager()->GetLinks();
679 for (const auto & rLink : rLinks)
681 ScAreaLink *pLink = dynamic_cast<ScAreaLink*>(rLink.get());
682 if (pLink)
684 ScMyAreaLink aAreaLink;
685 aAreaLink.aDestRange = pLink->GetDestArea();
686 aAreaLink.sSourceStr = pLink->GetSource();
687 aAreaLink.sFilter = pLink->GetFilter();
688 aAreaLink.sFilterOptions = pLink->GetOptions();
689 aAreaLink.sURL = pLink->GetFile();
690 aAreaLink.nRefresh = pLink->GetRefreshDelay();
691 rAreaLinks.AddNewAreaLink( aAreaLink );
695 rAreaLinks.Sort();
698 // core implementation
699 void ScXMLExport::GetDetectiveOpList( ScMyDetectiveOpContainer& rDetOp )
701 if (pDoc)
703 ScDetOpList* pOpList(pDoc->GetDetOpList());
704 if( pOpList )
706 size_t nCount = pOpList->Count();
707 for (size_t nIndex = 0; nIndex < nCount; ++nIndex )
709 const ScDetOpData& rDetData = pOpList->GetObject( nIndex);
710 const ScAddress& rDetPos = rDetData.GetPos();
711 SCTAB nTab = rDetPos.Tab();
712 if ( nTab < pDoc->GetTableCount() )
714 rDetOp.AddOperation( rDetData.GetOperation(), rDetPos, static_cast<sal_uInt32>( nIndex) );
716 // cells with detective operations are written even if empty
717 pSharedData->SetLastColumn( nTab, rDetPos.Col() );
718 pSharedData->SetLastRow( nTab, rDetPos.Row() );
721 rDetOp.Sort();
726 void ScXMLExport::WriteSingleColumn(const sal_Int32 nRepeatColumns, const sal_Int32 nStyleIndex,
727 const sal_Int32 nIndex, const bool bIsAutoStyle, const bool bIsVisible)
729 CheckAttrList();
730 AddAttribute(sAttrStyleName, pColumnStyles->GetStyleNameByIndex(nStyleIndex));
731 if (!bIsVisible)
732 AddAttribute(XML_NAMESPACE_TABLE, XML_VISIBILITY, XML_COLLAPSE);
733 if (nRepeatColumns > 1)
735 OUString sOUEndCol(OUString::number(nRepeatColumns));
736 AddAttribute(sAttrColumnsRepeated, sOUEndCol);
738 if (nIndex != -1)
739 AddAttribute(XML_NAMESPACE_TABLE, XML_DEFAULT_CELL_STYLE_NAME, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
740 SvXMLElementExport aElemC(*this, sElemCol, true, true);
743 void ScXMLExport::WriteColumn(const sal_Int32 nColumn, const sal_Int32 nRepeatColumns,
744 const sal_Int32 nStyleIndex, const bool bIsVisible)
746 sal_Int32 nRepeat(1);
747 sal_Int32 nPrevIndex(pDefaults->GetColDefaults()[nColumn].nIndex);
748 bool bPrevAutoStyle(pDefaults->GetColDefaults()[nColumn].bIsAutoStyle);
749 for (sal_Int32 i = nColumn + 1; i < nColumn + nRepeatColumns; ++i)
751 if ((pDefaults->GetColDefaults()[i].nIndex != nPrevIndex) ||
752 (pDefaults->GetColDefaults()[i].bIsAutoStyle != bPrevAutoStyle))
754 WriteSingleColumn(nRepeat, nStyleIndex, nPrevIndex, bPrevAutoStyle, bIsVisible);
755 nPrevIndex = pDefaults->GetColDefaults()[i].nIndex;
756 bPrevAutoStyle = pDefaults->GetColDefaults()[i].bIsAutoStyle;
757 nRepeat = 1;
759 else
760 ++nRepeat;
762 WriteSingleColumn(nRepeat, nStyleIndex, nPrevIndex, bPrevAutoStyle, bIsVisible);
765 void ScXMLExport::OpenHeaderColumn()
767 StartElement( XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS, true );
770 void ScXMLExport::CloseHeaderColumn()
772 EndElement(XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS, true);
775 void ScXMLExport::ExportColumns(const sal_Int32 nTable, const ScRange& aColumnHeaderRange, const bool bHasColumnHeader)
777 sal_Int32 nColsRepeated (1);
778 sal_Int32 nIndex;
779 sal_Int32 nPrevColumn(0);
780 bool bPrevIsVisible (true);
781 bool bWasHeader (false);
782 bool bIsClosed (true);
783 sal_Int32 nPrevIndex (-1);
784 sal_Int32 nColumn;
785 for (nColumn = 0; nColumn <= pSharedData->GetLastColumn(nTable); ++nColumn)
787 CheckAttrList();
788 bool bIsVisible(true);
789 nIndex = pColumnStyles->GetStyleNameIndex(nTable, nColumn, bIsVisible);
791 const bool bIsHeader = bHasColumnHeader && (aColumnHeaderRange.aStart.Col() <= nColumn) && (nColumn <= aColumnHeaderRange.aEnd.Col());
792 if (bIsHeader != bWasHeader)
794 if (bIsHeader)
796 if (nColumn > 0)
798 WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
799 if (pGroupColumns->IsGroupEnd(nColumn - 1))
800 pGroupColumns->CloseGroups(nColumn - 1);
802 bPrevIsVisible = bIsVisible;
803 nPrevIndex = nIndex;
804 nPrevColumn = nColumn;
805 nColsRepeated = 1;
806 if(pGroupColumns->IsGroupStart(nColumn))
807 pGroupColumns->OpenGroups(nColumn);
808 OpenHeaderColumn();
809 bWasHeader = true;
810 bIsClosed = false;
812 else
814 WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
815 CloseHeaderColumn();
816 if (pGroupColumns->IsGroupEnd(nColumn - 1))
817 pGroupColumns->CloseGroups(nColumn - 1);
818 if(pGroupColumns->IsGroupStart(nColumn))
819 pGroupColumns->OpenGroups(nColumn);
820 bPrevIsVisible = bIsVisible;
821 nPrevIndex = nIndex;
822 nPrevColumn = nColumn;
823 nColsRepeated = 1;
824 bWasHeader = false;
825 bIsClosed = true;
828 else if (nColumn == 0)
830 if (pGroupColumns->IsGroupStart(nColumn))
831 pGroupColumns->OpenGroups(nColumn);
832 bPrevIsVisible = bIsVisible;
833 nPrevIndex = nIndex;
835 else if ((bIsVisible == bPrevIsVisible) && (nIndex == nPrevIndex) &&
836 !pGroupColumns->IsGroupStart(nColumn) && !pGroupColumns->IsGroupEnd(nColumn - 1))
837 ++nColsRepeated;
838 else
840 WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
841 if (pGroupColumns->IsGroupEnd(nColumn - 1))
843 if (bIsHeader)
844 CloseHeaderColumn();
845 pGroupColumns->CloseGroups(nColumn - 1);
846 if (bIsHeader)
847 OpenHeaderColumn();
849 if (pGroupColumns->IsGroupStart(nColumn))
851 if (bIsHeader)
852 CloseHeaderColumn();
853 pGroupColumns->OpenGroups(nColumn);
854 if (bIsHeader)
855 OpenHeaderColumn();
857 bPrevIsVisible = bIsVisible;
858 nPrevIndex = nIndex;
859 nPrevColumn = nColumn;
860 nColsRepeated = 1;
863 assert(nPrevIndex >= 0 && "coverity#1438402");
864 WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
865 if (!bIsClosed)
866 CloseHeaderColumn();
867 if (pGroupColumns->IsGroupEnd(nColumn - 1))
868 pGroupColumns->CloseGroups(nColumn - 1);
871 void ScXMLExport::ExportExternalRefCacheStyles()
873 sal_Int32 nEntryIndex = GetCellStylesPropertySetMapper()->FindEntryIndex(
874 "NumberFormat", XML_NAMESPACE_STYLE, "data-style-name");
876 if (nEntryIndex < 0)
877 // No entry index for the number format is found.
878 return;
880 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
881 if (!pRefMgr->hasExternalData())
882 // No external reference data cached.
883 return;
885 // Export each unique number format used in the external ref cache.
886 vector<sal_uInt32> aNumFmts;
887 pRefMgr->getAllCachedNumberFormats(aNumFmts);
888 const OUString aDefaultStyle = OUString("Default").intern();
889 for (const auto& rNumFmt : aNumFmts)
891 sal_Int32 nNumFmt = static_cast<sal_Int32>(rNumFmt);
893 addDataStyle(nNumFmt);
895 uno::Any aVal;
896 aVal <<= nNumFmt;
897 vector<XMLPropertyState> aProps;
898 aVal <<= aDefaultStyle;
899 aProps.emplace_back(nEntryIndex, aVal);
901 OUString aName;
902 sal_Int32 nIndex;
903 if (GetAutoStylePool()->Add(aName, XML_STYLE_FAMILY_TABLE_CELL, aDefaultStyle, aProps))
905 pCellStyles->AddStyleName(aName, nIndex);
907 else
909 bool bIsAuto;
910 nIndex = pCellStyles->GetIndexOfStyleName(
911 aName, XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX, bIsAuto);
914 // store the number format to index mapping for later use.
915 aNumFmtIndexMap.emplace(nNumFmt, nIndex);
919 namespace {
921 void handleFont(
922 std::vector<XMLPropertyState>& rPropStates,
923 const SfxPoolItem* p, const rtl::Reference<XMLPropertySetMapper>& xMapper, const OUString& rXMLName )
925 sal_Int32 nEntryCount = xMapper->GetEntryCount();
927 // Apparently font info needs special handling.
928 const SvxFontItem* pItem = static_cast<const SvxFontItem*>(p);
930 sal_Int32 nIndexFontName = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, rXMLName, 0);
932 if (nIndexFontName == -1 || nIndexFontName >= nEntryCount)
933 return;
935 uno::Any aAny;
936 if (!pItem->QueryValue(aAny, MID_FONT_FAMILY_NAME))
937 return;
939 rPropStates.emplace_back(nIndexFontName, aAny);
942 const SvxFieldData* toXMLPropertyStates(
943 std::vector<XMLPropertyState>& rPropStates, const std::vector<const SfxPoolItem*>& rSecAttrs,
944 const rtl::Reference<XMLPropertySetMapper>& xMapper, const ScXMLEditAttributeMap& rAttrMap )
946 const SvxFieldData* pField = nullptr;
947 sal_Int32 nEntryCount = xMapper->GetEntryCount();
948 rPropStates.reserve(rSecAttrs.size());
949 for (const SfxPoolItem* p : rSecAttrs)
951 if (p->Which() == EE_FEATURE_FIELD)
953 pField = static_cast<const SvxFieldItem*>(p)->GetField();
954 continue;
957 const ScXMLEditAttributeMap::Entry* pEntry = rAttrMap.getEntryByItemID(p->Which());
958 if (!pEntry)
959 continue;
961 sal_Int32 nIndex = xMapper->GetEntryIndex(
962 pEntry->nmXMLNS, OUString::createFromAscii(pEntry->mpXMLName), 0);
964 if (nIndex == -1 || nIndex >= nEntryCount)
965 continue;
967 uno::Any aAny;
968 switch (p->Which())
970 case EE_CHAR_FONTINFO:
971 handleFont(rPropStates, p, xMapper, "font-name");
972 break;
973 case EE_CHAR_FONTINFO_CJK:
974 handleFont(rPropStates, p, xMapper, "font-name-asian");
975 break;
976 case EE_CHAR_FONTINFO_CTL:
977 handleFont(rPropStates, p, xMapper, "font-name-complex");
978 break;
979 case EE_CHAR_WEIGHT:
980 case EE_CHAR_WEIGHT_CJK:
981 case EE_CHAR_WEIGHT_CTL:
983 if (!static_cast<const SvxWeightItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
984 continue;
986 rPropStates.emplace_back(nIndex, aAny);
988 break;
989 case EE_CHAR_FONTHEIGHT:
990 case EE_CHAR_FONTHEIGHT_CJK:
991 case EE_CHAR_FONTHEIGHT_CTL:
993 if (!static_cast<const SvxFontHeightItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
994 continue;
996 rPropStates.emplace_back(nIndex, aAny);
998 break;
999 case EE_CHAR_ITALIC:
1000 case EE_CHAR_ITALIC_CJK:
1001 case EE_CHAR_ITALIC_CTL:
1003 if (!static_cast<const SvxPostureItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1004 continue;
1006 rPropStates.emplace_back(nIndex, aAny);
1008 break;
1009 case EE_CHAR_UNDERLINE:
1011 // Underline attribute needs to export multiple entries.
1012 sal_Int32 nIndexStyle = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-underline-style", 0);
1013 if (nIndexStyle == -1 || nIndexStyle > nEntryCount)
1014 break;
1016 sal_Int32 nIndexWidth = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-underline-width", 0);
1017 if (nIndexWidth == -1 || nIndexWidth > nEntryCount)
1018 break;
1020 sal_Int32 nIndexType = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-underline-type", 0);
1021 if (nIndexType == -1 || nIndexType > nEntryCount)
1022 break;
1024 sal_Int32 nIndexColor = xMapper->FindEntryIndex("CharUnderlineColor", XML_NAMESPACE_STYLE, "text-underline-color");
1025 if (nIndexColor == -1 || nIndexColor > nEntryCount)
1026 break;
1028 sal_Int32 nIndexHasColor = xMapper->FindEntryIndex("CharUnderlineHasColor", XML_NAMESPACE_STYLE, "text-underline-color");
1029 if (nIndexHasColor == -1 || nIndexHasColor > nEntryCount)
1030 break;
1032 const SvxUnderlineItem* pUL = static_cast<const SvxUnderlineItem*>(p);
1033 pUL->QueryValue(aAny, MID_TL_STYLE);
1034 rPropStates.emplace_back(nIndexStyle, aAny);
1035 rPropStates.emplace_back(nIndexType, aAny);
1036 rPropStates.emplace_back(nIndexWidth, aAny);
1038 pUL->QueryValue(aAny, MID_TL_COLOR);
1039 rPropStates.emplace_back(nIndexColor, aAny);
1041 pUL->QueryValue(aAny, MID_TL_HASCOLOR);
1042 rPropStates.emplace_back(nIndexHasColor, aAny);
1044 break;
1045 case EE_CHAR_OVERLINE:
1047 // Same with overline. Do just as we do with underline attributes.
1048 sal_Int32 nIndexStyle = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-overline-style", 0);
1049 if (nIndexStyle == -1 || nIndexStyle > nEntryCount)
1050 break;
1052 sal_Int32 nIndexWidth = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-overline-width", 0);
1053 if (nIndexWidth == -1 || nIndexWidth > nEntryCount)
1054 break;
1056 sal_Int32 nIndexType = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-overline-type", 0);
1057 if (nIndexType == -1 || nIndexType > nEntryCount)
1058 break;
1060 sal_Int32 nIndexColor = xMapper->FindEntryIndex("CharOverlineColor", XML_NAMESPACE_STYLE, "text-overline-color");
1061 if (nIndexColor == -1 || nIndexColor > nEntryCount)
1062 break;
1064 sal_Int32 nIndexHasColor = xMapper->FindEntryIndex("CharOverlineHasColor", XML_NAMESPACE_STYLE, "text-overline-color");
1065 if (nIndexHasColor == -1 || nIndexHasColor > nEntryCount)
1066 break;
1068 const SvxOverlineItem* pOL = static_cast<const SvxOverlineItem*>(p);
1069 pOL->QueryValue(aAny, MID_TL_STYLE);
1070 rPropStates.emplace_back(nIndexStyle, aAny);
1071 rPropStates.emplace_back(nIndexType, aAny);
1072 rPropStates.emplace_back(nIndexWidth, aAny);
1074 pOL->QueryValue(aAny, MID_TL_COLOR);
1075 rPropStates.emplace_back(nIndexColor, aAny);
1077 pOL->QueryValue(aAny, MID_TL_HASCOLOR);
1078 rPropStates.emplace_back(nIndexHasColor, aAny);
1080 break;
1081 case EE_CHAR_COLOR:
1083 if (!static_cast<const SvxColorItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1084 continue;
1086 ::Color nColor;
1087 if ( aAny >>= nColor )
1089 sal_Int32 nIndexColor = ( nColor == COL_AUTO ) ? xMapper->GetEntryIndex(
1090 XML_NAMESPACE_STYLE, GetXMLToken( XML_USE_WINDOW_FONT_COLOR ), 0 ) : nIndex;
1091 rPropStates.emplace_back( nIndexColor, aAny );
1094 break;
1095 case EE_CHAR_WLM:
1097 if (!static_cast<const SvxWordLineModeItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1098 continue;
1100 rPropStates.emplace_back(nIndex, aAny);
1102 break;
1103 case EE_CHAR_STRIKEOUT:
1105 if (!static_cast<const SvxCrossedOutItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1106 continue;
1108 rPropStates.emplace_back(nIndex, aAny);
1110 break;
1111 case EE_CHAR_RELIEF:
1113 if (!static_cast<const SvxCharReliefItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1114 continue;
1116 rPropStates.emplace_back(nIndex, aAny);
1118 break;
1119 case EE_CHAR_OUTLINE:
1121 if (!static_cast<const SvxContourItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1122 continue;
1124 rPropStates.emplace_back(nIndex, aAny);
1126 break;
1127 case EE_CHAR_SHADOW:
1129 if (!static_cast<const SvxShadowedItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1130 continue;
1132 rPropStates.emplace_back(nIndex, aAny);
1134 break;
1135 case EE_CHAR_KERNING:
1137 if (!static_cast<const SvxKerningItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1138 continue;
1140 rPropStates.emplace_back(nIndex, aAny);
1142 break;
1143 case EE_CHAR_PAIRKERNING:
1145 if (!static_cast<const SvxAutoKernItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1146 continue;
1148 rPropStates.emplace_back(nIndex, aAny);
1150 break;
1151 case EE_CHAR_FONTWIDTH:
1153 if (!static_cast<const SvxCharScaleWidthItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1154 continue;
1156 rPropStates.emplace_back(nIndex, aAny);
1158 break;
1159 case EE_CHAR_ESCAPEMENT:
1161 sal_Int32 nIndexEsc = xMapper->FindEntryIndex("CharEscapement", XML_NAMESPACE_STYLE, "text-position");
1162 if (nIndexEsc == -1 || nIndexEsc > nEntryCount)
1163 break;
1165 sal_Int32 nIndexEscHeight = xMapper->FindEntryIndex("CharEscapementHeight", XML_NAMESPACE_STYLE, "text-position");
1166 if (nIndexEscHeight == -1 || nIndexEscHeight > nEntryCount)
1167 break;
1169 const SvxEscapementItem* pEsc = static_cast<const SvxEscapementItem*>(p);
1171 pEsc->QueryValue(aAny);
1172 rPropStates.emplace_back(nIndexEsc, aAny);
1174 pEsc->QueryValue(aAny, MID_ESC_HEIGHT);
1175 rPropStates.emplace_back(nIndexEscHeight, aAny);
1178 break;
1179 case EE_CHAR_EMPHASISMARK:
1181 if (!static_cast<const SvxEmphasisMarkItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1182 continue;
1184 rPropStates.emplace_back(nIndex, aAny);
1186 break;
1187 case EE_CHAR_LANGUAGE:
1188 case EE_CHAR_LANGUAGE_CJK:
1189 case EE_CHAR_LANGUAGE_CTL:
1191 if (!static_cast<const SvxLanguageItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1192 continue;
1194 // Export multiple entries.
1195 sal_Int32 nIndexLanguage, nIndexCountry, nIndexScript, nIndexTag;
1196 switch (p->Which())
1198 case EE_CHAR_LANGUAGE:
1199 nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_FO, "language", 0);
1200 nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_FO, "country", 0);
1201 nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_FO, "script", 0);
1202 nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "rfc-language-tag", 0);
1203 break;
1204 case EE_CHAR_LANGUAGE_CJK:
1205 nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "language-asian", 0);
1206 nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "country-asian", 0);
1207 nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "script-asian", 0);
1208 nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "rfc-language-tag-asian", 0);
1209 break;
1210 case EE_CHAR_LANGUAGE_CTL:
1211 nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "language-complex", 0);
1212 nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "country-complex", 0);
1213 nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "script-complex", 0);
1214 nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "rfc-language-tag-complex", 0);
1215 break;
1216 default:
1217 nIndexLanguage = nIndexCountry = nIndexScript = nIndexTag = -1;
1219 assert( nIndexLanguage >= 0 && nIndexCountry >= 0 && nIndexScript >= 0 && nIndexTag >= 0);
1220 rPropStates.emplace_back( nIndexLanguage, aAny);
1221 rPropStates.emplace_back( nIndexCountry, aAny);
1222 rPropStates.emplace_back( nIndexScript, aAny);
1223 rPropStates.emplace_back( nIndexTag, aAny);
1225 break;
1226 default:
1227 continue;
1231 return pField;
1236 void ScXMLExport::ExportCellTextAutoStyles(sal_Int32 nTable)
1238 if (!ValidTab(nTable))
1239 return;
1241 rtl::Reference<XMLPropertySetMapper> xMapper = GetTextParagraphExport()->GetTextPropMapper()->getPropertySetMapper();
1242 rtl::Reference<SvXMLAutoStylePoolP> xStylePool = GetAutoStylePool();
1243 const ScXMLEditAttributeMap& rAttrMap = GetEditAttributeMap();
1245 sc::EditTextIterator aIter(*pDoc, nTable);
1246 sal_Int32 nCellCount = 0;
1247 for (const EditTextObject* pEdit = aIter.first(); pEdit; pEdit = aIter.next(), ++nCellCount)
1249 std::vector<editeng::Section> aAttrs;
1250 pEdit->GetAllSections(aAttrs);
1251 if (aAttrs.empty())
1252 continue;
1254 for (const auto& rSec : aAttrs)
1256 const std::vector<const SfxPoolItem*>& rSecAttrs = rSec.maAttributes;
1257 if (rSecAttrs.empty())
1258 // No formats applied to this section. Skip it.
1259 continue;
1261 std::vector<XMLPropertyState> aPropStates;
1262 toXMLPropertyStates(aPropStates, rSecAttrs, xMapper, rAttrMap);
1263 if (!aPropStates.empty())
1264 xStylePool->Add(XML_STYLE_FAMILY_TEXT_TEXT, OUString(), aPropStates);
1268 GetProgressBarHelper()->ChangeReference(GetProgressBarHelper()->GetReference() + nCellCount);
1271 void ScXMLExport::WriteRowContent()
1273 ScMyRowFormatRange aRange;
1274 sal_Int32 nIndex(-1);
1275 #if OSL_DEBUG_LEVEL > 0
1276 sal_Int32 nPrevCol(0);
1277 #endif
1278 sal_Int32 nCols(0);
1279 sal_Int32 nPrevValidationIndex(-1);
1280 bool bIsAutoStyle(true);
1281 bool bIsFirst(true);
1282 while (pRowFormatRanges->GetNext(aRange))
1284 #if OSL_DEBUG_LEVEL > 0
1285 OSL_ENSURE(bIsFirst || (!bIsFirst && (nPrevCol + nCols == aRange.nStartColumn)), "here are some columns missing");
1286 #endif
1287 if (bIsFirst)
1289 nIndex = aRange.nIndex;
1290 nPrevValidationIndex = aRange.nValidationIndex;
1291 bIsAutoStyle = aRange.bIsAutoStyle;
1292 nCols = aRange.nRepeatColumns;
1293 bIsFirst = false;
1294 #if OSL_DEBUG_LEVEL > 0
1295 nPrevCol = aRange.nStartColumn;
1296 #endif
1298 else
1300 if (((aRange.nIndex == nIndex && aRange.bIsAutoStyle == bIsAutoStyle) ||
1301 (aRange.nIndex == nIndex && nIndex == -1)) &&
1302 nPrevValidationIndex == aRange.nValidationIndex)
1303 nCols += aRange.nRepeatColumns;
1304 else
1306 if (nIndex != -1)
1307 AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
1308 if (nPrevValidationIndex > -1)
1309 AddAttribute(XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, pValidationsContainer->GetValidationName(nPrevValidationIndex));
1310 if (nCols > 1)
1312 AddAttribute(sAttrColumnsRepeated, OUString::number(nCols));
1314 SvXMLElementExport aElemC(*this, sElemCell, true, true);
1315 nIndex = aRange.nIndex;
1316 bIsAutoStyle = aRange.bIsAutoStyle;
1317 nCols = aRange.nRepeatColumns;
1318 nPrevValidationIndex = aRange.nValidationIndex;
1319 #if OSL_DEBUG_LEVEL > 0
1320 nPrevCol = aRange.nStartColumn;
1321 #endif
1325 if (!bIsFirst)
1327 if (nIndex != -1)
1328 AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
1329 if (nPrevValidationIndex > -1)
1330 AddAttribute(XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, pValidationsContainer->GetValidationName(nPrevValidationIndex));
1331 if (nCols > 1)
1333 AddAttribute(sAttrColumnsRepeated, OUString::number(nCols));
1335 SvXMLElementExport aElemC(*this, sElemCell, true, true);
1339 void ScXMLExport::WriteRowStartTag(
1340 const sal_Int32 nIndex, const sal_Int32 nEqualRows,
1341 bool bHidden, bool bFiltered)
1343 AddAttribute(sAttrStyleName, pRowStyles->GetStyleNameByIndex(nIndex));
1344 if (bHidden)
1346 if (bFiltered)
1347 AddAttribute(XML_NAMESPACE_TABLE, XML_VISIBILITY, XML_FILTER);
1348 else
1349 AddAttribute(XML_NAMESPACE_TABLE, XML_VISIBILITY, XML_COLLAPSE);
1351 if (nEqualRows > 1)
1353 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, OUString::number(nEqualRows));
1356 StartElement( sElemRow, true);
1359 void ScXMLExport::OpenHeaderRows()
1361 StartElement( XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, true);
1362 bRowHeaderOpen = true;
1365 void ScXMLExport::CloseHeaderRows()
1367 EndElement(XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, true);
1370 void ScXMLExport::OpenNewRow(
1371 const sal_Int32 nIndex, const sal_Int32 nStartRow, const sal_Int32 nEqualRows,
1372 bool bHidden, bool bFiltered)
1374 nOpenRow = nStartRow;
1375 if (pGroupRows->IsGroupStart(nStartRow))
1377 if (bHasRowHeader && bRowHeaderOpen)
1378 CloseHeaderRows();
1379 pGroupRows->OpenGroups(nStartRow);
1380 if (bHasRowHeader && bRowHeaderOpen)
1381 OpenHeaderRows();
1383 if (bHasRowHeader && !bRowHeaderOpen && nStartRow >= aRowHeaderRange.aStart.Row() && nStartRow <= aRowHeaderRange.aEnd.Row())
1385 if (nStartRow == aRowHeaderRange.aStart.Row())
1386 OpenHeaderRows();
1387 sal_Int32 nEquals;
1388 if (aRowHeaderRange.aEnd.Row() < nStartRow + nEqualRows - 1)
1389 nEquals = aRowHeaderRange.aEnd.Row() - nStartRow + 1;
1390 else
1391 nEquals = nEqualRows;
1392 WriteRowStartTag(nIndex, nEquals, bHidden, bFiltered);
1393 nOpenRow = nStartRow + nEquals - 1;
1394 if (nEquals < nEqualRows)
1396 CloseRow(nStartRow + nEquals - 1);
1397 WriteRowStartTag(nIndex, nEqualRows - nEquals, bHidden, bFiltered);
1398 nOpenRow = nStartRow + nEqualRows - 1;
1401 else
1402 WriteRowStartTag(nIndex, nEqualRows, bHidden, bFiltered);
1405 void ScXMLExport::OpenAndCloseRow(
1406 const sal_Int32 nIndex, const sal_Int32 nStartRow, const sal_Int32 nEqualRows,
1407 bool bHidden, bool bFiltered)
1409 OpenNewRow(nIndex, nStartRow, nEqualRows, bHidden, bFiltered);
1410 WriteRowContent();
1411 CloseRow(nStartRow + nEqualRows - 1);
1412 pRowFormatRanges->Clear();
1415 void ScXMLExport::OpenRow(const sal_Int32 nTable, const sal_Int32 nStartRow, const sal_Int32 nRepeatRow, ScXMLCachedRowAttrAccess& rRowAttr)
1417 if (nRepeatRow > 1)
1419 sal_Int32 nPrevIndex(0), nIndex;
1420 bool bPrevHidden = false;
1421 bool bPrevFiltered = false;
1422 bool bHidden = false;
1423 bool bFiltered = false;
1424 sal_Int32 nEqualRows(1);
1425 sal_Int32 nEndRow(nStartRow + nRepeatRow);
1426 sal_Int32 nEndRowHidden = nStartRow - 1;
1427 sal_Int32 nEndRowFiltered = nStartRow - 1;
1428 sal_Int32 nRow;
1429 for (nRow = nStartRow; nRow < nEndRow; ++nRow)
1431 if (nRow == nStartRow)
1433 nPrevIndex = pRowStyles->GetStyleNameIndex(nTable, nRow);
1434 if (pDoc)
1436 if (nRow > nEndRowHidden)
1438 bPrevHidden = rRowAttr.rowHidden(nTable, nRow, nEndRowHidden);
1439 bHidden = bPrevHidden;
1441 if (nRow > nEndRowFiltered)
1443 bPrevFiltered = rRowAttr.rowFiltered(nTable, nRow, nEndRowFiltered);
1444 bFiltered = bPrevFiltered;
1449 else
1451 nIndex = pRowStyles->GetStyleNameIndex(nTable, nRow);
1452 if (pDoc)
1454 if (nRow > nEndRowHidden)
1455 bHidden = rRowAttr.rowHidden(nTable, nRow, nEndRowHidden);
1456 if (nRow > nEndRowFiltered)
1457 bFiltered = rRowAttr.rowFiltered(nTable, nRow, nEndRowFiltered);
1459 if (nIndex == nPrevIndex && bHidden == bPrevHidden && bFiltered == bPrevFiltered &&
1460 !(bHasRowHeader && ((nRow == aRowHeaderRange.aStart.Row()) || (nRow - 1 == aRowHeaderRange.aEnd.Row()))) &&
1461 !(pGroupRows->IsGroupStart(nRow)) &&
1462 !(pGroupRows->IsGroupEnd(nRow - 1)))
1463 ++nEqualRows;
1464 else
1466 assert(nPrevIndex >= 0 && "coverity#1438402");
1467 ScRowFormatRanges* pTempRowFormatRanges = new ScRowFormatRanges(pRowFormatRanges.get());
1468 OpenAndCloseRow(nPrevIndex, nRow - nEqualRows, nEqualRows, bPrevHidden, bPrevFiltered);
1469 pRowFormatRanges.reset(pTempRowFormatRanges);
1470 nEqualRows = 1;
1471 nPrevIndex = nIndex;
1472 bPrevHidden = bHidden;
1473 bPrevFiltered = bFiltered;
1477 assert(nPrevIndex >= 0 && "coverity#1438402");
1478 OpenNewRow(nPrevIndex, nRow - nEqualRows, nEqualRows, bPrevHidden, bPrevFiltered);
1480 else
1482 sal_Int32 nIndex = pRowStyles->GetStyleNameIndex(nTable, nStartRow);
1483 bool bHidden = false;
1484 bool bFiltered = false;
1485 if (pDoc)
1487 sal_Int32 nEndRowHidden;
1488 sal_Int32 nEndRowFiltered;
1489 bHidden = rRowAttr.rowHidden(nTable, nStartRow, nEndRowHidden);
1490 bFiltered = rRowAttr.rowFiltered(nTable, nStartRow, nEndRowFiltered);
1492 assert(nIndex >= 0 && "coverity#1438402");
1493 OpenNewRow(nIndex, nStartRow, 1, bHidden, bFiltered);
1495 nOpenRow = nStartRow + nRepeatRow - 1;
1498 void ScXMLExport::CloseRow(const sal_Int32 nRow)
1500 if (nOpenRow > -1)
1502 EndElement(sElemRow, true);
1503 if (bHasRowHeader && nRow == aRowHeaderRange.aEnd.Row())
1505 CloseHeaderRows();
1506 bRowHeaderOpen = false;
1508 if (pGroupRows->IsGroupEnd(nRow))
1510 if (bHasRowHeader && bRowHeaderOpen)
1511 CloseHeaderRows();
1512 pGroupRows->CloseGroups(nRow);
1513 if (bHasRowHeader && bRowHeaderOpen)
1514 OpenHeaderRows();
1517 nOpenRow = -1;
1520 void ScXMLExport::ExportFormatRanges(const sal_Int32 nStartCol, const sal_Int32 nStartRow,
1521 const sal_Int32 nEndCol, const sal_Int32 nEndRow, const sal_Int32 nSheet)
1523 pRowFormatRanges->Clear();
1524 ScXMLCachedRowAttrAccess aRowAttr(pDoc);
1525 if (nStartRow == nEndRow)
1527 pCellStyles->GetFormatRanges(nStartCol, nEndCol, nStartRow, nSheet, pRowFormatRanges.get());
1528 if (nOpenRow == - 1)
1529 OpenRow(nSheet, nStartRow, 1, aRowAttr);
1530 WriteRowContent();
1531 pRowFormatRanges->Clear();
1533 else
1535 if (nOpenRow > -1)
1537 pCellStyles->GetFormatRanges(nStartCol, pSharedData->GetLastColumn(nSheet), nStartRow, nSheet, pRowFormatRanges.get());
1538 WriteRowContent();
1539 CloseRow(nStartRow);
1540 sal_Int32 nRows(1);
1541 sal_Int32 nTotalRows(nEndRow - nStartRow + 1 - 1);
1542 while (nRows < nTotalRows)
1544 pRowFormatRanges->Clear();
1545 pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1546 sal_Int32 nMaxRows = pRowFormatRanges->GetMaxRows();
1547 OSL_ENSURE(nMaxRows, "something wents wrong");
1548 if (nMaxRows >= nTotalRows - nRows)
1550 OpenRow(nSheet, nStartRow + nRows, nTotalRows - nRows, aRowAttr);
1551 nRows += nTotalRows - nRows;
1553 else
1555 OpenRow(nSheet, nStartRow + nRows, nMaxRows, aRowAttr);
1556 nRows += nMaxRows;
1558 if (!pRowFormatRanges->GetSize())
1559 pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1560 WriteRowContent();
1561 CloseRow(nStartRow + nRows - 1);
1563 if (nTotalRows == 1)
1564 CloseRow(nStartRow);
1565 OpenRow(nSheet, nEndRow, 1, aRowAttr);
1566 pRowFormatRanges->Clear();
1567 pCellStyles->GetFormatRanges(0, nEndCol, nEndRow, nSheet, pRowFormatRanges.get());
1568 WriteRowContent();
1570 else
1572 sal_Int32 nRows(0);
1573 sal_Int32 nTotalRows(nEndRow - nStartRow + 1 - 1);
1574 while (nRows < nTotalRows)
1576 pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1577 sal_Int32 nMaxRows = pRowFormatRanges->GetMaxRows();
1578 if (nMaxRows >= nTotalRows - nRows)
1580 OpenRow(nSheet, nStartRow + nRows, nTotalRows - nRows, aRowAttr);
1581 nRows += nTotalRows - nRows;
1583 else
1585 OpenRow(nSheet, nStartRow + nRows, nMaxRows, aRowAttr);
1586 nRows += nMaxRows;
1588 if (!pRowFormatRanges->GetSize())
1589 pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1590 WriteRowContent();
1591 CloseRow(nStartRow + nRows - 1);
1593 OpenRow(nSheet, nEndRow, 1, aRowAttr);
1594 pRowFormatRanges->Clear();
1595 pCellStyles->GetFormatRanges(0, nEndCol, nEndRow, nSheet, pRowFormatRanges.get());
1596 WriteRowContent();
1601 void ScXMLExport::GetColumnRowHeader(bool& rHasColumnHeader, ScRange& rColumnHeaderRange,
1602 bool& rHasRowHeader, ScRange& rRowHeaderRange,
1603 OUString& rPrintRanges) const
1605 uno::Reference <sheet::XPrintAreas> xPrintAreas (xCurrentTable, uno::UNO_QUERY);
1606 if (xPrintAreas.is())
1608 rHasRowHeader = xPrintAreas->getPrintTitleRows();
1609 rHasColumnHeader = xPrintAreas->getPrintTitleColumns();
1610 table::CellRangeAddress rTempRowHeaderRange = xPrintAreas->getTitleRows();
1611 rRowHeaderRange = ScRange(rTempRowHeaderRange.StartColumn,
1612 rTempRowHeaderRange.StartRow,
1613 rTempRowHeaderRange.Sheet,
1614 rTempRowHeaderRange.EndColumn,
1615 rTempRowHeaderRange.EndRow,
1616 rTempRowHeaderRange.Sheet);
1617 table::CellRangeAddress rTempColumnHeaderRange = xPrintAreas->getTitleColumns();
1618 rColumnHeaderRange = ScRange(rTempColumnHeaderRange.StartColumn,
1619 rTempColumnHeaderRange.StartRow,
1620 rTempColumnHeaderRange.Sheet,
1621 rTempColumnHeaderRange.EndColumn,
1622 rTempColumnHeaderRange.EndRow,
1623 rTempColumnHeaderRange.Sheet);
1624 uno::Sequence< table::CellRangeAddress > aRangeList( xPrintAreas->getPrintAreas() );
1625 ScRangeStringConverter::GetStringFromRangeList( rPrintRanges, aRangeList, pDoc, FormulaGrammar::CONV_OOO );
1629 void ScXMLExport::FillFieldGroup(ScOutlineArray* pFields, ScMyOpenCloseColumnRowGroup* pGroups)
1631 size_t nDepth = pFields->GetDepth();
1632 for (size_t i = 0; i < nDepth; ++i)
1634 size_t nFields = pFields->GetCount(i);
1635 for (size_t j = 0; j < nFields; ++j)
1637 ScMyColumnRowGroup aGroup;
1638 const ScOutlineEntry* pEntry = pFields->GetEntry(i, j);
1639 aGroup.nField = pEntry->GetStart();
1640 aGroup.nLevel = static_cast<sal_Int16>(i);
1641 aGroup.bDisplay = !(pEntry->IsHidden());
1642 pGroups->AddGroup(aGroup, pEntry->GetEnd());
1645 if (nDepth)
1646 pGroups->Sort();
1649 void ScXMLExport::FillColumnRowGroups()
1651 if (pDoc)
1653 ScOutlineTable* pOutlineTable = pDoc->GetOutlineTable( static_cast<SCTAB>(nCurrentTable) );
1654 if(pOutlineTable)
1656 ScOutlineArray& rCols(pOutlineTable->GetColArray());
1657 ScOutlineArray& rRows(pOutlineTable->GetRowArray());
1658 FillFieldGroup(&rCols, pGroupColumns.get());
1659 FillFieldGroup(&rRows, pGroupRows.get());
1660 pSharedData->SetLastColumn(nCurrentTable, pGroupColumns->GetLast());
1661 pSharedData->SetLastRow(nCurrentTable, pGroupRows->GetLast());
1666 void ScXMLExport::SetBodyAttributes()
1668 if (pDoc && pDoc->IsDocProtected())
1670 AddAttribute(XML_NAMESPACE_TABLE, XML_STRUCTURE_PROTECTED, XML_TRUE);
1671 OUStringBuffer aBuffer;
1672 uno::Sequence<sal_Int8> aPassHash;
1673 ScPasswordHash eHashUsed = PASSHASH_UNSPECIFIED;
1674 const ScDocProtection* p = pDoc->GetDocProtection();
1675 if (p)
1677 if (p->hasPasswordHash(PASSHASH_SHA1))
1679 aPassHash = p->getPasswordHash(PASSHASH_SHA1);
1680 eHashUsed = PASSHASH_SHA1;
1682 else if (p->hasPasswordHash(PASSHASH_SHA256))
1684 aPassHash = p->getPasswordHash(PASSHASH_SHA256);
1685 eHashUsed = PASSHASH_SHA256;
1687 else if (p->hasPasswordHash(PASSHASH_XL, PASSHASH_SHA1))
1689 aPassHash = p->getPasswordHash(PASSHASH_XL, PASSHASH_SHA1);
1690 eHashUsed = PASSHASH_XL;
1693 ::comphelper::Base64::encode(aBuffer, aPassHash);
1694 if (!aBuffer.isEmpty())
1696 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
1697 if ( getDefaultVersion() >= SvtSaveOptions::ODFVER_012 )
1699 if (eHashUsed == PASSHASH_XL)
1701 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
1702 ScPassHashHelper::getHashURI(PASSHASH_XL));
1703 if (getDefaultVersion() > SvtSaveOptions::ODFVER_012)
1704 AddAttribute(XML_NAMESPACE_LO_EXT, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2,
1705 ScPassHashHelper::getHashURI(PASSHASH_SHA1));
1707 else if (eHashUsed == PASSHASH_SHA1)
1709 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
1710 ScPassHashHelper::getHashURI(PASSHASH_SHA1));
1712 else if (eHashUsed == PASSHASH_SHA256)
1714 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
1715 ScPassHashHelper::getHashURI(PASSHASH_SHA256));
1722 static bool lcl_CopyStreamElement( const uno::Reference< io::XInputStream >& xInput,
1723 const uno::Reference< io::XOutputStream >& xOutput,
1724 sal_Int32 nCount )
1726 const sal_Int32 nBufSize = 16*1024;
1727 uno::Sequence<sal_Int8> aSequence(nBufSize);
1729 sal_Int32 nRemaining = nCount;
1730 bool bFirst = true;
1732 while ( nRemaining > 0 )
1734 sal_Int32 nRead = xInput->readBytes( aSequence, std::min( nRemaining, nBufSize ) );
1735 if (bFirst)
1737 // safety check: Make sure the copied part actually points to the start of an element
1738 if ( nRead < 1 || aSequence[0] != static_cast<sal_Int8>('<') )
1740 return false; // abort and set an error
1742 bFirst = false;
1744 if (nRead == nRemaining)
1746 // safety check: Make sure the copied part also ends at the end of an element
1747 if ( aSequence[nRead-1] != static_cast<sal_Int8>('>') )
1749 return false; // abort and set an error
1753 if ( nRead == nBufSize )
1755 xOutput->writeBytes( aSequence );
1756 nRemaining -= nRead;
1758 else
1760 if ( nRead > 0 )
1762 uno::Sequence<sal_Int8> aTempBuf( aSequence.getConstArray(), nRead );
1763 xOutput->writeBytes( aTempBuf );
1765 nRemaining = 0;
1768 return true; // successful
1771 static void lcl_SkipBytesInBlocks( const uno::Reference< io::XInputStream >& xInput, sal_Int32 nBytesToSkip )
1773 // skipBytes in zip stream is implemented as reading.
1774 // For now, split into several calls to avoid allocating a large buffer.
1775 // Later, skipBytes should be changed.
1777 const sal_Int32 nMaxSize = 32*1024;
1779 if ( nBytesToSkip > 0 )
1781 sal_Int32 nRemaining = nBytesToSkip;
1782 while ( nRemaining > 0 )
1784 sal_Int32 nSkip = std::min( nRemaining, nMaxSize );
1785 xInput->skipBytes( nSkip );
1786 nRemaining -= nSkip;
1791 void ScXMLExport::CopySourceStream( sal_Int32 nStartOffset, sal_Int32 nEndOffset, sal_Int32& rNewStart, sal_Int32& rNewEnd )
1793 uno::Reference<xml::sax::XDocumentHandler> xHandler = GetDocHandler();
1794 uno::Reference<io::XActiveDataSource> xDestSource( xHandler, uno::UNO_QUERY );
1795 if ( xDestSource.is() )
1797 uno::Reference<io::XOutputStream> xDestStream = xDestSource->getOutputStream();
1798 uno::Reference<io::XSeekable> xDestSeek( xDestStream, uno::UNO_QUERY );
1799 if ( xDestSeek.is() )
1801 // temporary: set same stream again to clear buffer
1802 xDestSource->setOutputStream( xDestStream );
1804 if ( getExportFlags() & SvXMLExportFlags::PRETTY )
1806 const OString aOutStr("\n ");
1807 uno::Sequence<sal_Int8> aOutSeq( reinterpret_cast<sal_Int8 const *>(aOutStr.getStr()), aOutStr.getLength() );
1808 xDestStream->writeBytes( aOutSeq );
1811 rNewStart = static_cast<sal_Int32>(xDestSeek->getPosition());
1813 if ( nStartOffset > nSourceStreamPos )
1814 lcl_SkipBytesInBlocks( xSourceStream, nStartOffset - nSourceStreamPos );
1816 if ( !lcl_CopyStreamElement( xSourceStream, xDestStream, nEndOffset - nStartOffset ) )
1818 // If copying went wrong, set an error.
1819 // ScXMLImportWrapper then resets all stream flags, so the next save attempt will use normal saving.
1821 uno::Sequence<OUString> aEmptySeq;
1822 SetError(XMLERROR_CANCEL|XMLERROR_FLAG_SEVERE, aEmptySeq);
1824 nSourceStreamPos = nEndOffset;
1826 rNewEnd = static_cast<sal_Int32>(xDestSeek->getPosition());
1831 const ScXMLEditAttributeMap& ScXMLExport::GetEditAttributeMap() const
1833 if (!mpEditAttrMap)
1834 mpEditAttrMap.reset(new ScXMLEditAttributeMap);
1835 return *mpEditAttrMap;
1838 void ScXMLExport::RegisterDefinedStyleNames( const uno::Reference< css::sheet::XSpreadsheetDocument > & xSpreadDoc )
1840 ScFormatSaveData* pFormatData = ScModelObj::getImplementation(xSpreadDoc)->GetFormatSaveData();
1841 auto xAutoStylePool = GetAutoStylePool();
1842 for (const auto& rFormatInfo : pFormatData->maIDToName)
1844 xAutoStylePool->RegisterDefinedName(XML_STYLE_FAMILY_TABLE_CELL, rFormatInfo.second);
1848 void ScXMLExport::ExportContent_()
1850 nCurrentTable = 0;
1851 if (!pSharedData)
1853 SCTAB nTableCount(0);
1854 sal_Int32 nShapesCount(0);
1855 CollectSharedData(nTableCount, nShapesCount);
1856 OSL_FAIL("no shared data set");
1857 if (!pSharedData)
1858 return;
1860 ScXMLExportDatabaseRanges aExportDatabaseRanges(*this);
1861 if (!GetModel().is())
1862 return;
1864 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
1865 if ( !xSpreadDoc.is() )
1866 return;
1868 ScSheetSaveData* pSheetData = ScModelObj::getImplementation(xSpreadDoc)->GetSheetSaveData();
1869 if (pSheetData)
1870 pSheetData->ResetSaveEntries();
1872 uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
1873 if ( xIndex.is() )
1875 //_GetNamespaceMap().ClearQNamesCache();
1876 pChangeTrackingExportHelper->CollectAndWriteChanges();
1877 WriteCalculationSettings(xSpreadDoc);
1878 sal_Int32 nTableCount(xIndex->getCount());
1879 ScMyAreaLinksContainer aAreaLinks;
1880 GetAreaLinks( aAreaLinks );
1881 ScMyEmptyDatabaseRangesContainer aEmptyRanges(aExportDatabaseRanges.GetEmptyDatabaseRanges());
1882 ScMyDetectiveOpContainer aDetectiveOpContainer;
1883 GetDetectiveOpList( aDetectiveOpContainer );
1885 pCellStyles->Sort();
1886 pMergedRangesContainer->Sort();
1887 pSharedData->GetDetectiveObjContainer()->Sort();
1889 mpCellsItr->Clear();
1890 mpCellsItr->SetShapes( pSharedData->GetShapesContainer() );
1891 mpCellsItr->SetNoteShapes( pSharedData->GetNoteShapes() );
1892 mpCellsItr->SetMergedRanges( pMergedRangesContainer.get() );
1893 mpCellsItr->SetAreaLinks( &aAreaLinks );
1894 mpCellsItr->SetEmptyDatabaseRanges( &aEmptyRanges );
1895 mpCellsItr->SetDetectiveObj( pSharedData->GetDetectiveObjContainer() );
1896 mpCellsItr->SetDetectiveOp( &aDetectiveOpContainer );
1898 if (nTableCount > 0)
1899 pValidationsContainer->WriteValidations(*this);
1900 WriteTheLabelRanges( xSpreadDoc );
1901 for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable)
1903 sal_Int32 nStartOffset = -1;
1904 sal_Int32 nEndOffset = -1;
1905 if (pSheetData && pDoc && pDoc->IsStreamValid(static_cast<SCTAB>(nTable)) && !pDoc->GetChangeTrack())
1906 pSheetData->GetStreamPos( nTable, nStartOffset, nEndOffset );
1908 if ( nStartOffset >= 0 && nEndOffset >= 0 && xSourceStream.is() )
1910 sal_Int32 nNewStart = -1;
1911 sal_Int32 nNewEnd = -1;
1912 CopySourceStream( nStartOffset, nEndOffset, nNewStart, nNewEnd );
1914 // store position of copied sheet in output
1915 pSheetData->AddSavePos( nTable, nNewStart, nNewEnd );
1917 // skip iterator entries for this sheet
1918 mpCellsItr->SkipTable(static_cast<SCTAB>(nTable));
1920 else
1922 uno::Reference<sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
1923 WriteTable(nTable, xTable);
1925 IncrementProgressBar(false);
1928 WriteExternalRefCaches();
1929 WriteNamedExpressions();
1930 WriteDataStream();
1931 aExportDatabaseRanges.WriteDatabaseRanges();
1932 WriteExternalDataMapping();
1933 ScXMLExportDataPilot aExportDataPilot(*this);
1934 aExportDataPilot.WriteDataPilots();
1935 WriteConsolidation();
1936 ScXMLExportDDELinks aExportDDELinks(*this);
1937 aExportDDELinks.WriteDDELinks(xSpreadDoc);
1938 IncrementProgressBar(true, 0);
1939 GetProgressBarHelper()->SetValue(GetProgressBarHelper()->GetReference());
1942 void ScXMLExport::ExportStyles_( bool bUsed )
1944 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
1945 if (xSpreadDoc.is())
1946 RegisterDefinedStyleNames( xSpreadDoc);
1948 if (!pSharedData)
1950 SCTAB nTableCount(0);
1951 sal_Int32 nShapesCount(0);
1952 CollectSharedData(nTableCount, nShapesCount);
1954 rtl::Reference<ScXMLStyleExport> aStylesExp(new ScXMLStyleExport(*this, GetAutoStylePool().get()));
1955 if (GetModel().is())
1957 uno::Reference <lang::XMultiServiceFactory> xMultiServiceFactory(GetModel(), uno::UNO_QUERY);
1958 if (xMultiServiceFactory.is())
1960 uno::Reference <beans::XPropertySet> xProperties(xMultiServiceFactory->createInstance("com.sun.star.sheet.Defaults"), uno::UNO_QUERY);
1961 if (xProperties.is())
1962 aStylesExp->exportDefaultStyle(xProperties, XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME, xCellStylesExportPropertySetMapper);
1963 if (pSharedData->HasShapes())
1965 GetShapeExport()->ExportGraphicDefaults();
1968 uno::Reference <style::XStyleFamiliesSupplier> xStyleFamiliesSupplier (GetModel(), uno::UNO_QUERY);
1969 if (xStyleFamiliesSupplier.is())
1971 uno::Reference <container::XNameAccess> xStylesFamilies(xStyleFamiliesSupplier->getStyleFamilies());
1972 if (xStylesFamilies.is())
1974 uno::Reference <container::XIndexAccess> xCellStyles(xStylesFamilies->getByName("CellStyles"), uno::UNO_QUERY);
1975 if (xCellStyles.is())
1977 sal_Int32 nCount(xCellStyles->getCount());
1978 for (sal_Int32 i = 0; i < nCount; ++i)
1980 uno::Reference <beans::XPropertySet> xCellProperties(xCellStyles->getByIndex(i), uno::UNO_QUERY);
1981 if (xCellProperties.is())
1983 sal_Int32 nNumberFormat = 0;
1984 if (xCellProperties->getPropertyValue(SC_UNONAME_NUMFMT) >>= nNumberFormat)
1985 addDataStyle(nNumberFormat);
1992 exportDataStyles();
1994 aStylesExp->exportStyleFamily(OUString("CellStyles"),
1995 OUString(XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME), xCellStylesExportPropertySetMapper, false, XML_STYLE_FAMILY_TABLE_CELL);
1997 SvXMLExport::ExportStyles_(bUsed);
2000 void ScXMLExport::AddStyleFromCells(const uno::Reference<beans::XPropertySet>& xProperties,
2001 const uno::Reference<sheet::XSpreadsheet>& xTable,
2002 sal_Int32 nTable, const OUString* pOldName)
2004 css::uno::Any aAny = xProperties->getPropertyValue("FormatID");
2005 sal_uInt64 nKey = 0;
2006 aAny >>= nKey;
2008 //! pass xCellRanges instead
2009 uno::Reference<sheet::XSheetCellRanges> xCellRanges( xProperties, uno::UNO_QUERY );
2011 OUString sStyleName;
2012 sal_Int32 nNumberFormat(-1);
2013 sal_Int32 nValidationIndex(-1);
2014 std::vector< XMLPropertyState > aPropStates(xCellStylesExportPropertySetMapper->Filter( xProperties ));
2015 std::vector< XMLPropertyState >::iterator aItr(aPropStates.begin());
2016 std::vector< XMLPropertyState >::iterator aEndItr(aPropStates.end());
2017 sal_Int32 nCount(0);
2018 while (aItr != aEndItr)
2020 if (aItr->mnIndex != -1)
2022 switch (xCellStylesPropertySetMapper->GetEntryContextId(aItr->mnIndex))
2024 case CTF_SC_VALIDATION :
2026 pValidationsContainer->AddValidation(aItr->maValue, nValidationIndex);
2027 // this is not very slow, because it is most the last property or
2028 // if it is not the last property it is the property before the last property,
2029 // so in the worst case only one property has to be copied, but in the best case no
2030 // property has to be copied
2031 aItr = aPropStates.erase(aItr);
2032 aEndItr = aPropStates.end(); // old aEndItr is invalidated!
2034 break;
2035 case CTF_SC_CELLSTYLE :
2037 aItr->maValue >>= sStyleName;
2038 aItr->mnIndex = -1;
2039 ++aItr;
2040 ++nCount;
2042 break;
2043 case CTF_SC_NUMBERFORMAT :
2045 if (aItr->maValue >>= nNumberFormat)
2046 addDataStyle(nNumberFormat);
2047 ++aItr;
2048 ++nCount;
2050 break;
2051 default:
2053 ++aItr;
2054 ++nCount;
2056 break;
2059 else
2061 ++aItr;
2062 ++nCount;
2065 if (nCount == 1) // this is the CellStyle and should be removed if alone
2066 aPropStates.clear();
2067 if (nNumberFormat == -1)
2068 xProperties->getPropertyValue(SC_UNONAME_NUMFMT) >>= nNumberFormat;
2069 if (!sStyleName.isEmpty())
2071 if (!aPropStates.empty())
2073 sal_Int32 nIndex;
2074 if (pOldName)
2076 if (GetAutoStylePool()->AddNamed(*pOldName, XML_STYLE_FAMILY_TABLE_CELL, sStyleName, aPropStates))
2078 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_CELL, *pOldName);
2079 // add to pCellStyles, so the name is found for normal sheets
2080 pCellStyles->AddStyleName(*pOldName, nIndex);
2083 else
2085 OUString sName;
2086 bool bAdded = false;
2087 if (nKey)
2089 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
2090 ScFormatSaveData* pFormatData = ScModelObj::getImplementation(xSpreadDoc)->GetFormatSaveData();
2091 auto itr = pFormatData->maIDToName.find(nKey);
2092 if (itr != pFormatData->maIDToName.end())
2094 sName = itr->second;
2095 bAdded = GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TABLE_CELL, sStyleName, aPropStates);
2096 if (bAdded)
2097 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_CELL, sName);
2100 bool bIsAutoStyle(true);
2101 if (bAdded || GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_CELL, sStyleName, aPropStates))
2103 pCellStyles->AddStyleName(sName, nIndex);
2105 else
2106 nIndex = pCellStyles->GetIndexOfStyleName(sName, XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX, bIsAutoStyle);
2108 uno::Sequence<table::CellRangeAddress> aAddresses(xCellRanges->getRangeAddresses());
2109 bool bGetMerge(true);
2110 for (table::CellRangeAddress const & address : aAddresses)
2112 pSharedData->SetLastColumn(nTable, address.EndColumn);
2113 pSharedData->SetLastRow(nTable, address.EndRow);
2114 pCellStyles->AddRangeStyleName(address, nIndex, bIsAutoStyle, nValidationIndex, nNumberFormat);
2115 if (bGetMerge)
2116 bGetMerge = GetMerged(&address, xTable);
2120 else
2122 OUString sEncodedStyleName(EncodeStyleName(sStyleName));
2123 sal_Int32 nIndex(0);
2124 pCellStyles->AddStyleName(sEncodedStyleName, nIndex, false);
2125 if ( !pOldName )
2127 uno::Sequence<table::CellRangeAddress> aAddresses(xCellRanges->getRangeAddresses());
2128 bool bGetMerge(true);
2129 for (table::CellRangeAddress const & address : aAddresses)
2131 if (bGetMerge)
2132 bGetMerge = GetMerged(&address, xTable);
2133 pCellStyles->AddRangeStyleName(address, nIndex, false, nValidationIndex, nNumberFormat);
2134 if( sStyleName != "Default" || nValidationIndex != -1 )
2136 pSharedData->SetLastColumn(nTable, address.EndColumn);
2137 pSharedData->SetLastRow(nTable, address.EndRow);
2145 void ScXMLExport::AddStyleFromColumn(const uno::Reference<beans::XPropertySet>& xColumnProperties,
2146 const OUString* pOldName, sal_Int32& rIndex, bool& rIsVisible)
2148 std::vector<XMLPropertyState> aPropStates(xColumnStylesExportPropertySetMapper->Filter(xColumnProperties));
2149 if(!aPropStates.empty())
2151 auto aItr = std::find_if(aPropStates.begin(), aPropStates.end(),
2152 [this](const XMLPropertyState& rPropState) {
2153 return xColumnStylesPropertySetMapper->GetEntryContextId(rPropState.mnIndex) == CTF_SC_ISVISIBLE; });
2154 if (aItr != aPropStates.end())
2156 aItr->maValue >>= rIsVisible;
2159 OUString sParent;
2160 if (pOldName)
2162 if (GetAutoStylePool()->AddNamed(*pOldName, XML_STYLE_FAMILY_TABLE_COLUMN, sParent, aPropStates))
2164 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_COLUMN, *pOldName);
2165 // add to pColumnStyles, so the name is found for normal sheets
2166 rIndex = pColumnStyles->AddStyleName(*pOldName);
2169 else
2171 OUString sName;
2172 if (GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_COLUMN, sParent, aPropStates))
2174 rIndex = pColumnStyles->AddStyleName(sName);
2176 else
2177 rIndex = pColumnStyles->GetIndexOfStyleName(sName, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_PREFIX);
2182 void ScXMLExport::AddStyleFromRow(const uno::Reference<beans::XPropertySet>& xRowProperties,
2183 const OUString* pOldName, sal_Int32& rIndex)
2185 std::vector<XMLPropertyState> aPropStates(xRowStylesExportPropertySetMapper->Filter(xRowProperties));
2186 if(!aPropStates.empty())
2188 OUString sParent;
2189 if (pOldName)
2191 if (GetAutoStylePool()->AddNamed(*pOldName, XML_STYLE_FAMILY_TABLE_ROW, sParent, aPropStates))
2193 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_ROW, *pOldName);
2194 // add to pRowStyles, so the name is found for normal sheets
2195 rIndex = pRowStyles->AddStyleName(*pOldName);
2198 else
2200 OUString sName;
2201 if (GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_ROW, sParent, aPropStates))
2203 rIndex = pRowStyles->AddStyleName(sName);
2205 else
2206 rIndex = pRowStyles->GetIndexOfStyleName(sName, XML_STYLE_FAMILY_TABLE_ROW_STYLES_PREFIX);
2211 static uno::Any lcl_GetEnumerated( uno::Reference<container::XEnumerationAccess> const & xEnumAccess, sal_Int32 nIndex )
2213 uno::Any aRet;
2214 uno::Reference<container::XEnumeration> xEnum( xEnumAccess->createEnumeration() );
2217 sal_Int32 nSkip = nIndex;
2218 while ( nSkip > 0 )
2220 (void) xEnum->nextElement();
2221 --nSkip;
2223 aRet = xEnum->nextElement();
2225 catch (container::NoSuchElementException&)
2227 // leave aRet empty
2229 return aRet;
2232 void ScXMLExport::collectAutoStyles()
2234 SvXMLExport::collectAutoStyles();
2236 if (mbAutoStylesCollected)
2237 return;
2239 if (!GetModel().is())
2240 return;
2242 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
2243 if (!xSpreadDoc.is())
2244 return;
2246 uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
2247 if (!xIndex.is())
2248 return;
2250 if (getExportFlags() & SvXMLExportFlags::CONTENT)
2252 // Reserve the loaded cell style names.
2253 RegisterDefinedStyleNames( xSpreadDoc);
2255 // re-create automatic styles with old names from stored data
2256 ScSheetSaveData* pSheetData = ScModelObj::getImplementation(xSpreadDoc)->GetSheetSaveData();
2257 if (pSheetData && pDoc)
2259 // formulas have to be calculated now, to detect changed results
2260 // (during normal save, they will be calculated anyway)
2261 SCTAB nTabCount = pDoc->GetTableCount();
2262 for (SCTAB nTab=0; nTab<nTabCount; ++nTab)
2263 if (pDoc->IsStreamValid(nTab))
2264 pDoc->InterpretDirtyCells(ScRange(0, 0, nTab, MAXCOL, MAXROW, nTab));
2266 // stored cell styles
2267 const std::vector<ScCellStyleEntry>& rCellEntries = pSheetData->GetCellStyles();
2268 for (const auto& rCellEntry : rCellEntries)
2270 ScAddress aPos = rCellEntry.maCellPos;
2271 sal_Int32 nTable = aPos.Tab();
2272 bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2273 if (bCopySheet)
2275 uno::Reference <sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2276 uno::Reference <beans::XPropertySet> xProperties(
2277 xTable->getCellByPosition( aPos.Col(), aPos.Row() ), uno::UNO_QUERY );
2279 AddStyleFromCells(xProperties, xTable, nTable, &rCellEntry.maName);
2283 // stored column styles
2284 const std::vector<ScCellStyleEntry>& rColumnEntries = pSheetData->GetColumnStyles();
2285 for (const auto& rColumnEntry : rColumnEntries)
2287 ScAddress aPos = rColumnEntry.maCellPos;
2288 sal_Int32 nTable = aPos.Tab();
2289 bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2290 if (bCopySheet)
2292 uno::Reference<table::XColumnRowRange> xColumnRowRange(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2293 uno::Reference<table::XTableColumns> xTableColumns(xColumnRowRange->getColumns());
2294 uno::Reference<beans::XPropertySet> xColumnProperties(xTableColumns->getByIndex( aPos.Col() ), uno::UNO_QUERY);
2296 sal_Int32 nIndex(-1);
2297 bool bIsVisible(true);
2298 AddStyleFromColumn( xColumnProperties, &rColumnEntry.maName, nIndex, bIsVisible );
2302 // stored row styles
2303 const std::vector<ScCellStyleEntry>& rRowEntries = pSheetData->GetRowStyles();
2304 for (const auto& rRowEntry : rRowEntries)
2306 ScAddress aPos = rRowEntry.maCellPos;
2307 sal_Int32 nTable = aPos.Tab();
2308 bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2309 if (bCopySheet)
2311 uno::Reference<table::XColumnRowRange> xColumnRowRange(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2312 uno::Reference<table::XTableRows> xTableRows(xColumnRowRange->getRows());
2313 uno::Reference<beans::XPropertySet> xRowProperties(xTableRows->getByIndex( aPos.Row() ), uno::UNO_QUERY);
2315 sal_Int32 nIndex(-1);
2316 AddStyleFromRow( xRowProperties, &rRowEntry.maName, nIndex );
2320 // stored table styles
2321 const std::vector<ScCellStyleEntry>& rTableEntries = pSheetData->GetTableStyles();
2322 for (const auto& rTableEntry : rTableEntries)
2324 ScAddress aPos = rTableEntry.maCellPos;
2325 sal_Int32 nTable = aPos.Tab();
2326 bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2327 if (bCopySheet)
2329 //! separate method AddStyleFromTable needed?
2330 uno::Reference<beans::XPropertySet> xTableProperties(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2331 if (xTableProperties.is())
2333 std::vector<XMLPropertyState> aPropStates(xTableStylesExportPropertySetMapper->Filter(xTableProperties));
2334 OUString sName( rTableEntry.maName );
2335 GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TABLE_TABLE, OUString(), aPropStates);
2336 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_TABLE, sName);
2341 // stored styles for notes
2343 rtl::Reference<SvXMLExportPropertyMapper> xShapeMapper = XMLShapeExport::CreateShapePropMapper( *this );
2344 GetShapeExport(); // make sure the graphics styles family is added
2346 const std::vector<ScNoteStyleEntry>& rNoteEntries = pSheetData->GetNoteStyles();
2347 for (const auto& rNoteEntry : rNoteEntries)
2349 ScAddress aPos = rNoteEntry.maCellPos;
2350 SCTAB nTable = aPos.Tab();
2351 bool bCopySheet = pDoc->IsStreamValid( nTable );
2352 if (bCopySheet)
2354 //! separate method AddStyleFromNote needed?
2356 ScPostIt* pNote = pDoc->GetNote(aPos);
2357 OSL_ENSURE( pNote, "note not found" );
2358 if (pNote)
2360 SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
2361 // all uno shapes are created anyway in CollectSharedData
2362 uno::Reference<beans::XPropertySet> xShapeProperties( pDrawObj->getUnoShape(), uno::UNO_QUERY );
2363 if (xShapeProperties.is())
2365 if ( !rNoteEntry.maStyleName.isEmpty() )
2367 std::vector<XMLPropertyState> aPropStates(xShapeMapper->Filter(xShapeProperties));
2368 OUString sName( rNoteEntry.maStyleName );
2369 GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_SD_GRAPHICS_ID, OUString(), aPropStates);
2370 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_SD_GRAPHICS_ID, sName);
2372 if ( !rNoteEntry.maTextStyle.isEmpty() )
2374 std::vector<XMLPropertyState> aPropStates(
2375 GetTextParagraphExport()->GetParagraphPropertyMapper()->Filter(xShapeProperties));
2376 OUString sName( rNoteEntry.maTextStyle );
2377 GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_PARAGRAPH, OUString(), aPropStates);
2378 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_PARAGRAPH, sName);
2385 // note paragraph styles
2387 rtl::Reference<SvXMLExportPropertyMapper> xParaPropMapper = GetTextParagraphExport()->GetParagraphPropertyMapper();
2389 const std::vector<ScTextStyleEntry>& rNoteParaEntries = pSheetData->GetNoteParaStyles();
2390 for (const auto& rNoteParaEntry : rNoteParaEntries)
2392 ScAddress aPos = rNoteParaEntry.maCellPos;
2393 SCTAB nTable = aPos.Tab();
2394 bool bCopySheet = pDoc->IsStreamValid( nTable );
2395 if (bCopySheet)
2397 ScPostIt* pNote = pDoc->GetNote( aPos );
2398 OSL_ENSURE( pNote, "note not found" );
2399 if (pNote)
2401 SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
2402 uno::Reference<container::XEnumerationAccess> xCellText(pDrawObj->getUnoShape(), uno::UNO_QUERY);
2403 uno::Reference<beans::XPropertySet> xParaProp(
2404 lcl_GetEnumerated( xCellText, rNoteParaEntry.maSelection.nStartPara ), uno::UNO_QUERY );
2405 if ( xParaProp.is() )
2407 std::vector<XMLPropertyState> aPropStates(xParaPropMapper->Filter(xParaProp));
2408 OUString sName( rNoteParaEntry.maName );
2409 GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_PARAGRAPH, OUString(), aPropStates);
2410 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_PARAGRAPH, sName);
2416 // note text styles
2418 rtl::Reference<SvXMLExportPropertyMapper> xTextPropMapper = XMLTextParagraphExport::CreateCharExtPropMapper( *this );
2420 const std::vector<ScTextStyleEntry>& rNoteTextEntries = pSheetData->GetNoteTextStyles();
2421 for (const auto& rNoteTextEntry : rNoteTextEntries)
2423 ScAddress aPos = rNoteTextEntry.maCellPos;
2424 SCTAB nTable = aPos.Tab();
2425 bool bCopySheet = pDoc->IsStreamValid( nTable );
2426 if (bCopySheet)
2428 ScPostIt* pNote = pDoc->GetNote( aPos );
2429 OSL_ENSURE( pNote, "note not found" );
2430 if (pNote)
2432 SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
2433 uno::Reference<text::XSimpleText> xCellText(pDrawObj->getUnoShape(), uno::UNO_QUERY);
2434 uno::Reference<beans::XPropertySet> xCursorProp(xCellText->createTextCursor(), uno::UNO_QUERY);
2435 ScDrawTextCursor* pCursor = ScDrawTextCursor::getImplementation( xCursorProp );
2436 if (pCursor)
2438 pCursor->SetSelection( rNoteTextEntry.maSelection );
2440 std::vector<XMLPropertyState> aPropStates(xTextPropMapper->Filter(xCursorProp));
2441 OUString sName( rNoteTextEntry.maName );
2442 GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_TEXT, OUString(), aPropStates);
2443 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_TEXT, sName);
2449 // stored text styles
2451 const std::vector<ScTextStyleEntry>& rTextEntries = pSheetData->GetTextStyles();
2452 for (const auto& rTextEntry : rTextEntries)
2454 ScAddress aPos = rTextEntry.maCellPos;
2455 sal_Int32 nTable = aPos.Tab();
2456 bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2457 if (bCopySheet)
2459 //! separate method AddStyleFromText needed?
2460 //! cache sheet object
2462 uno::Reference<table::XCellRange> xCellRange(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2463 uno::Reference<text::XSimpleText> xCellText(xCellRange->getCellByPosition(aPos.Col(), aPos.Row()), uno::UNO_QUERY);
2464 uno::Reference<beans::XPropertySet> xCursorProp(xCellText->createTextCursor(), uno::UNO_QUERY);
2465 ScCellTextCursor* pCursor = ScCellTextCursor::getImplementation( xCursorProp );
2466 if (pCursor)
2468 pCursor->SetSelection( rTextEntry.maSelection );
2470 std::vector<XMLPropertyState> aPropStates(xTextPropMapper->Filter(xCursorProp));
2471 OUString sName( rTextEntry.maName );
2472 GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_TEXT, OUString(), aPropStates);
2473 GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_TEXT, sName);
2479 ExportExternalRefCacheStyles();
2481 if (!pSharedData)
2483 SCTAB nTableCount(0);
2484 sal_Int32 nShapesCount(0);
2485 CollectSharedData(nTableCount, nShapesCount);
2487 sal_Int32 nTableCount(xIndex->getCount());
2488 pCellStyles->AddNewTable(nTableCount - 1);
2489 CollectShapesAutoStyles(nTableCount);
2490 for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable, IncrementProgressBar(false))
2492 uno::Reference <sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2493 if (!xTable.is())
2494 continue;
2496 // table styles array must be complete, including copied tables - Add should find the stored style
2497 uno::Reference<beans::XPropertySet> xTableProperties(xTable, uno::UNO_QUERY);
2498 if (xTableProperties.is())
2500 std::vector<XMLPropertyState> aPropStates(xTableStylesExportPropertySetMapper->Filter(xTableProperties));
2501 if(!aPropStates.empty())
2503 OUString sName;
2504 GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_TABLE, OUString(), aPropStates);
2505 aTableStyles.push_back(sName);
2509 // collect other auto-styles only for non-copied sheets
2510 uno::Reference<sheet::XUniqueCellFormatRangesSupplier> xCellFormatRanges ( xTable, uno::UNO_QUERY );
2511 if ( xCellFormatRanges.is() )
2513 uno::Reference<container::XIndexAccess> xFormatRangesIndex(xCellFormatRanges->getUniqueCellFormatRanges());
2514 if (xFormatRangesIndex.is())
2516 sal_Int32 nFormatRangesCount(xFormatRangesIndex->getCount());
2517 GetProgressBarHelper()->ChangeReference(GetProgressBarHelper()->GetReference() + nFormatRangesCount);
2518 for (sal_Int32 nFormatRange = 0; nFormatRange < nFormatRangesCount; ++nFormatRange)
2520 uno::Reference< sheet::XSheetCellRanges> xCellRanges(xFormatRangesIndex->getByIndex(nFormatRange), uno::UNO_QUERY);
2521 if (xCellRanges.is())
2523 uno::Reference <beans::XPropertySet> xProperties (xCellRanges, uno::UNO_QUERY);
2524 if (xProperties.is())
2526 AddStyleFromCells(xProperties, xTable, nTable, nullptr);
2527 IncrementProgressBar(false);
2533 uno::Reference<table::XColumnRowRange> xColumnRowRange (xTable, uno::UNO_QUERY);
2534 if (xColumnRowRange.is() && pDoc)
2536 pDoc->SyncColRowFlags();
2537 uno::Reference<table::XTableColumns> xTableColumns(xColumnRowRange->getColumns());
2538 if (xTableColumns.is())
2540 sal_Int32 nColumns(pDoc->GetLastChangedCol(sal::static_int_cast<SCTAB>(nTable)));
2541 pSharedData->SetLastColumn(nTable, nColumns);
2542 table::CellRangeAddress aCellAddress(GetEndAddress(xTable));
2543 if (aCellAddress.EndColumn > nColumns)
2545 ++nColumns;
2546 pColumnStyles->AddNewTable(nTable, aCellAddress.EndColumn);
2548 else
2549 pColumnStyles->AddNewTable(nTable, nColumns);
2550 sal_Int32 nColumn = 0;
2551 while (nColumn <= MAXCOL)
2553 sal_Int32 nIndex(-1);
2554 bool bIsVisible(true);
2555 uno::Reference <beans::XPropertySet> xColumnProperties(xTableColumns->getByIndex(nColumn), uno::UNO_QUERY);
2556 if (xColumnProperties.is())
2558 AddStyleFromColumn( xColumnProperties, nullptr, nIndex, bIsVisible );
2559 pColumnStyles->AddFieldStyleName(nTable, nColumn, nIndex, bIsVisible);
2561 sal_Int32 nOld(nColumn);
2562 nColumn = pDoc->GetNextDifferentChangedCol(sal::static_int_cast<SCTAB>(nTable), static_cast<SCCOL>(nColumn));
2563 for (sal_Int32 i = nOld + 1; i < nColumn; ++i)
2564 pColumnStyles->AddFieldStyleName(nTable, i, nIndex, bIsVisible);
2566 if (aCellAddress.EndColumn > nColumns)
2568 bool bIsVisible(true);
2569 sal_Int32 nIndex(pColumnStyles->GetStyleNameIndex(nTable, nColumns, bIsVisible));
2570 for (sal_Int32 i = nColumns + 1; i <= aCellAddress.EndColumn; ++i)
2571 pColumnStyles->AddFieldStyleName(nTable, i, nIndex, bIsVisible);
2574 uno::Reference<table::XTableRows> xTableRows(xColumnRowRange->getRows());
2575 if (xTableRows.is())
2577 sal_Int32 nRows(pDoc->GetLastChangedRow(sal::static_int_cast<SCTAB>(nTable)));
2578 pSharedData->SetLastRow(nTable, nRows);
2580 pRowStyles->AddNewTable(nTable, MAXROW);
2581 sal_Int32 nRow = 0;
2582 while (nRow <= MAXROW)
2584 sal_Int32 nIndex = 0;
2585 uno::Reference <beans::XPropertySet> xRowProperties(xTableRows->getByIndex(nRow), uno::UNO_QUERY);
2586 if(xRowProperties.is())
2588 AddStyleFromRow( xRowProperties, nullptr, nIndex );
2589 pRowStyles->AddFieldStyleName(nTable, nRow, nIndex);
2591 sal_Int32 nOld(nRow);
2592 nRow = pDoc->GetNextDifferentChangedRow(sal::static_int_cast<SCTAB>(nTable), static_cast<SCROW>(nRow));
2593 if (nRow > nOld + 1)
2594 pRowStyles->AddFieldStyleName(nTable, nOld + 1, nIndex, nRow - 1);
2598 ExportCellTextAutoStyles(nTable);
2601 pChangeTrackingExportHelper->CollectAutoStyles();
2604 if (getExportFlags() & SvXMLExportFlags::MASTERSTYLES)
2605 GetPageExport()->collectAutoStyles(true);
2607 mbAutoStylesCollected = true;
2610 void ScXMLExport::ExportAutoStyles_()
2612 if (!GetModel().is())
2613 return;
2615 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
2616 if (!xSpreadDoc.is())
2617 return;
2619 uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
2620 if (!xIndex.is())
2621 return;
2623 collectAutoStyles();
2625 if (getExportFlags() & SvXMLExportFlags::CONTENT)
2627 GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_COLUMN);
2628 GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_ROW);
2629 GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_TABLE);
2630 exportAutoDataStyles();
2631 GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_CELL);
2633 GetShapeExport()->exportAutoStyles();
2634 GetFormExport()->exportAutoStyles( );
2636 if (pDoc)
2638 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
2639 // #i100879# write the table style for cached tables only if there are cached tables
2640 // (same logic as in ExportExternalRefCacheStyles)
2641 if (pRefMgr->hasExternalData())
2643 // Special table style for the external ref cache tables.
2644 AddAttribute(XML_NAMESPACE_STYLE, XML_NAME, sExternalRefTabStyleName);
2645 AddAttribute(XML_NAMESPACE_STYLE, XML_FAMILY, XML_TABLE);
2646 SvXMLElementExport aElemStyle(*this, XML_NAMESPACE_STYLE, XML_STYLE, true, true);
2647 AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY, XML_FALSE);
2648 SvXMLElementExport aElemStyleTabProps(*this, XML_NAMESPACE_STYLE, XML_TABLE_PROPERTIES, true, true);
2653 if (getExportFlags() & SvXMLExportFlags::MASTERSTYLES)
2655 GetPageExport()->exportAutoStyles();
2658 // #i30251#; only write Text Styles once
2660 if ((getExportFlags() & SvXMLExportFlags::CONTENT) || (getExportFlags() & SvXMLExportFlags::MASTERSTYLES))
2661 GetTextParagraphExport()->exportTextAutoStyles();
2664 void ScXMLExport::ExportMasterStyles_()
2666 GetPageExport()->exportMasterStyles( true );
2669 void ScXMLExport::CollectInternalShape( uno::Reference< drawing::XShape > const & xShape )
2671 // detective objects and notes
2672 if( SvxShape* pShapeImp = SvxShape::getImplementation( xShape ) )
2674 if( SdrObject* pObject = pShapeImp->GetSdrObject() )
2676 // collect note caption objects from all layers (internal or hidden)
2677 if( ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( pObject, static_cast< SCTAB >( nCurrentTable ) ) )
2679 if(pDoc->GetNote(pCaptData->maStart))
2681 pSharedData->AddNoteObj( xShape, pCaptData->maStart );
2683 // #i60851# When the file is saved while editing a new note,
2684 // the cell is still empty -> last column/row must be updated
2685 OSL_ENSURE( pCaptData->maStart.Tab() == nCurrentTable, "invalid table in object data" );
2686 pSharedData->SetLastColumn( nCurrentTable, pCaptData->maStart.Col() );
2687 pSharedData->SetLastRow( nCurrentTable, pCaptData->maStart.Row() );
2690 // other objects from internal layer only (detective)
2691 else if( pObject->GetLayer() == SC_LAYER_INTERN )
2693 ScDetectiveFunc aDetFunc( pDoc, static_cast<SCTAB>(nCurrentTable) );
2694 ScAddress aPosition;
2695 ScRange aSourceRange;
2696 bool bRedLine;
2697 ScDetectiveObjType eObjType = aDetFunc.GetDetectiveObjectType(
2698 pObject, nCurrentTable, aPosition, aSourceRange, bRedLine );
2699 pSharedData->GetDetectiveObjContainer()->AddObject( eObjType, static_cast<SCTAB>(nCurrentTable), aPosition, aSourceRange, bRedLine );
2705 bool ScXMLExport::GetMerged (const table::CellRangeAddress* pCellAddress,
2706 const uno::Reference <sheet::XSpreadsheet>& xTable)
2708 bool bReady(false);
2709 sal_Int32 nRow(pCellAddress->StartRow);
2710 sal_Int32 nCol(pCellAddress->StartColumn);
2711 sal_Int32 nEndRow(pCellAddress->EndRow);
2712 sal_Int32 nEndCol(pCellAddress->EndColumn);
2713 bool bRowInc(nEndRow > nRow);
2714 while(!bReady && nRow <= nEndRow && nCol <= nEndCol)
2716 uno::Reference<sheet::XSheetCellRange> xSheetCellRange(xTable->getCellRangeByPosition(nCol, nRow, nCol, nRow), uno::UNO_QUERY);
2717 if (xSheetCellRange.is())
2719 uno::Reference<sheet::XSheetCellCursor> xCursor(xTable->createCursorByRange(xSheetCellRange));
2720 if(xCursor.is())
2722 uno::Reference<sheet::XCellRangeAddressable> xCellAddress (xCursor, uno::UNO_QUERY);
2723 xCursor->collapseToMergedArea();
2724 table::CellRangeAddress aCellAddress2(xCellAddress->getRangeAddress());
2725 ScRange aScRange = ScRange( aCellAddress2.StartColumn, aCellAddress2.StartRow, aCellAddress2.Sheet,
2726 aCellAddress2.EndColumn, aCellAddress2.EndRow, aCellAddress2.Sheet );
2728 if ((aScRange.aEnd.Row() > nRow ||
2729 aScRange.aEnd.Col() > nCol) &&
2730 aScRange.aStart.Row() == nRow &&
2731 aScRange.aStart.Col() == nCol)
2733 pMergedRangesContainer->AddRange(aScRange);
2734 pSharedData->SetLastColumn(aScRange.aEnd.Tab(), aScRange.aEnd.Col());
2735 pSharedData->SetLastRow(aScRange.aEnd.Tab(), aScRange.aEnd.Row());
2737 else
2738 bReady = true;
2741 if (!bReady)
2743 if (bRowInc)
2744 ++nRow;
2745 else
2746 ++nCol;
2749 OSL_ENSURE(!(!bReady && nEndRow > nRow && nEndCol > nCol), "should not be possible");
2750 return !bReady;
2753 bool ScXMLExport::IsMatrix (const ScAddress& aCell,
2754 ScRange& aCellAddress, bool& bIsFirst) const
2756 bIsFirst = false;
2758 ScRange aMatrixRange;
2760 if (pDoc && pDoc->GetMatrixFormulaRange(aCell, aMatrixRange))
2762 aCellAddress = aMatrixRange;
2763 if ((aCellAddress.aStart.Col() == aCell.Col() && aCellAddress.aStart.Row() == aCell.Row()) &&
2764 (aCellAddress.aEnd.Col() > aCell.Col() || aCellAddress.aEnd.Row() > aCell.Row()))
2766 bIsFirst = true;
2767 return true;
2769 else if (aCellAddress.aStart.Col() != aCell.Col() || aCellAddress.aStart.Row() != aCell.Row() ||
2770 aCellAddress.aEnd.Col() != aCell.Col() || aCellAddress.aEnd.Row()!= aCell.Row())
2771 return true;
2772 else
2774 bIsFirst = true;
2775 return true;
2779 return false;
2782 void ScXMLExport::WriteTable(sal_Int32 nTable, const uno::Reference<sheet::XSpreadsheet>& xTable)
2784 if (!xTable.is())
2785 return;
2787 xCurrentTable.set(xTable);
2788 xCurrentTableCellRange.set(xTable, uno::UNO_QUERY);
2789 uno::Reference<container::XNamed> xName (xTable, uno::UNO_QUERY );
2790 if (!xName.is())
2791 return;
2793 nCurrentTable = sal::static_int_cast<sal_uInt16>( nTable );
2794 OUString sOUTableName(xName->getName());
2795 AddAttribute(sAttrName, sOUTableName);
2796 AddAttribute(sAttrStyleName, aTableStyles[nTable]);
2798 uno::Reference<util::XProtectable> xProtectable (xTable, uno::UNO_QUERY);
2799 ScTableProtection* pProtect = nullptr;
2800 if (xProtectable.is() && xProtectable->isProtected())
2802 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE);
2803 if (pDoc)
2805 pProtect = pDoc->GetTabProtection(nTable);
2806 if (pProtect)
2808 OUStringBuffer aBuffer;
2809 ScPasswordHash eHashUsed = PASSHASH_UNSPECIFIED;
2810 if (pProtect->hasPasswordHash(PASSHASH_SHA1))
2812 ::comphelper::Base64::encode(aBuffer,
2813 pProtect->getPasswordHash(PASSHASH_SHA1));
2814 eHashUsed = PASSHASH_SHA1;
2816 else if (pProtect->hasPasswordHash(PASSHASH_SHA256))
2818 ::comphelper::Base64::encode(aBuffer,
2819 pProtect->getPasswordHash(PASSHASH_SHA256));
2820 eHashUsed = PASSHASH_SHA256;
2822 else if (pProtect->hasPasswordHash(PASSHASH_XL, PASSHASH_SHA1))
2824 // Double-hash this by SHA1 on top of the legacy xls hash.
2825 uno::Sequence<sal_Int8> aHash = pProtect->getPasswordHash(PASSHASH_XL, PASSHASH_SHA1);
2826 ::comphelper::Base64::encode(aBuffer, aHash);
2827 eHashUsed = PASSHASH_XL;
2829 if (!aBuffer.isEmpty())
2831 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
2832 if ( getDefaultVersion() >= SvtSaveOptions::ODFVER_012 )
2834 if (eHashUsed == PASSHASH_XL)
2836 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
2837 ScPassHashHelper::getHashURI(PASSHASH_XL));
2838 if (getDefaultVersion() > SvtSaveOptions::ODFVER_012)
2839 AddAttribute(XML_NAMESPACE_LO_EXT, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2,
2840 ScPassHashHelper::getHashURI(PASSHASH_SHA1));
2842 else if (eHashUsed == PASSHASH_SHA1)
2844 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
2845 ScPassHashHelper::getHashURI(PASSHASH_SHA1));
2847 else if (eHashUsed == PASSHASH_SHA256)
2849 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
2850 ScPassHashHelper::getHashURI(PASSHASH_SHA256));
2857 OUString sPrintRanges;
2858 ScRange aColumnHeaderRange;
2859 bool bHasColumnHeader;
2860 GetColumnRowHeader(bHasColumnHeader, aColumnHeaderRange, bHasRowHeader, aRowHeaderRange, sPrintRanges);
2861 if( !sPrintRanges.isEmpty() )
2862 AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT_RANGES, sPrintRanges );
2863 else if (pDoc && !pDoc->IsPrintEntireSheet(static_cast<SCTAB>(nTable)))
2864 AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT, XML_FALSE);
2865 SvXMLElementExport aElemT(*this, sElemTab, true, true);
2867 if (pProtect && pProtect->isProtected() && getDefaultVersion() > SvtSaveOptions::ODFVER_012)
2869 if (pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS))
2870 AddAttribute(XML_NAMESPACE_LO_EXT, XML_SELECT_PROTECTED_CELLS, XML_TRUE);
2871 if (pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS))
2872 AddAttribute(XML_NAMESPACE_LO_EXT, XML_SELECT_UNPROTECTED_CELLS, XML_TRUE);
2874 if (pProtect->isOptionEnabled(ScTableProtection::INSERT_COLUMNS))
2875 AddAttribute(XML_NAMESPACE_LO_EXT, XML_INSERT_COLUMNS, XML_TRUE);
2876 if (pProtect->isOptionEnabled(ScTableProtection::INSERT_ROWS))
2877 AddAttribute(XML_NAMESPACE_LO_EXT, XML_INSERT_ROWS, XML_TRUE);
2879 if (pProtect->isOptionEnabled(ScTableProtection::DELETE_COLUMNS))
2880 AddAttribute(XML_NAMESPACE_LO_EXT, XML_DELETE_COLUMNS, XML_TRUE);
2881 if (pProtect->isOptionEnabled(ScTableProtection::DELETE_ROWS))
2882 AddAttribute(XML_NAMESPACE_LO_EXT, XML_DELETE_ROWS, XML_TRUE);
2884 OUString aElemName = GetNamespaceMap().GetQNameByKey(
2885 XML_NAMESPACE_LO_EXT, GetXMLToken(XML_TABLE_PROTECTION));
2887 SvXMLElementExport aElemProtected(*this, aElemName, true, true);
2890 CheckAttrList();
2892 if ( pDoc && pDoc->GetSheetEvents( static_cast<SCTAB>(nTable) ) &&
2893 getDefaultVersion() >= SvtSaveOptions::ODFVER_012 )
2895 // store sheet events
2896 uno::Reference<document::XEventsSupplier> xSupplier(xTable, uno::UNO_QUERY);
2897 uno::Reference<container::XNameAccess> xEvents(xSupplier->getEvents(), uno::UNO_QUERY);
2898 GetEventExport().ExportExt( xEvents );
2901 WriteTableSource();
2902 WriteScenario();
2903 uno::Reference<drawing::XDrawPage> xDrawPage;
2904 if (pSharedData->HasForm(nTable, xDrawPage) && xDrawPage.is())
2906 ::xmloff::OOfficeFormsExport aForms(*this);
2907 GetFormExport()->exportForms( xDrawPage );
2908 bool bRet(GetFormExport()->seekPage( xDrawPage ));
2909 OSL_ENSURE( bRet, "OFormLayerXMLExport::seekPage failed!" );
2911 if (pSharedData->HasDrawPage())
2913 GetShapeExport()->seekShapes(uno::Reference<drawing::XShapes>(pSharedData->GetDrawPage(nTable), uno::UNO_QUERY));
2914 WriteTableShapes();
2916 table::CellRangeAddress aRange(GetEndAddress(xTable));
2917 pSharedData->SetLastColumn(nTable, aRange.EndColumn);
2918 pSharedData->SetLastRow(nTable, aRange.EndRow);
2919 mpCellsItr->SetCurrentTable(static_cast<SCTAB>(nTable), xCurrentTable);
2920 pGroupColumns->NewTable();
2921 pGroupRows->NewTable();
2922 FillColumnRowGroups();
2923 if (bHasColumnHeader)
2924 pSharedData->SetLastColumn(nTable, aColumnHeaderRange.aEnd.Col());
2925 bRowHeaderOpen = false;
2926 if (bHasRowHeader)
2927 pSharedData->SetLastRow(nTable, aRowHeaderRange.aEnd.Row());
2928 pDefaults->FillDefaultStyles(nTable, pSharedData->GetLastRow(nTable),
2929 pSharedData->GetLastColumn(nTable), pCellStyles.get(), pDoc);
2930 pRowFormatRanges->SetColDefaults(&pDefaults->GetColDefaults());
2931 pCellStyles->SetColDefaults(&pDefaults->GetColDefaults());
2932 ExportColumns(nTable, aColumnHeaderRange, bHasColumnHeader);
2933 bool bIsFirst(true);
2934 sal_Int32 nEqualCells(0);
2935 ScMyCell aCell;
2936 ScMyCell aPrevCell;
2937 while (mpCellsItr->GetNext(aCell, pCellStyles.get()))
2939 if (bIsFirst)
2941 ExportFormatRanges(0, 0, aCell.maCellAddress.Col()-1, aCell.maCellAddress.Row(), nTable);
2942 aPrevCell = aCell;
2943 bIsFirst = false;
2945 else
2947 if ((aPrevCell.maCellAddress.Row() == aCell.maCellAddress.Row()) &&
2948 (aPrevCell.maCellAddress.Col() + nEqualCells + 1 == aCell.maCellAddress.Col()))
2950 if(IsCellEqual(aPrevCell, aCell))
2951 ++nEqualCells;
2952 else
2954 WriteCell(aPrevCell, nEqualCells);
2955 nEqualCells = 0;
2956 aPrevCell = aCell;
2959 else
2961 WriteCell(aPrevCell, nEqualCells);
2962 ExportFormatRanges(aPrevCell.maCellAddress.Col() + nEqualCells + 1, aPrevCell.maCellAddress.Row(),
2963 aCell.maCellAddress.Col()-1, aCell.maCellAddress.Row(), nTable);
2964 nEqualCells = 0;
2965 aPrevCell = aCell;
2969 if (!bIsFirst)
2971 WriteCell(aPrevCell, nEqualCells);
2972 ExportFormatRanges(aPrevCell.maCellAddress.Col() + nEqualCells + 1, aPrevCell.maCellAddress.Row(),
2973 pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
2975 else
2976 ExportFormatRanges(0, 0, pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
2978 CloseRow(pSharedData->GetLastRow(nTable));
2980 if (pDoc)
2982 // Export sheet-local named ranges.
2983 ScRangeName* pRangeName = pDoc->GetRangeName(nTable);
2984 if (pRangeName && !pRangeName->empty())
2986 WriteNamedRange(pRangeName);
2989 if(getDefaultVersion() > SvtSaveOptions::ODFVER_012)
2991 //export new conditional format information
2992 ExportConditionalFormat(nTable);
2998 namespace {
3000 void writeContent(
3001 ScXMLExport& rExport, const OUString& rStyleName, const OUString& rContent, const SvxFieldData* pField )
3003 std::unique_ptr<SvXMLElementExport> pElem;
3004 if (!rStyleName.isEmpty())
3006 // Formatted section with automatic style.
3007 rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME, rStyleName);
3008 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3009 XML_NAMESPACE_TEXT, GetXMLToken(XML_SPAN));
3010 pElem.reset(new SvXMLElementExport(rExport, aElemName, false, false));
3013 if (pField)
3015 // Write an field item.
3016 OUString aFieldVal = ScEditUtil::GetCellFieldValue(*pField, rExport.GetDocument(), nullptr);
3017 switch (pField->GetClassId())
3019 case text::textfield::Type::URL:
3021 // <text:a xlink:href="url" xlink:type="simple">value</text:a>
3023 const SvxURLField* pURLField = static_cast<const SvxURLField*>(pField);
3024 const OUString& aURL = pURLField->GetURL();
3025 rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, rExport.GetRelativeReference(aURL));
3026 rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, "simple");
3027 const OUString& aTargetFrame = pURLField->GetTargetFrame();
3028 if (!aTargetFrame.isEmpty())
3029 rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_TARGET_FRAME_NAME, aTargetFrame);
3031 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3032 XML_NAMESPACE_TEXT, GetXMLToken(XML_A));
3033 SvXMLElementExport aElem(rExport, aElemName, false, false);
3034 rExport.Characters(aFieldVal);
3036 break;
3037 case text::textfield::Type::DATE:
3039 // <text:date style:data-style-name="N2" text:date-value="YYYY-MM-DD">value</text:date>
3041 Date aDate(Date::SYSTEM);
3042 OUStringBuffer aBuf;
3043 sal_Int32 nVal = aDate.GetYear();
3044 aBuf.append(nVal);
3045 aBuf.append('-');
3046 nVal = aDate.GetMonth();
3047 if (nVal < 10)
3048 aBuf.append('0');
3049 aBuf.append(nVal);
3050 aBuf.append('-');
3051 nVal = aDate.GetDay();
3052 if (nVal < 10)
3053 aBuf.append('0');
3054 aBuf.append(nVal);
3055 rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_DATA_STYLE_NAME, "N2");
3056 rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_DATE_VALUE, aBuf.makeStringAndClear());
3058 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3059 XML_NAMESPACE_TEXT, GetXMLToken(XML_DATE));
3060 SvXMLElementExport aElem(rExport, aElemName, false, false);
3061 rExport.Characters(aFieldVal);
3063 break;
3064 case text::textfield::Type::DOCINFO_TITLE:
3066 // <text:title>value</text:title>
3068 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3069 XML_NAMESPACE_TEXT, GetXMLToken(XML_TITLE));
3070 SvXMLElementExport aElem(rExport, aElemName, false, false);
3071 rExport.Characters(aFieldVal);
3073 break;
3074 case text::textfield::Type::TABLE:
3076 // <text:sheet-name>value</text:sheet-name>
3078 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3079 XML_NAMESPACE_TEXT, GetXMLToken(XML_SHEET_NAME));
3080 SvXMLElementExport aElem(rExport, aElemName, false, false);
3081 rExport.Characters(aFieldVal);
3083 break;
3084 default:
3085 rExport.Characters(aFieldVal);
3088 else
3089 rExport.Characters(rContent);
3092 void flushParagraph(
3093 ScXMLExport& rExport, const OUString& rParaText,
3094 rtl::Reference<XMLPropertySetMapper> const & xMapper, rtl::Reference<SvXMLAutoStylePoolP> const & xStylePool,
3095 const ScXMLEditAttributeMap& rAttrMap,
3096 std::vector<editeng::Section>::const_iterator it, std::vector<editeng::Section>::const_iterator const & itEnd )
3098 OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3099 XML_NAMESPACE_TEXT, GetXMLToken(XML_P));
3100 SvXMLElementExport aElemP(rExport, aElemName, false, false);
3102 for (; it != itEnd; ++it)
3104 const editeng::Section& rSec = *it;
3106 OUString aContent(rParaText.copy(rSec.mnStart, rSec.mnEnd - rSec.mnStart));
3108 std::vector<XMLPropertyState> aPropStates;
3109 const SvxFieldData* pField = toXMLPropertyStates(aPropStates, rSec.maAttributes, xMapper, rAttrMap);
3110 OUString aStyleName = xStylePool->Find(XML_STYLE_FAMILY_TEXT_TEXT, OUString(), aPropStates);
3111 writeContent(rExport, aStyleName, aContent, pField);
3117 void ScXMLExport::WriteCell(ScMyCell& aCell, sal_Int32 nEqualCellCount)
3119 // nEqualCellCount is the number of additional cells
3120 SetRepeatAttribute(nEqualCellCount, (aCell.nType != table::CellContentType_EMPTY));
3122 if (aCell.nStyleIndex != -1)
3123 AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(aCell.nStyleIndex, aCell.bIsAutoStyle));
3124 if (aCell.nValidationIndex > -1)
3125 AddAttribute(XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, pValidationsContainer->GetValidationName(aCell.nValidationIndex));
3126 const bool bIsFirstMatrixCell(aCell.bIsMatrixBase);
3127 if (bIsFirstMatrixCell)
3129 SCCOL nColumns( aCell.aMatrixRange.aEnd.Col() - aCell.aMatrixRange.aStart.Col() + 1 );
3130 SCROW nRows( aCell.aMatrixRange.aEnd.Row() - aCell.aMatrixRange.aStart.Row() + 1 );
3131 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_COLUMNS_SPANNED, OUString::number(nColumns));
3132 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_ROWS_SPANNED, OUString::number(nRows));
3134 bool bIsEmpty(false);
3135 switch (aCell.nType)
3137 case table::CellContentType_EMPTY :
3139 bIsEmpty = true;
3141 break;
3142 case table::CellContentType_VALUE :
3144 GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3145 aCell.nNumberFormat, aCell.maBaseCell.mfValue);
3146 if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3147 GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3148 aCell.nNumberFormat, aCell.maBaseCell.mfValue, false, XML_NAMESPACE_CALC_EXT, false);
3150 break;
3151 case table::CellContentType_TEXT :
3153 OUString sFormattedString(lcl_GetFormattedString(pDoc, aCell.maBaseCell, aCell.maCellAddress));
3154 OUString sCellString = aCell.maBaseCell.getString(pDoc);
3155 GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3156 sCellString, sFormattedString);
3157 if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3158 GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3159 sCellString, sFormattedString, false, XML_NAMESPACE_CALC_EXT);
3161 break;
3162 case table::CellContentType_FORMULA :
3164 if (aCell.maBaseCell.meType == CELLTYPE_FORMULA)
3166 const bool bIsMatrix(bIsFirstMatrixCell || aCell.bIsMatrixCovered);
3167 ScFormulaCell* pFormulaCell = aCell.maBaseCell.mpFormula;
3168 if (!bIsMatrix || bIsFirstMatrixCell)
3170 if (!mpCompileFormulaCxt)
3172 const formula::FormulaGrammar::Grammar eGrammar = pDoc->GetStorageGrammar();
3173 mpCompileFormulaCxt.reset(new sc::CompileFormulaContext(pDoc, eGrammar));
3176 OUString aFormula = pFormulaCell->GetFormula(*mpCompileFormulaCxt);
3177 sal_uInt16 nNamespacePrefix =
3178 (mpCompileFormulaCxt->getGrammar() == formula::FormulaGrammar::GRAM_ODFF ? XML_NAMESPACE_OF : XML_NAMESPACE_OOOC);
3180 if (!bIsMatrix)
3182 AddAttribute(sAttrFormula, GetNamespaceMap().GetQNameByKey(nNamespacePrefix, aFormula, false));
3184 else
3186 AddAttribute(sAttrFormula, GetNamespaceMap().GetQNameByKey(nNamespacePrefix, aFormula.copy(1, aFormula.getLength()-2), false));
3189 if (pFormulaCell->GetErrCode() != FormulaError::NONE)
3191 AddAttribute(sAttrValueType, XML_STRING);
3192 AddAttribute(sAttrStringValue, aCell.maBaseCell.getString(pDoc));
3193 if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3195 //export calcext:value-type="error"
3196 AddAttribute(XML_NAMESPACE_CALC_EXT,XML_VALUE_TYPE, OUString("error"));
3199 else if (pFormulaCell->IsValue())
3201 bool bIsStandard;
3202 OUString sCurrency;
3203 GetNumberFormatAttributesExportHelper()->GetCellType(aCell.nNumberFormat, sCurrency, bIsStandard);
3204 if (pDoc)
3206 GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3207 aCell.nNumberFormat, pDoc->GetValue(aCell.maCellAddress));
3208 if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3210 GetNumberFormatAttributesExportHelper()->SetNumberFormatAttributes(
3211 aCell.nNumberFormat, pDoc->GetValue(aCell.maCellAddress), false, XML_NAMESPACE_CALC_EXT, false );
3215 else
3217 if (!aCell.maBaseCell.getString(pDoc).isEmpty())
3219 AddAttribute(sAttrValueType, XML_STRING);
3220 AddAttribute(sAttrStringValue, aCell.maBaseCell.getString(pDoc));
3221 if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3223 AddAttribute(XML_NAMESPACE_CALC_EXT,XML_VALUE_TYPE, XML_STRING);
3229 break;
3230 default:
3231 break;
3233 OUString* pCellString(&sElemCell);
3234 if (aCell.bIsCovered)
3236 pCellString = &sElemCoveredCell;
3238 else
3240 if (aCell.bIsMergedBase)
3242 SCCOL nColumns( aCell.aMergeRange.aEnd.Col() - aCell.aMergeRange.aStart.Col() + 1 );
3243 SCROW nRows( aCell.aMergeRange.aEnd.Row() - aCell.aMergeRange.aStart.Row() + 1 );
3244 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED, OUString::number(nColumns));
3245 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED, OUString::number(nRows));
3248 SvXMLElementExport aElemC(*this, *pCellString, true, true);
3249 CheckAttrList();
3250 WriteAreaLink(aCell);
3251 WriteAnnotation(aCell);
3252 WriteDetective(aCell);
3254 if (!bIsEmpty)
3256 if (aCell.maBaseCell.meType == CELLTYPE_EDIT)
3258 WriteEditCell(aCell.maBaseCell.mpEditText);
3260 else if (aCell.maBaseCell.meType == CELLTYPE_FORMULA && aCell.maBaseCell.mpFormula->IsMultilineResult())
3262 WriteMultiLineFormulaResult(aCell.maBaseCell.mpFormula);
3264 else
3266 SvXMLElementExport aElemP(*this, sElemP, true, false);
3268 OUString aParaStr =
3269 ScCellFormat::GetOutputString(*pDoc, aCell.maCellAddress, aCell.maBaseCell);
3271 bool bPrevCharWasSpace = true;
3272 GetTextParagraphExport()->exportCharacterData(aParaStr, bPrevCharWasSpace);
3275 WriteShapes(aCell);
3276 if (!bIsEmpty)
3277 IncrementProgressBar(false);
3280 void ScXMLExport::WriteEditCell(const EditTextObject* pText)
3282 rtl::Reference<XMLPropertySetMapper> xMapper = GetTextParagraphExport()->GetTextPropMapper()->getPropertySetMapper();
3283 rtl::Reference<SvXMLAutoStylePoolP> xStylePool = GetAutoStylePool();
3284 const ScXMLEditAttributeMap& rAttrMap = GetEditAttributeMap();
3286 // Get raw paragraph texts first.
3287 std::vector<OUString> aParaTexts;
3288 sal_Int32 nParaCount = pText->GetParagraphCount();
3289 aParaTexts.reserve(nParaCount);
3290 for (sal_Int32 i = 0; i < nParaCount; ++i)
3291 aParaTexts.push_back(pText->GetText(i));
3293 // Get all section data and iterate through them.
3294 std::vector<editeng::Section> aAttrs;
3295 pText->GetAllSections(aAttrs);
3296 std::vector<editeng::Section>::const_iterator itSec = aAttrs.begin(), itSecEnd = aAttrs.end();
3297 std::vector<editeng::Section>::const_iterator itPara = itSec;
3298 sal_Int32 nCurPara = 0; // current paragraph
3299 for (; itSec != itSecEnd; ++itSec)
3301 const editeng::Section& rSec = *itSec;
3302 if (nCurPara == rSec.mnParagraph)
3303 // Still in the same paragraph.
3304 continue;
3306 // Start of a new paragraph. Flush the old paragraph.
3307 flushParagraph(*this, aParaTexts[nCurPara], xMapper, xStylePool, rAttrMap, itPara, itSec);
3308 nCurPara = rSec.mnParagraph;
3309 itPara = itSec;
3312 flushParagraph(*this, aParaTexts[nCurPara], xMapper, xStylePool, rAttrMap, itPara, itSecEnd);
3315 void ScXMLExport::WriteMultiLineFormulaResult(const ScFormulaCell* pCell)
3317 OUString aElemName = GetNamespaceMap().GetQNameByKey(XML_NAMESPACE_TEXT, GetXMLToken(XML_P));
3319 OUString aResStr = pCell->GetResultString().getString();
3320 const sal_Unicode* p = aResStr.getStr();
3321 const sal_Unicode* pEnd = p + static_cast<size_t>(aResStr.getLength());
3322 const sal_Unicode* pPara = p; // paragraph head.
3323 for (; p != pEnd; ++p)
3325 if (*p != '\n')
3326 continue;
3328 // flush the paragraph.
3329 OUString aContent;
3330 if (*pPara == '\n')
3331 ++pPara;
3332 if (p > pPara)
3333 aContent = OUString(pPara, p-pPara);
3335 SvXMLElementExport aElem(*this, aElemName, false, false);
3336 Characters(aContent);
3338 pPara = p;
3341 OUString aContent;
3342 if (*pPara == '\n')
3343 ++pPara;
3344 if (pEnd > pPara)
3345 aContent = OUString(pPara, pEnd-pPara);
3347 SvXMLElementExport aElem(*this, aElemName, false, false);
3348 Characters(aContent);
3351 void ScXMLExport::ExportShape(const uno::Reference < drawing::XShape >& xShape, awt::Point* pPoint)
3353 uno::Reference < beans::XPropertySet > xShapeProps ( xShape, uno::UNO_QUERY );
3354 bool bIsChart( false );
3355 OUString sPropCLSID ("CLSID");
3356 if (xShapeProps.is())
3358 sal_Int32 nZOrder = 0;
3359 if (xShapeProps->getPropertyValue("ZOrder") >>= nZOrder)
3361 AddAttribute(XML_NAMESPACE_DRAW, XML_ZINDEX, OUString::number(nZOrder));
3363 uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xShapeProps->getPropertySetInfo();
3364 if( xPropSetInfo->hasPropertyByName( sPropCLSID ) )
3366 OUString sCLSID;
3367 if (xShapeProps->getPropertyValue( sPropCLSID ) >>= sCLSID)
3369 if ( sCLSID.equalsIgnoreAsciiCase(GetChartExport()->getChartCLSID()) )
3371 // we have a chart
3372 OUString sRanges;
3373 if ( pDoc )
3375 OUString aChartName;
3376 xShapeProps->getPropertyValue( "PersistName" ) >>= aChartName;
3377 ScChartListenerCollection* pCollection = pDoc->GetChartListenerCollection();
3378 if (pCollection)
3380 ScChartListener* pListener = pCollection->findByName(aChartName);
3381 if (pListener)
3383 const ScRangeListRef& rRangeList = pListener->GetRangeList();
3384 if ( rRangeList.is() )
3386 ScRangeStringConverter::GetStringFromRangeList( sRanges, rRangeList.get(), pDoc, FormulaGrammar::CONV_OOO );
3387 if ( !sRanges.isEmpty() )
3389 bIsChart = true;
3390 SvXMLAttributeList* pAttrList = new SvXMLAttributeList();
3391 pAttrList->AddAttribute(
3392 GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_DRAW, GetXMLToken( XML_NOTIFY_ON_UPDATE_OF_RANGES ) ), sRanges );
3393 GetShapeExport()->exportShape( xShape, SEF_DEFAULT, pPoint, pAttrList );
3400 if ( sRanges.isEmpty() )
3402 uno::Reference< frame::XModel > xChartModel;
3403 if( ( xShapeProps->getPropertyValue( "Model" ) >>= xChartModel ) &&
3404 xChartModel.is())
3406 uno::Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY );
3407 uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartModel, uno::UNO_QUERY );
3408 if( xChartDoc.is() && xReceiver.is() &&
3409 ! xChartDoc->hasInternalDataProvider())
3411 // we have a chart that gets its data from Calc
3412 bIsChart = true;
3413 uno::Sequence< OUString > aRepresentations(
3414 xReceiver->getUsedRangeRepresentations());
3415 SvXMLAttributeList* pAttrList = nullptr;
3416 if(aRepresentations.getLength())
3418 // add the ranges used by the chart to the shape
3419 // element to be able to start listening after
3420 // load (when the chart is not yet loaded)
3421 uno::Reference< chart2::data::XRangeXMLConversion > xRangeConverter( xChartDoc->getDataProvider(), uno::UNO_QUERY );
3422 sRanges = lcl_RangeSequenceToString( aRepresentations, xRangeConverter );
3423 pAttrList = new SvXMLAttributeList();
3424 pAttrList->AddAttribute(
3425 GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_DRAW, GetXMLToken(XML_NOTIFY_ON_UPDATE_OF_RANGES) ), sRanges );
3427 GetShapeExport()->exportShape(xShape, SEF_DEFAULT, pPoint, pAttrList);
3435 if (!bIsChart)
3437 // #i66550 HLINK_FOR_SHAPES
3438 OUString sHlink;
3441 uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );
3442 if ( xProps.is() )
3443 xProps->getPropertyValue( SC_UNONAME_HYPERLINK ) >>= sHlink;
3445 catch ( const beans::UnknownPropertyException& )
3447 // no hyperlink property
3450 std::unique_ptr< SvXMLElementExport > pDrawA;
3451 // enclose shapes with <draw:a> element only if sHlink contains something
3452 if ( !sHlink.isEmpty() )
3454 // need to get delete the attributes that are pre-loaded
3455 // for the shape export ( otherwise they will become
3456 // attributes of the draw:a element ) This *shouldn't*
3457 // affect performance adversely as there are only a
3458 // couple of attributes involved
3459 uno::Reference< xml::sax::XAttributeList > xSaveAttribs( new SvXMLAttributeList( GetAttrList() ) );
3460 ClearAttrList();
3461 // Add Hlink
3462 AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
3463 AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sHlink);
3464 pDrawA.reset( new SvXMLElementExport( *this, XML_NAMESPACE_DRAW, XML_A, false, false ) );
3465 // Attribute list has been cleared by previous operation
3466 // re-add pre-loaded attributes
3467 AddAttributeList( xSaveAttribs );
3469 GetShapeExport()->exportShape(xShape, SEF_DEFAULT, pPoint);
3471 IncrementProgressBar(false);
3474 void ScXMLExport::WriteShapes(const ScMyCell& rMyCell)
3476 if( rMyCell.bHasShape && !rMyCell.aShapeList.empty() && pDoc )
3478 awt::Point aPoint;
3479 tools::Rectangle aRect = pDoc->GetMMRect(rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(),
3480 rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(), rMyCell.maCellAddress.Tab());
3481 bool bNegativePage = pDoc->IsNegativePage(rMyCell.maCellAddress.Tab());
3482 if (bNegativePage)
3483 aPoint.X = aRect.Right();
3484 else
3485 aPoint.X = aRect.Left();
3486 aPoint.Y = aRect.Top();
3487 for (const auto& rShape : rMyCell.aShapeList)
3489 if (rShape.xShape.is())
3491 if (bNegativePage)
3492 aPoint.X = 2 * rShape.xShape->getPosition().X + rShape.xShape->getSize().Width - aPoint.X;
3494 // We only write the end address if we want the shape to resize with the cell
3495 if ( rShape.bResizeWithCell &&
3496 rShape.xShape->getShapeType() != "com.sun.star.drawing.CaptionShape" )
3498 OUString sEndAddress;
3499 ScRangeStringConverter::GetStringFromAddress(sEndAddress, rShape.aEndAddress, pDoc, FormulaGrammar::CONV_OOO);
3500 AddAttribute(XML_NAMESPACE_TABLE, XML_END_CELL_ADDRESS, sEndAddress);
3501 OUStringBuffer sBuffer;
3502 GetMM100UnitConverter().convertMeasureToXML(
3503 sBuffer, rShape.nEndX);
3504 AddAttribute(XML_NAMESPACE_TABLE, XML_END_X, sBuffer.makeStringAndClear());
3505 GetMM100UnitConverter().convertMeasureToXML(
3506 sBuffer, rShape.nEndY);
3507 AddAttribute(XML_NAMESPACE_TABLE, XML_END_Y, sBuffer.makeStringAndClear());
3509 ExportShape(rShape.xShape, &aPoint);
3515 void ScXMLExport::WriteTableShapes()
3517 ScMyTableShapes* pTableShapes(pSharedData->GetTableShapes());
3518 if (pTableShapes && !(*pTableShapes)[nCurrentTable].empty())
3520 OSL_ENSURE(pTableShapes->size() > static_cast<size_t>(nCurrentTable), "wrong Table");
3521 SvXMLElementExport aShapesElem(*this, XML_NAMESPACE_TABLE, XML_SHAPES, true, false);
3522 for (const auto& rxShape : (*pTableShapes)[nCurrentTable])
3524 if (rxShape.is())
3526 if (pDoc->IsNegativePage(static_cast<SCTAB>(nCurrentTable)))
3528 awt::Point aPoint(rxShape->getPosition());
3529 awt::Size aSize(rxShape->getSize());
3530 aPoint.X += aPoint.X + aSize.Width;
3531 aPoint.Y = 0;
3532 ExportShape(rxShape, &aPoint);
3534 else
3535 ExportShape(rxShape, nullptr);
3538 (*pTableShapes)[nCurrentTable].clear();
3542 void ScXMLExport::WriteAreaLink( const ScMyCell& rMyCell )
3544 if( rMyCell.bHasAreaLink )
3546 const ScMyAreaLink& rAreaLink = rMyCell.aAreaLink;
3547 AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, rAreaLink.sSourceStr );
3548 AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
3549 AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, GetRelativeReference(rAreaLink.sURL) );
3550 AddAttribute( XML_NAMESPACE_TABLE, XML_FILTER_NAME, rAreaLink.sFilter );
3551 if( !rAreaLink.sFilterOptions.isEmpty() )
3552 AddAttribute( XML_NAMESPACE_TABLE, XML_FILTER_OPTIONS, rAreaLink.sFilterOptions );
3553 OUStringBuffer sValue;
3554 AddAttribute( XML_NAMESPACE_TABLE, XML_LAST_COLUMN_SPANNED, OUString::number(rAreaLink.GetColCount()) );
3555 AddAttribute( XML_NAMESPACE_TABLE, XML_LAST_ROW_SPANNED, OUString::number(rAreaLink.GetRowCount()) );
3556 if( rAreaLink.nRefresh )
3558 ::sax::Converter::convertDuration( sValue,
3559 static_cast<double>(rAreaLink.nRefresh) / 86400 );
3560 AddAttribute( XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, sValue.makeStringAndClear() );
3562 SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_CELL_RANGE_SOURCE, true, true );
3566 void ScXMLExport::exportAnnotationMeta( const uno::Reference < drawing::XShape >& xShape)
3568 ScPostIt* pNote = pCurrentCell->pNote;
3570 if (pNote)
3572 // TODO : notes
3573 //is it still useful, as this call back is only called from ScXMLExport::WriteAnnotation
3574 // and should be in sync with pCurrentCell
3575 SdrCaptionObj* pNoteCaption = pNote->GetOrCreateCaption(pCurrentCell->maCellAddress);
3576 uno::Reference<drawing::XShape> xCurrentShape( pNoteCaption->getUnoShape(), uno::UNO_QUERY );
3577 if (xCurrentShape.get()!=xShape.get())
3578 return;
3580 const OUString& sAuthor(pNote->GetAuthor());
3581 if (!sAuthor.isEmpty())
3583 SvXMLElementExport aCreatorElem( *this, XML_NAMESPACE_DC,
3584 XML_CREATOR, true,
3585 false );
3586 Characters(sAuthor);
3589 const OUString& aDate(pNote->GetDate());
3590 if (pDoc)
3592 SvNumberFormatter* pNumForm = pDoc->GetFormatTable();
3593 double fDate;
3594 sal_uInt32 nfIndex = pNumForm->GetFormatIndex(NF_DATE_SYS_DDMMYYYY, LANGUAGE_SYSTEM);
3595 if (pNumForm->IsNumberFormat(aDate, nfIndex, fDate))
3597 OUStringBuffer sBuf;
3598 GetMM100UnitConverter().convertDateTime(sBuf, fDate,true);
3599 SvXMLElementExport aDateElem( *this, XML_NAMESPACE_DC,
3600 XML_DATE, true,
3601 false );
3602 Characters(sBuf.makeStringAndClear());
3604 else
3606 SvXMLElementExport aDateElem( *this, XML_NAMESPACE_META,
3607 XML_DATE_STRING, true,
3608 false );
3609 Characters(aDate);
3612 else
3614 SvXMLElementExport aDateElem( *this, XML_NAMESPACE_META,
3615 XML_DATE_STRING, true,
3616 false );
3617 Characters(aDate);
3622 void ScXMLExport::WriteAnnotation(ScMyCell& rMyCell)
3624 ScPostIt* pNote = pDoc->GetNote(rMyCell.maCellAddress);
3625 if (pNote)
3627 if (pNote->IsCaptionShown())
3628 AddAttribute(XML_NAMESPACE_OFFICE, XML_DISPLAY, XML_TRUE);
3630 pCurrentCell = &rMyCell;
3632 SdrCaptionObj* pNoteCaption = pNote->GetOrCreateCaption(rMyCell.maCellAddress);
3633 if (pNoteCaption)
3635 uno::Reference<drawing::XShape> xShape( pNoteCaption->getUnoShape(), uno::UNO_QUERY );
3636 if (xShape.is())
3637 GetShapeExport()->exportShape(xShape, SEF_DEFAULT|XMLShapeExportFlags::ANNOTATION);
3640 pCurrentCell = nullptr;
3645 void ScXMLExport::WriteDetective( const ScMyCell& rMyCell )
3647 if( rMyCell.bHasDetectiveObj || rMyCell.bHasDetectiveOp )
3649 const ScMyDetectiveObjVec& rObjVec = rMyCell.aDetectiveObjVec;
3650 const ScMyDetectiveOpVec& rOpVec = rMyCell.aDetectiveOpVec;
3651 sal_Int32 nObjCount(rObjVec.size());
3652 sal_Int32 nOpCount(rOpVec.size());
3653 if( nObjCount || nOpCount )
3655 SvXMLElementExport aDetElem( *this, XML_NAMESPACE_TABLE, XML_DETECTIVE, true, true );
3656 OUString sString;
3657 for(const auto& rObj : rObjVec)
3659 if (rObj.eObjType != SC_DETOBJ_CIRCLE)
3661 if( (rObj.eObjType == SC_DETOBJ_ARROW) || (rObj.eObjType == SC_DETOBJ_TOOTHERTAB))
3663 ScRangeStringConverter::GetStringFromRange( sString, rObj.aSourceRange, pDoc, FormulaGrammar::CONV_OOO );
3664 AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, sString );
3666 ScXMLConverter::GetStringFromDetObjType( sString, rObj.eObjType );
3667 AddAttribute( XML_NAMESPACE_TABLE, XML_DIRECTION, sString );
3668 if( rObj.bHasError )
3669 AddAttribute( XML_NAMESPACE_TABLE, XML_CONTAINS_ERROR, XML_TRUE );
3671 else
3672 AddAttribute( XML_NAMESPACE_TABLE, XML_MARKED_INVALID, XML_TRUE );
3673 SvXMLElementExport aRangeElem( *this, XML_NAMESPACE_TABLE, XML_HIGHLIGHTED_RANGE, true, true );
3675 for(const auto& rOp : rOpVec)
3677 OUString sOpString;
3678 ScXMLConverter::GetStringFromDetOpType( sOpString, rOp.eOpType );
3679 AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, sOpString );
3680 AddAttribute( XML_NAMESPACE_TABLE, XML_INDEX, OUString::number(rOp.nIndex) );
3681 SvXMLElementExport aRangeElem( *this, XML_NAMESPACE_TABLE, XML_OPERATION, true, true );
3687 void ScXMLExport::SetRepeatAttribute(sal_Int32 nEqualCellCount, bool bIncProgress)
3689 // nEqualCellCount is additional cells, so the attribute value is nEqualCellCount+1
3690 if (nEqualCellCount > 0)
3692 sal_Int32 nTemp(nEqualCellCount + 1);
3693 OUString sOUEqualCellCount(OUString::number(nTemp));
3694 AddAttribute(sAttrColumnsRepeated, sOUEqualCellCount);
3695 if (bIncProgress)
3696 IncrementProgressBar(false, nEqualCellCount);
3700 bool ScXMLExport::IsEditCell(const ScMyCell& rCell)
3702 return rCell.maBaseCell.meType == CELLTYPE_EDIT;
3705 bool ScXMLExport::IsCellEqual (ScMyCell& aCell1, ScMyCell& aCell2)
3707 bool bIsEqual = false;
3708 if( !aCell1.bIsMergedBase && !aCell2.bIsMergedBase &&
3709 aCell1.bIsCovered == aCell2.bIsCovered &&
3710 !aCell1.bIsMatrixBase && !aCell2.bIsMatrixBase &&
3711 aCell1.bIsMatrixCovered == aCell2.bIsMatrixCovered &&
3712 aCell1.bHasAnnotation == aCell2.bHasAnnotation &&
3713 !aCell1.bHasShape && !aCell2.bHasShape &&
3714 aCell1.bHasAreaLink == aCell2.bHasAreaLink &&
3715 !aCell1.bHasDetectiveObj && !aCell2.bHasDetectiveObj)
3717 if( (aCell1.bHasAreaLink &&
3718 (aCell1.aAreaLink.GetColCount() == 1) &&
3719 (aCell2.aAreaLink.GetColCount() == 1) &&
3720 aCell1.aAreaLink.Compare( aCell2.aAreaLink ) ) ||
3721 !aCell1.bHasAreaLink )
3723 if (!aCell1.bHasAnnotation)
3725 if ((((aCell1.nStyleIndex == aCell2.nStyleIndex) && (aCell1.bIsAutoStyle == aCell2.bIsAutoStyle)) ||
3726 ((aCell1.nStyleIndex == aCell2.nStyleIndex) && (aCell1.nStyleIndex == -1))) &&
3727 aCell1.nValidationIndex == aCell2.nValidationIndex &&
3728 aCell1.nType == aCell2.nType)
3730 switch ( aCell1.nType )
3732 case table::CellContentType_EMPTY :
3734 bIsEqual = true;
3736 break;
3737 case table::CellContentType_VALUE :
3739 // #i29101# number format may be different from column default styles,
3740 // but can lead to different value types, so it must also be compared
3741 bIsEqual = (aCell1.nNumberFormat == aCell2.nNumberFormat) &&
3742 (aCell1.maBaseCell.mfValue == aCell2.maBaseCell.mfValue);
3744 break;
3745 case table::CellContentType_TEXT :
3747 if (IsEditCell(aCell1) || IsEditCell(aCell2))
3748 bIsEqual = false;
3749 else
3751 bIsEqual = (aCell1.maBaseCell.getString(pDoc) == aCell2.maBaseCell.getString(pDoc));
3754 break;
3755 case table::CellContentType_FORMULA :
3757 bIsEqual = false;
3759 break;
3760 default :
3762 bIsEqual = false;
3764 break;
3770 return bIsEqual;
3773 void ScXMLExport::WriteCalculationSettings(const uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc)
3775 uno::Reference<beans::XPropertySet> xPropertySet(xSpreadDoc, uno::UNO_QUERY);
3776 if (xPropertySet.is())
3778 bool bCalcAsShown (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_CALCASSHOWN) ));
3779 bool bIgnoreCase (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_IGNORECASE) ));
3780 bool bLookUpLabels (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_LOOKUPLABELS) ));
3781 bool bMatchWholeCell (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_MATCHWHOLE) ));
3782 bool bUseRegularExpressions (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_REGEXENABLED) ));
3783 bool bUseWildcards (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_WILDCARDSENABLED) ));
3784 if (bUseWildcards && bUseRegularExpressions)
3785 bUseRegularExpressions = false; // mutually exclusive, wildcards take precedence
3786 bool bIsIterationEnabled (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_ITERENABLED) ));
3787 sal_uInt16 nYear2000 (pDoc ? pDoc->GetDocOptions().GetYear2000() : 0);
3788 sal_Int32 nIterationCount(100);
3789 xPropertySet->getPropertyValue( SC_UNO_ITERCOUNT ) >>= nIterationCount;
3790 double fIterationEpsilon = 0;
3791 xPropertySet->getPropertyValue( SC_UNO_ITEREPSILON ) >>= fIterationEpsilon;
3792 util::Date aNullDate;
3793 xPropertySet->getPropertyValue( SC_UNO_NULLDATE ) >>= aNullDate;
3794 if (bCalcAsShown || bIgnoreCase || !bLookUpLabels || !bMatchWholeCell || !bUseRegularExpressions ||
3795 bUseWildcards ||
3796 bIsIterationEnabled || nIterationCount != 100 || !::rtl::math::approxEqual(fIterationEpsilon, 0.001) ||
3797 aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899 || nYear2000 != 1930)
3799 if (bIgnoreCase)
3800 AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_FALSE);
3801 if (bCalcAsShown)
3802 AddAttribute(XML_NAMESPACE_TABLE, XML_PRECISION_AS_SHOWN, XML_TRUE);
3803 if (!bMatchWholeCell)
3804 AddAttribute(XML_NAMESPACE_TABLE, XML_SEARCH_CRITERIA_MUST_APPLY_TO_WHOLE_CELL, XML_FALSE);
3805 if (!bLookUpLabels)
3806 AddAttribute(XML_NAMESPACE_TABLE, XML_AUTOMATIC_FIND_LABELS, XML_FALSE);
3807 if (!bUseRegularExpressions)
3808 AddAttribute(XML_NAMESPACE_TABLE, XML_USE_REGULAR_EXPRESSIONS, XML_FALSE);
3809 if (bUseWildcards)
3810 AddAttribute(XML_NAMESPACE_TABLE, XML_USE_WILDCARDS, XML_TRUE);
3811 if (nYear2000 != 1930)
3813 AddAttribute(XML_NAMESPACE_TABLE, XML_NULL_YEAR, OUString::number(nYear2000));
3815 SvXMLElementExport aCalcSettings(*this, XML_NAMESPACE_TABLE, XML_CALCULATION_SETTINGS, true, true);
3817 if (aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899)
3819 OUStringBuffer sDate;
3820 SvXMLUnitConverter::convertDateTime(sDate, 0.0, aNullDate);
3821 AddAttribute(XML_NAMESPACE_TABLE, XML_DATE_VALUE, sDate.makeStringAndClear());
3822 SvXMLElementExport aElemNullDate(*this, XML_NAMESPACE_TABLE, XML_NULL_DATE, true, true);
3824 if (bIsIterationEnabled || nIterationCount != 100 || !::rtl::math::approxEqual(fIterationEpsilon, 0.001))
3826 OUStringBuffer sBuffer;
3827 if (bIsIterationEnabled)
3828 AddAttribute(XML_NAMESPACE_TABLE, XML_STATUS, XML_ENABLE);
3829 if (nIterationCount != 100)
3831 AddAttribute(XML_NAMESPACE_TABLE, XML_STEPS, OUString::number(nIterationCount));
3833 if (!::rtl::math::approxEqual(fIterationEpsilon, 0.001))
3835 ::sax::Converter::convertDouble(sBuffer,
3836 fIterationEpsilon);
3837 AddAttribute(XML_NAMESPACE_TABLE, XML_MAXIMUM_DIFFERENCE, sBuffer.makeStringAndClear());
3839 SvXMLElementExport aElemIteration(*this, XML_NAMESPACE_TABLE, XML_ITERATION, true, true);
3846 void ScXMLExport::WriteTableSource()
3848 uno::Reference <sheet::XSheetLinkable> xLinkable (xCurrentTable, uno::UNO_QUERY);
3849 if (xLinkable.is() && GetModel().is())
3851 sheet::SheetLinkMode nMode (xLinkable->getLinkMode());
3852 if (nMode != sheet::SheetLinkMode_NONE)
3854 OUString sLink (xLinkable->getLinkUrl());
3855 uno::Reference <beans::XPropertySet> xProps (GetModel(), uno::UNO_QUERY);
3856 if (xProps.is())
3858 uno::Reference <container::XIndexAccess> xIndex(xProps->getPropertyValue(SC_UNO_SHEETLINKS), uno::UNO_QUERY);
3859 if (xIndex.is())
3861 sal_Int32 nCount(xIndex->getCount());
3862 if (nCount)
3864 bool bFound(false);
3865 uno::Reference <beans::XPropertySet> xLinkProps;
3866 for (sal_Int32 i = 0; (i < nCount) && !bFound; ++i)
3868 xLinkProps.set(xIndex->getByIndex(i), uno::UNO_QUERY);
3869 if (xLinkProps.is())
3871 OUString sNewLink;
3872 if (xLinkProps->getPropertyValue(SC_UNONAME_LINKURL) >>= sNewLink)
3873 bFound = sLink == sNewLink;
3876 if (bFound && xLinkProps.is())
3878 OUString sFilter;
3879 OUString sFilterOptions;
3880 OUString sTableName (xLinkable->getLinkSheetName());
3881 sal_Int32 nRefresh(0);
3882 xLinkProps->getPropertyValue(SC_UNONAME_FILTER) >>= sFilter;
3883 xLinkProps->getPropertyValue(SC_UNONAME_FILTOPT) >>= sFilterOptions;
3884 xLinkProps->getPropertyValue(SC_UNONAME_REFDELAY) >>= nRefresh;
3885 if (!sLink.isEmpty())
3887 AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
3888 AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetRelativeReference(sLink));
3889 if (!sTableName.isEmpty())
3890 AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_NAME, sTableName);
3891 if (!sFilter.isEmpty())
3892 AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_NAME, sFilter);
3893 if (!sFilterOptions.isEmpty())
3894 AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_OPTIONS, sFilterOptions);
3895 if (nMode != sheet::SheetLinkMode_NORMAL)
3896 AddAttribute(XML_NAMESPACE_TABLE, XML_MODE, XML_COPY_RESULTS_ONLY);
3897 if( nRefresh )
3899 OUStringBuffer sBuffer;
3900 ::sax::Converter::convertDuration( sBuffer,
3901 static_cast<double>(nRefresh) / 86400 );
3902 AddAttribute( XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, sBuffer.makeStringAndClear() );
3904 SvXMLElementExport aSourceElem(*this, XML_NAMESPACE_TABLE, XML_TABLE_SOURCE, true, true);
3914 // core implementation
3915 void ScXMLExport::WriteScenario()
3917 if (pDoc && pDoc->IsScenario(static_cast<SCTAB>(nCurrentTable)))
3919 OUString sComment;
3920 Color aColor;
3921 ScScenarioFlags nFlags;
3922 pDoc->GetScenarioData(static_cast<SCTAB>(nCurrentTable), sComment, aColor, nFlags);
3923 if (!(nFlags & ScScenarioFlags::ShowFrame))
3924 AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_BORDER, XML_FALSE);
3925 OUStringBuffer aBuffer;
3926 ::sax::Converter::convertColor(aBuffer, aColor);
3927 AddAttribute(XML_NAMESPACE_TABLE, XML_BORDER_COLOR, aBuffer.makeStringAndClear());
3928 if (!(nFlags & ScScenarioFlags::TwoWay))
3929 AddAttribute(XML_NAMESPACE_TABLE, XML_COPY_BACK, XML_FALSE);
3930 if (!(nFlags & ScScenarioFlags::Attrib))
3931 AddAttribute(XML_NAMESPACE_TABLE, XML_COPY_STYLES, XML_FALSE);
3932 if (nFlags & ScScenarioFlags::Value)
3933 AddAttribute(XML_NAMESPACE_TABLE, XML_COPY_FORMULAS, XML_FALSE);
3934 if (nFlags & ScScenarioFlags::Protected)
3935 AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE);
3936 ::sax::Converter::convertBool(aBuffer,
3937 pDoc->IsActiveScenario(static_cast<SCTAB>(nCurrentTable)));
3938 AddAttribute(XML_NAMESPACE_TABLE, XML_IS_ACTIVE, aBuffer.makeStringAndClear());
3939 const ScRangeList* pRangeList = pDoc->GetScenarioRanges(static_cast<SCTAB>(nCurrentTable));
3940 OUString sRangeListStr;
3941 ScRangeStringConverter::GetStringFromRangeList( sRangeListStr, pRangeList, pDoc, FormulaGrammar::CONV_OOO );
3942 AddAttribute(XML_NAMESPACE_TABLE, XML_SCENARIO_RANGES, sRangeListStr);
3943 if (!sComment.isEmpty())
3944 AddAttribute(XML_NAMESPACE_TABLE, XML_COMMENT, sComment);
3945 SvXMLElementExport aElem(*this, XML_NAMESPACE_TABLE, XML_SCENARIO, true, true);
3949 void ScXMLExport::WriteTheLabelRanges( const uno::Reference< sheet::XSpreadsheetDocument >& xSpreadDoc )
3951 uno::Reference< beans::XPropertySet > xDocProp( xSpreadDoc, uno::UNO_QUERY );
3952 if( !xDocProp.is() ) return;
3954 sal_Int32 nCount(0);
3955 uno::Reference< container::XIndexAccess > xColRangesIAccess(xDocProp->getPropertyValue( SC_UNO_COLLABELRNG ), uno::UNO_QUERY);
3956 if( xColRangesIAccess.is() )
3957 nCount += xColRangesIAccess->getCount();
3959 uno::Reference< container::XIndexAccess > xRowRangesIAccess(xDocProp->getPropertyValue( SC_UNO_ROWLABELRNG ), uno::UNO_QUERY);
3960 if( xRowRangesIAccess.is() )
3961 nCount += xRowRangesIAccess->getCount();
3963 if( nCount )
3965 SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_LABEL_RANGES, true, true );
3966 WriteLabelRanges( xColRangesIAccess, true );
3967 WriteLabelRanges( xRowRangesIAccess, false );
3971 void ScXMLExport::WriteLabelRanges( const uno::Reference< container::XIndexAccess >& xRangesIAccess, bool bColumn )
3973 if( !xRangesIAccess.is() ) return;
3975 sal_Int32 nCount(xRangesIAccess->getCount());
3976 for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
3978 uno::Reference< sheet::XLabelRange > xRange(xRangesIAccess->getByIndex( nIndex ), uno::UNO_QUERY);
3979 if( xRange.is() )
3981 OUString sRangeStr;
3982 table::CellRangeAddress aCellRange( xRange->getLabelArea() );
3983 ScRangeStringConverter::GetStringFromRange( sRangeStr, aCellRange, pDoc, FormulaGrammar::CONV_OOO );
3984 AddAttribute( XML_NAMESPACE_TABLE, XML_LABEL_CELL_RANGE_ADDRESS, sRangeStr );
3985 aCellRange = xRange->getDataArea();
3986 ScRangeStringConverter::GetStringFromRange( sRangeStr, aCellRange, pDoc, FormulaGrammar::CONV_OOO );
3987 AddAttribute( XML_NAMESPACE_TABLE, XML_DATA_CELL_RANGE_ADDRESS, sRangeStr );
3988 AddAttribute( XML_NAMESPACE_TABLE, XML_ORIENTATION, bColumn ? XML_COLUMN : XML_ROW );
3989 SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_LABEL_RANGE, true, true );
3994 void ScXMLExport::WriteNamedExpressions()
3996 if (!pDoc)
3997 return;
3998 ScRangeName* pNamedRanges = pDoc->GetRangeName();
3999 WriteNamedRange(pNamedRanges);
4002 void ScXMLExport::WriteExternalDataMapping()
4004 if (!pDoc)
4005 return;
4007 if (getDefaultVersion() <= SvtSaveOptions::ODFVER_012)
4008 // Export this only for 1.2 extended and above.
4009 return;
4011 sc::ExternalDataMapper& rDataMapper = pDoc->GetExternalDataMapper();
4012 auto& rDataSources = rDataMapper.getDataSources();
4014 if (!rDataSources.empty())
4016 SvXMLElementExport aMappings(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_MAPPINGS, true, true);
4017 for (auto& itr : rDataSources)
4019 AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, itr.getURL());
4020 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_PROVIDER, itr.getProvider());
4021 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_DATA_FREQUENCY, OUString::number(sc::ExternalDataSource::getUpdateFrequency()));
4022 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_ID, itr.getID());
4023 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_DATABASE_NAME, itr.getDBName());
4025 SvXMLElementExport aMapping(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_MAPPING, true, true);
4026 // Add the data transformations
4027 WriteExternalDataTransformations(itr.getDataTransformation());
4032 void ScXMLExport::WriteExternalDataTransformations(const std::vector<std::shared_ptr<sc::DataTransformation>>& aDataTransformations)
4034 SvXMLElementExport aTransformations(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_TRANSFORMATIONS, true, true);
4035 for (auto& itr : aDataTransformations)
4037 sc::TransformationType aTransformationType = itr->getTransformationType();
4039 switch(aTransformationType)
4041 case sc::TransformationType::DELETE_TRANSFORMATION:
4043 // Delete Columns Transformation
4044 std::shared_ptr<sc::ColumnRemoveTransformation> aDeleteTransformation = std::dynamic_pointer_cast<sc::ColumnRemoveTransformation>(itr);
4045 std::set<SCCOL> aColumns = aDeleteTransformation->getColumns();
4046 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_REMOVE_TRANSFORMATION, true, true);
4047 for(auto& col : aColumns)
4049 // Add Columns
4050 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4051 SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4054 break;
4055 case sc::TransformationType::SPLIT_TRANSFORMATION:
4057 std::shared_ptr<sc::SplitColumnTransformation> aSplitTransformation = std::dynamic_pointer_cast<sc::SplitColumnTransformation>(itr);
4059 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(aSplitTransformation->getColumn()));
4060 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_SEPARATOR, OUString::number(aSplitTransformation->getSeparator()));
4061 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_SPLIT_TRANSFORMATION, true, true);
4063 break;
4064 case sc::TransformationType::MERGE_TRANSFORMATION:
4066 // Merge Transformation
4067 std::shared_ptr<sc::MergeColumnTransformation> aMergeTransformation = std::dynamic_pointer_cast<sc::MergeColumnTransformation>(itr);
4068 std::set<SCCOL> aColumns = aMergeTransformation->getColumns();
4070 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MERGE_STRING, aMergeTransformation->getMergeString());
4071 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_MERGE_TRANSFORMATION, true, true);
4073 for(auto& col : aColumns)
4075 // Columns
4076 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4077 SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4080 break;
4081 case sc::TransformationType::SORT_TRANSFORMATION:
4083 // Sort Transformation
4084 std::shared_ptr<sc::SortTransformation> aSortTransformation = std::dynamic_pointer_cast<sc::SortTransformation>(itr);
4085 ScSortParam aSortParam = aSortTransformation->getSortParam();
4086 const sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
4087 const sc::DataStream* pStrm = rMgr.getDataStream();
4088 if (!pStrm)
4089 // No data stream.
4090 return;
4092 // Streamed range
4093 ScRange aRange = pStrm->GetRange();
4095 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_SORT_TRANSFORMATION, true, true);
4097 writeSort(*this, aSortParam, aRange, pDoc);
4099 break;
4100 case sc::TransformationType::TEXT_TRANSFORMATION:
4102 // Text Transformation
4103 std::shared_ptr<sc::TextTransformation> aTextTransformation = std::dynamic_pointer_cast<sc::TextTransformation>(itr);
4105 sc::TEXT_TRANSFORM_TYPE aTextTransformType = aTextTransformation->getTextTransformationType();
4107 switch ( aTextTransformType )
4109 case sc::TEXT_TRANSFORM_TYPE::TO_LOWER:
4110 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_CASEMAP_LOWERCASE);
4111 break;
4112 case sc::TEXT_TRANSFORM_TYPE::TO_UPPER:
4113 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_CASEMAP_UPPERCASE);
4114 break;
4115 case sc::TEXT_TRANSFORM_TYPE::CAPITALIZE:
4116 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_CASEMAP_CAPITALIZE);
4117 break;
4118 case sc::TEXT_TRANSFORM_TYPE::TRIM:
4119 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_TRIM);
4120 break;
4123 std::set<SCCOL> aColumns = aTextTransformation->getColumns();
4125 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_TEXT_TRANSFORMATION, true, true);
4127 for(auto& col : aColumns)
4129 // Columns
4130 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4131 SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4134 break;
4135 case sc::TransformationType::AGGREGATE_FUNCTION:
4137 // Aggregate Transformation
4138 std::shared_ptr<sc::AggregateFunction> aAggregateFunction = std::dynamic_pointer_cast<sc::AggregateFunction>(itr);
4139 std::set<SCCOL> aColumns = aAggregateFunction->getColumns();
4141 sc::AGGREGATE_FUNCTION aAggregateType = aAggregateFunction->getAggregateType();
4143 switch (aAggregateType)
4145 case sc::AGGREGATE_FUNCTION::SUM:
4146 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_SUM);
4147 break;
4148 case sc::AGGREGATE_FUNCTION::AVERAGE:
4149 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_AVERAGE);
4150 break;
4151 case sc::AGGREGATE_FUNCTION::MIN:
4152 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_MIN);
4153 break;
4154 case sc::AGGREGATE_FUNCTION::MAX:
4155 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_MAX);
4156 break;
4159 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT,XML_COLUMN_AGGREGATE_TRANSFORMATION, true, true);
4161 for(auto& col : aColumns)
4163 // Columns
4164 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4165 SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4168 break;
4169 case sc::TransformationType::NUMBER_TRANSFORMATION:
4171 // Number Transformation
4172 std::shared_ptr<sc::NumberTransformation> aNumberTransformation = std::dynamic_pointer_cast<sc::NumberTransformation>(itr);
4174 sc::NUMBER_TRANSFORM_TYPE aNumberTransformType = aNumberTransformation->getNumberTransfromationType();
4176 switch ( aNumberTransformType )
4178 case sc::NUMBER_TRANSFORM_TYPE::ROUND:
4179 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_ROUND);
4180 break;
4181 case sc::NUMBER_TRANSFORM_TYPE::ROUND_UP:
4182 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_ROUND_UP);
4183 break;
4184 case sc::NUMBER_TRANSFORM_TYPE::ROUND_DOWN:
4185 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_ROUND_DOWN);
4186 break;
4187 case sc::NUMBER_TRANSFORM_TYPE::ABSOLUTE:
4188 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_ABS);
4189 break;
4190 case sc::NUMBER_TRANSFORM_TYPE::LOG_E:
4191 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_LOG);
4192 break;
4193 case sc::NUMBER_TRANSFORM_TYPE::LOG_10:
4194 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_LOG_10);
4195 break;
4196 case sc::NUMBER_TRANSFORM_TYPE::CUBE:
4197 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_CUBE);
4198 break;
4199 case sc::NUMBER_TRANSFORM_TYPE::SQUARE:
4200 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_SQUARE);
4201 break;
4202 case sc::NUMBER_TRANSFORM_TYPE::SQUARE_ROOT:
4203 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_SQUARE_ROOT);
4204 break;
4205 case sc::NUMBER_TRANSFORM_TYPE::EXPONENT:
4206 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_EXPONENTIAL);
4207 break;
4208 case sc::NUMBER_TRANSFORM_TYPE::IS_EVEN:
4209 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_EVEN);
4210 break;
4211 case sc::NUMBER_TRANSFORM_TYPE::IS_ODD:
4212 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_ODD);
4213 break;
4214 case sc::NUMBER_TRANSFORM_TYPE::SIGN:
4215 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_SIGN);
4216 break;
4219 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_PRECISION, OUString::number(aNumberTransformation->getPrecision()));
4220 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_NUMBER_TRANSFORMATION, true, true);
4222 std::set<SCCOL> aColumns = aNumberTransformation->getColumn();
4223 for(auto& col : aColumns)
4225 // Columns
4226 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4227 SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4230 break;
4231 case sc::TransformationType::REMOVE_NULL_TRANSFORMATION:
4233 // Replace Null Transformation
4234 std::shared_ptr<sc::ReplaceNullTransformation> aReplaceNullTransformation = std::dynamic_pointer_cast<sc::ReplaceNullTransformation>(itr);
4235 std::set<SCCOL> aColumns = aReplaceNullTransformation->getColumn();
4237 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_REPLACE_STRING, aReplaceNullTransformation->getReplaceString());
4238 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_REPLACENULL_TRANSFORMATION, true, true);
4240 for(auto& col : aColumns)
4242 // Columns
4243 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4244 SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4247 break;
4248 case sc::TransformationType::DATETIME_TRANSFORMATION:
4250 // Number Transformation
4251 std::shared_ptr<sc::DateTimeTransformation> aDateTimeTransformation = std::dynamic_pointer_cast<sc::DateTimeTransformation>(itr);
4253 sc::DATETIME_TRANSFORMATION_TYPE aDateTimeTransformationType = aDateTimeTransformation->getDateTimeTransfromationType();
4255 switch ( aDateTimeTransformationType )
4257 case sc::DATETIME_TRANSFORMATION_TYPE::DATE_STRING:
4258 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_DATE_STRING);
4259 break;
4260 case sc::DATETIME_TRANSFORMATION_TYPE::YEAR:
4261 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_YEAR);
4262 break;
4263 case sc::DATETIME_TRANSFORMATION_TYPE::START_OF_YEAR:
4264 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_START_OF_YEAR);
4265 break;
4266 case sc::DATETIME_TRANSFORMATION_TYPE::END_OF_YEAR:
4267 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_END_OF_YEAR);
4268 break;
4269 case sc::DATETIME_TRANSFORMATION_TYPE::MONTH:
4270 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_MONTH);
4271 break;
4272 case sc::DATETIME_TRANSFORMATION_TYPE::MONTH_NAME:
4273 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_MONTH_NAME);
4274 break;
4275 case sc::DATETIME_TRANSFORMATION_TYPE::START_OF_MONTH:
4276 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_START_OF_MONTH);
4277 break;
4278 case sc::DATETIME_TRANSFORMATION_TYPE::END_OF_MONTH:
4279 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_END_OF_MONTH);
4280 break;
4281 case sc::DATETIME_TRANSFORMATION_TYPE::DAY:
4282 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_DAY);
4283 break;
4284 case sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_WEEK:
4285 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_DAY_OF_WEEK);
4286 break;
4287 case sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_YEAR:
4288 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_DAY_OF_YEAR);
4289 break;
4290 case sc::DATETIME_TRANSFORMATION_TYPE::QUARTER:
4291 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_QUARTER);
4292 break;
4293 case sc::DATETIME_TRANSFORMATION_TYPE::START_OF_QUARTER:
4294 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_START_OF_QUARTER);
4295 break;
4296 case sc::DATETIME_TRANSFORMATION_TYPE::END_OF_QUARTER:
4297 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_END_OF_QUARTER);
4298 break;
4299 case sc::DATETIME_TRANSFORMATION_TYPE::TIME:
4300 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_TIME);
4301 break;
4302 case sc::DATETIME_TRANSFORMATION_TYPE::HOUR:
4303 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_HOUR);
4304 break;
4305 case sc::DATETIME_TRANSFORMATION_TYPE::MINUTE:
4306 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_MINUTE);
4307 break;
4308 case sc::DATETIME_TRANSFORMATION_TYPE::SECOND:
4309 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, XML_SECONDS);
4310 break;
4313 SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_DATETIME_TRANSFORMATION, true, true);
4315 std::set<SCCOL> aColumns = aDateTimeTransformation->getColumn();
4316 for(auto& col : aColumns)
4318 // Columns
4319 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4320 SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4323 break;
4324 default:
4325 break;
4330 void ScXMLExport::WriteDataStream()
4332 if (!pDoc)
4333 return;
4335 SvtMiscOptions aMiscOptions;
4336 if (!aMiscOptions.IsExperimentalMode())
4337 // Export this only in experimental mode.
4338 return;
4340 if (getDefaultVersion() <= SvtSaveOptions::ODFVER_012)
4341 // Export this only for 1.2 extended and above.
4342 return;
4344 const sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
4345 const sc::DataStream* pStrm = rMgr.getDataStream();
4346 if (!pStrm)
4347 // No data stream.
4348 return;
4350 // Source URL
4351 AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetRelativeReference(pStrm->GetURL()));
4353 // Streamed range
4354 ScRange aRange = pStrm->GetRange();
4355 OUString aRangeStr;
4356 ScRangeStringConverter::GetStringFromRange(
4357 aRangeStr, aRange, pDoc, formula::FormulaGrammar::CONV_OOO);
4358 AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, aRangeStr);
4360 // Empty line refresh option.
4361 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_EMPTY_LINE_REFRESH, pStrm->IsRefreshOnEmptyLine() ? XML_TRUE : XML_FALSE);
4363 // New data insertion position. Either top of bottom. Default to bottom.
4364 xmloff::token::XMLTokenEnum eInsertPosition = XML_BOTTOM;
4365 if (pStrm->GetMove() == sc::DataStream::MOVE_DOWN)
4366 eInsertPosition = XML_TOP;
4368 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_INSERTION_POSITION, eInsertPosition);
4370 SvXMLElementExport aElem(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_STREAM_SOURCE, true, true);
4373 void ScXMLExport::WriteNamedRange(ScRangeName* pRangeName)
4375 //write a global or local ScRangeName
4376 SvXMLElementExport aElemNEs(*this, XML_NAMESPACE_TABLE, XML_NAMED_EXPRESSIONS, true, true);
4377 for (const auto& rxEntry : *pRangeName)
4379 AddAttribute(sAttrName, rxEntry.second->GetName());
4381 OUString sBaseCellAddress;
4382 rxEntry.second->ValidateTabRefs();
4383 ScRangeStringConverter::GetStringFromAddress( sBaseCellAddress, rxEntry.second->GetPos(), pDoc,
4384 FormulaGrammar::CONV_OOO, ' ', false, ScRefFlags::ADDR_ABS_3D);
4385 AddAttribute(XML_NAMESPACE_TABLE, XML_BASE_CELL_ADDRESS, sBaseCellAddress);
4387 OUString sSymbol;
4388 rxEntry.second->GetSymbol(sSymbol, pDoc->GetStorageGrammar());
4389 OUString sTempSymbol(sSymbol);
4390 ScRange aRange;
4391 if (rxEntry.second->IsReference(aRange))
4394 OUString sContent(sTempSymbol.copy(1, sTempSymbol.getLength() -2 ));
4395 AddAttribute(XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, sContent);
4397 sal_Int32 nRangeType = rxEntry.second->GetUnoType();
4398 OUStringBuffer sBufferRangeType;
4399 if ((nRangeType & sheet::NamedRangeFlag::COLUMN_HEADER) == sheet::NamedRangeFlag::COLUMN_HEADER)
4400 sBufferRangeType.append(GetXMLToken(XML_REPEAT_COLUMN));
4401 if ((nRangeType & sheet::NamedRangeFlag::ROW_HEADER) == sheet::NamedRangeFlag::ROW_HEADER)
4403 if (!sBufferRangeType.isEmpty())
4404 sBufferRangeType.append(" ");
4405 sBufferRangeType.append(GetXMLToken(XML_REPEAT_ROW));
4407 if ((nRangeType & sheet::NamedRangeFlag::FILTER_CRITERIA) == sheet::NamedRangeFlag::FILTER_CRITERIA)
4409 if (!sBufferRangeType.isEmpty())
4410 sBufferRangeType.append(" ");
4411 sBufferRangeType.append(GetXMLToken(XML_FILTER));
4413 if ((nRangeType & sheet::NamedRangeFlag::PRINT_AREA) == sheet::NamedRangeFlag::PRINT_AREA)
4415 if (!sBufferRangeType.isEmpty())
4416 sBufferRangeType.append(" ");
4417 sBufferRangeType.append(GetXMLToken(XML_PRINT_RANGE));
4419 OUString sRangeType = sBufferRangeType.makeStringAndClear();
4420 if (!sRangeType.isEmpty())
4421 AddAttribute(XML_NAMESPACE_TABLE, XML_RANGE_USABLE_AS, sRangeType);
4422 SvXMLElementExport aElemNR(*this, XML_NAMESPACE_TABLE, XML_NAMED_RANGE, true, true);
4425 else
4427 AddAttribute(XML_NAMESPACE_TABLE, XML_EXPRESSION, sTempSymbol);
4428 SvXMLElementExport aElemNE(*this, XML_NAMESPACE_TABLE, XML_NAMED_EXPRESSION, true, true);
4433 namespace {
4435 OUString getCondFormatEntryType(const ScColorScaleEntry& rEntry, bool bFirst = true)
4437 switch(rEntry.GetType())
4439 case COLORSCALE_MIN:
4440 return OUString("minimum");
4441 case COLORSCALE_MAX:
4442 return OUString("maximum");
4443 case COLORSCALE_PERCENT:
4444 return OUString("percent");
4445 case COLORSCALE_PERCENTILE:
4446 return OUString("percentile");
4447 case COLORSCALE_FORMULA:
4448 return OUString("formula");
4449 case COLORSCALE_VALUE:
4450 return OUString("number");
4451 case COLORSCALE_AUTO:
4452 // only important for data bars
4453 if(bFirst)
4454 return OUString("auto-minimum");
4455 else
4456 return OUString("auto-maximum");
4458 return OUString();
4461 OUString getDateStringForType(condformat::ScCondFormatDateType eType)
4463 switch(eType)
4465 case condformat::TODAY:
4466 return OUString("today");
4467 case condformat::YESTERDAY:
4468 return OUString("yesterday");
4469 case condformat::TOMORROW:
4470 return OUString("tomorrow");
4471 case condformat::LAST7DAYS:
4472 return OUString("last-7-days");
4473 case condformat::THISWEEK:
4474 return OUString("this-week");
4475 case condformat::LASTWEEK:
4476 return OUString("last-week");
4477 case condformat::NEXTWEEK:
4478 return OUString("next-week");
4479 case condformat::THISMONTH:
4480 return OUString("this-month");
4481 case condformat::LASTMONTH:
4482 return OUString("last-month");
4483 case condformat::NEXTMONTH:
4484 return OUString("next-month");
4485 case condformat::THISYEAR:
4486 return OUString("this-year");
4487 case condformat::LASTYEAR:
4488 return OUString("last-year");
4489 case condformat::NEXTYEAR:
4490 return OUString("next-year");
4493 return OUString();
4498 void ScXMLExport::ExportConditionalFormat(SCTAB nTab)
4500 ScConditionalFormatList* pCondFormatList = pDoc->GetCondFormList(nTab);
4501 if(!pCondFormatList)
4502 return;
4504 if (pCondFormatList->empty())
4505 return;
4507 SvXMLElementExport aElementCondFormats(*this, XML_NAMESPACE_CALC_EXT, XML_CONDITIONAL_FORMATS, true, true);
4509 for(const auto& rxCondFormat : *pCondFormatList)
4511 OUString sRanges;
4512 const ScRangeList& rRangeList = rxCondFormat->GetRange();
4513 ScRangeStringConverter::GetStringFromRangeList( sRanges, &rRangeList, pDoc, formula::FormulaGrammar::CONV_OOO );
4514 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TARGET_RANGE_ADDRESS, sRanges);
4515 SvXMLElementExport aElementCondFormat(*this, XML_NAMESPACE_CALC_EXT, XML_CONDITIONAL_FORMAT, true, true);
4516 size_t nEntries = rxCondFormat->size();
4517 for(size_t i = 0; i < nEntries; ++i)
4519 const ScFormatEntry* pFormatEntry = rxCondFormat->GetEntry(i);
4520 if(pFormatEntry->GetType()==ScFormatEntry::Type::Condition)
4522 const ScCondFormatEntry* pEntry = static_cast<const ScCondFormatEntry*>(pFormatEntry);
4523 OUStringBuffer aCond;
4524 ScAddress aPos = pEntry->GetSrcPos();
4525 switch(pEntry->GetOperation())
4527 case ScConditionMode::Equal:
4528 aCond.append('=');
4529 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4530 break;
4531 case ScConditionMode::Less:
4532 aCond.append('<');
4533 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4534 break;
4535 case ScConditionMode::Greater:
4536 aCond.append('>');
4537 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4538 break;
4539 case ScConditionMode::EqLess:
4540 aCond.append("<=");
4541 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4542 break;
4543 case ScConditionMode::EqGreater:
4544 aCond.append(">=");
4545 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4546 break;
4547 case ScConditionMode::NotEqual:
4548 aCond.append("!=");
4549 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4550 break;
4551 case ScConditionMode::Between:
4552 aCond.append("between(");
4553 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4554 aCond.append(',');
4555 aCond.append(pEntry->GetExpression(aPos, 1, 0, formula::FormulaGrammar::GRAM_ODFF));
4556 aCond.append(')');
4557 break;
4558 case ScConditionMode::NotBetween:
4559 aCond.append("not-between(");
4560 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4561 aCond.append(',');
4562 aCond.append(pEntry->GetExpression(aPos, 1, 0, formula::FormulaGrammar::GRAM_ODFF));
4563 aCond.append(')');
4564 break;
4565 case ScConditionMode::Duplicate:
4566 aCond.append("duplicate");
4567 break;
4568 case ScConditionMode::NotDuplicate:
4569 aCond.append("unique");
4570 break;
4571 case ScConditionMode::Direct:
4572 aCond.append("formula-is(");
4573 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4574 aCond.append(')');
4575 break;
4576 case ScConditionMode::Top10:
4577 aCond.append("top-elements(");
4578 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4579 aCond.append(")");
4580 break;
4581 case ScConditionMode::Bottom10:
4582 aCond.append("bottom-elements(");
4583 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4584 aCond.append(")");
4585 break;
4586 case ScConditionMode::TopPercent:
4587 aCond.append("top-percent(");
4588 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4589 aCond.append(")");
4590 break;
4591 case ScConditionMode::BottomPercent:
4592 aCond.append("bottom-percent(");
4593 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4594 aCond.append(")");
4595 break;
4596 case ScConditionMode::AboveAverage:
4597 aCond.append("above-average");
4598 break;
4599 case ScConditionMode::BelowAverage:
4600 aCond.append("below-average");
4601 break;
4602 case ScConditionMode::AboveEqualAverage:
4603 aCond.append("above-equal-average");
4604 break;
4605 case ScConditionMode::BelowEqualAverage:
4606 aCond.append("below-equal-average");
4607 break;
4608 case ScConditionMode::Error:
4609 aCond.append("is-error");
4610 break;
4611 case ScConditionMode::NoError:
4612 aCond.append("is-no-error");
4613 break;
4614 case ScConditionMode::BeginsWith:
4615 aCond.append("begins-with(");
4616 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4617 aCond.append(")");
4618 break;
4619 case ScConditionMode::EndsWith:
4620 aCond.append("ends-with(");
4621 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4622 aCond.append(")");
4623 break;
4624 case ScConditionMode::ContainsText:
4625 aCond.append("contains-text(");
4626 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4627 aCond.append(")");
4628 break;
4629 case ScConditionMode::NotContainsText:
4630 aCond.append("not-contains-text(");
4631 aCond.append(pEntry->GetExpression(aPos, 0, 0, formula::FormulaGrammar::GRAM_ODFF));
4632 aCond.append(")");
4633 break;
4634 case ScConditionMode::NONE:
4635 continue;
4636 default:
4637 SAL_WARN("sc", "unimplemented conditional format export");
4639 OUString sStyle = ScStyleNameConversion::DisplayToProgrammaticName(pEntry->GetStyle(), SfxStyleFamily::Para);
4640 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_APPLY_STYLE_NAME, sStyle);
4641 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, aCond.makeStringAndClear());
4643 OUString sBaseAddress;
4644 ScRangeStringConverter::GetStringFromAddress( sBaseAddress, aPos, pDoc,formula::FormulaGrammar::CONV_ODF );
4645 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_BASE_CELL_ADDRESS, sBaseAddress);
4646 SvXMLElementExport aElementCondEntry(*this, XML_NAMESPACE_CALC_EXT, XML_CONDITION, true, true);
4648 else if(pFormatEntry->GetType() == ScFormatEntry::Type::Colorscale)
4650 SvXMLElementExport aElementColorScale(*this, XML_NAMESPACE_CALC_EXT, XML_COLOR_SCALE, true, true);
4651 const ScColorScaleFormat& rColorScale = static_cast<const ScColorScaleFormat&>(*pFormatEntry);
4652 for(const auto& rxItem : rColorScale)
4654 if(rxItem->GetType() == COLORSCALE_FORMULA)
4656 OUString sFormula = rxItem->GetFormula(formula::FormulaGrammar::GRAM_ODFF);
4657 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, sFormula);
4659 else
4660 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, OUString::number(rxItem->GetValue()));
4662 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, getCondFormatEntryType(*rxItem));
4663 OUStringBuffer aBuffer;
4664 ::sax::Converter::convertColor(aBuffer, rxItem->GetColor());
4665 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLOR, aBuffer.makeStringAndClear());
4666 SvXMLElementExport aElementColorScaleEntry(*this, XML_NAMESPACE_CALC_EXT, XML_COLOR_SCALE_ENTRY, true, true);
4669 else if(pFormatEntry->GetType() == ScFormatEntry::Type::Databar)
4671 const ScDataBarFormatData* pFormatData = static_cast<const ScDataBarFormat&>(*pFormatEntry).GetDataBarData();
4672 if(!pFormatData->mbGradient)
4673 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_GRADIENT, XML_FALSE);
4674 if(pFormatData->mbOnlyBar)
4675 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_SHOW_VALUE, XML_FALSE);
4677 if (pFormatData->mnMinLength != 0.0)
4678 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MIN_LENGTH, OUString::number(pFormatData->mnMinLength));
4680 if (pFormatData->mnMaxLength != 0.0)
4681 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MAX_LENGTH, OUString::number(pFormatData->mnMaxLength));
4683 if(pFormatData->mbNeg)
4685 if(pFormatData->mpNegativeColor)
4687 OUStringBuffer aBuffer;
4688 ::sax::Converter::convertColor(aBuffer, *pFormatData->mpNegativeColor);
4689 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_NEGATIVE_COLOR, aBuffer.makeStringAndClear());
4691 else
4693 OUStringBuffer aBuffer;
4694 ::sax::Converter::convertColor(aBuffer, COL_LIGHTRED);
4695 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_NEGATIVE_COLOR, aBuffer.makeStringAndClear());
4699 if(pFormatData->meAxisPosition != databar::AUTOMATIC)
4701 if(pFormatData->meAxisPosition == databar::NONE)
4703 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_AXIS_POSITION, OUString("none"));
4705 else
4707 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_AXIS_POSITION, OUString("middle"));
4711 OUStringBuffer aBuffer;
4712 ::sax::Converter::convertColor(aBuffer, pFormatData->maPositiveColor);
4713 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_POSITIVE_COLOR, aBuffer.makeStringAndClear());
4715 aBuffer.truncate();
4716 ::sax::Converter::convertColor(aBuffer, pFormatData->maAxisColor);
4717 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_AXIS_COLOR, aBuffer.makeStringAndClear());
4718 SvXMLElementExport aElementDataBar(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_BAR, true, true);
4721 if(pFormatData->mpLowerLimit->GetType() == COLORSCALE_FORMULA)
4723 OUString sFormula = pFormatData->mpLowerLimit->GetFormula(formula::FormulaGrammar::GRAM_ODFF);
4724 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, sFormula);
4726 else
4727 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, OUString::number(pFormatData->mpLowerLimit->GetValue()));
4728 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, getCondFormatEntryType(*pFormatData->mpLowerLimit));
4729 SvXMLElementExport aElementDataBarEntryLower(*this, XML_NAMESPACE_CALC_EXT, XML_FORMATTING_ENTRY, true, true);
4733 if(pFormatData->mpUpperLimit->GetType() == COLORSCALE_FORMULA)
4735 OUString sFormula = pFormatData->mpUpperLimit->GetFormula(formula::FormulaGrammar::GRAM_ODFF);
4736 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, sFormula);
4738 else
4739 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, OUString::number(pFormatData->mpUpperLimit->GetValue()));
4740 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, getCondFormatEntryType(*pFormatData->mpUpperLimit, false));
4741 SvXMLElementExport aElementDataBarEntryUpper(*this, XML_NAMESPACE_CALC_EXT, XML_FORMATTING_ENTRY, true, true);
4744 else if(pFormatEntry->GetType() == ScFormatEntry::Type::Iconset)
4746 const ScIconSetFormat& rIconSet = static_cast<const ScIconSetFormat&>(*pFormatEntry);
4747 OUString aIconSetName = OUString::createFromAscii(ScIconSetFormat::getIconSetName(rIconSet.GetIconSetData()->eIconSetType));
4748 AddAttribute( XML_NAMESPACE_CALC_EXT, XML_ICON_SET_TYPE, aIconSetName );
4749 if (rIconSet.GetIconSetData()->mbCustom)
4750 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_CUSTOM, OUString::boolean(true));
4752 SvXMLElementExport aElementColorScale(*this, XML_NAMESPACE_CALC_EXT, XML_ICON_SET, true, true);
4754 if (rIconSet.GetIconSetData()->mbCustom)
4756 for (const auto& [rType, rIndex] : rIconSet.GetIconSetData()->maCustomVector)
4758 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_CUSTOM_ICONSET_NAME, OUString::createFromAscii(ScIconSetFormat::getIconSetName(rType)));
4759 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_CUSTOM_ICONSET_INDEX, OUString::number(rIndex));
4760 SvXMLElementExport aCustomIcon(*this, XML_NAMESPACE_CALC_EXT, XML_CUSTOM_ICONSET, true, true);
4765 if(!rIconSet.GetIconSetData()->mbShowValue)
4766 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_SHOW_VALUE, XML_FALSE);
4767 for (auto const& it : rIconSet)
4769 if(it->GetType() == COLORSCALE_FORMULA)
4771 OUString sFormula = it->GetFormula(formula::FormulaGrammar::GRAM_ODFF);
4772 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, sFormula);
4774 else
4775 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_VALUE, OUString::number(it->GetValue()));
4777 AddAttribute(XML_NAMESPACE_CALC_EXT, XML_TYPE, getCondFormatEntryType(*it));
4778 SvXMLElementExport aElementColorScaleEntry(*this, XML_NAMESPACE_CALC_EXT, XML_FORMATTING_ENTRY, true, true);
4781 else if(pFormatEntry->GetType() == ScFormatEntry::Type::Date)
4783 const ScCondDateFormatEntry& rDateFormat = static_cast<const ScCondDateFormatEntry&>(*pFormatEntry);
4784 OUString aDateType = getDateStringForType(rDateFormat.GetDateType());
4785 OUString aStyleName = ScStyleNameConversion::DisplayToProgrammaticName(rDateFormat.GetStyleName(), SfxStyleFamily::Para );
4786 AddAttribute( XML_NAMESPACE_CALC_EXT, XML_STYLE, aStyleName);
4787 AddAttribute( XML_NAMESPACE_CALC_EXT, XML_DATE, aDateType);
4788 SvXMLElementExport aElementDateFormat(*this, XML_NAMESPACE_CALC_EXT, XML_DATE_IS, true, true);
4794 void ScXMLExport::WriteExternalRefCaches()
4796 if (!pDoc)
4797 return;
4799 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
4800 pRefMgr->resetSrcFileData(GetOrigFileName());
4801 sal_uInt16 nCount = pRefMgr->getExternalFileCount();
4802 for (sal_uInt16 nFileId = 0; nFileId < nCount; ++nFileId)
4804 const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
4805 if (!pUrl)
4806 continue;
4808 vector<OUString> aTabNames;
4809 pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
4810 if (aTabNames.empty())
4811 continue;
4813 for (const auto& rTabName : aTabNames)
4815 ScExternalRefCache::TableTypeRef pTable = pRefMgr->getCacheTable(nFileId, rTabName, false);
4816 if (!pTable.get() || !pTable->isReferenced())
4817 continue;
4819 AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, "'" + *pUrl + "'#" + rTabName);
4820 AddAttribute(XML_NAMESPACE_TABLE, XML_PRINT, GetXMLToken(XML_FALSE));
4821 AddAttribute(XML_NAMESPACE_TABLE, XML_STYLE_NAME, sExternalRefTabStyleName);
4822 SvXMLElementExport aElemTable(*this, XML_NAMESPACE_TABLE, XML_TABLE, true, true);
4824 const ScExternalRefManager::SrcFileData* pExtFileData = pRefMgr->getExternalFileData(nFileId);
4825 if (pExtFileData)
4827 OUString aRelUrl;
4828 if (!pExtFileData->maRelativeName.isEmpty())
4829 aRelUrl = pExtFileData->maRelativeName;
4830 else
4831 aRelUrl = GetRelativeReference(pExtFileData->maRelativeName);
4832 AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
4833 AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, aRelUrl);
4834 AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_NAME, rTabName);
4835 if (!pExtFileData->maFilterName.isEmpty())
4836 AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_NAME, pExtFileData->maFilterName);
4837 if (!pExtFileData->maFilterOptions.isEmpty())
4838 AddAttribute(XML_NAMESPACE_TABLE, XML_FILTER_OPTIONS, pExtFileData->maFilterOptions);
4839 AddAttribute(XML_NAMESPACE_TABLE, XML_MODE, XML_COPY_RESULTS_ONLY);
4841 SvXMLElementExport aElemTableSource(*this, XML_NAMESPACE_TABLE, XML_TABLE_SOURCE, true, true);
4844 // Determine maximum column count of used area, for repeated cells.
4845 SCCOL nMaxColsUsed = 1; // assume that there is at least one cell somewhere..
4846 vector<SCROW> aRows;
4847 pTable->getAllRows(aRows);
4848 for (SCROW nRow : aRows)
4850 vector<SCCOL> aCols;
4851 pTable->getAllCols(nRow, aCols);
4852 if (!aCols.empty())
4854 SCCOL nCol = aCols.back();
4855 if (nMaxColsUsed <= nCol)
4856 nMaxColsUsed = nCol + 1;
4860 // Column definitions have to be present to make a valid file
4862 if (nMaxColsUsed > 1)
4863 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
4864 OUString::number(nMaxColsUsed));
4865 SvXMLElementExport aElemColumn(*this, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true);
4868 // Write cache content for this table.
4869 SCROW nLastRow = 0;
4870 bool bFirstRow = true;
4871 for (SCROW nRow : aRows)
4873 if (bFirstRow)
4875 if (nRow > 0)
4877 if (nRow > 1)
4879 OUStringBuffer aVal;
4880 aVal.append(nRow);
4881 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, aVal.makeStringAndClear());
4883 SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true);
4884 OUStringBuffer aVal;
4885 aVal.append(static_cast<sal_Int32>(nMaxColsUsed));
4886 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
4887 SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
4890 else
4892 SCROW nRowGap = nRow - nLastRow;
4893 if (nRowGap > 1)
4895 if (nRowGap > 2)
4897 OUStringBuffer aVal;
4898 aVal.append(static_cast<sal_Int32>(nRowGap-1));
4899 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, aVal.makeStringAndClear());
4901 SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true);
4902 OUStringBuffer aVal;
4903 aVal.append(static_cast<sal_Int32>(nMaxColsUsed));
4904 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
4905 SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
4908 SvXMLElementExport aElemRow(*this, XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true);
4910 vector<SCCOL> aCols;
4911 pTable->getAllCols(nRow, aCols);
4912 SCCOL nLastCol = 0;
4913 bool bFirstCol = true;
4914 for (SCCOL nCol : aCols)
4916 if (bFirstCol)
4918 if (nCol > 0)
4920 if (nCol > 1)
4922 OUStringBuffer aVal;
4923 aVal.append(static_cast<sal_Int32>(nCol));
4924 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
4926 SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
4929 else
4931 SCCOL nColGap = nCol - nLastCol;
4932 if (nColGap > 1)
4934 if (nColGap > 2)
4936 OUStringBuffer aVal;
4937 aVal.append(static_cast<sal_Int32>(nColGap-1));
4938 AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, aVal.makeStringAndClear());
4940 SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
4944 // Write out this cell.
4945 sal_uInt32 nNumFmt = 0;
4946 ScExternalRefCache::TokenRef pToken = pTable->getCell(nCol, nRow, &nNumFmt);
4947 OUString aStrVal;
4948 if (pToken.get())
4950 sal_Int32 nIndex = GetNumberFormatStyleIndex(nNumFmt);
4951 if (nIndex >= 0)
4953 const OUString & aStyleName = pCellStyles->GetStyleNameByIndex(nIndex, true);
4954 AddAttribute(XML_NAMESPACE_TABLE, XML_STYLE_NAME, aStyleName);
4957 switch(pToken->GetType())
4959 case svDouble:
4961 AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT);
4962 OUStringBuffer aVal;
4963 aVal.append(pToken->GetDouble());
4964 aStrVal = aVal.makeStringAndClear();
4965 AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE, aStrVal);
4967 break;
4968 case svString:
4970 AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING);
4971 aStrVal = pToken->GetString().getString();
4973 break;
4974 default:
4978 SvXMLElementExport aElemCell(*this, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
4979 SvXMLElementExport aElemText(*this, XML_NAMESPACE_TEXT, XML_P, true, false);
4980 Characters(aStrVal);
4982 nLastCol = nCol;
4983 bFirstCol = false;
4985 nLastRow = nRow;
4986 bFirstRow = false;
4992 // core implementation
4993 void ScXMLExport::WriteConsolidation()
4995 if (pDoc)
4997 const ScConsolidateParam* pCons(pDoc->GetConsolidateDlgData());
4998 if( pCons )
5000 OUString sStrData;
5002 ScXMLConverter::GetStringFromFunction( sStrData, pCons->eFunction );
5003 AddAttribute( XML_NAMESPACE_TABLE, XML_FUNCTION, sStrData );
5005 sStrData.clear();
5006 for( sal_Int32 nIndex = 0; nIndex < pCons->nDataAreaCount; ++nIndex )
5007 ScRangeStringConverter::GetStringFromArea( sStrData, pCons->pDataAreas[ nIndex ], pDoc, FormulaGrammar::CONV_OOO, ' ', true );
5008 AddAttribute( XML_NAMESPACE_TABLE, XML_SOURCE_CELL_RANGE_ADDRESSES, sStrData );
5010 ScRangeStringConverter::GetStringFromAddress( sStrData, ScAddress( pCons->nCol, pCons->nRow, pCons->nTab ), pDoc, FormulaGrammar::CONV_OOO );
5011 AddAttribute( XML_NAMESPACE_TABLE, XML_TARGET_CELL_ADDRESS, sStrData );
5013 if( pCons->bByCol && !pCons->bByRow )
5014 AddAttribute( XML_NAMESPACE_TABLE, XML_USE_LABEL, XML_COLUMN );
5015 else if( !pCons->bByCol && pCons->bByRow )
5016 AddAttribute( XML_NAMESPACE_TABLE, XML_USE_LABEL, XML_ROW );
5017 else if( pCons->bByCol && pCons->bByRow )
5018 AddAttribute( XML_NAMESPACE_TABLE, XML_USE_LABEL, XML_BOTH );
5020 if( pCons->bReferenceData )
5021 AddAttribute( XML_NAMESPACE_TABLE, XML_LINK_TO_SOURCE_DATA, XML_TRUE );
5023 SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_CONSOLIDATION, true, true );
5028 SvXMLAutoStylePoolP* ScXMLExport::CreateAutoStylePool()
5030 return new ScXMLAutoStylePoolP(*this);
5033 XMLPageExport* ScXMLExport::CreatePageExport()
5035 return new XMLTableMasterPageExport( *this );
5038 void ScXMLExport::GetChangeTrackViewSettings(uno::Sequence<beans::PropertyValue>& rProps)
5040 ScChangeViewSettings* pViewSettings(GetDocument() ? GetDocument()->GetChangeViewSettings() : nullptr);
5041 if (pViewSettings)
5043 sal_Int32 nChangePos(rProps.getLength());
5044 rProps.realloc(nChangePos + 1);
5045 beans::PropertyValue* pProps(rProps.getArray());
5047 uno::Sequence<beans::PropertyValue> aChangeProps(SC_VIEWCHANGES_COUNT);
5048 beans::PropertyValue* pChangeProps(aChangeProps.getArray());
5049 pChangeProps[SC_SHOW_CHANGES].Name = "ShowChanges";
5050 pChangeProps[SC_SHOW_CHANGES].Value <<= pViewSettings->ShowChanges();
5051 pChangeProps[SC_SHOW_ACCEPTED_CHANGES].Name = "ShowAcceptedChanges";
5052 pChangeProps[SC_SHOW_ACCEPTED_CHANGES].Value <<= pViewSettings->IsShowAccepted();
5053 pChangeProps[SC_SHOW_REJECTED_CHANGES].Name = "ShowRejectedChanges";
5054 pChangeProps[SC_SHOW_REJECTED_CHANGES].Value <<= pViewSettings->IsShowRejected();
5055 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME].Name = "ShowChangesByDatetime";
5056 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME].Value <<= pViewSettings->HasDate();
5057 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_MODE].Name = "ShowChangesByDatetimeMode";
5058 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_MODE].Value <<= static_cast<sal_Int16>(pViewSettings->GetTheDateMode());
5059 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_FIRST_DATETIME].Name = "ShowChangesByDatetimeFirstDatetime";
5060 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_FIRST_DATETIME].Value <<= pViewSettings->GetTheFirstDateTime().GetUNODateTime();
5061 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_SECOND_DATETIME].Name = "ShowChangesByDatetimeSecondDatetime";
5062 pChangeProps[SC_SHOW_CHANGES_BY_DATETIME_SECOND_DATETIME].Value <<= pViewSettings->GetTheLastDateTime().GetUNODateTime();
5063 pChangeProps[SC_SHOW_CHANGES_BY_AUTHOR].Name = "ShowChangesByAuthor";
5064 pChangeProps[SC_SHOW_CHANGES_BY_AUTHOR].Value <<= pViewSettings->HasAuthor();
5065 pChangeProps[SC_SHOW_CHANGES_BY_AUTHOR_NAME].Name = "ShowChangesByAuthorName";
5066 pChangeProps[SC_SHOW_CHANGES_BY_AUTHOR_NAME].Value <<= pViewSettings->GetTheAuthorToShow();
5067 pChangeProps[SC_SHOW_CHANGES_BY_COMMENT].Name = "ShowChangesByComment";
5068 pChangeProps[SC_SHOW_CHANGES_BY_COMMENT].Value <<= pViewSettings->HasComment();
5069 pChangeProps[SC_SHOW_CHANGES_BY_COMMENT_TEXT].Name = "ShowChangesByCommentText";
5070 pChangeProps[SC_SHOW_CHANGES_BY_COMMENT_TEXT].Value <<= pViewSettings->GetTheComment();
5071 pChangeProps[SC_SHOW_CHANGES_BY_RANGES].Name = "ShowChangesByRanges";
5072 pChangeProps[SC_SHOW_CHANGES_BY_RANGES].Value <<= pViewSettings->HasRange();
5073 OUString sRangeList;
5074 ScRangeStringConverter::GetStringFromRangeList(sRangeList, &(pViewSettings->GetTheRangeList()), GetDocument(), FormulaGrammar::CONV_OOO);
5075 pChangeProps[SC_SHOW_CHANGES_BY_RANGES_LIST].Name = "ShowChangesByRangesList";
5076 pChangeProps[SC_SHOW_CHANGES_BY_RANGES_LIST].Value <<= sRangeList;
5078 pProps[nChangePos].Name = "TrackedChangesViewSettings";
5079 pProps[nChangePos].Value <<= aChangeProps;
5083 void ScXMLExport::GetViewSettings(uno::Sequence<beans::PropertyValue>& rProps)
5085 if (GetModel().is())
5087 rProps.realloc(4);
5088 beans::PropertyValue* pProps(rProps.getArray());
5089 ScModelObj* pDocObj(ScModelObj::getImplementation( GetModel() ));
5090 if (pDocObj)
5092 SfxObjectShell* pEmbeddedObj = pDocObj->GetEmbeddedObject();
5093 if (pEmbeddedObj)
5095 tools::Rectangle aRect(pEmbeddedObj->GetVisArea());
5096 sal_uInt16 i(0);
5097 pProps[i].Name = "VisibleAreaTop";
5098 pProps[i].Value <<= static_cast<sal_Int32>(aRect.getY());
5099 pProps[++i].Name = "VisibleAreaLeft";
5100 pProps[i].Value <<= static_cast<sal_Int32>(aRect.getX());
5101 pProps[++i].Name = "VisibleAreaWidth";
5102 pProps[i].Value <<= static_cast<sal_Int32>(aRect.getWidth());
5103 pProps[++i].Name = "VisibleAreaHeight";
5104 pProps[i].Value <<= static_cast<sal_Int32>(aRect.getHeight());
5108 GetChangeTrackViewSettings(rProps);
5111 void ScXMLExport::GetConfigurationSettings(uno::Sequence<beans::PropertyValue>& rProps)
5113 if (GetModel().is())
5115 uno::Reference <lang::XMultiServiceFactory> xMultiServiceFactory(GetModel(), uno::UNO_QUERY);
5116 if (xMultiServiceFactory.is())
5118 uno::Reference <beans::XPropertySet> xProperties(xMultiServiceFactory->createInstance("com.sun.star.comp.SpreadsheetSettings"), uno::UNO_QUERY);
5119 if (xProperties.is())
5120 SvXMLUnitConverter::convertPropertySet(rProps, xProperties);
5122 sal_Int32 nPropsToAdd = 0;
5123 OUStringBuffer aTrackedChangesKey;
5124 if (GetDocument() && GetDocument()->GetChangeTrack() && GetDocument()->GetChangeTrack()->IsProtected())
5126 ::comphelper::Base64::encode(aTrackedChangesKey,
5127 GetDocument()->GetChangeTrack()->GetProtection());
5128 if (!aTrackedChangesKey.isEmpty())
5129 ++nPropsToAdd;
5132 bool bVBACompat = false;
5133 uno::Reference <container::XNameAccess> xCodeNameAccess;
5134 OSL_ENSURE( pDoc, "ScXMLExport::GetConfigurationSettings - no ScDocument!" );
5135 if( pDoc && pDoc->IsInVBAMode() )
5137 // VBA compatibility mode
5138 bVBACompat = true;
5139 ++nPropsToAdd;
5140 // code names
5141 xCodeNameAccess = new XMLCodeNameProvider( pDoc );
5142 if( xCodeNameAccess->hasElements() )
5143 ++nPropsToAdd;
5144 else
5145 xCodeNameAccess.clear();
5148 if( nPropsToAdd > 0 )
5150 sal_Int32 nCount(rProps.getLength());
5151 rProps.realloc(nCount + nPropsToAdd);
5152 if (!aTrackedChangesKey.isEmpty())
5154 rProps[nCount].Name = "TrackedChangesProtectionKey";
5155 rProps[nCount].Value <<= aTrackedChangesKey.makeStringAndClear();
5156 ++nCount;
5158 if( bVBACompat )
5160 rProps[nCount].Name = "VBACompatibilityMode";
5161 rProps[nCount].Value <<= bVBACompat;
5162 ++nCount;
5164 if( xCodeNameAccess.is() )
5166 rProps[nCount].Name = "ScriptConfiguration";
5167 rProps[nCount].Value <<= xCodeNameAccess;
5168 ++nCount;
5175 XMLShapeExport* ScXMLExport::CreateShapeExport()
5177 return new ScXMLShapeExport(*this);
5180 XMLNumberFormatAttributesExportHelper* ScXMLExport::GetNumberFormatAttributesExportHelper()
5182 if (!pNumberFormatAttributesExportHelper)
5183 pNumberFormatAttributesExportHelper.reset(new XMLNumberFormatAttributesExportHelper(GetNumberFormatsSupplier(), *this ));
5184 return pNumberFormatAttributesExportHelper.get();
5187 void ScXMLExport::CollectUserDefinedNamespaces(const SfxItemPool* pPool, sal_uInt16 nAttrib)
5189 sal_uInt32 nItems(pPool->GetItemCount2( nAttrib ));
5190 for( sal_uInt32 i = 0; i < nItems; ++i )
5192 const SfxPoolItem* pItem;
5193 if( nullptr != (pItem = pPool->GetItem2( nAttrib, i ) ) )
5195 const SvXMLAttrContainerItem *pUnknown(static_cast<const SvXMLAttrContainerItem *>(pItem));
5196 if( pUnknown->GetAttrCount() > 0 )
5198 sal_uInt16 nIdx(pUnknown->GetFirstNamespaceIndex());
5199 while( USHRT_MAX != nIdx )
5201 if( (XML_NAMESPACE_UNKNOWN_FLAG & nIdx) != 0 )
5203 const OUString& rPrefix = pUnknown->GetPrefix( nIdx );
5204 // Add namespace declaration for unknown attributes if
5205 // there aren't existing ones for the prefix used by the
5206 // attributes
5207 GetNamespaceMap_().Add( rPrefix,
5208 pUnknown->GetNamespace( nIdx ) );
5210 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 uno::Reference< lang::XUnoTunnel > xObjShellTunnel( xModel, uno::UNO_QUERY );
5245 SfxObjectShell* pFoundShell = reinterpret_cast<SfxObjectShell*>( xObjShellTunnel.is() ? xObjShellTunnel->getSomething(SfxObjectShell::getUnoTunnelId()) : 0 );
5246 if ( pFoundShell && ooo::vba::isAlienExcelDoc( *pFoundShell ) )
5248 xRowStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScFromXLSRowStylesProperties, xScPropHdlFactory, true);
5249 xRowStylesExportPropertySetMapper = new ScXMLRowExportPropertyMapper(xRowStylesPropertySetMapper);
5250 GetAutoStylePool()->SetFamilyPropSetMapper( XML_STYLE_FAMILY_TABLE_ROW,
5251 xRowStylesExportPropertySetMapper );
5254 CollectUserDefinedNamespaces(GetDocument()->GetPool(), ATTR_USERDEF);
5255 CollectUserDefinedNamespaces(GetDocument()->GetEditPool(), EE_PARA_XMLATTRIBS);
5256 CollectUserDefinedNamespaces(GetDocument()->GetEditPool(), EE_CHAR_XMLATTRIBS);
5257 ScDrawLayer* pDrawLayer = GetDocument()->GetDrawLayer();
5258 if (pDrawLayer)
5260 CollectUserDefinedNamespaces(&pDrawLayer->GetItemPool(), EE_PARA_XMLATTRIBS);
5261 CollectUserDefinedNamespaces(&pDrawLayer->GetItemPool(), EE_CHAR_XMLATTRIBS);
5262 CollectUserDefinedNamespaces(&pDrawLayer->GetItemPool(), SDRATTR_XMLATTRIBUTES);
5265 // sheet events use officeooo namespace
5266 if( (getExportFlags() & SvXMLExportFlags::CONTENT) &&
5267 getDefaultVersion() >= SvtSaveOptions::ODFVER_012 )
5269 bool bAnySheetEvents = false;
5270 SCTAB nTabCount = pDoc->GetTableCount();
5271 for (SCTAB nTab=0; nTab<nTabCount; ++nTab)
5272 if (pDoc->GetSheetEvents(nTab))
5273 bAnySheetEvents = true;
5274 if (bAnySheetEvents)
5275 GetNamespaceMap_().Add(
5276 GetXMLToken( XML_NP_OFFICE_EXT ),
5277 GetXMLToken( XML_N_OFFICE_EXT ),
5278 XML_NAMESPACE_OFFICE_EXT );
5282 return SvXMLExport::exportDoc( eClass );
5285 // XExporter
5286 void SAL_CALL ScXMLExport::setSourceDocument( const uno::Reference<lang::XComponent>& xComponent )
5288 SolarMutexGuard aGuard;
5289 SvXMLExport::setSourceDocument( xComponent );
5291 pDoc = ScXMLConverter::GetScDocument( GetModel() );
5292 OSL_ENSURE( pDoc, "ScXMLExport::setSourceDocument - no ScDocument!" );
5293 if (!pDoc)
5294 throw lang::IllegalArgumentException();
5296 // create ScChangeTrackingExportHelper after document is known
5297 pChangeTrackingExportHelper.reset(new ScChangeTrackingExportHelper(*this));
5299 // Set the document's storage grammar corresponding to the ODF version that
5300 // is to be written.
5301 SvtSaveOptions::ODFDefaultVersion meODFDefaultVersion = getDefaultVersion();
5302 switch (meODFDefaultVersion)
5304 // ODF 1.0 and 1.1 use GRAM_PODF, everything later or unspecified GRAM_ODFF
5305 case SvtSaveOptions::ODFVER_010:
5306 case SvtSaveOptions::ODFVER_011:
5307 pDoc->SetStorageGrammar( formula::FormulaGrammar::GRAM_PODF);
5308 break;
5309 default:
5310 pDoc->SetStorageGrammar( formula::FormulaGrammar::GRAM_ODFF);
5314 // XFilter
5315 sal_Bool SAL_CALL ScXMLExport::filter( const css::uno::Sequence< css::beans::PropertyValue >& aDescriptor )
5317 SolarMutexGuard aGuard;
5318 if (pDoc)
5319 pDoc->EnableIdle(false);
5320 bool bReturn(SvXMLExport::filter(aDescriptor));
5321 if (pDoc)
5322 pDoc->EnableIdle(true);
5323 return bReturn;
5326 void SAL_CALL ScXMLExport::cancel()
5328 SolarMutexGuard aGuard;
5329 if (pDoc)
5330 pDoc->EnableIdle(true);
5331 SvXMLExport::cancel();
5334 // XInitialization
5335 void SAL_CALL ScXMLExport::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
5337 SolarMutexGuard aGuard;
5338 SvXMLExport::initialize(aArguments);
5341 // XUnoTunnel
5342 sal_Int64 SAL_CALL ScXMLExport::getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier )
5344 SolarMutexGuard aGuard;
5345 return SvXMLExport::getSomething(aIdentifier);
5348 void ScXMLExport::DisposingModel()
5350 SvXMLExport::DisposingModel();
5351 pDoc = nullptr;
5352 xCurrentTable = nullptr;
5355 void ScXMLExport::SetSharedData(std::unique_ptr<ScMySharedData> pTemp) { pSharedData = std::move(pTemp); }
5357 std::unique_ptr<ScMySharedData> ScXMLExport::ReleaseSharedData() { return std::move(pSharedData); }
5358 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */