LibreOffice Module sc (master)  1
xmlexprt.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 #include <sal/log.hxx>
22 
23 #include "xmlexprt.hxx"
24 #include "XMLConverter.hxx"
25 #include "xmlstyle.hxx"
26 #include <unonames.hxx>
27 #include <document.hxx>
28 #include <olinetab.hxx>
29 #include <formulacell.hxx>
30 #include <rangenam.hxx>
32 #include <drwlayer.hxx>
33 #include "XMLExportDataPilot.hxx"
35 #include "XMLExportDDELinks.hxx"
36 #include "XMLExportIterator.hxx"
40 #include <sheetdata.hxx>
41 #include <docoptio.hxx>
42 #include "XMLExportSharedData.hxx"
43 #include <chgviset.hxx>
44 #include <docuno.hxx>
45 #include <textuno.hxx>
46 #include <chartlis.hxx>
47 #include <scitems.hxx>
48 #include <docpool.hxx>
49 #include <userdat.hxx>
50 #include <chgtrack.hxx>
51 #include <rangeutl.hxx>
52 #include <postit.hxx>
53 #include <externalrefmgr.hxx>
54 #include <editutil.hxx>
55 #include <tabprotection.hxx>
56 #include "cachedattraccess.hxx"
57 #include <colorscale.hxx>
58 #include <conditio.hxx>
59 #include <cellvalue.hxx>
60 #include <stylehelper.hxx>
61 #include <edittextiterator.hxx>
62 #include "editattributemap.hxx"
63 #include <arealink.hxx>
64 #include <datastream.hxx>
65 #include <documentlinkmgr.hxx>
66 #include <tokenstringcontext.hxx>
67 #include <cellform.hxx>
68 #include <datamapper.hxx>
69 #include <datatransformation.hxx>
70 
71 #include <xmloff/xmltoken.hxx>
72 #include <xmloff/xmlnamespace.hxx>
73 #include <xmloff/xmluconv.hxx>
74 #include <xmloff/namespacemap.hxx>
75 #include <xmloff/families.hxx>
76 #include <xmloff/numehelp.hxx>
77 #include <xmloff/txtparae.hxx>
78 #include <editeng/autokernitem.hxx>
81 #include <editeng/colritem.hxx>
82 #include <editeng/contouritem.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>
105 
106 #include <sax/tools/converter.hxx>
107 #include <tools/fldunit.hxx>
108 
109 #include <rtl/ustring.hxx>
110 
111 #include <tools/color.hxx>
112 #include <rtl/math.hxx>
113 #include <svl/zforlist.hxx>
114 #include <svx/unoshape.hxx>
115 #include <comphelper/base64.hxx>
116 #include <comphelper/extract.hxx>
117 #include <svx/svdoashp.hxx>
118 #include <svx/svdobj.hxx>
119 #include <svx/svdocapt.hxx>
120 #include <vcl/svapp.hxx>
121 #include <svx/unoapi.hxx>
124 
126 #include <com/sun/star/beans/XPropertySet.hpp>
127 #include <com/sun/star/container/XNamed.hpp>
128 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
129 #include <com/sun/star/form/XFormsSupplier2.hpp>
130 #include <com/sun/star/io/XActiveDataSource.hpp>
131 #include <com/sun/star/io/XSeekable.hpp>
132 #include <com/sun/star/sheet/XUsedAreaCursor.hpp>
133 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
134 #include <com/sun/star/sheet/XPrintAreas.hpp>
135 #include <com/sun/star/sheet/XUniqueCellFormatRangesSupplier.hpp>
136 #include <com/sun/star/sheet/XLabelRange.hpp>
137 #include <com/sun/star/sheet/NamedRangeFlag.hpp>
138 #include <com/sun/star/sheet/XSheetCellCursor.hpp>
139 #include <com/sun/star/sheet/XSheetCellRanges.hpp>
140 #include <com/sun/star/sheet/XSheetLinkable.hpp>
141 #include <com/sun/star/sheet/GlobalSheetSettings.hpp>
142 #include <com/sun/star/table/XColumnRowRange.hpp>
143 #include <com/sun/star/util/XProtectable.hpp>
144 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
145 #include <com/sun/star/chart2/XChartDocument.hpp>
146 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
147 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
148 
149 #include <com/sun/star/document/XDocumentProperties.hpp>
150 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
151 
152 #include "XMLCodeNameProvider.hxx"
153 
154 #include <sfx2/linkmgr.hxx>
155 #include <sfx2/objsh.hxx>
156 
157 #include <memory>
158 #include <vector>
160 #include <officecfg/Office/Common.hxx>
161 
162 namespace com::sun::star::uno { class XComponentContext; }
163 
164 
165 
167 #define SC_LAYERID "LayerID"
168 
169 #define SC_VIEWCHANGES_COUNT 13
170 #define SC_SHOW_CHANGES 0
171 #define SC_SHOW_ACCEPTED_CHANGES 1
172 #define SC_SHOW_REJECTED_CHANGES 2
173 #define SC_SHOW_CHANGES_BY_DATETIME 3
174 #define SC_SHOW_CHANGES_BY_DATETIME_MODE 4
175 #define SC_SHOW_CHANGES_BY_DATETIME_FIRST_DATETIME 5
176 #define SC_SHOW_CHANGES_BY_DATETIME_SECOND_DATETIME 6
177 #define SC_SHOW_CHANGES_BY_AUTHOR 7
178 #define SC_SHOW_CHANGES_BY_AUTHOR_NAME 8
179 #define SC_SHOW_CHANGES_BY_COMMENT 9
180 #define SC_SHOW_CHANGES_BY_COMMENT_TEXT 10
181 #define SC_SHOW_CHANGES_BY_RANGES 11
182 #define SC_SHOW_CHANGES_BY_RANGES_LIST 12
183 
184 using namespace formula;
185 using namespace com::sun::star;
186 using namespace xmloff::token;
187 using ::std::vector;
188 using ::com::sun::star::uno::UNO_QUERY;
189 
190 namespace
191 {
192 OUString lcl_RangeSequenceToString(
193  const uno::Sequence< OUString > & rRanges,
194  const uno::Reference< chart2::data::XRangeXMLConversion > & xFormatConverter )
195 {
196  OUStringBuffer aResult;
197  const sal_Int32 nMaxIndex( rRanges.getLength() - 1 );
198  const sal_Unicode cSep(' ');
199  for( sal_Int32 i=0; i<=nMaxIndex; ++i )
200  {
201  OUString aRange( rRanges[i] );
202  if( xFormatConverter.is())
203  aRange = xFormatConverter->convertRangeToXML( aRange );
204  aResult.append( aRange );
205  if( i < nMaxIndex )
206  aResult.append( cSep );
207  }
208  return aResult.makeStringAndClear();
209 }
210 
211 OUString lcl_GetFormattedString(ScDocument* pDoc, const ScRefCellValue& rCell, const ScAddress& rAddr)
212 {
213  // return text/edit cell string content, with line feeds in edit cells
214 
215  if (!pDoc)
216  return EMPTY_OUSTRING;
217 
218  switch (rCell.meType)
219  {
220  case CELLTYPE_STRING:
221  {
222  OUString aStr;
223  const Color* pColor;
224  SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
225 
226  sal_uInt32 nFormat = pDoc->GetNumberFormat(rAddr);
227  ScCellFormat::GetString(rCell, nFormat, aStr, &pColor, *pFormatter, *pDoc);
228  return aStr;
229  }
230  case CELLTYPE_EDIT:
231  {
232  const EditTextObject* pData = rCell.mpEditText;
233  if (!pData)
234  return EMPTY_OUSTRING;
235 
236  EditEngine& rEngine = pDoc->GetEditEngine();
237  rEngine.SetText(*pData);
238  return rEngine.GetText();
239  }
240  break;
241  default:
242  ;
243  }
244 
245  return EMPTY_OUSTRING;
246 }
247 
248 } // anonymous namespace
249 
250 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
251 Calc_XMLExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
252 {
253  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLExporter", SvXMLExportFlags::ALL));
254 }
255 
256 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
257 Calc_XMLMetaExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
258 {
259  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLMetaExporter", SvXMLExportFlags::META));
260 }
261 
262 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
263 Calc_XMLStylesExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
264 {
265  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLStylesExporter", SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS));
266 }
267 
268 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
269 Calc_XMLContentExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
270 {
271  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLContentExporter", SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::FONTDECLS));
272 }
273 
274 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
275 Calc_XMLSettingsExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
276 {
277  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLSettingsExporter", SvXMLExportFlags::SETTINGS));
278 }
279 
280 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
281 Calc_XMLOasisExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
282 {
283  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisExporter", SvXMLExportFlags::ALL|SvXMLExportFlags::OASIS));
284 }
285 
286 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
287 Calc_XMLOasisMetaExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
288 {
289  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisMetaExporter", SvXMLExportFlags::META|SvXMLExportFlags::OASIS));
290 }
291 
292 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
293 Calc_XMLOasisStylesExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
294 {
295  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisStylesExporter", SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::OASIS));
296 }
297 
298 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
299 Calc_XMLOasisContentExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
300 {
301  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisContentExporter", SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::OASIS));
302 }
303 
304 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
305 Calc_XMLOasisSettingsExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
306 {
307  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisSettingsExporter", SvXMLExportFlags::SETTINGS|SvXMLExportFlags::OASIS));
308 }
309 
310 namespace {
311 
312 class ScXMLShapeExport : public XMLShapeExport
313 {
314 public:
315  explicit ScXMLShapeExport(SvXMLExport& rExp) : XMLShapeExport(rExp) {}
316 
318  virtual void onExport( const uno::Reference < drawing::XShape >& xShape ) override;
319 };
320 
321 }
322 
323 void ScXMLShapeExport::onExport( const uno::Reference < drawing::XShape >& xShape )
324 {
325  uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
326  if( xShapeProp.is() )
327  {
328  sal_Int16 nLayerID = 0;
329  if( (xShapeProp->getPropertyValue( SC_LAYERID ) >>= nLayerID) && (SdrLayerID(nLayerID) == SC_LAYER_BACK) )
330  GetExport().AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_BACKGROUND, XML_TRUE);
331  }
332 }
333 
335 {
336  css::uno::Reference<css::sheet::XGlobalSheetSettings> xProperties =
337  css::sheet::GlobalSheetSettings::create( comphelper::getProcessComponentContext() );
338  const FieldUnit eFieldUnit = static_cast<FieldUnit>(xProperties->getMetric());
339  return SvXMLUnitConverter::GetMeasureUnit(eFieldUnit);
340 }
341 
342 constexpr OUStringLiteral gsLayerID( u"" SC_LAYERID );
343 
345  const css::uno::Reference< css::uno::XComponentContext >& rContext,
346  OUString const & implementationName, SvXMLExportFlags nExportFlag)
347 : SvXMLExport(
348  rContext, implementationName, GetMeasureUnit(), XML_SPREADSHEET, nExportFlag ),
349  pDoc(nullptr),
350  nSourceStreamPos(0),
351  aTableStyles(),
352  pCurrentCell(nullptr),
353  nOpenRow(-1),
354  nProgressCount(0),
355  nCurrentTable(0),
356  bHasRowHeader(false),
357  bRowHeaderOpen(false)
358 {
359  if (getExportFlags() & SvXMLExportFlags::CONTENT)
360  {
363  pColumnStyles.reset( new ScColumnStyles() );
364  pRowStyles.reset( new ScRowStyles() );
365  pRowFormatRanges.reset( new ScRowFormatRanges() );
368  mpCellsItr.reset(new ScMyNotEmptyCellsIterator(*this));
369  pDefaults.reset( new ScMyDefaultStyles );
370  }
371  pCellStyles.reset( new ScFormatRangeStyles() );
372 
373  // document is not set here - create ScChangeTrackingExportHelper later
374 
385 
386  GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_CELL, XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME,
388  GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_COLUMN, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_NAME,
390  GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_ROW, XML_STYLE_FAMILY_TABLE_ROW_STYLES_NAME,
392  GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_TABLE, XML_STYLE_FAMILY_TABLE_TABLE_STYLES_NAME,
394 
395  if( !(getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT)) )
396  return;
397 
398  // This name is reserved for the external ref cache tables. This
399  // should not conflict with user-defined styles since this name is
400  // used for a table style which is not available in the UI.
401  sExternalRefTabStyleName = "ta_extref";
402  GetAutoStylePool()->RegisterName(XmlStyleFamily::TABLE_TABLE, sExternalRefTabStyleName);
403 
416 }
417 
419 {
420  pGroupColumns.reset();
421  pGroupRows.reset();
422  pColumnStyles.reset();
423  pRowStyles.reset();
424  pCellStyles.reset();
425  pRowFormatRanges.reset();
426  pMergedRangesContainer.reset();
427  pValidationsContainer.reset();
429  pDefaults.reset();
431 }
432 
433 void ScXMLExport::SetSourceStream( const uno::Reference<io::XInputStream>& xNewStream )
434 {
435  xSourceStream = xNewStream;
436 
437  if ( !xSourceStream.is() )
438  return;
439 
440  // make sure it's a plain UTF-8 stream as written by OOo itself
441 
442  const char pXmlHeader[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
443  sal_Int32 nLen = strlen(pXmlHeader);
444 
445  uno::Sequence<sal_Int8> aFileStart(nLen);
446  sal_Int32 nRead = xSourceStream->readBytes( aFileStart, nLen );
447 
448  if ( nRead != nLen || memcmp( aFileStart.getConstArray(), pXmlHeader, nLen ) != 0 )
449  {
450  // invalid - ignore stream, save normally
451  xSourceStream.clear();
452  }
453  else
454  {
455  // keep track of the bytes already read
456  nSourceStreamPos = nRead;
457 
458  const ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(GetModel())->GetSheetSaveData();
459  if (pSheetData)
460  {
461  // add the loaded namespaces to the name space map
462 
463  if ( !pSheetData->AddLoadedNamespaces( GetNamespaceMap_() ) )
464  {
465  // conflicts in the namespaces - ignore the stream, save normally
466  xSourceStream.clear();
467  }
468  }
469  }
470 }
471 
472 sal_Int32 ScXMLExport::GetNumberFormatStyleIndex(sal_Int32 nNumFmt) const
473 {
474  NumberFormatIndexMap::const_iterator itr = aNumFmtIndexMap.find(nNumFmt);
475  if (itr == aNumFmtIndexMap.end())
476  return -1;
477 
478  return itr->second;
479 }
480 
481 void ScXMLExport::CollectSharedData(SCTAB& nTableCount, sal_Int32& nShapesCount)
482 {
483  if (!GetModel().is())
484  return;
485 
486  uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc(GetModel(), uno::UNO_QUERY);
487  if (!xSpreadDoc.is())
488  return;
489 
490  uno::Reference<container::XIndexAccess> xIndex(xSpreadDoc->getSheets(), uno::UNO_QUERY);
491  if (!xIndex.is())
492  return;
493 
494  nTableCount = xIndex->getCount();
495  if (!pSharedData)
496  pSharedData.reset(new ScMySharedData(nTableCount));
497 
498  pCellStyles->AddNewTable(nTableCount - 1);
499 
500  for (SCTAB nTable = 0; nTable < nTableCount; ++nTable)
501  {
502  nCurrentTable = sal::static_int_cast<sal_uInt16>(nTable);
503  uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xIndex->getByIndex(nTable), uno::UNO_QUERY);
504  if (!xDrawPageSupplier.is())
505  continue;
506 
507  uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage());
508  ScMyDrawPage aDrawPage;
509  aDrawPage.bHasForms = false;
510  aDrawPage.xDrawPage.set(xDrawPage);
511  pSharedData->AddDrawPage(aDrawPage, nTable);
512  if (!xDrawPage.is())
513  continue;
514 
515  sal_Int32 nShapes = xDrawPage->getCount();
516  for (sal_Int32 nShape = 0; nShape < nShapes; ++nShape)
517  {
518  uno::Reference<drawing::XShape> xShape(xDrawPage->getByIndex(nShape), uno::UNO_QUERY);
519  if (!xShape.is())
520  continue;
521 
522  uno::Reference<beans::XPropertySet> xShapeProp(xShape, uno::UNO_QUERY);
523  if (!xShapeProp.is())
524  continue;
525 
526  sal_Int16 nLayerID = 0;
527  bool bExtracted = xShapeProp->getPropertyValue(gsLayerID) >>= nLayerID;
528  if (!bExtracted)
529  continue;
530 
531  if ((SdrLayerID(nLayerID) == SC_LAYER_INTERN) || (SdrLayerID(nLayerID) == SC_LAYER_HIDDEN))
532  {
533  CollectInternalShape(xShape);
534  continue;
535  }
536 
537  ++nShapesCount;
538 
539  SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape(xShape);
540  if (!pSdrObj)
541  continue;
542 
543  if (ScDrawObjData *pAnchor = ScDrawLayer::GetNonRotatedObjData(pSdrObj))
544  {
545  ScMyShape aMyShape;
546  aMyShape.aAddress = pAnchor->maStart;
547  SAL_WARN_IF(aMyShape.aAddress.Tab() != nTable, "sc", "not anchored to current sheet!");
548  aMyShape.aAddress.SetTab(nTable);
549  aMyShape.aEndAddress = pAnchor->maEnd;
550  aMyShape.aEndAddress.SetTab( nTable );
551  aMyShape.nEndX = pAnchor->maEndOffset.X();
552  aMyShape.nEndY = pAnchor->maEndOffset.Y();
553  aMyShape.xShape = xShape;
554  aMyShape.bResizeWithCell = ScDrawLayer::IsResizeWithCell(*pSdrObj);
555  pSharedData->AddNewShape(aMyShape);
556  pSharedData->SetLastColumn(nTable, pAnchor->maStart.Col());
557  pSharedData->SetLastRow(nTable, pAnchor->maStart.Row());
558  }
559  else
560  pSharedData->AddTableShape(nTable, xShape);
561  }
562  }
563 }
564 
566 {
567  // #i84077# To avoid compiler warnings about uninitialized aShapeItr,
568  // it's initialized using this dummy list. The iterator contains shapes
569  // from all sheets, so it can't be declared inside the nTable loop where
570  // it is used.
571  ScMyShapeList aDummyInitList;
572 
573  pSharedData->SortShapesContainer();
574  pSharedData->SortNoteShapes();
575  const ScMyShapeList* pShapeList(nullptr);
576  ScMyShapeList::const_iterator aShapeItr = aDummyInitList.end();
577  if (pSharedData->GetShapesContainer())
578  {
579  pShapeList = &pSharedData->GetShapesContainer()->GetShapes();
580  aShapeItr = pShapeList->begin();
581  }
582  if (pSharedData->HasDrawPage())
583  {
584  for (SCTAB nTable = 0; nTable < nTableCount; ++nTable)
585  {
586  uno::Reference<drawing::XDrawPage> xDrawPage(pSharedData->GetDrawPage(nTable));
587 
588  if (xDrawPage.is())
589  {
590  GetShapeExport()->seekShapes(xDrawPage);
591  uno::Reference< form::XFormsSupplier2 > xFormsSupplier( xDrawPage, uno::UNO_QUERY );
592  if( xFormsSupplier.is() && xFormsSupplier->hasForms() )
593  {
594  GetFormExport()->examineForms(xDrawPage);
595  pSharedData->SetDrawPageHasForms(nTable, true);
596  }
597  ScMyTableShapes* pTableShapes(pSharedData->GetTableShapes());
598  if (pTableShapes)
599  {
600  for (const auto& rxShape : (*pTableShapes)[nTable])
601  {
602  GetShapeExport()->collectShapeAutoStyles(rxShape);
603  IncrementProgressBar(false);
604  }
605  }
606  if (pShapeList)
607  {
608  ScMyShapeList::const_iterator aEndItr(pShapeList->end());
609  while ( aShapeItr != aEndItr && ( aShapeItr->aAddress.Tab() == nTable ) )
610  {
611  GetShapeExport()->collectShapeAutoStyles(aShapeItr->xShape);
612  IncrementProgressBar(false);
613  ++aShapeItr;
614  }
615  }
616  if (pSharedData->GetNoteShapes())
617  {
618  const ScMyNoteShapeList& rNoteShapes = pSharedData->GetNoteShapes()->GetNotes();
619  for (const auto& rNoteShape : rNoteShapes)
620  {
621  if ( rNoteShape.aPos.Tab() == nTable )
622  GetShapeExport()->collectShapeAutoStyles(rNoteShape.xShape);
623  }
624  }
625  }
626  }
627  }
628  pSharedData->SortNoteShapes(); // sort twice, because some more shapes are added
629 }
630 
632 {
633  sal_Int32 nCellCount(pDoc ? pDoc->GetCellCount() : 0);
634  SCTAB nTableCount(0);
635  sal_Int32 nShapesCount(0);
636  GetAutoStylePool()->ClearEntries();
637  CollectSharedData(nTableCount, nShapesCount);
638 
639  uno::Sequence<beans::NamedValue> stats
640  {
641  { "TableCount", uno::makeAny(static_cast<sal_Int32>(nTableCount)) },
642  { "CellCount", uno::makeAny(nCellCount) },
643  { "ObjectCount", uno::makeAny(nShapesCount) }
644  };
645 
646  // update document statistics at the model
647  uno::Reference<document::XDocumentPropertiesSupplier> xPropSup(GetModel(),
648  uno::UNO_QUERY_THROW);
649  uno::Reference<document::XDocumentProperties> xDocProps(
650  xPropSup->getDocumentProperties());
651  if (xDocProps.is()) {
652  xDocProps->setDocumentStatistics(stats);
653  }
654 
655  // export document properties
657 }
658 
660 {
661  GetFontAutoStylePool(); // make sure the pool is created
663 }
664 
665 table::CellRangeAddress ScXMLExport::GetEndAddress(const uno::Reference<sheet::XSpreadsheet>& xTable)
666 {
667  table::CellRangeAddress aCellAddress;
668  uno::Reference<sheet::XSheetCellCursor> xCursor(xTable->createCursor());
669  uno::Reference<sheet::XUsedAreaCursor> xUsedArea (xCursor, uno::UNO_QUERY);
670  uno::Reference<sheet::XCellRangeAddressable> xCellAddress (xCursor, uno::UNO_QUERY);
671  if (xUsedArea.is() && xCellAddress.is())
672  {
673  xUsedArea->gotoEndOfUsedArea(true);
674  aCellAddress = xCellAddress->getRangeAddress();
675  }
676  return aCellAddress;
677 }
678 
680 {
681  if (pDoc->GetLinkManager())
682  {
683  const sfx2::SvBaseLinks& rLinks = pDoc->GetLinkManager()->GetLinks();
684  for (const auto & rLink : rLinks)
685  {
686  ScAreaLink *pLink = dynamic_cast<ScAreaLink*>(rLink.get());
687  if (pLink)
688  {
689  ScMyAreaLink aAreaLink;
690  aAreaLink.aDestRange = pLink->GetDestArea();
691  aAreaLink.sSourceStr = pLink->GetSource();
692  aAreaLink.sFilter = pLink->GetFilter();
693  aAreaLink.sFilterOptions = pLink->GetOptions();
694  aAreaLink.sURL = pLink->GetFile();
695  aAreaLink.nRefresh = pLink->GetRefreshDelay();
696  rAreaLinks.AddNewAreaLink( aAreaLink );
697  }
698  }
699  }
700  rAreaLinks.Sort();
701 }
702 
703 // core implementation
705 {
706  if (!pDoc)
707  return;
708 
709  ScDetOpList* pOpList(pDoc->GetDetOpList());
710  if( !pOpList )
711  return;
712 
713  size_t nCount = pOpList->Count();
714  for (size_t nIndex = 0; nIndex < nCount; ++nIndex )
715  {
716  const ScDetOpData& rDetData = pOpList->GetObject( nIndex);
717  const ScAddress& rDetPos = rDetData.GetPos();
718  SCTAB nTab = rDetPos.Tab();
719  if ( nTab < pDoc->GetTableCount() )
720  {
721  rDetOp.AddOperation( rDetData.GetOperation(), rDetPos, static_cast<sal_uInt32>( nIndex) );
722 
723  // cells with detective operations are written even if empty
724  pSharedData->SetLastColumn( nTab, rDetPos.Col() );
725  pSharedData->SetLastRow( nTab, rDetPos.Row() );
726  }
727  }
728  rDetOp.Sort();
729 }
730 
731 void ScXMLExport::WriteSingleColumn(const sal_Int32 nRepeatColumns, const sal_Int32 nStyleIndex,
732  const sal_Int32 nIndex, const bool bIsAutoStyle, const bool bIsVisible)
733 {
734  CheckAttrList();
735  AddAttribute(sAttrStyleName, pColumnStyles->GetStyleNameByIndex(nStyleIndex));
736  if (!bIsVisible)
738  if (nRepeatColumns > 1)
739  {
740  OUString sOUEndCol(OUString::number(nRepeatColumns));
742  }
743  if (nIndex != -1)
744  AddAttribute(XML_NAMESPACE_TABLE, XML_DEFAULT_CELL_STYLE_NAME, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
745  SvXMLElementExport aElemC(*this, sElemCol, true, true);
746 }
747 
748 void ScXMLExport::WriteColumn(const sal_Int32 nColumn, const sal_Int32 nRepeatColumns,
749  const sal_Int32 nStyleIndex, const bool bIsVisible)
750 {
751  sal_Int32 nRepeat(1);
752  sal_Int32 nPrevIndex(pDefaults->GetColDefaults()[nColumn].nIndex);
753  bool bPrevAutoStyle(pDefaults->GetColDefaults()[nColumn].bIsAutoStyle);
754  for (sal_Int32 i = nColumn + 1; i < nColumn + nRepeatColumns; ++i)
755  {
756  if ((pDefaults->GetColDefaults()[i].nIndex != nPrevIndex) ||
757  (pDefaults->GetColDefaults()[i].bIsAutoStyle != bPrevAutoStyle))
758  {
759  WriteSingleColumn(nRepeat, nStyleIndex, nPrevIndex, bPrevAutoStyle, bIsVisible);
760  nPrevIndex = pDefaults->GetColDefaults()[i].nIndex;
761  bPrevAutoStyle = pDefaults->GetColDefaults()[i].bIsAutoStyle;
762  nRepeat = 1;
763  }
764  else
765  ++nRepeat;
766  }
767  WriteSingleColumn(nRepeat, nStyleIndex, nPrevIndex, bPrevAutoStyle, bIsVisible);
768 }
769 
771 {
773 }
774 
776 {
778 }
779 
780 void ScXMLExport::ExportColumns(const sal_Int32 nTable, const ScRange& aColumnHeaderRange, const bool bHasColumnHeader)
781 {
782  sal_Int32 nColsRepeated (1);
783  sal_Int32 nIndex;
784  sal_Int32 nPrevColumn(0);
785  bool bPrevIsVisible (true);
786  bool bWasHeader (false);
787  bool bIsClosed (true);
788  sal_Int32 nPrevIndex (-1);
789  sal_Int32 nColumn;
790  for (nColumn = 0; nColumn <= pSharedData->GetLastColumn(nTable); ++nColumn)
791  {
792  CheckAttrList();
793  bool bIsVisible(true);
794  nIndex = pColumnStyles->GetStyleNameIndex(nTable, nColumn, bIsVisible);
795 
796  const bool bIsHeader = bHasColumnHeader && (aColumnHeaderRange.aStart.Col() <= nColumn) && (nColumn <= aColumnHeaderRange.aEnd.Col());
797  if (bIsHeader != bWasHeader)
798  {
799  if (bIsHeader)
800  {
801  if (nColumn > 0)
802  {
803  WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
804  if (pGroupColumns->IsGroupEnd(nColumn - 1))
805  pGroupColumns->CloseGroups(nColumn - 1);
806  }
807  bPrevIsVisible = bIsVisible;
808  nPrevIndex = nIndex;
809  nPrevColumn = nColumn;
810  nColsRepeated = 1;
811  if(pGroupColumns->IsGroupStart(nColumn))
812  pGroupColumns->OpenGroups(nColumn);
814  bWasHeader = true;
815  bIsClosed = false;
816  }
817  else
818  {
819  WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
821  if (pGroupColumns->IsGroupEnd(nColumn - 1))
822  pGroupColumns->CloseGroups(nColumn - 1);
823  if(pGroupColumns->IsGroupStart(nColumn))
824  pGroupColumns->OpenGroups(nColumn);
825  bPrevIsVisible = bIsVisible;
826  nPrevIndex = nIndex;
827  nPrevColumn = nColumn;
828  nColsRepeated = 1;
829  bWasHeader = false;
830  bIsClosed = true;
831  }
832  }
833  else if (nColumn == 0)
834  {
835  if (pGroupColumns->IsGroupStart(nColumn))
836  pGroupColumns->OpenGroups(nColumn);
837  bPrevIsVisible = bIsVisible;
838  nPrevIndex = nIndex;
839  }
840  else if ((bIsVisible == bPrevIsVisible) && (nIndex == nPrevIndex) &&
841  !pGroupColumns->IsGroupStart(nColumn) && !pGroupColumns->IsGroupEnd(nColumn - 1))
842  ++nColsRepeated;
843  else
844  {
845  WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
846  if (pGroupColumns->IsGroupEnd(nColumn - 1))
847  {
848  if (bIsHeader)
850  pGroupColumns->CloseGroups(nColumn - 1);
851  if (bIsHeader)
853  }
854  if (pGroupColumns->IsGroupStart(nColumn))
855  {
856  if (bIsHeader)
858  pGroupColumns->OpenGroups(nColumn);
859  if (bIsHeader)
861  }
862  bPrevIsVisible = bIsVisible;
863  nPrevIndex = nIndex;
864  nPrevColumn = nColumn;
865  nColsRepeated = 1;
866  }
867  }
868  // tdf#138466
869  if (nPrevIndex != -1)
870  WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
871  if (!bIsClosed)
873  if (pGroupColumns->IsGroupEnd(nColumn - 1))
874  pGroupColumns->CloseGroups(nColumn - 1);
875 }
876 
878 {
879  sal_Int32 nEntryIndex = GetCellStylesPropertySetMapper()->FindEntryIndex(
880  "NumberFormat", XML_NAMESPACE_STYLE, u"data-style-name");
881 
882  if (nEntryIndex < 0)
883  // No entry index for the number format is found.
884  return;
885 
887  if (!pRefMgr->hasExternalData())
888  // No external reference data cached.
889  return;
890 
891  // Export each unique number format used in the external ref cache.
892  vector<sal_uInt32> aNumFmts;
893  pRefMgr->getAllCachedNumberFormats(aNumFmts);
894  const OUString aDefaultStyle = OUString("Default").intern();
895  for (const auto& rNumFmt : aNumFmts)
896  {
897  sal_Int32 nNumFmt = static_cast<sal_Int32>(rNumFmt);
898 
899  addDataStyle(nNumFmt);
900 
901  uno::Any aVal;
902  aVal <<= nNumFmt;
903  vector<XMLPropertyState> aProps;
904  aVal <<= aDefaultStyle;
905  aProps.emplace_back(nEntryIndex, aVal);
906 
907  OUString aName;
908  sal_Int32 nIndex;
909  if (GetAutoStylePool()->Add(aName, XmlStyleFamily::TABLE_CELL, aDefaultStyle, aProps))
910  {
911  pCellStyles->AddStyleName(aName, nIndex);
912  }
913  else
914  {
915  bool bIsAuto;
916  nIndex = pCellStyles->GetIndexOfStyleName(
918  }
919 
920  // store the number format to index mapping for later use.
921  aNumFmtIndexMap.emplace(nNumFmt, nIndex);
922  }
923 }
924 
925 namespace {
926 
927 void handleFont(
928  std::vector<XMLPropertyState>& rPropStates,
929  const SfxPoolItem* p, const rtl::Reference<XMLPropertySetMapper>& xMapper, std::u16string_view rXMLName )
930 {
931  sal_Int32 nEntryCount = xMapper->GetEntryCount();
932 
933  // Apparently font info needs special handling.
934  const SvxFontItem* pItem = static_cast<const SvxFontItem*>(p);
935 
936  sal_Int32 nIndexFontName = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, rXMLName, 0);
937 
938  if (nIndexFontName == -1 || nIndexFontName >= nEntryCount)
939  return;
940 
941  uno::Any aAny;
942  if (!pItem->QueryValue(aAny, MID_FONT_FAMILY_NAME))
943  return;
944 
945  rPropStates.emplace_back(nIndexFontName, aAny);
946 }
947 
948 const SvxFieldData* toXMLPropertyStates(
949  std::vector<XMLPropertyState>& rPropStates, const std::vector<const SfxPoolItem*>& rSecAttrs,
950  const rtl::Reference<XMLPropertySetMapper>& xMapper, const ScXMLEditAttributeMap& rAttrMap )
951 {
952  const SvxFieldData* pField = nullptr;
953  sal_Int32 nEntryCount = xMapper->GetEntryCount();
954  rPropStates.reserve(rSecAttrs.size());
955  for (const SfxPoolItem* p : rSecAttrs)
956  {
957  if (p->Which() == EE_FEATURE_FIELD)
958  {
959  pField = static_cast<const SvxFieldItem*>(p)->GetField();
960  continue;
961  }
962 
963  const ScXMLEditAttributeMap::Entry* pEntry = rAttrMap.getEntryByItemID(p->Which());
964  if (!pEntry)
965  continue;
966 
967  sal_Int32 nIndex = xMapper->GetEntryIndex(
968  pEntry->nmXMLNS, OUString::createFromAscii(pEntry->mpXMLName), 0);
969 
970  if (nIndex == -1 || nIndex >= nEntryCount)
971  continue;
972 
973  uno::Any aAny;
974  switch (p->Which())
975  {
976  case EE_CHAR_FONTINFO:
977  handleFont(rPropStates, p, xMapper, u"font-name");
978  break;
980  handleFont(rPropStates, p, xMapper, u"font-name-asian");
981  break;
983  handleFont(rPropStates, p, xMapper, u"font-name-complex");
984  break;
985  case EE_CHAR_WEIGHT:
986  case EE_CHAR_WEIGHT_CJK:
987  case EE_CHAR_WEIGHT_CTL:
988  {
989  if (!static_cast<const SvxWeightItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
990  continue;
991 
992  rPropStates.emplace_back(nIndex, aAny);
993  }
994  break;
995  case EE_CHAR_FONTHEIGHT:
998  {
999  if (!static_cast<const SvxFontHeightItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1000  continue;
1001 
1002  rPropStates.emplace_back(nIndex, aAny);
1003  }
1004  break;
1005  case EE_CHAR_ITALIC:
1006  case EE_CHAR_ITALIC_CJK:
1007  case EE_CHAR_ITALIC_CTL:
1008  {
1009  if (!static_cast<const SvxPostureItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1010  continue;
1011 
1012  rPropStates.emplace_back(nIndex, aAny);
1013  }
1014  break;
1015  case EE_CHAR_UNDERLINE:
1016  {
1017  // Underline attribute needs to export multiple entries.
1018  sal_Int32 nIndexStyle = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, u"text-underline-style", 0);
1019  if (nIndexStyle == -1 || nIndexStyle > nEntryCount)
1020  break;
1021 
1022  sal_Int32 nIndexWidth = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, u"text-underline-width", 0);
1023  if (nIndexWidth == -1 || nIndexWidth > nEntryCount)
1024  break;
1025 
1026  sal_Int32 nIndexType = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, u"text-underline-type", 0);
1027  if (nIndexType == -1 || nIndexType > nEntryCount)
1028  break;
1029 
1030  sal_Int32 nIndexColor = xMapper->FindEntryIndex("CharUnderlineColor", XML_NAMESPACE_STYLE, u"text-underline-color");
1031  if (nIndexColor == -1 || nIndexColor > nEntryCount)
1032  break;
1033 
1034  sal_Int32 nIndexHasColor = xMapper->FindEntryIndex("CharUnderlineHasColor", XML_NAMESPACE_STYLE, u"text-underline-color");
1035  if (nIndexHasColor == -1 || nIndexHasColor > nEntryCount)
1036  break;
1037 
1038  const SvxUnderlineItem* pUL = static_cast<const SvxUnderlineItem*>(p);
1039  pUL->QueryValue(aAny, MID_TL_STYLE);
1040  rPropStates.emplace_back(nIndexStyle, aAny);
1041  rPropStates.emplace_back(nIndexType, aAny);
1042  rPropStates.emplace_back(nIndexWidth, aAny);
1043 
1044  pUL->QueryValue(aAny, MID_TL_COLOR);
1045  rPropStates.emplace_back(nIndexColor, aAny);
1046 
1047  pUL->QueryValue(aAny, MID_TL_HASCOLOR);
1048  rPropStates.emplace_back(nIndexHasColor, aAny);
1049  }
1050  break;
1051  case EE_CHAR_OVERLINE:
1052  {
1053  // Same with overline. Do just as we do with underline attributes.
1054  sal_Int32 nIndexStyle = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, u"text-overline-style", 0);
1055  if (nIndexStyle == -1 || nIndexStyle > nEntryCount)
1056  break;
1057 
1058  sal_Int32 nIndexWidth = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, u"text-overline-width", 0);
1059  if (nIndexWidth == -1 || nIndexWidth > nEntryCount)
1060  break;
1061 
1062  sal_Int32 nIndexType = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, u"text-overline-type", 0);
1063  if (nIndexType == -1 || nIndexType > nEntryCount)
1064  break;
1065 
1066  sal_Int32 nIndexColor = xMapper->FindEntryIndex("CharOverlineColor", XML_NAMESPACE_STYLE, u"text-overline-color");
1067  if (nIndexColor == -1 || nIndexColor > nEntryCount)
1068  break;
1069 
1070  sal_Int32 nIndexHasColor = xMapper->FindEntryIndex("CharOverlineHasColor", XML_NAMESPACE_STYLE, u"text-overline-color");
1071  if (nIndexHasColor == -1 || nIndexHasColor > nEntryCount)
1072  break;
1073 
1074  const SvxOverlineItem* pOL = static_cast<const SvxOverlineItem*>(p);
1075  pOL->QueryValue(aAny, MID_TL_STYLE);
1076  rPropStates.emplace_back(nIndexStyle, aAny);
1077  rPropStates.emplace_back(nIndexType, aAny);
1078  rPropStates.emplace_back(nIndexWidth, aAny);
1079 
1080  pOL->QueryValue(aAny, MID_TL_COLOR);
1081  rPropStates.emplace_back(nIndexColor, aAny);
1082 
1083  pOL->QueryValue(aAny, MID_TL_HASCOLOR);
1084  rPropStates.emplace_back(nIndexHasColor, aAny);
1085  }
1086  break;
1087  case EE_CHAR_COLOR:
1088  {
1089  if (!static_cast<const SvxColorItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1090  continue;
1091 
1092  ::Color nColor;
1093  if ( aAny >>= nColor )
1094  {
1095  sal_Int32 nIndexColor = ( nColor == COL_AUTO ) ? xMapper->GetEntryIndex(
1096  XML_NAMESPACE_STYLE, GetXMLToken( XML_USE_WINDOW_FONT_COLOR ), 0 ) : nIndex;
1097  rPropStates.emplace_back( nIndexColor, aAny );
1098  }
1099  }
1100  break;
1101  case EE_CHAR_WLM:
1102  {
1103  if (!static_cast<const SvxWordLineModeItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1104  continue;
1105 
1106  rPropStates.emplace_back(nIndex, aAny);
1107  }
1108  break;
1109  case EE_CHAR_STRIKEOUT:
1110  {
1111  if (!static_cast<const SvxCrossedOutItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1112  continue;
1113 
1114  rPropStates.emplace_back(nIndex, aAny);
1115  }
1116  break;
1117  case EE_CHAR_RELIEF:
1118  {
1119  if (!static_cast<const SvxCharReliefItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1120  continue;
1121 
1122  rPropStates.emplace_back(nIndex, aAny);
1123  }
1124  break;
1125  case EE_CHAR_OUTLINE:
1126  {
1127  if (!static_cast<const SvxContourItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1128  continue;
1129 
1130  rPropStates.emplace_back(nIndex, aAny);
1131  }
1132  break;
1133  case EE_CHAR_SHADOW:
1134  {
1135  if (!static_cast<const SvxShadowedItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1136  continue;
1137 
1138  rPropStates.emplace_back(nIndex, aAny);
1139  }
1140  break;
1141  case EE_CHAR_KERNING:
1142  {
1143  if (!static_cast<const SvxKerningItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1144  continue;
1145 
1146  rPropStates.emplace_back(nIndex, aAny);
1147  }
1148  break;
1149  case EE_CHAR_PAIRKERNING:
1150  {
1151  if (!static_cast<const SvxAutoKernItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1152  continue;
1153 
1154  rPropStates.emplace_back(nIndex, aAny);
1155  }
1156  break;
1157  case EE_CHAR_FONTWIDTH:
1158  {
1159  if (!static_cast<const SvxCharScaleWidthItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1160  continue;
1161 
1162  rPropStates.emplace_back(nIndex, aAny);
1163  }
1164  break;
1165  case EE_CHAR_ESCAPEMENT:
1166  {
1167  sal_Int32 nIndexEsc = xMapper->FindEntryIndex("CharEscapement", XML_NAMESPACE_STYLE, u"text-position");
1168  if (nIndexEsc == -1 || nIndexEsc > nEntryCount)
1169  break;
1170 
1171  sal_Int32 nIndexEscHeight = xMapper->FindEntryIndex("CharEscapementHeight", XML_NAMESPACE_STYLE, u"text-position");
1172  if (nIndexEscHeight == -1 || nIndexEscHeight > nEntryCount)
1173  break;
1174 
1175  const SvxEscapementItem* pEsc = static_cast<const SvxEscapementItem*>(p);
1176 
1177  pEsc->QueryValue(aAny);
1178  rPropStates.emplace_back(nIndexEsc, aAny);
1179 
1180  pEsc->QueryValue(aAny, MID_ESC_HEIGHT);
1181  rPropStates.emplace_back(nIndexEscHeight, aAny);
1182 
1183  }
1184  break;
1185  case EE_CHAR_EMPHASISMARK:
1186  {
1187  if (!static_cast<const SvxEmphasisMarkItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1188  continue;
1189 
1190  rPropStates.emplace_back(nIndex, aAny);
1191  }
1192  break;
1193  case EE_CHAR_LANGUAGE:
1194  case EE_CHAR_LANGUAGE_CJK:
1195  case EE_CHAR_LANGUAGE_CTL:
1196  {
1197  if (!static_cast<const SvxLanguageItem*>(p)->QueryValue(aAny, pEntry->mnFlag))
1198  continue;
1199 
1200  // Export multiple entries.
1201  sal_Int32 nIndexLanguage, nIndexCountry, nIndexScript, nIndexTag;
1202  switch (p->Which())
1203  {
1204  case EE_CHAR_LANGUAGE:
1205  nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_FO, u"language", 0);
1206  nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_FO, u"country", 0);
1207  nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_FO, u"script", 0);
1208  nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, u"rfc-language-tag", 0);
1209  break;
1210  case EE_CHAR_LANGUAGE_CJK:
1211  nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, u"language-asian", 0);
1212  nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, u"country-asian", 0);
1213  nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, u"script-asian", 0);
1214  nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, u"rfc-language-tag-asian", 0);
1215  break;
1216  case EE_CHAR_LANGUAGE_CTL:
1217  nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, u"language-complex", 0);
1218  nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, u"country-complex", 0);
1219  nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, u"script-complex", 0);
1220  nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, u"rfc-language-tag-complex", 0);
1221  break;
1222  default:
1223  nIndexLanguage = nIndexCountry = nIndexScript = nIndexTag = -1;
1224  }
1225  assert( nIndexLanguage >= 0 && nIndexCountry >= 0 && nIndexScript >= 0 && nIndexTag >= 0);
1226  rPropStates.emplace_back( nIndexLanguage, aAny);
1227  rPropStates.emplace_back( nIndexCountry, aAny);
1228  rPropStates.emplace_back( nIndexScript, aAny);
1229  rPropStates.emplace_back( nIndexTag, aAny);
1230  }
1231  break;
1232  default:
1233  continue;
1234  }
1235  }
1236 
1237  return pField;
1238 }
1239 
1240 }
1241 
1243 {
1244  if (!ValidTab(nTable))
1245  return;
1246 
1247  rtl::Reference<XMLPropertySetMapper> xMapper = GetTextParagraphExport()->GetTextPropMapper()->getPropertySetMapper();
1249  const ScXMLEditAttributeMap& rAttrMap = GetEditAttributeMap();
1250 
1251  sc::EditTextIterator aIter(*pDoc, nTable);
1252  sal_Int32 nCellCount = 0;
1253  for (const EditTextObject* pEdit = aIter.first(); pEdit; pEdit = aIter.next(), ++nCellCount)
1254  {
1255  std::vector<editeng::Section> aAttrs;
1256  pEdit->GetAllSections(aAttrs);
1257  if (aAttrs.empty())
1258  continue;
1259 
1260  for (const auto& rSec : aAttrs)
1261  {
1262  const std::vector<const SfxPoolItem*>& rSecAttrs = rSec.maAttributes;
1263  if (rSecAttrs.empty())
1264  // No formats applied to this section. Skip it.
1265  continue;
1266 
1267  std::vector<XMLPropertyState> aPropStates;
1268  toXMLPropertyStates(aPropStates, rSecAttrs, xMapper, rAttrMap);
1269  if (!aPropStates.empty())
1270  xStylePool->Add(XmlStyleFamily::TEXT_TEXT, OUString(), aPropStates);
1271  }
1272  }
1273 
1274  GetProgressBarHelper()->ChangeReference(GetProgressBarHelper()->GetReference() + nCellCount);
1275 }
1276 
1278 {
1279  ScMyRowFormatRange aRange;
1280  sal_Int32 nIndex(-1);
1281 #if OSL_DEBUG_LEVEL > 0
1282  sal_Int32 nPrevCol(0);
1283 #endif
1284  sal_Int32 nCols(0);
1285  sal_Int32 nPrevValidationIndex(-1);
1286  bool bIsAutoStyle(true);
1287  bool bIsFirst(true);
1288  while (pRowFormatRanges->GetNext(aRange))
1289  {
1290 #if OSL_DEBUG_LEVEL > 0
1291  OSL_ENSURE(bIsFirst || (!bIsFirst && (nPrevCol + nCols == aRange.nStartColumn)), "here are some columns missing");
1292 #endif
1293  if (bIsFirst)
1294  {
1295  nIndex = aRange.nIndex;
1296  nPrevValidationIndex = aRange.nValidationIndex;
1297  bIsAutoStyle = aRange.bIsAutoStyle;
1298  nCols = aRange.nRepeatColumns;
1299  bIsFirst = false;
1300 #if OSL_DEBUG_LEVEL > 0
1301  nPrevCol = aRange.nStartColumn;
1302 #endif
1303  }
1304  else
1305  {
1306  if (((aRange.nIndex == nIndex && aRange.bIsAutoStyle == bIsAutoStyle) ||
1307  (aRange.nIndex == nIndex && nIndex == -1)) &&
1308  nPrevValidationIndex == aRange.nValidationIndex)
1309  nCols += aRange.nRepeatColumns;
1310  else
1311  {
1312  if (nIndex != -1)
1313  AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
1314  if (nPrevValidationIndex > -1)
1315  AddAttribute(XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, pValidationsContainer->GetValidationName(nPrevValidationIndex));
1316  if (nCols > 1)
1317  {
1318  AddAttribute(sAttrColumnsRepeated, OUString::number(nCols));
1319  }
1320  SvXMLElementExport aElemC(*this, sElemCell, true, true);
1321  nIndex = aRange.nIndex;
1322  bIsAutoStyle = aRange.bIsAutoStyle;
1323  nCols = aRange.nRepeatColumns;
1324  nPrevValidationIndex = aRange.nValidationIndex;
1325 #if OSL_DEBUG_LEVEL > 0
1326  nPrevCol = aRange.nStartColumn;
1327 #endif
1328  }
1329  }
1330  }
1331  if (!bIsFirst)
1332  {
1333  if (nIndex != -1)
1334  AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
1335  if (nPrevValidationIndex > -1)
1336  AddAttribute(XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, pValidationsContainer->GetValidationName(nPrevValidationIndex));
1337  if (nCols > 1)
1338  {
1339  AddAttribute(sAttrColumnsRepeated, OUString::number(nCols));
1340  }
1341  SvXMLElementExport aElemC(*this, sElemCell, true, true);
1342  }
1343 }
1344 
1346  const sal_Int32 nIndex, const sal_Int32 nEqualRows,
1347  bool bHidden, bool bFiltered)
1348 {
1349  AddAttribute(sAttrStyleName, pRowStyles->GetStyleNameByIndex(nIndex));
1350  if (bHidden)
1351  {
1352  if (bFiltered)
1354  else
1356  }
1357  if (nEqualRows > 1)
1358  {
1359  AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_REPEATED, OUString::number(nEqualRows));
1360  }
1361 
1362  StartElement( sElemRow, true);
1363 }
1364 
1366 {
1368  bRowHeaderOpen = true;
1369 }
1370 
1372 {
1374 }
1375 
1377  const sal_Int32 nIndex, const sal_Int32 nStartRow, const sal_Int32 nEqualRows,
1378  bool bHidden, bool bFiltered)
1379 {
1380  nOpenRow = nStartRow;
1381  if (pGroupRows->IsGroupStart(nStartRow))
1382  {
1384  CloseHeaderRows();
1385  pGroupRows->OpenGroups(nStartRow);
1387  OpenHeaderRows();
1388  }
1389  if (bHasRowHeader && !bRowHeaderOpen && nStartRow >= aRowHeaderRange.aStart.Row() && nStartRow <= aRowHeaderRange.aEnd.Row())
1390  {
1391  if (nStartRow == aRowHeaderRange.aStart.Row())
1392  OpenHeaderRows();
1393  sal_Int32 nEquals;
1394  if (aRowHeaderRange.aEnd.Row() < nStartRow + nEqualRows - 1)
1395  nEquals = aRowHeaderRange.aEnd.Row() - nStartRow + 1;
1396  else
1397  nEquals = nEqualRows;
1398  WriteRowStartTag(nIndex, nEquals, bHidden, bFiltered);
1399  nOpenRow = nStartRow + nEquals - 1;
1400  if (nEquals < nEqualRows)
1401  {
1402  CloseRow(nStartRow + nEquals - 1);
1403  WriteRowStartTag(nIndex, nEqualRows - nEquals, bHidden, bFiltered);
1404  nOpenRow = nStartRow + nEqualRows - 1;
1405  }
1406  }
1407  else
1408  WriteRowStartTag(nIndex, nEqualRows, bHidden, bFiltered);
1409 }
1410 
1412  const sal_Int32 nIndex, const sal_Int32 nStartRow, const sal_Int32 nEqualRows,
1413  bool bHidden, bool bFiltered)
1414 {
1415  OpenNewRow(nIndex, nStartRow, nEqualRows, bHidden, bFiltered);
1416  WriteRowContent();
1417  CloseRow(nStartRow + nEqualRows - 1);
1418  pRowFormatRanges->Clear();
1419 }
1420 
1421 void ScXMLExport::OpenRow(const sal_Int32 nTable, const sal_Int32 nStartRow, const sal_Int32 nRepeatRow, ScXMLCachedRowAttrAccess& rRowAttr)
1422 {
1423  if (nRepeatRow > 1)
1424  {
1425  sal_Int32 nPrevIndex(0), nIndex;
1426  bool bPrevHidden = false;
1427  bool bPrevFiltered = false;
1428  bool bHidden = false;
1429  bool bFiltered = false;
1430  sal_Int32 nEqualRows(1);
1431  sal_Int32 nEndRow(nStartRow + nRepeatRow);
1432  sal_Int32 nEndRowHidden = nStartRow - 1;
1433  sal_Int32 nEndRowFiltered = nStartRow - 1;
1434  sal_Int32 nRow;
1435  for (nRow = nStartRow; nRow < nEndRow; ++nRow)
1436  {
1437  if (nRow == nStartRow)
1438  {
1439  nPrevIndex = pRowStyles->GetStyleNameIndex(nTable, nRow);
1440  if (pDoc)
1441  {
1442  if (nRow > nEndRowHidden)
1443  {
1444  bPrevHidden = rRowAttr.rowHidden(nTable, nRow, nEndRowHidden);
1445  bHidden = bPrevHidden;
1446  }
1447  if (nRow > nEndRowFiltered)
1448  {
1449  bPrevFiltered = rRowAttr.rowFiltered(nTable, nRow, nEndRowFiltered);
1450  bFiltered = bPrevFiltered;
1451  }
1452  }
1453 
1454  }
1455  else
1456  {
1457  nIndex = pRowStyles->GetStyleNameIndex(nTable, nRow);
1458  if (pDoc)
1459  {
1460  if (nRow > nEndRowHidden)
1461  bHidden = rRowAttr.rowHidden(nTable, nRow, nEndRowHidden);
1462  if (nRow > nEndRowFiltered)
1463  bFiltered = rRowAttr.rowFiltered(nTable, nRow, nEndRowFiltered);
1464  }
1465  if (nIndex == nPrevIndex && bHidden == bPrevHidden && bFiltered == bPrevFiltered &&
1466  !(bHasRowHeader && ((nRow == aRowHeaderRange.aStart.Row()) || (nRow - 1 == aRowHeaderRange.aEnd.Row()))) &&
1467  !(pGroupRows->IsGroupStart(nRow)) &&
1468  !(pGroupRows->IsGroupEnd(nRow - 1)))
1469  ++nEqualRows;
1470  else
1471  {
1472  assert(nPrevIndex >= 0 && "coverity#1438402");
1473  ScRowFormatRanges* pTempRowFormatRanges = new ScRowFormatRanges(pRowFormatRanges.get());
1474  OpenAndCloseRow(nPrevIndex, nRow - nEqualRows, nEqualRows, bPrevHidden, bPrevFiltered);
1475  pRowFormatRanges.reset(pTempRowFormatRanges);
1476  nEqualRows = 1;
1477  nPrevIndex = nIndex;
1478  bPrevHidden = bHidden;
1479  bPrevFiltered = bFiltered;
1480  }
1481  }
1482  }
1483  assert(nPrevIndex >= 0 && "coverity#1438402");
1484  OpenNewRow(nPrevIndex, nRow - nEqualRows, nEqualRows, bPrevHidden, bPrevFiltered);
1485  }
1486  else
1487  {
1488  sal_Int32 nIndex = pRowStyles->GetStyleNameIndex(nTable, nStartRow);
1489  bool bHidden = false;
1490  bool bFiltered = false;
1491  if (pDoc)
1492  {
1493  sal_Int32 nEndRowHidden;
1494  sal_Int32 nEndRowFiltered;
1495  bHidden = rRowAttr.rowHidden(nTable, nStartRow, nEndRowHidden);
1496  bFiltered = rRowAttr.rowFiltered(nTable, nStartRow, nEndRowFiltered);
1497  }
1498  assert(nIndex >= 0 && "coverity#1438402");
1499  OpenNewRow(nIndex, nStartRow, 1, bHidden, bFiltered);
1500  }
1501  nOpenRow = nStartRow + nRepeatRow - 1;
1502 }
1503 
1504 void ScXMLExport::CloseRow(const sal_Int32 nRow)
1505 {
1506  if (nOpenRow > -1)
1507  {
1508  EndElement(sElemRow, true);
1509  if (bHasRowHeader && nRow == aRowHeaderRange.aEnd.Row())
1510  {
1511  CloseHeaderRows();
1512  bRowHeaderOpen = false;
1513  }
1514  if (pGroupRows->IsGroupEnd(nRow))
1515  {
1517  CloseHeaderRows();
1518  pGroupRows->CloseGroups(nRow);
1520  OpenHeaderRows();
1521  }
1522  }
1523  nOpenRow = -1;
1524 }
1525 
1526 void ScXMLExport::ExportFormatRanges(const sal_Int32 nStartCol, const sal_Int32 nStartRow,
1527  const sal_Int32 nEndCol, const sal_Int32 nEndRow, const sal_Int32 nSheet)
1528 {
1529  pRowFormatRanges->Clear();
1530  ScXMLCachedRowAttrAccess aRowAttr(pDoc);
1531  if (nStartRow == nEndRow)
1532  {
1533  pCellStyles->GetFormatRanges(nStartCol, nEndCol, nStartRow, nSheet, pRowFormatRanges.get());
1534  if (nOpenRow == - 1)
1535  OpenRow(nSheet, nStartRow, 1, aRowAttr);
1536  WriteRowContent();
1537  pRowFormatRanges->Clear();
1538  }
1539  else
1540  {
1541  if (nOpenRow > -1)
1542  {
1543  pCellStyles->GetFormatRanges(nStartCol, pSharedData->GetLastColumn(nSheet), nStartRow, nSheet, pRowFormatRanges.get());
1544  WriteRowContent();
1545  CloseRow(nStartRow);
1546  sal_Int32 nRows(1);
1547  sal_Int32 nTotalRows(nEndRow - nStartRow + 1 - 1);
1548  while (nRows < nTotalRows)
1549  {
1550  pRowFormatRanges->Clear();
1551  pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1552  sal_Int32 nMaxRows = pRowFormatRanges->GetMaxRows();
1553  OSL_ENSURE(nMaxRows, "something went wrong");
1554  if (nMaxRows >= nTotalRows - nRows)
1555  {
1556  OpenRow(nSheet, nStartRow + nRows, nTotalRows - nRows, aRowAttr);
1557  nRows += nTotalRows - nRows;
1558  }
1559  else
1560  {
1561  OpenRow(nSheet, nStartRow + nRows, nMaxRows, aRowAttr);
1562  nRows += nMaxRows;
1563  }
1564  if (!pRowFormatRanges->GetSize())
1565  pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1566  WriteRowContent();
1567  CloseRow(nStartRow + nRows - 1);
1568  }
1569  if (nTotalRows == 1)
1570  CloseRow(nStartRow);
1571  OpenRow(nSheet, nEndRow, 1, aRowAttr);
1572  pRowFormatRanges->Clear();
1573  pCellStyles->GetFormatRanges(0, nEndCol, nEndRow, nSheet, pRowFormatRanges.get());
1574  WriteRowContent();
1575  }
1576  else
1577  {
1578  sal_Int32 nRows(0);
1579  sal_Int32 nTotalRows(nEndRow - nStartRow + 1 - 1);
1580  while (nRows < nTotalRows)
1581  {
1582  pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1583  sal_Int32 nMaxRows = pRowFormatRanges->GetMaxRows();
1584  OSL_ENSURE(nMaxRows, "something went wrong");
1585  if (nMaxRows >= nTotalRows - nRows)
1586  {
1587  OpenRow(nSheet, nStartRow + nRows, nTotalRows - nRows, aRowAttr);
1588  nRows += nTotalRows - nRows;
1589  }
1590  else
1591  {
1592  OpenRow(nSheet, nStartRow + nRows, nMaxRows, aRowAttr);
1593  nRows += nMaxRows;
1594  }
1595  if (!pRowFormatRanges->GetSize())
1596  pCellStyles->GetFormatRanges(0, pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, pRowFormatRanges.get());
1597  WriteRowContent();
1598  CloseRow(nStartRow + nRows - 1);
1599  }
1600  OpenRow(nSheet, nEndRow, 1, aRowAttr);
1601  pRowFormatRanges->Clear();
1602  pCellStyles->GetFormatRanges(0, nEndCol, nEndRow, nSheet, pRowFormatRanges.get());
1603  WriteRowContent();
1604  }
1605  }
1606 }
1607 
1608 void ScXMLExport::GetColumnRowHeader(bool& rHasColumnHeader, ScRange& rColumnHeaderRange,
1609  bool& rHasRowHeader, ScRange& rRowHeaderRange,
1610  OUString& rPrintRanges) const
1611 {
1612  uno::Reference <sheet::XPrintAreas> xPrintAreas (xCurrentTable, uno::UNO_QUERY);
1613  if (!xPrintAreas.is())
1614  return;
1615 
1616  rHasRowHeader = xPrintAreas->getPrintTitleRows();
1617  rHasColumnHeader = xPrintAreas->getPrintTitleColumns();
1618  table::CellRangeAddress rTempRowHeaderRange = xPrintAreas->getTitleRows();
1619  rRowHeaderRange = ScRange(rTempRowHeaderRange.StartColumn,
1620  rTempRowHeaderRange.StartRow,
1621  rTempRowHeaderRange.Sheet,
1622  rTempRowHeaderRange.EndColumn,
1623  rTempRowHeaderRange.EndRow,
1624  rTempRowHeaderRange.Sheet);
1625  table::CellRangeAddress rTempColumnHeaderRange = xPrintAreas->getTitleColumns();
1626  rColumnHeaderRange = ScRange(rTempColumnHeaderRange.StartColumn,
1627  rTempColumnHeaderRange.StartRow,
1628  rTempColumnHeaderRange.Sheet,
1629  rTempColumnHeaderRange.EndColumn,
1630  rTempColumnHeaderRange.EndRow,
1631  rTempColumnHeaderRange.Sheet);
1632  uno::Sequence< table::CellRangeAddress > aRangeList( xPrintAreas->getPrintAreas() );
1633  ScRangeStringConverter::GetStringFromRangeList( rPrintRanges, aRangeList, pDoc, FormulaGrammar::CONV_OOO );
1634 }
1635 
1637 {
1638  size_t nDepth = pFields->GetDepth();
1639  for (size_t i = 0; i < nDepth; ++i)
1640  {
1641  size_t nFields = pFields->GetCount(i);
1642  for (size_t j = 0; j < nFields; ++j)
1643  {
1644  ScMyColumnRowGroup aGroup;
1645  const ScOutlineEntry* pEntry = pFields->GetEntry(i, j);
1646  aGroup.nField = pEntry->GetStart();
1647  aGroup.nLevel = static_cast<sal_Int16>(i);
1648  aGroup.bDisplay = !(pEntry->IsHidden());
1649  pGroups->AddGroup(aGroup, pEntry->GetEnd());
1650  }
1651  }
1652  if (nDepth)
1653  pGroups->Sort();
1654 }
1655 
1657 {
1658  if (!pDoc)
1659  return;
1660 
1661  ScOutlineTable* pOutlineTable = pDoc->GetOutlineTable( static_cast<SCTAB>(nCurrentTable) );
1662  if(pOutlineTable)
1663  {
1664  ScOutlineArray& rCols(pOutlineTable->GetColArray());
1665  ScOutlineArray& rRows(pOutlineTable->GetRowArray());
1666  FillFieldGroup(&rCols, pGroupColumns.get());
1667  FillFieldGroup(&rRows, pGroupRows.get());
1668  pSharedData->SetLastColumn(nCurrentTable, pGroupColumns->GetLast());
1669  pSharedData->SetLastRow(nCurrentTable, pGroupRows->GetLast());
1670  }
1671 }
1672 
1674 {
1675  if (!(pDoc && pDoc->IsDocProtected()))
1676  return;
1677 
1679  OUStringBuffer aBuffer;
1680  uno::Sequence<sal_Int8> aPassHash;
1682  const ScDocProtection* p = pDoc->GetDocProtection();
1683  if (p)
1684  {
1686  {
1687  aPassHash = p->getPasswordHash(PASSHASH_SHA1);
1688  eHashUsed = PASSHASH_SHA1;
1689  }
1690  else if (p->hasPasswordHash(PASSHASH_SHA256))
1691  {
1692  aPassHash = p->getPasswordHash(PASSHASH_SHA256);
1693  eHashUsed = PASSHASH_SHA256;
1694  }
1696  {
1697  aPassHash = p->getPasswordHash(PASSHASH_XL, PASSHASH_SHA1);
1698  eHashUsed = PASSHASH_XL;
1699  }
1700  }
1701  ::comphelper::Base64::encode(aBuffer, aPassHash);
1702  if (aBuffer.isEmpty())
1703  return;
1704 
1705  AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
1707  return;
1708 
1709  if (eHashUsed == PASSHASH_XL)
1710  {
1716  }
1717  else if (eHashUsed == PASSHASH_SHA1)
1718  {
1721  }
1722  else if (eHashUsed == PASSHASH_SHA256)
1723  {
1726  }
1727 }
1728 
1729 static bool lcl_CopyStreamElement( const uno::Reference< io::XInputStream >& xInput,
1730  const uno::Reference< io::XOutputStream >& xOutput,
1731  sal_Int32 nCount )
1732 {
1733  const sal_Int32 nBufSize = 16*1024;
1734  uno::Sequence<sal_Int8> aSequence(nBufSize);
1735 
1736  sal_Int32 nRemaining = nCount;
1737  bool bFirst = true;
1738 
1739  while ( nRemaining > 0 )
1740  {
1741  sal_Int32 nRead = xInput->readBytes( aSequence, std::min( nRemaining, nBufSize ) );
1742  if (bFirst)
1743  {
1744  // safety check: Make sure the copied part actually points to the start of an element
1745  if ( nRead < 1 || aSequence[0] != static_cast<sal_Int8>('<') )
1746  {
1747  return false; // abort and set an error
1748  }
1749  bFirst = false;
1750  }
1751  if (nRead == nRemaining)
1752  {
1753  // safety check: Make sure the copied part also ends at the end of an element
1754  if ( aSequence[nRead-1] != static_cast<sal_Int8>('>') )
1755  {
1756  return false; // abort and set an error
1757  }
1758  }
1759 
1760  if ( nRead == nBufSize )
1761  {
1762  xOutput->writeBytes( aSequence );
1763  nRemaining -= nRead;
1764  }
1765  else
1766  {
1767  if ( nRead > 0 )
1768  {
1769  uno::Sequence<sal_Int8> aTempBuf( aSequence.getConstArray(), nRead );
1770  xOutput->writeBytes( aTempBuf );
1771  }
1772  nRemaining = 0;
1773  }
1774  }
1775  return true; // successful
1776 }
1777 
1778 static void lcl_SkipBytesInBlocks( const uno::Reference< io::XInputStream >& xInput, sal_Int32 nBytesToSkip )
1779 {
1780  // skipBytes in zip stream is implemented as reading.
1781  // For now, split into several calls to avoid allocating a large buffer.
1782  // Later, skipBytes should be changed.
1783 
1784  const sal_Int32 nMaxSize = 32*1024;
1785 
1786  if ( nBytesToSkip > 0 )
1787  {
1788  sal_Int32 nRemaining = nBytesToSkip;
1789  while ( nRemaining > 0 )
1790  {
1791  sal_Int32 nSkip = std::min( nRemaining, nMaxSize );
1792  xInput->skipBytes( nSkip );
1793  nRemaining -= nSkip;
1794  }
1795  }
1796 }
1797 
1798 void ScXMLExport::CopySourceStream( sal_Int32 nStartOffset, sal_Int32 nEndOffset, sal_Int32& rNewStart, sal_Int32& rNewEnd )
1799 {
1800  uno::Reference<xml::sax::XDocumentHandler> xHandler = GetDocHandler();
1801  uno::Reference<io::XActiveDataSource> xDestSource( xHandler, uno::UNO_QUERY );
1802  if ( !xDestSource.is() )
1803  return;
1804 
1805  uno::Reference<io::XOutputStream> xDestStream = xDestSource->getOutputStream();
1806  uno::Reference<io::XSeekable> xDestSeek( xDestStream, uno::UNO_QUERY );
1807  if ( !xDestSeek.is() )
1808  return;
1809 
1810  // temporary: set same stream again to clear buffer
1811  xDestSource->setOutputStream( xDestStream );
1812 
1813  if ( getExportFlags() & SvXMLExportFlags::PRETTY )
1814  {
1815  const OString aOutStr("\n ");
1816  uno::Sequence<sal_Int8> aOutSeq( reinterpret_cast<sal_Int8 const *>(aOutStr.getStr()), aOutStr.getLength() );
1817  xDestStream->writeBytes( aOutSeq );
1818  }
1819 
1820  rNewStart = static_cast<sal_Int32>(xDestSeek->getPosition());
1821 
1822  if ( nStartOffset > nSourceStreamPos )
1824 
1825  if ( !lcl_CopyStreamElement( xSourceStream, xDestStream, nEndOffset - nStartOffset ) )
1826  {
1827  // If copying went wrong, set an error.
1828  // ScXMLImportWrapper then resets all stream flags, so the next save attempt will use normal saving.
1829 
1830  uno::Sequence<OUString> aEmptySeq;
1832  }
1833  nSourceStreamPos = nEndOffset;
1834 
1835  rNewEnd = static_cast<sal_Int32>(xDestSeek->getPosition());
1836 }
1837 
1839 {
1840  if (!mpEditAttrMap)
1842  return *mpEditAttrMap;
1843 }
1844 
1845 void ScXMLExport::RegisterDefinedStyleNames( const uno::Reference< css::sheet::XSpreadsheetDocument > & xSpreadDoc )
1846 {
1847  ScFormatSaveData* pFormatData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetFormatSaveData();
1848  auto xAutoStylePool = GetAutoStylePool();
1849  for (const auto& rFormatInfo : pFormatData->maIDToName)
1850  {
1851  xAutoStylePool->RegisterDefinedName(XmlStyleFamily::TABLE_CELL, rFormatInfo.second);
1852  }
1853 }
1854 
1856 {
1857  nCurrentTable = 0;
1858  if (!pSharedData)
1859  {
1860  SCTAB nTableCount(0);
1861  sal_Int32 nShapesCount(0);
1862  CollectSharedData(nTableCount, nShapesCount);
1863  OSL_FAIL("no shared data set");
1864  if (!pSharedData)
1865  return;
1866  }
1867  ScXMLExportDatabaseRanges aExportDatabaseRanges(*this);
1868  if (!GetModel().is())
1869  return;
1870 
1871  uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
1872  if ( !xSpreadDoc.is() )
1873  return;
1874 
1875  ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetSheetSaveData();
1876  if (pSheetData)
1877  pSheetData->ResetSaveEntries();
1878 
1879  uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
1880  if ( xIndex.is() )
1881  {
1882  //_GetNamespaceMap().ClearQNamesCache();
1883  pChangeTrackingExportHelper->CollectAndWriteChanges();
1884  WriteCalculationSettings(xSpreadDoc);
1885  sal_Int32 nTableCount(xIndex->getCount());
1886  ScMyAreaLinksContainer aAreaLinks;
1887  GetAreaLinks( aAreaLinks );
1888  ScMyEmptyDatabaseRangesContainer aEmptyRanges(aExportDatabaseRanges.GetEmptyDatabaseRanges());
1889  ScMyDetectiveOpContainer aDetectiveOpContainer;
1890  GetDetectiveOpList( aDetectiveOpContainer );
1891 
1892  pCellStyles->Sort();
1893  pMergedRangesContainer->Sort();
1894  pSharedData->GetDetectiveObjContainer()->Sort();
1895 
1896  mpCellsItr->Clear();
1897  mpCellsItr->SetShapes( pSharedData->GetShapesContainer() );
1898  mpCellsItr->SetNoteShapes( pSharedData->GetNoteShapes() );
1899  mpCellsItr->SetMergedRanges( pMergedRangesContainer.get() );
1900  mpCellsItr->SetAreaLinks( &aAreaLinks );
1901  mpCellsItr->SetEmptyDatabaseRanges( &aEmptyRanges );
1902  mpCellsItr->SetDetectiveObj( pSharedData->GetDetectiveObjContainer() );
1903  mpCellsItr->SetDetectiveOp( &aDetectiveOpContainer );
1904 
1905  if (nTableCount > 0)
1906  pValidationsContainer->WriteValidations(*this);
1907  WriteTheLabelRanges( xSpreadDoc );
1908  for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable)
1909  {
1910  sal_Int32 nStartOffset = -1;
1911  sal_Int32 nEndOffset = -1;
1912  if (pSheetData && pDoc && pDoc->IsStreamValid(static_cast<SCTAB>(nTable)) && !pDoc->GetChangeTrack())
1913  pSheetData->GetStreamPos( nTable, nStartOffset, nEndOffset );
1914 
1915  if ( nStartOffset >= 0 && nEndOffset >= 0 && xSourceStream.is() )
1916  {
1917  sal_Int32 nNewStart = -1;
1918  sal_Int32 nNewEnd = -1;
1919  CopySourceStream( nStartOffset, nEndOffset, nNewStart, nNewEnd );
1920 
1921  // store position of copied sheet in output
1922  pSheetData->AddSavePos( nTable, nNewStart, nNewEnd );
1923 
1924  // skip iterator entries for this sheet
1925  mpCellsItr->SkipTable(static_cast<SCTAB>(nTable));
1926  }
1927  else
1928  {
1929  uno::Reference<sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
1930  WriteTable(nTable, xTable);
1931  }
1932  IncrementProgressBar(false);
1933  }
1934  }
1937  WriteDataStream();
1938  aExportDatabaseRanges.WriteDatabaseRanges();
1940  ScXMLExportDataPilot aExportDataPilot(*this);
1941  aExportDataPilot.WriteDataPilots();
1943  ScXMLExportDDELinks aExportDDELinks(*this);
1944  aExportDDELinks.WriteDDELinks(xSpreadDoc);
1945  IncrementProgressBar(true, 0);
1946  GetProgressBarHelper()->SetValue(GetProgressBarHelper()->GetReference());
1947 }
1948 
1949 void ScXMLExport::ExportStyles_( bool bUsed )
1950 {
1951  uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
1952  if (xSpreadDoc.is())
1953  RegisterDefinedStyleNames( xSpreadDoc);
1954 
1955  if (!pSharedData)
1956  {
1957  SCTAB nTableCount(0);
1958  sal_Int32 nShapesCount(0);
1959  CollectSharedData(nTableCount, nShapesCount);
1960  }
1962  if (GetModel().is())
1963  {
1964  uno::Reference <lang::XMultiServiceFactory> xMultiServiceFactory(GetModel(), uno::UNO_QUERY);
1965  if (xMultiServiceFactory.is())
1966  {
1967  uno::Reference <beans::XPropertySet> xProperties(xMultiServiceFactory->createInstance("com.sun.star.sheet.Defaults"), uno::UNO_QUERY);
1968  if (xProperties.is())
1969  aStylesExp->exportDefaultStyle(xProperties, XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME, xCellStylesExportPropertySetMapper);
1970  if (pSharedData->HasShapes())
1971  {
1972  GetShapeExport()->ExportGraphicDefaults();
1973  }
1974  }
1975  collectDataStyles(false);
1976  }
1977  exportDataStyles();
1978 
1979  aStylesExp->exportStyleFamily(OUString("CellStyles"),
1980  OUString(XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME), xCellStylesExportPropertySetMapper, false, XmlStyleFamily::TABLE_CELL);
1981 
1983 }
1984 
1985 void ScXMLExport::AddStyleFromCells(const uno::Reference<beans::XPropertySet>& xProperties,
1986  const uno::Reference<sheet::XSpreadsheet>& xTable,
1987  sal_Int32 nTable, const OUString* pOldName)
1988 {
1989  css::uno::Any aAny = xProperties->getPropertyValue("FormatID");
1990  sal_uInt64 nKey = 0;
1991  aAny >>= nKey;
1992 
1994  uno::Reference<sheet::XSheetCellRanges> xCellRanges( xProperties, uno::UNO_QUERY );
1995 
1996  OUString sStyleName;
1997  sal_Int32 nNumberFormat(-1);
1998  sal_Int32 nValidationIndex(-1);
1999  std::vector< XMLPropertyState > aPropStates(xCellStylesExportPropertySetMapper->Filter( xProperties ));
2000  std::vector< XMLPropertyState >::iterator aItr(aPropStates.begin());
2001  std::vector< XMLPropertyState >::iterator aEndItr(aPropStates.end());
2002  sal_Int32 nCount(0);
2003  while (aItr != aEndItr)
2004  {
2005  if (aItr->mnIndex != -1)
2006  {
2007  switch (xCellStylesPropertySetMapper->GetEntryContextId(aItr->mnIndex))
2008  {
2009  case CTF_SC_VALIDATION :
2010  {
2011  pValidationsContainer->AddValidation(aItr->maValue, nValidationIndex);
2012  // this is not very slow, because it is most the last property or
2013  // if it is not the last property it is the property before the last property,
2014  // so in the worst case only one property has to be copied, but in the best case no
2015  // property has to be copied
2016  aItr = aPropStates.erase(aItr);
2017  aEndItr = aPropStates.end(); // old aEndItr is invalidated!
2018  }
2019  break;
2020  case CTF_SC_CELLSTYLE :
2021  {
2022  aItr->maValue >>= sStyleName;
2023  aItr->mnIndex = -1;
2024  ++aItr;
2025  ++nCount;
2026  }
2027  break;
2028  case CTF_SC_NUMBERFORMAT :
2029  {
2030  if (aItr->maValue >>= nNumberFormat)
2031  addDataStyle(nNumberFormat);
2032  ++aItr;
2033  ++nCount;
2034  }
2035  break;
2036  default:
2037  {
2038  ++aItr;
2039  ++nCount;
2040  }
2041  break;
2042  }
2043  }
2044  else
2045  {
2046  ++aItr;
2047  ++nCount;
2048  }
2049  }
2050  if (nCount == 1) // this is the CellStyle and should be removed if alone
2051  aPropStates.clear();
2052  if (nNumberFormat == -1)
2053  xProperties->getPropertyValue(SC_UNONAME_NUMFMT) >>= nNumberFormat;
2054  if (sStyleName.isEmpty())
2055  return;
2056 
2057  if (!aPropStates.empty())
2058  {
2059  sal_Int32 nIndex;
2060  if (pOldName)
2061  {
2062  if (GetAutoStylePool()->AddNamed(*pOldName, XmlStyleFamily::TABLE_CELL, sStyleName, aPropStates))
2063  {
2064  GetAutoStylePool()->RegisterName(XmlStyleFamily::TABLE_CELL, *pOldName);
2065  // add to pCellStyles, so the name is found for normal sheets
2066  pCellStyles->AddStyleName(*pOldName, nIndex);
2067  }
2068  }
2069  else
2070  {
2071  OUString sName;
2072  bool bAdded = false;
2073  if (nKey)
2074  {
2075  uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
2076  ScFormatSaveData* pFormatData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetFormatSaveData();
2077  auto itr = pFormatData->maIDToName.find(nKey);
2078  if (itr != pFormatData->maIDToName.end())
2079  {
2080  sName = itr->second;
2081  bAdded = GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TABLE_CELL, sStyleName, aPropStates);
2082  if (bAdded)
2083  GetAutoStylePool()->RegisterName(XmlStyleFamily::TABLE_CELL, sName);
2084  }
2085  }
2086  bool bIsAutoStyle(true);
2087  if (bAdded || GetAutoStylePool()->Add(sName, XmlStyleFamily::TABLE_CELL, sStyleName, aPropStates))
2088  {
2089  pCellStyles->AddStyleName(sName, nIndex);
2090  }
2091  else
2092  nIndex = pCellStyles->GetIndexOfStyleName(sName, XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX, bIsAutoStyle);
2093 
2094  const uno::Sequence<table::CellRangeAddress> aAddresses(xCellRanges->getRangeAddresses());
2095  bool bGetMerge(true);
2096  for (table::CellRangeAddress const & address : aAddresses)
2097  {
2098  pSharedData->SetLastColumn(nTable, address.EndColumn);
2099  pSharedData->SetLastRow(nTable, address.EndRow);
2100  pCellStyles->AddRangeStyleName(address, nIndex, bIsAutoStyle, nValidationIndex, nNumberFormat);
2101  if (bGetMerge)
2102  bGetMerge = GetMerged(&address, xTable);
2103  }
2104  }
2105  }
2106  else
2107  {
2108  OUString sEncodedStyleName(EncodeStyleName(sStyleName));
2109  sal_Int32 nIndex(0);
2110  pCellStyles->AddStyleName(sEncodedStyleName, nIndex, false);
2111  if ( !pOldName )
2112  {
2113  const uno::Sequence<table::CellRangeAddress> aAddresses(xCellRanges->getRangeAddresses());
2114  bool bGetMerge(true);
2115  for (table::CellRangeAddress const & address : aAddresses)
2116  {
2117  if (bGetMerge)
2118  bGetMerge = GetMerged(&address, xTable);
2119  pCellStyles->AddRangeStyleName(address, nIndex, false, nValidationIndex, nNumberFormat);
2120  if( sStyleName != "Default" || nValidationIndex != -1 )
2121  {
2122  pSharedData->SetLastColumn(nTable, address.EndColumn);
2123  pSharedData->SetLastRow(nTable, address.EndRow);
2124  }
2125  }
2126  }
2127  }
2128 }
2129 
2130 void ScXMLExport::AddStyleFromColumn(const uno::Reference<beans::XPropertySet>& xColumnProperties,
2131  const OUString* pOldName, sal_Int32& rIndex, bool& rIsVisible)
2132 {
2133  std::vector<XMLPropertyState> aPropStates(xColumnStylesExportPropertySetMapper->Filter(xColumnProperties));
2134  if(aPropStates.empty())
2135  return;
2136 
2137  auto aItr = std::find_if(aPropStates.begin(), aPropStates.end(),
2138  [this](const XMLPropertyState& rPropState) {
2139  return xColumnStylesPropertySetMapper->GetEntryContextId(rPropState.mnIndex) == CTF_SC_ISVISIBLE; });
2140  if (aItr != aPropStates.end())
2141  {
2142  aItr->maValue >>= rIsVisible;
2143  }
2144 
2145  const OUString sParent;
2146  if (pOldName)
2147  {
2148  if (GetAutoStylePool()->AddNamed(*pOldName, XmlStyleFamily::TABLE_COLUMN, sParent, aPropStates))
2149  {
2150  GetAutoStylePool()->RegisterName(XmlStyleFamily::TABLE_COLUMN, *pOldName);
2151  // add to pColumnStyles, so the name is found for normal sheets
2152  rIndex = pColumnStyles->AddStyleName(*pOldName);
2153  }
2154  }
2155  else
2156  {
2157  OUString sName;
2158  if (GetAutoStylePool()->Add(sName, XmlStyleFamily::TABLE_COLUMN, sParent, aPropStates))
2159  {
2160  rIndex = pColumnStyles->AddStyleName(sName);
2161  }
2162  else
2163  rIndex = pColumnStyles->GetIndexOfStyleName(sName, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_PREFIX);
2164  }
2165 }
2166 
2167 void ScXMLExport::AddStyleFromRow(const uno::Reference<beans::XPropertySet>& xRowProperties,
2168  const OUString* pOldName, sal_Int32& rIndex)
2169 {
2170  std::vector<XMLPropertyState> aPropStates(xRowStylesExportPropertySetMapper->Filter(xRowProperties));
2171  if(aPropStates.empty())
2172  return;
2173 
2174  const OUString sParent;
2175  if (pOldName)
2176  {
2177  if (GetAutoStylePool()->AddNamed(*pOldName, XmlStyleFamily::TABLE_ROW, sParent, aPropStates))
2178  {
2179  GetAutoStylePool()->RegisterName(XmlStyleFamily::TABLE_ROW, *pOldName);
2180  // add to pRowStyles, so the name is found for normal sheets
2181  rIndex = pRowStyles->AddStyleName(*pOldName);
2182  }
2183  }
2184  else
2185  {
2186  OUString sName;
2187  if (GetAutoStylePool()->Add(sName, XmlStyleFamily::TABLE_ROW, sParent, aPropStates))
2188  {
2189  rIndex = pRowStyles->AddStyleName(sName);
2190  }
2191  else
2192  rIndex = pRowStyles->GetIndexOfStyleName(sName, XML_STYLE_FAMILY_TABLE_ROW_STYLES_PREFIX);
2193  }
2194 }
2195 
2196 static uno::Any lcl_GetEnumerated( uno::Reference<container::XEnumerationAccess> const & xEnumAccess, sal_Int32 nIndex )
2197 {
2198  uno::Any aRet;
2199  uno::Reference<container::XEnumeration> xEnum( xEnumAccess->createEnumeration() );
2200  try
2201  {
2202  sal_Int32 nSkip = nIndex;
2203  while ( nSkip > 0 )
2204  {
2205  (void) xEnum->nextElement();
2206  --nSkip;
2207  }
2208  aRet = xEnum->nextElement();
2209  }
2210  catch (container::NoSuchElementException&)
2211  {
2212  // leave aRet empty
2213  }
2214  return aRet;
2215 }
2216 
2218 {
2220 
2222  return;
2223 
2224  if (!GetModel().is())
2225  return;
2226 
2227  uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
2228  if (!xSpreadDoc.is())
2229  return;
2230 
2231  uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
2232  if (!xIndex.is())
2233  return;
2234 
2235  if (getExportFlags() & SvXMLExportFlags::CONTENT)
2236  {
2237  // Reserve the loaded cell style names.
2238  RegisterDefinedStyleNames( xSpreadDoc);
2239 
2240  // re-create automatic styles with old names from stored data
2241  ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(xSpreadDoc)->GetSheetSaveData();
2242  if (pSheetData && pDoc)
2243  {
2244  // formulas have to be calculated now, to detect changed results
2245  // (during normal save, they will be calculated anyway)
2246  SCTAB nTabCount = pDoc->GetTableCount();
2247  for (SCTAB nTab=0; nTab<nTabCount; ++nTab)
2248  if (pDoc->IsStreamValid(nTab))
2249  pDoc->InterpretDirtyCells(ScRange(0, 0, nTab, pDoc->MaxCol(), pDoc->MaxRow(), nTab));
2250 
2251  // stored cell styles
2252  const std::vector<ScCellStyleEntry>& rCellEntries = pSheetData->GetCellStyles();
2253  for (const auto& rCellEntry : rCellEntries)
2254  {
2255  ScAddress aPos = rCellEntry.maCellPos;
2256  sal_Int32 nTable = aPos.Tab();
2257  bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2258  if (bCopySheet)
2259  {
2260  uno::Reference <sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2261  uno::Reference <beans::XPropertySet> xProperties(
2262  xTable->getCellByPosition( aPos.Col(), aPos.Row() ), uno::UNO_QUERY );
2263 
2264  AddStyleFromCells(xProperties, xTable, nTable, &rCellEntry.maName);
2265  }
2266  }
2267 
2268  // stored column styles
2269  const std::vector<ScCellStyleEntry>& rColumnEntries = pSheetData->GetColumnStyles();
2270  for (const auto& rColumnEntry : rColumnEntries)
2271  {
2272  ScAddress aPos = rColumnEntry.maCellPos;
2273  sal_Int32 nTable = aPos.Tab();
2274  bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2275  if (bCopySheet)
2276  {
2277  uno::Reference<table::XColumnRowRange> xColumnRowRange(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2278  uno::Reference<table::XTableColumns> xTableColumns(xColumnRowRange->getColumns());
2279  uno::Reference<beans::XPropertySet> xColumnProperties(xTableColumns->getByIndex( aPos.Col() ), uno::UNO_QUERY);
2280 
2281  sal_Int32 nIndex(-1);
2282  bool bIsVisible(true);
2283  AddStyleFromColumn( xColumnProperties, &rColumnEntry.maName, nIndex, bIsVisible );
2284  }
2285  }
2286 
2287  // stored row styles
2288  const std::vector<ScCellStyleEntry>& rRowEntries = pSheetData->GetRowStyles();
2289  for (const auto& rRowEntry : rRowEntries)
2290  {
2291  ScAddress aPos = rRowEntry.maCellPos;
2292  sal_Int32 nTable = aPos.Tab();
2293  bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2294  if (bCopySheet)
2295  {
2296  uno::Reference<table::XColumnRowRange> xColumnRowRange(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2297  uno::Reference<table::XTableRows> xTableRows(xColumnRowRange->getRows());
2298  uno::Reference<beans::XPropertySet> xRowProperties(xTableRows->getByIndex( aPos.Row() ), uno::UNO_QUERY);
2299 
2300  sal_Int32 nIndex(-1);
2301  AddStyleFromRow( xRowProperties, &rRowEntry.maName, nIndex );
2302  }
2303  }
2304 
2305  // stored table styles
2306  const std::vector<ScCellStyleEntry>& rTableEntries = pSheetData->GetTableStyles();
2307  for (const auto& rTableEntry : rTableEntries)
2308  {
2309  ScAddress aPos = rTableEntry.maCellPos;
2310  sal_Int32 nTable = aPos.Tab();
2311  bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2312  if (bCopySheet)
2313  {
2315  uno::Reference<beans::XPropertySet> xTableProperties(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2316  if (xTableProperties.is())
2317  {
2318  std::vector<XMLPropertyState> aPropStates(xTableStylesExportPropertySetMapper->Filter(xTableProperties));
2319  OUString sName( rTableEntry.maName );
2320  GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TABLE_TABLE, OUString(), aPropStates);
2321  GetAutoStylePool()->RegisterName(XmlStyleFamily::TABLE_TABLE, sName);
2322  }
2323  }
2324  }
2325 
2326  // stored styles for notes
2327 
2329  GetShapeExport(); // make sure the graphics styles family is added
2330 
2331  const std::vector<ScNoteStyleEntry>& rNoteEntries = pSheetData->GetNoteStyles();
2332  for (const auto& rNoteEntry : rNoteEntries)
2333  {
2334  ScAddress aPos = rNoteEntry.maCellPos;
2335  SCTAB nTable = aPos.Tab();
2336  bool bCopySheet = pDoc->IsStreamValid( nTable );
2337  if (bCopySheet)
2338  {
2340 
2341  ScPostIt* pNote = pDoc->GetNote(aPos);
2342  OSL_ENSURE( pNote, "note not found" );
2343  if (pNote)
2344  {
2345  SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
2346  // all uno shapes are created anyway in CollectSharedData
2347  uno::Reference<beans::XPropertySet> xShapeProperties( pDrawObj->getUnoShape(), uno::UNO_QUERY );
2348  if (xShapeProperties.is())
2349  {
2350  if ( !rNoteEntry.maStyleName.isEmpty() )
2351  {
2352  std::vector<XMLPropertyState> aPropStates(xShapeMapper->Filter(xShapeProperties));
2353  OUString sName( rNoteEntry.maStyleName );
2354  GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::SD_GRAPHICS_ID, OUString(), aPropStates);
2355  GetAutoStylePool()->RegisterName(XmlStyleFamily::SD_GRAPHICS_ID, sName);
2356  }
2357  if ( !rNoteEntry.maTextStyle.isEmpty() )
2358  {
2359  std::vector<XMLPropertyState> aPropStates(
2360  GetTextParagraphExport()->GetParagraphPropertyMapper()->Filter(xShapeProperties));
2361  OUString sName( rNoteEntry.maTextStyle );
2362  GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TEXT_PARAGRAPH, OUString(), aPropStates);
2363  GetAutoStylePool()->RegisterName(XmlStyleFamily::TEXT_PARAGRAPH, sName);
2364  }
2365  }
2366  }
2367  }
2368  }
2369 
2370  // note paragraph styles
2371 
2372  rtl::Reference<SvXMLExportPropertyMapper> xParaPropMapper = GetTextParagraphExport()->GetParagraphPropertyMapper();
2373 
2374  const std::vector<ScTextStyleEntry>& rNoteParaEntries = pSheetData->GetNoteParaStyles();
2375  for (const auto& rNoteParaEntry : rNoteParaEntries)
2376  {
2377  ScAddress aPos = rNoteParaEntry.maCellPos;
2378  SCTAB nTable = aPos.Tab();
2379  bool bCopySheet = pDoc->IsStreamValid( nTable );
2380  if (bCopySheet)
2381  {
2382  ScPostIt* pNote = pDoc->GetNote( aPos );
2383  OSL_ENSURE( pNote, "note not found" );
2384  if (pNote)
2385  {
2386  SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
2387  uno::Reference<container::XEnumerationAccess> xCellText(pDrawObj->getUnoShape(), uno::UNO_QUERY);
2388  uno::Reference<beans::XPropertySet> xParaProp(
2389  lcl_GetEnumerated( xCellText, rNoteParaEntry.maSelection.nStartPara ), uno::UNO_QUERY );
2390  if ( xParaProp.is() )
2391  {
2392  std::vector<XMLPropertyState> aPropStates(xParaPropMapper->Filter(xParaProp));
2393  OUString sName( rNoteParaEntry.maName );
2394  GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TEXT_PARAGRAPH, OUString(), aPropStates);
2395  GetAutoStylePool()->RegisterName(XmlStyleFamily::TEXT_PARAGRAPH, sName);
2396  }
2397  }
2398  }
2399  }
2400 
2401  // note text styles
2402 
2404 
2405  const std::vector<ScTextStyleEntry>& rNoteTextEntries = pSheetData->GetNoteTextStyles();
2406  for (const auto& rNoteTextEntry : rNoteTextEntries)
2407  {
2408  ScAddress aPos = rNoteTextEntry.maCellPos;
2409  SCTAB nTable = aPos.Tab();
2410  bool bCopySheet = pDoc->IsStreamValid( nTable );
2411  if (bCopySheet)
2412  {
2413  ScPostIt* pNote = pDoc->GetNote( aPos );
2414  OSL_ENSURE( pNote, "note not found" );
2415  if (pNote)
2416  {
2417  SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos );
2418  uno::Reference<text::XSimpleText> xCellText(pDrawObj->getUnoShape(), uno::UNO_QUERY);
2419  uno::Reference<beans::XPropertySet> xCursorProp(xCellText->createTextCursor(), uno::UNO_QUERY);
2420  ScDrawTextCursor* pCursor = comphelper::getUnoTunnelImplementation<ScDrawTextCursor>( xCursorProp );
2421  if (pCursor)
2422  {
2423  pCursor->SetSelection( rNoteTextEntry.maSelection );
2424 
2425  std::vector<XMLPropertyState> aPropStates(xTextPropMapper->Filter(xCursorProp));
2426  OUString sName( rNoteTextEntry.maName );
2427  GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TEXT_TEXT, OUString(), aPropStates);
2428  GetAutoStylePool()->RegisterName(XmlStyleFamily::TEXT_TEXT, sName);
2429  }
2430  }
2431  }
2432  }
2433 
2434  // stored text styles
2435 
2436  // Calling createTextCursor fires up editeng, which is very slow, and often subsequent style entries
2437  // refer to the same cell, so cache it.
2438  ScAddress aPrevPos;
2439  uno::Reference<beans::XPropertySet> xPrevCursorProp;
2440  const std::vector<ScTextStyleEntry>& rTextEntries = pSheetData->GetTextStyles();
2441  for (const auto& rTextEntry : rTextEntries)
2442  {
2443  ScAddress aPos = rTextEntry.maCellPos;
2444  sal_Int32 nTable = aPos.Tab();
2445  bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) );
2446  if (!bCopySheet)
2447  continue;
2448 
2451 
2452  uno::Reference<beans::XPropertySet> xCursorProp;
2453  if (xPrevCursorProp && aPrevPos == aPos)
2454  xCursorProp = xPrevCursorProp;
2455  else
2456  {
2457  uno::Reference<table::XCellRange> xCellRange(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2458  uno::Reference<text::XSimpleText> xCellText(xCellRange->getCellByPosition(aPos.Col(), aPos.Row()), uno::UNO_QUERY);
2459  xCursorProp.set(xCellText->createTextCursor(), uno::UNO_QUERY);
2460  }
2461  ScCellTextCursor* pCursor = comphelper::getUnoTunnelImplementation<ScCellTextCursor>( xCursorProp );
2462  if (!pCursor)
2463  continue;
2464  pCursor->SetSelection( rTextEntry.maSelection );
2465 
2466  std::vector<XMLPropertyState> aPropStates(xTextPropMapper->Filter(xCursorProp));
2467  OUString sName( rTextEntry.maName );
2468  GetAutoStylePool()->AddNamed(sName, XmlStyleFamily::TEXT_TEXT, OUString(), aPropStates);
2469  GetAutoStylePool()->RegisterName(XmlStyleFamily::TEXT_TEXT, sName);
2470  xPrevCursorProp = xCursorProp;
2471  aPrevPos = aPos;
2472  }
2473  }
2474 
2476 
2477  if (!pSharedData)
2478  {
2479  SCTAB nTableCount(0);
2480  sal_Int32 nShapesCount(0);
2481  CollectSharedData(nTableCount, nShapesCount);
2482  }
2483  sal_Int32 nTableCount(xIndex->getCount());
2484  pCellStyles->AddNewTable(nTableCount - 1);
2485  CollectShapesAutoStyles(nTableCount);
2486  for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable, IncrementProgressBar(false))
2487  {
2488  uno::Reference <sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY);
2489  if (!xTable.is())
2490  continue;
2491 
2492  // table styles array must be complete, including copied tables - Add should find the stored style
2493  uno::Reference<beans::XPropertySet> xTableProperties(xTable, uno::UNO_QUERY);
2494  if (xTableProperties.is())
2495  {
2496  std::vector<XMLPropertyState> aPropStates(xTableStylesExportPropertySetMapper->Filter(xTableProperties));
2497  if(!aPropStates.empty())
2498  {
2499  OUString sName;
2500  GetAutoStylePool()->Add(sName, XmlStyleFamily::TABLE_TABLE, OUString(), aPropStates);
2501  aTableStyles.push_back(sName);
2502  }
2503  }
2504 
2505  // collect other auto-styles only for non-copied sheets
2506  uno::Reference<sheet::XUniqueCellFormatRangesSupplier> xCellFormatRanges ( xTable, uno::UNO_QUERY );
2507  if ( xCellFormatRanges.is() )
2508  {
2509  uno::Reference<container::XIndexAccess> xFormatRangesIndex(xCellFormatRanges->getUniqueCellFormatRanges());
2510  if (xFormatRangesIndex.is())
2511  {
2512  sal_Int32 nFormatRangesCount(xFormatRangesIndex->getCount());
2513  GetProgressBarHelper()->ChangeReference(GetProgressBarHelper()->GetReference() + nFormatRangesCount);
2514  for (sal_Int32 nFormatRange = 0; nFormatRange < nFormatRangesCount; ++nFormatRange)
2515  {
2516  uno::Reference< sheet::XSheetCellRanges> xCellRanges(xFormatRangesIndex->getByIndex(nFormatRange), uno::UNO_QUERY);
2517  if (xCellRanges.is())
2518  {
2519  uno::Reference <beans::XPropertySet> xProperties (xCellRanges, uno::UNO_QUERY);
2520  if (xProperties.is())
2521  {
2522  AddStyleFromCells(xProperties, xTable, nTable, nullptr);
2523  IncrementProgressBar(false);
2524  }
2525  }
2526  }
2527  }
2528  }
2529  uno::Reference<table::XColumnRowRange> xColumnRowRange (xTable, uno::UNO_QUERY);
2530  if (xColumnRowRange.is() && pDoc)
2531  {
2532  pDoc->SyncColRowFlags();
2533  uno::Reference<table::XTableColumns> xTableColumns(xColumnRowRange->getColumns());
2534  if (xTableColumns.is())
2535  {
2536  sal_Int32 nColumns(pDoc->GetLastChangedCol(sal::static_int_cast<SCTAB>(nTable)));
2537  pSharedData->SetLastColumn(nTable, nColumns);
2538  table::CellRangeAddress aCellAddress(GetEndAddress(xTable));
2539  if (aCellAddress.EndColumn > nColumns)
2540  {
2541  ++nColumns;
2542  pColumnStyles->AddNewTable(nTable, aCellAddress.EndColumn);
2543  }
2544  else
2545  pColumnStyles->AddNewTable(nTable, nColumns);
2546  sal_Int32 nColumn = 0;
2547  while (nColumn <= pDoc->MaxCol())
2548  {
2549  sal_Int32 nIndex(-1);
2550  bool bIsVisible(true);
2551  uno::Reference <beans::XPropertySet> xColumnProperties(xTableColumns->getByIndex(nColumn), uno::UNO_QUERY);
2552  if (xColumnProperties.is())
2553  {
2554  AddStyleFromColumn( xColumnProperties, nullptr, nIndex, bIsVisible );
2555  pColumnStyles->AddFieldStyleName(nTable, nColumn, nIndex, bIsVisible);
2556  }
2557  sal_Int32 nOld(nColumn);
2558  nColumn = pDoc->GetNextDifferentChangedCol(sal::static_int_cast<SCTAB>(nTable), static_cast<SCCOL>(nColumn));
2559  for (sal_Int32 i = nOld + 1; i < nColumn; ++i)
2560  pColumnStyles->AddFieldStyleName(nTable, i, nIndex, bIsVisible);
2561  }
2562  if (aCellAddress.EndColumn > nColumns)
2563  {
2564  bool bIsVisible(true);
2565  sal_Int32 nIndex(pColumnStyles->GetStyleNameIndex(nTable, nColumns, bIsVisible));
2566  for (sal_Int32 i = nColumns + 1; i <= aCellAddress.EndColumn; ++i)
2567  pColumnStyles->AddFieldStyleName(nTable, i, nIndex, bIsVisible);
2568  }
2569  }
2570  uno::Reference<table::XTableRows> xTableRows(xColumnRowRange->getRows());
2571  if (xTableRows.is())
2572  {
2573  sal_Int32 nRows(pDoc->GetLastChangedRow(sal::static_int_cast<SCTAB>(nTable)));
2574  pSharedData->SetLastRow(nTable, nRows);
2575 
2576  pRowStyles->AddNewTable(nTable, pDoc->MaxRow());
2577  sal_Int32 nRow = 0;
2578  while (nRow <= pDoc->MaxRow())
2579  {
2580  sal_Int32 nIndex = 0;
2581  uno::Reference <beans::XPropertySet> xRowProperties(xTableRows->getByIndex(nRow), uno::UNO_QUERY);
2582  if(xRowProperties.is())
2583  {
2584  AddStyleFromRow( xRowProperties, nullptr, nIndex );
2585  pRowStyles->AddFieldStyleName(nTable, nRow, nIndex);
2586  }
2587  sal_Int32 nOld(nRow);
2588  nRow = pDoc->GetNextDifferentChangedRow(sal::static_int_cast<SCTAB>(nTable), static_cast<SCROW>(nRow));
2589  if (nRow > nOld + 1)
2590  pRowStyles->AddFieldStyleName(nTable, nOld + 1, nIndex, nRow - 1);
2591  }
2592  }
2593  }
2594  ExportCellTextAutoStyles(nTable);
2595  }
2596 
2597  pChangeTrackingExportHelper->CollectAutoStyles();
2598  }
2599 
2600  if (getExportFlags() & SvXMLExportFlags::MASTERSTYLES)
2601  GetPageExport()->collectAutoStyles(true);
2602 
2603  mbAutoStylesCollected = true;
2604 }
2605 
2607 {
2608  if (!GetModel().is())
2609  return;
2610 
2611  uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
2612  if (!xSpreadDoc.is())
2613  return;
2614 
2615  uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
2616  if (!xIndex.is())
2617  return;
2618 
2620 
2621  if (getExportFlags() & SvXMLExportFlags::CONTENT)
2622  {
2623  GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_COLUMN);
2624  GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_ROW);
2625  GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_TABLE);
2627  GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_CELL);
2628 
2629  GetShapeExport()->exportAutoStyles();
2630  GetFormExport()->exportAutoStyles( );
2631 
2632  if (pDoc)
2633  {
2635  // #i100879# write the table style for cached tables only if there are cached tables
2636  // (same logic as in ExportExternalRefCacheStyles)
2637  if (pRefMgr->hasExternalData())
2638  {
2639  // Special table style for the external ref cache tables.
2642  SvXMLElementExport aElemStyle(*this, XML_NAMESPACE_STYLE, XML_STYLE, true, true);
2644  SvXMLElementExport aElemStyleTabProps(*this, XML_NAMESPACE_STYLE, XML_TABLE_PROPERTIES, true, true);
2645  }
2646  }
2647  }
2648 
2649  if (getExportFlags() & SvXMLExportFlags::MASTERSTYLES)
2650  {
2652  GetPageExport()->exportAutoStyles();
2653  }
2654 
2655  // #i30251#; only write Text Styles once
2656 
2657  if ((getExportFlags() & SvXMLExportFlags::CONTENT) || (getExportFlags() & SvXMLExportFlags::MASTERSTYLES))
2658  GetTextParagraphExport()->exportTextAutoStyles();
2659 }
2660 
2662 {
2663  GetPageExport()->exportMasterStyles( true );
2664 }
2665 
2666 void ScXMLExport::CollectInternalShape( uno::Reference< drawing::XShape > const & xShape )
2667 {
2668  // detective objects and notes
2670  if( !pObject )
2671  return;
2672 
2673  // collect note caption objects from all layers (internal or hidden)
2674  if( ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( pObject, static_cast< SCTAB >( nCurrentTable ) ) )
2675  {
2676  if(pDoc->GetNote(pCaptData->maStart))
2677  {
2678  pSharedData->AddNoteObj( xShape, pCaptData->maStart );
2679 
2680  // #i60851# When the file is saved while editing a new note,
2681  // the cell is still empty -> last column/row must be updated
2682  OSL_ENSURE( pCaptData->maStart.Tab() == nCurrentTable, "invalid table in object data" );
2683  pSharedData->SetLastColumn( nCurrentTable, pCaptData->maStart.Col() );
2684  pSharedData->SetLastRow( nCurrentTable, pCaptData->maStart.Row() );
2685  }
2686  }
2687  // other objects from internal layer only (detective)
2688  else if( pObject->GetLayer() == SC_LAYER_INTERN )
2689  {
2690  ScDetectiveFunc aDetFunc( *pDoc, static_cast<SCTAB>(nCurrentTable) );
2691  ScAddress aPosition;
2692  ScRange aSourceRange;
2693  bool bRedLine;
2694  ScDetectiveObjType eObjType = aDetFunc.GetDetectiveObjectType(
2695  pObject, nCurrentTable, aPosition, aSourceRange, bRedLine );
2696  pSharedData->GetDetectiveObjContainer()->AddObject( eObjType, static_cast<SCTAB>(nCurrentTable), aPosition, aSourceRange, bRedLine );
2697  }
2698 }
2699 
2700 bool ScXMLExport::GetMerged (const table::CellRangeAddress* pCellAddress,
2701  const uno::Reference <sheet::XSpreadsheet>& xTable)
2702 {
2703  bool bReady(false);
2704  sal_Int32 nRow(pCellAddress->StartRow);
2705  sal_Int32 nCol(pCellAddress->StartColumn);
2706  sal_Int32 nEndRow(pCellAddress->EndRow);
2707  sal_Int32 nEndCol(pCellAddress->EndColumn);
2708  bool bRowInc(nEndRow > nRow);
2709  while(!bReady && nRow <= nEndRow && nCol <= nEndCol)
2710  {
2711  uno::Reference<sheet::XSheetCellRange> xSheetCellRange(xTable->getCellRangeByPosition(nCol, nRow, nCol, nRow), uno::UNO_QUERY);
2712  if (xSheetCellRange.is())
2713  {
2714  uno::Reference<sheet::XSheetCellCursor> xCursor(xTable->createCursorByRange(xSheetCellRange));
2715  if(xCursor.is())
2716  {
2717  uno::Reference<sheet::XCellRangeAddressable> xCellAddress (xCursor, uno::UNO_QUERY);
2718  xCursor->collapseToMergedArea();
2719  table::CellRangeAddress aCellAddress2(xCellAddress->getRangeAddress());
2720  ScRange aScRange( aCellAddress2.StartColumn, aCellAddress2.StartRow, aCellAddress2.Sheet,
2721  aCellAddress2.EndColumn, aCellAddress2.EndRow, aCellAddress2.Sheet );
2722 
2723  if ((aScRange.aEnd.Row() > nRow ||
2724  aScRange.aEnd.Col() > nCol) &&
2725  aScRange.aStart.Row() == nRow &&
2726  aScRange.aStart.Col() == nCol)
2727  {
2728  pMergedRangesContainer->AddRange(aScRange);
2729  pSharedData->SetLastColumn(aScRange.aEnd.Tab(), aScRange.aEnd.Col());
2730  pSharedData->SetLastRow(aScRange.aEnd.Tab(), aScRange.aEnd.Row());
2731  }
2732  else
2733  bReady = true;
2734  }
2735  }
2736  if (!bReady)
2737  {
2738  if (bRowInc)
2739  ++nRow;
2740  else
2741  ++nCol;
2742  }
2743  }
2744  OSL_ENSURE(!(!bReady && nEndRow > nRow && nEndCol > nCol), "should not be possible");
2745  return !bReady;
2746 }
2747 
2749  ScRange& aCellAddress, bool& bIsFirst) const
2750 {
2751  bIsFirst = false;
2752 
2753  ScRange aMatrixRange;
2754 
2755  if (pDoc && pDoc->GetMatrixFormulaRange(aCell, aMatrixRange))
2756  {
2757  aCellAddress = aMatrixRange;
2758  if ((aCellAddress.aStart.Col() == aCell.Col() && aCellAddress.aStart.Row() == aCell.Row()) &&
2759  (aCellAddress.aEnd.Col() > aCell.Col() || aCellAddress.aEnd.Row() > aCell.Row()))
2760  {
2761  bIsFirst = true;
2762  return true;
2763  }
2764  else if (aCellAddress.aStart.Col() != aCell.Col() || aCellAddress.aStart.Row() != aCell.Row() ||
2765  aCellAddress.aEnd.Col() != aCell.Col() || aCellAddress.aEnd.Row()!= aCell.Row())
2766  return true;
2767  else
2768  {
2769  bIsFirst = true;
2770  return true;
2771  }
2772  }
2773 
2774  return false;
2775 }
2776 
2777 void ScXMLExport::WriteTable(sal_Int32 nTable, const uno::Reference<sheet::XSpreadsheet>& xTable)
2778 {
2779  if (!xTable.is())
2780  return;
2781 
2782  xCurrentTable.set(xTable);
2783  uno::Reference<container::XNamed> xName (xTable, uno::UNO_QUERY );
2784  if (!xName.is())
2785  return;
2786 
2787  nCurrentTable = sal::static_int_cast<sal_uInt16>( nTable );
2788  OUString sOUTableName(xName->getName());
2789  AddAttribute(sAttrName, sOUTableName);
2791 
2792  uno::Reference<util::XProtectable> xProtectable (xTable, uno::UNO_QUERY);
2793  const ScTableProtection* pProtect = nullptr;
2794  if (xProtectable.is() && xProtectable->isProtected())
2795  {
2797  if (pDoc)
2798  {
2799  pProtect = pDoc->GetTabProtection(nTable);
2800  if (pProtect)
2801  {
2802  OUStringBuffer aBuffer;
2804  if (pProtect->hasPasswordHash(PASSHASH_SHA1))
2805  {
2807  pProtect->getPasswordHash(PASSHASH_SHA1));
2808  eHashUsed = PASSHASH_SHA1;
2809  }
2810  else if (pProtect->hasPasswordHash(PASSHASH_SHA256))
2811  {
2813  pProtect->getPasswordHash(PASSHASH_SHA256));
2814  eHashUsed = PASSHASH_SHA256;
2815  }
2816  else if (pProtect->hasPasswordHash(PASSHASH_XL, PASSHASH_SHA1))
2817  {
2818  // Double-hash this by SHA1 on top of the legacy xls hash.
2819  uno::Sequence<sal_Int8> aHash = pProtect->getPasswordHash(PASSHASH_XL, PASSHASH_SHA1);
2820  ::comphelper::Base64::encode(aBuffer, aHash);
2821  eHashUsed = PASSHASH_XL;
2822  }
2823  if (!aBuffer.isEmpty())
2824  {
2825  AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
2827  {
2828  if (eHashUsed == PASSHASH_XL)
2829  {
2835  }
2836  else if (eHashUsed == PASSHASH_SHA1)
2837  {
2840  }
2841  else if (eHashUsed == PASSHASH_SHA256)
2842  {
2845  }
2846  }
2847  }
2848  }
2849  }
2850  }
2851  OUString sPrintRanges;
2852  ScRange aColumnHeaderRange;
2853  bool bHasColumnHeader;
2854  GetColumnRowHeader(bHasColumnHeader, aColumnHeaderRange, bHasRowHeader, aRowHeaderRange, sPrintRanges);
2855  if( !sPrintRanges.isEmpty() )
2857  else if (pDoc && !pDoc->IsPrintEntireSheet(static_cast<SCTAB>(nTable)))
2859  SvXMLElementExport aElemT(*this, sElemTab, true, true);
2860 
2861  if (pProtect && pProtect->isProtected() && getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2862  {
2867 
2872 
2877 
2878  OUString aElemName = GetNamespaceMap().GetQNameByKey(
2880 
2881  SvXMLElementExport aElemProtected(*this, aElemName, true, true);
2882  }
2883 
2884  CheckAttrList();
2885 
2886  if ( pDoc && pDoc->GetSheetEvents( static_cast<SCTAB>(nTable) ) &&
2888  {
2889  // store sheet events
2890  uno::Reference<document::XEventsSupplier> xSupplier(xTable, uno::UNO_QUERY);
2891  uno::Reference<container::XNameAccess> xEvents = xSupplier->getEvents();
2892  GetEventExport().ExportExt( xEvents );
2893  }
2894 
2895  WriteTableSource();
2896  WriteScenario();
2897  uno::Reference<drawing::XDrawPage> xDrawPage;
2898  if (pSharedData->HasForm(nTable, xDrawPage) && xDrawPage.is())
2899  {
2900  ::xmloff::OOfficeFormsExport aForms(*this);
2901  GetFormExport()->exportForms( xDrawPage );
2902  bool bRet(GetFormExport()->seekPage( xDrawPage ));
2903  OSL_ENSURE( bRet, "OFormLayerXMLExport::seekPage failed!" );
2904  }
2905  if (pSharedData->HasDrawPage())
2906  {
2907  GetShapeExport()->seekShapes(pSharedData->GetDrawPage(nTable));
2908  WriteTableShapes();
2909  }
2910  table::CellRangeAddress aRange(GetEndAddress(xTable));
2911  pSharedData->SetLastColumn(nTable, aRange.EndColumn);
2912  pSharedData->SetLastRow(nTable, aRange.EndRow);
2913  mpCellsItr->SetCurrentTable(static_cast<SCTAB>(nTable), xCurrentTable);
2914  pGroupColumns->NewTable();
2915  pGroupRows->NewTable();
2917  if (bHasColumnHeader)
2918  pSharedData->SetLastColumn(nTable, aColumnHeaderRange.aEnd.Col());
2919  bRowHeaderOpen = false;
2920  if (bHasRowHeader)
2921  pSharedData->SetLastRow(nTable, aRowHeaderRange.aEnd.Row());
2922  pDefaults->FillDefaultStyles(nTable, pSharedData->GetLastRow(nTable),
2923  pSharedData->GetLastColumn(nTable), pCellStyles.get(), pDoc);
2924  pRowFormatRanges->SetColDefaults(&pDefaults->GetColDefaults());
2925  pCellStyles->SetColDefaults(&pDefaults->GetColDefaults());
2926  ExportColumns(nTable, aColumnHeaderRange, bHasColumnHeader);
2927  bool bIsFirst(true);
2928  sal_Int32 nEqualCells(0);
2929  ScMyCell aCell;
2930  ScMyCell aPrevCell;
2931  while (mpCellsItr->GetNext(aCell, pCellStyles.get()))
2932  {
2933  if (bIsFirst)
2934  {
2935  ExportFormatRanges(0, 0, aCell.maCellAddress.Col()-1, aCell.maCellAddress.Row(), nTable);
2936  aPrevCell = aCell;
2937  bIsFirst = false;
2938  }
2939  else
2940  {
2941  if ((aPrevCell.maCellAddress.Row() == aCell.maCellAddress.Row()) &&
2942  (aPrevCell.maCellAddress.Col() + nEqualCells + 1 == aCell.maCellAddress.Col()))
2943  {
2944  if(IsCellEqual(aPrevCell, aCell))
2945  ++nEqualCells;
2946  else
2947  {
2948  WriteCell(aPrevCell, nEqualCells);
2949  nEqualCells = 0;
2950  aPrevCell = aCell;
2951  }
2952  }
2953  else
2954  {
2955  WriteCell(aPrevCell, nEqualCells);
2956  ExportFormatRanges(aPrevCell.maCellAddress.Col() + nEqualCells + 1, aPrevCell.maCellAddress.Row(),
2957  aCell.maCellAddress.Col()-1, aCell.maCellAddress.Row(), nTable);
2958  nEqualCells = 0;
2959  aPrevCell = aCell;
2960  }
2961  }
2962  }
2963  if (!bIsFirst)
2964  {
2965  WriteCell(aPrevCell, nEqualCells);
2966  ExportFormatRanges(aPrevCell.maCellAddress.Col() + nEqualCells + 1, aPrevCell.maCellAddress.Row(),
2967  pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
2968  }
2969  else
2970  ExportFormatRanges(0, 0, pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
2971 
2972  CloseRow(pSharedData->GetLastRow(nTable));
2973 
2974  if (!pDoc)
2975  return;
2976 
2977  // Export sheet-local named ranges.
2978  ScRangeName* pRangeName = pDoc->GetRangeName(nTable);
2979  if (pRangeName && !pRangeName->empty())
2980  {
2981  WriteNamedRange(pRangeName);
2982  }
2983 
2985  {
2986  //export new conditional format information
2987  ExportConditionalFormat(nTable);
2988  }
2989 }
2990 
2991 namespace {
2992 
2993 void writeContent(
2994  ScXMLExport& rExport, const OUString& rStyleName, const OUString& rContent, const SvxFieldData* pField )
2995 {
2996  std::unique_ptr<SvXMLElementExport> pElem;
2997  if (!rStyleName.isEmpty())
2998  {
2999  // Formatted section with automatic style.
3000  rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME, rStyleName);
3001  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3002  XML_NAMESPACE_TEXT, GetXMLToken(XML_SPAN));
3003  pElem.reset(new SvXMLElementExport(rExport, aElemName, false, false));
3004  }
3005 
3006  if (pField)
3007  {
3008  // Write a field item.
3009  OUString aFieldVal = ScEditUtil::GetCellFieldValue(*pField, rExport.GetDocument(), nullptr);
3010  switch (pField->GetClassId())
3011  {
3012  case text::textfield::Type::URL:
3013  {
3014  // <text:a xlink:href="url" xlink:type="simple">value</text:a>
3015 
3016  const SvxURLField* pURLField = static_cast<const SvxURLField*>(pField);
3017  const OUString& aURL = pURLField->GetURL();
3018  rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, rExport.GetRelativeReference(aURL));
3019  rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, "simple");
3020  const OUString& aTargetFrame = pURLField->GetTargetFrame();
3021  if (!aTargetFrame.isEmpty())
3022  rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_TARGET_FRAME_NAME, aTargetFrame);
3023 
3024  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3025  XML_NAMESPACE_TEXT, GetXMLToken(XML_A));
3026  SvXMLElementExport aElem(rExport, aElemName, false, false);
3027  rExport.Characters(aFieldVal);
3028  }
3029  break;
3031  {
3032  // <text:date style:data-style-name="N2" text:date-value="YYYY-MM-DD">value</text:date>
3033 
3034  Date aDate(Date::SYSTEM);
3035  OUStringBuffer aBuf;
3036  sal_Int32 nVal = aDate.GetYear();
3037  aBuf.append(nVal);
3038  aBuf.append('-');
3039  nVal = aDate.GetMonth();
3040  if (nVal < 10)
3041  aBuf.append('0');
3042  aBuf.append(nVal);
3043  aBuf.append('-');
3044  nVal = aDate.GetDay();
3045  if (nVal < 10)
3046  aBuf.append('0');
3047  aBuf.append(nVal);
3048  rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_DATA_STYLE_NAME, "N2");
3049  rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_DATE_VALUE, aBuf.makeStringAndClear());
3050 
3051  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3052  XML_NAMESPACE_TEXT, GetXMLToken(XML_DATE));
3053  SvXMLElementExport aElem(rExport, aElemName, false, false);
3054  rExport.Characters(aFieldVal);
3055  }
3056  break;
3057  case text::textfield::Type::DOCINFO_TITLE:
3058  {
3059  // <text:title>value</text:title>
3060 
3061  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3062  XML_NAMESPACE_TEXT, GetXMLToken(XML_TITLE));
3063  SvXMLElementExport aElem(rExport, aElemName, false, false);
3064  rExport.Characters(aFieldVal);
3065  }
3066  break;
3068  {
3069  // <text:sheet-name>value</text:sheet-name>
3070 
3071  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3072  XML_NAMESPACE_TEXT, GetXMLToken(XML_SHEET_NAME));
3073  SvXMLElementExport aElem(rExport, aElemName, false, false);
3074  rExport.Characters(aFieldVal);
3075  }
3076  break;
3077  default:
3078  rExport.Characters(aFieldVal);
3079  }
3080  }
3081  else
3082  rExport.Characters(rContent);
3083 }
3084 
3085 void flushParagraph(
3086  ScXMLExport& rExport, const OUString& rParaText,
3088  const ScXMLEditAttributeMap& rAttrMap,
3089  std::vector<editeng::Section>::const_iterator it, std::vector<editeng::Section>::const_iterator const & itEnd )
3090 {
3091  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3092  XML_NAMESPACE_TEXT, GetXMLToken(XML_P));
3093  SvXMLElementExport aElemP(rExport, aElemName, false, false);
3094 
3095  for (; it != itEnd; ++it)
3096  {
3097  const editeng::Section& rSec = *it;
3098 
3099  OUString aContent(rParaText.copy(rSec.mnStart, rSec.mnEnd - rSec.mnStart));
3100 
3101  std::vector<XMLPropertyState> aPropStates;
3102  const SvxFieldData* pField = toXMLPropertyStates(aPropStates, rSec.maAttributes, xMapper, rAttrMap);
3103  OUString aStyleName = xStylePool->Find(XmlStyleFamily::TEXT_TEXT, OUString(), aPropStates);
3104  writeContent(rExport, aStyleName, aContent, pField);
3105  }
3106 }
3107 
3108 }
3109 
3110 void ScXMLExport::WriteCell(ScMyCell& aCell, sal_Int32 nEqualCellCount)
3111 {
3112  // nEqualCellCount is the number of additional cells
3113  SetRepeatAttribute(nEqualCellCount, (aCell.nType != table::CellContentType_EMPTY));
3114 
3115  if (aCell.nStyleIndex != -1)
3116  AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(aCell.nStyleIndex, aCell.bIsAutoStyle));
3117  if (aCell.nValidationIndex > -1)
3119  const bool bIsFirstMatrixCell(aCell.bIsMatrixBase);
3120  if (bIsFirstMatrixCell)
3121  {
3122  SCCOL nColumns( aCell.aMatrixRange.aEnd.Col() - aCell.aMatrixRange.aStart.Col() + 1 );
3123  SCROW nRows( aCell.aMatrixRange.aEnd.Row() - aCell.aMatrixRange.aStart.Row() + 1 );
3126  }
3127  bool bIsEmpty(false);
3128  switch (aCell.nType)
3129  {
3130  case table::CellContentType_EMPTY :
3131  {
3132  bIsEmpty = true;
3133  }
3134  break;
3135  case table::CellContentType_VALUE :
3136  {
3138  aCell.nNumberFormat, aCell.maBaseCell.mfValue);
3141  aCell.nNumberFormat, aCell.maBaseCell.mfValue, false, XML_NAMESPACE_CALC_EXT, false);
3142  }
3143  break;
3144  case table::CellContentType_TEXT :
3145  {
3146  OUString sFormattedString(lcl_GetFormattedString(pDoc, aCell.maBaseCell, aCell.maCellAddress));
3147  OUString sCellString = aCell.maBaseCell.getString(pDoc);
3149  sCellString, sFormattedString);
3152  sCellString, sFormattedString, false, XML_NAMESPACE_CALC_EXT);
3153  }
3154  break;
3155  case table::CellContentType_FORMULA :
3156  {
3157  if (aCell.maBaseCell.meType == CELLTYPE_FORMULA)
3158  {
3159  const bool bIsMatrix(bIsFirstMatrixCell || aCell.bIsMatrixCovered);
3160  ScFormulaCell* pFormulaCell = aCell.maBaseCell.mpFormula;
3161  if (!bIsMatrix || bIsFirstMatrixCell)
3162  {
3163  if (!mpCompileFormulaCxt)
3164  {
3166  mpCompileFormulaCxt.reset(new sc::CompileFormulaContext(*pDoc, eGrammar));
3167  }
3168 
3169  OUString aFormula = pFormulaCell->GetFormula(*mpCompileFormulaCxt);
3170  sal_uInt16 nNamespacePrefix =
3172 
3173  if (!bIsMatrix)
3174  {
3175  AddAttribute(sAttrFormula, GetNamespaceMap().GetQNameByKey(nNamespacePrefix, aFormula, false));
3176  }
3177  else
3178  {
3179  AddAttribute(sAttrFormula, GetNamespaceMap().GetQNameByKey(nNamespacePrefix, aFormula.copy(1, aFormula.getLength()-2), false));
3180  }
3181  }
3182  if (pFormulaCell->GetErrCode() != FormulaError::NONE)
3183  {
3187  {
3188  //export calcext:value-type="error"
3190  }
3191  }
3192  else if (pFormulaCell->IsValue())
3193  {
3194  bool bIsStandard;
3195  OUString sCurrency;
3196  GetNumberFormatAttributesExportHelper()->GetCellType(aCell.nNumberFormat, sCurrency, bIsStandard);
3197  if (pDoc)
3198  {
3200  aCell.nNumberFormat, pDoc->GetValue(aCell.maCellAddress));
3202  {
3204  aCell.nNumberFormat, pDoc->GetValue(aCell.maCellAddress), false, XML_NAMESPACE_CALC_EXT, false );
3205  }
3206  }
3207  }
3208  else
3209  {
3210  if (!aCell.maBaseCell.getString(pDoc).isEmpty())
3211  {
3215  {
3217  }
3218  }
3219  }
3220  }
3221  }
3222  break;
3223  default:
3224  break;
3225  }
3226  OUString* pCellString(&sElemCell);
3227  if (aCell.bIsCovered)
3228  {
3229  pCellString = &sElemCoveredCell;
3230  }
3231  else
3232  {
3233  if (aCell.bIsMergedBase)
3234  {
3235  SCCOL nColumns( aCell.aMergeRange.aEnd.Col() - aCell.aMergeRange.aStart.Col() + 1 );
3236  SCROW nRows( aCell.aMergeRange.aEnd.Row() - aCell.aMergeRange.aStart.Row() + 1 );
3237  AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED, OUString::number(nColumns));
3238  AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED, OUString::number(nRows));
3239  }
3240  }
3241  SvXMLElementExport aElemC(*this, *pCellString, true, true);
3242  CheckAttrList();
3243  WriteAreaLink(aCell);
3244  WriteAnnotation(aCell);
3245  WriteDetective(aCell);
3246 
3247  if (!bIsEmpty)
3248  {
3249  if (aCell.maBaseCell.meType == CELLTYPE_EDIT)
3250  {
3252  }
3254  {
3256  }
3257  else
3258  {
3259  SvXMLElementExport aElemP(*this, sElemP, true, false);
3260 
3261  OUString aParaStr =
3263 
3264  bool bPrevCharWasSpace = true;
3265  GetTextParagraphExport()->exportCharacterData(aParaStr, bPrevCharWasSpace);
3266  }
3267  }
3268  WriteShapes(aCell);
3269  if (!bIsEmpty)
3270  IncrementProgressBar(false);
3271 }
3272 
3274 {
3275  rtl::Reference<XMLPropertySetMapper> xMapper = GetTextParagraphExport()->GetTextPropMapper()->getPropertySetMapper();
3277  const ScXMLEditAttributeMap& rAttrMap = GetEditAttributeMap();
3278 
3279  // Get raw paragraph texts first.
3280  std::vector<OUString> aParaTexts;
3281  sal_Int32 nParaCount = pText->GetParagraphCount();
3282  aParaTexts.reserve(nParaCount);
3283  for (sal_Int32 i = 0; i < nParaCount; ++i)
3284  aParaTexts.push_back(pText->GetText(i));
3285 
3286  // Get all section data and iterate through them.
3287  std::vector<editeng::Section> aAttrs;
3288  pText->GetAllSections(aAttrs);
3289  std::vector<editeng::Section>::const_iterator itSec = aAttrs.begin(), itSecEnd = aAttrs.end();
3290  std::vector<editeng::Section>::const_iterator itPara = itSec;
3291  sal_Int32 nCurPara = 0; // current paragraph
3292  for (; itSec != itSecEnd; ++itSec)
3293  {
3294  const editeng::Section& rSec = *itSec;
3295  if (nCurPara == rSec.mnParagraph)
3296  // Still in the same paragraph.
3297  continue;
3298 
3299  // Start of a new paragraph. Flush the old paragraph.
3300  flushParagraph(*this, aParaTexts[nCurPara], xMapper, xStylePool, rAttrMap, itPara, itSec);
3301  nCurPara = rSec.mnParagraph;
3302  itPara = itSec;
3303  }
3304 
3305  flushParagraph(*this, aParaTexts[nCurPara], xMapper, xStylePool, rAttrMap, itPara, itSecEnd);
3306 }
3307 
3309 {
3311 
3312  OUString aResStr = pCell->GetResultString().getString();
3313  const sal_Unicode* p = aResStr.getStr();
3314  const sal_Unicode* pEnd = p + static_cast<size_t>(aResStr.getLength());
3315  const sal_Unicode* pPara = p; // paragraph head.
3316  for (; p != pEnd; ++p)
3317  {
3318  if (*p != '\n')
3319  continue;
3320 
3321  // flush the paragraph.
3322  OUString aContent;
3323  if (*pPara == '\n')
3324  ++pPara;
3325  if (p > pPara)
3326  aContent = OUString(pPara, p-pPara);
3327 
3328  SvXMLElementExport aElem(*this, aElemName, false, false);
3329  Characters(aContent);
3330 
3331  pPara = p;
3332  }
3333 
3334  OUString aContent;
3335  if (*pPara == '\n')
3336  ++pPara;
3337  if (pEnd > pPara)
3338  aContent = OUString(pPara, pEnd-pPara);
3339 
3340  SvXMLElementExport aElem(*this, aElemName, false, false);
3341  Characters(aContent);
3342 }
3343 
3344 void ScXMLExport::ExportShape(const uno::Reference < drawing::XShape >& xShape, awt::Point* pPoint)
3345 {
3346  uno::Reference < beans::XPropertySet > xShapeProps ( xShape, uno::UNO_QUERY );
3347  bool bIsChart( false );
3348  if (xShapeProps.is())
3349  {
3350  sal_Int32 nZOrder = 0;
3351  if (xShapeProps->getPropertyValue("ZOrder") >>= nZOrder)
3352  {
3353  AddAttribute(XML_NAMESPACE_DRAW, XML_ZINDEX, OUString::number(nZOrder));
3354  }
3355  uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xShapeProps->getPropertySetInfo();
3356  OUString sPropCLSID ("CLSID");
3357  if( xPropSetInfo->hasPropertyByName( sPropCLSID ) )
3358  {
3359  OUString sCLSID;
3360  if (xShapeProps->getPropertyValue( sPropCLSID ) >>= sCLSID)
3361  {
3362  if ( sCLSID.equalsIgnoreAsciiCase(GetChartExport()->getChartCLSID()) )
3363  {
3364  // we have a chart
3365  OUString sRanges;
3366  if ( pDoc )
3367  {
3368  OUString aChartName;
3369  xShapeProps->getPropertyValue( "PersistName" ) >>= aChartName;
3371  if (pCollection)
3372  {
3373  ScChartListener* pListener = pCollection->findByName(aChartName);
3374  if (pListener)
3375  {
3376  const ScRangeListRef& rRangeList = pListener->GetRangeList();
3377  if ( rRangeList.is() )
3378  {
3379  ScRangeStringConverter::GetStringFromRangeList( sRanges, rRangeList.get(), pDoc, FormulaGrammar::CONV_OOO );
3380  if ( !sRanges.isEmpty() )
3381  {
3382  bIsChart = true;
3384  pAttrList->AddAttribute(
3386  GetShapeExport()->exportShape( xShape, SEF_DEFAULT, pPoint, pAttrList.get() );
3387  }
3388  }
3389  }
3390  }
3391  }
3392 
3393  if ( sRanges.isEmpty() )
3394  {
3395  uno::Reference< frame::XModel > xChartModel;
3396  if( ( xShapeProps->getPropertyValue( "Model" ) >>= xChartModel ) &&
3397  xChartModel.is())
3398  {
3399  uno::Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY );
3400  uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartModel, uno::UNO_QUERY );
3401  if( xChartDoc.is() && xReceiver.is() &&
3402  ! xChartDoc->hasInternalDataProvider())
3403  {
3404  // we have a chart that gets its data from Calc
3405  bIsChart = true;
3406  uno::Sequence< OUString > aRepresentations(
3407  xReceiver->getUsedRangeRepresentations());
3409  if(aRepresentations.hasElements())
3410  {
3411  // add the ranges used by the chart to the shape
3412  // element to be able to start listening after
3413  // load (when the chart is not yet loaded)
3414  uno::Reference< chart2::data::XRangeXMLConversion > xRangeConverter( xChartDoc->getDataProvider(), uno::UNO_QUERY );
3415  sRanges = lcl_RangeSequenceToString( aRepresentations, xRangeConverter );
3416  pAttrList = new SvXMLAttributeList();
3417  pAttrList->AddAttribute(
3419  }
3420  GetShapeExport()->exportShape(xShape, SEF_DEFAULT, pPoint, pAttrList.get());
3421  }
3422  }
3423  }
3424  }
3425  }
3426  }
3427  }
3428  if (!bIsChart)
3429  {
3430  OUString sHlink;
3431  try
3432  {
3433  uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );
3434  if ( xProps.is() )
3435  xProps->getPropertyValue( SC_UNONAME_HYPERLINK ) >>= sHlink;
3436  }
3437  catch ( const beans::UnknownPropertyException& )
3438  {
3439  // no hyperlink property
3440  }
3441 
3442  std::unique_ptr< SvXMLElementExport > pDrawA;
3443  // enclose shapes with <draw:a> element only if sHlink contains something
3444  if ( !sHlink.isEmpty() )
3445  {
3446  // need to get delete the attributes that are pre-loaded
3447  // for the shape export ( otherwise they will become
3448  // attributes of the draw:a element ) This *shouldn't*
3449  // affect performance adversely as there are only a
3450  // couple of attributes involved
3451  uno::Reference< xml::sax::XAttributeList > xSaveAttribs( new SvXMLAttributeList( GetAttrList() ) );
3452  ClearAttrList();
3453  // Add Hlink
3456  pDrawA.reset( new SvXMLElementExport( *this, XML_NAMESPACE_DRAW, XML_A, false, false ) );
3457  // Attribute list has been cleared by previous operation
3458  // re-add pre-loaded attributes
3459  AddAttributeList( xSaveAttribs );
3460  }
3461  GetShapeExport()->exportShape(xShape, SEF_DEFAULT, pPoint);
3462  }
3463  IncrementProgressBar(false);
3464 }
3465 
3467 {
3468  if( !(rMyCell.bHasShape && !rMyCell.aShapeList.empty() && pDoc) )
3469  return;
3470 
3471  // Reference point to turn absolute coordinates in reference point + offset. That happens in most
3472  // cases in XMLShapeExport::ImpExportNewTrans_DecomposeAndRefPoint, which gets the absolute
3473  // coordinates as translation from matrix in property "Transformation". For cell anchored shapes
3474  // the reference point is left-top (in LTR mode) of that cell, which contains the shape.
3475  tools::Rectangle aCellRectFull = pDoc->GetMMRect(
3476  rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(), rMyCell.maCellAddress.Col(),
3477  rMyCell.maCellAddress.Row(), rMyCell.maCellAddress.Tab(), false /*bHiddenAsZero*/);
3478  awt::Point aPoint;
3479  bool bNegativePage = pDoc->IsNegativePage(rMyCell.maCellAddress.Tab());
3480  if (bNegativePage)
3481  aPoint.X = aCellRectFull.Right();
3482  else
3483  aPoint.X = aCellRectFull.Left();
3484  aPoint.Y = aCellRectFull.Top();
3485 
3486  for (const auto& rShape : rMyCell.aShapeList)
3487  {
3488  if (rShape.xShape.is())
3489  {
3490  // The current object geometry is based on bHiddenAsZero=true, but ODF file format
3491  // needs it as if there were no hidden rows or columns. We manipulate the geometry
3492  // accordingly for writing xml markup and restore geometry later.
3493  bool bNeedsRestore = false;
3494  SdrObject* pObj = GetSdrObjectFromXShape(rShape.xShape);
3495  // Remember original geometry
3496  std::unique_ptr<SdrObjGeoData> pGeoData;
3497  if (pObj)
3498  pGeoData = pObj->GetGeoData();
3499 
3500  // Hiding row or column affects the shape based on its snap rect. So we need start and
3501  // end cell address of snap rect. In case of a transformed shape, it is not in rMyCell.
3502  ScAddress aSnapStartAddress = rMyCell.maCellAddress;
3503  ScDrawObjData* pObjData = nullptr;
3504  bool bIsShapeTransformed = false;
3505  if (pObj)
3506  {
3507  pObjData = ScDrawLayer::GetObjData(pObj);
3508  bIsShapeTransformed = pObj->GetRotateAngle() != 0_deg100 || pObj->GetShearAngle() != 0_deg100;
3509  }
3510  if (bIsShapeTransformed && pObjData)
3511  aSnapStartAddress = pObjData->maStart;
3512 
3513  // In case rows or columns are hidden above or before the snap rect, move the shape to the
3514  // position it would have, if these rows and columns are visible.
3515  tools::Rectangle aRectFull = pDoc->GetMMRect(
3516  aSnapStartAddress.Col(), aSnapStartAddress.Row(), aSnapStartAddress.Col(),
3517  aSnapStartAddress.Row(), aSnapStartAddress.Tab(), false /*bHiddenAsZero*/);
3518  tools::Rectangle aRectReduced = pDoc->GetMMRect(
3519  aSnapStartAddress.Col(), aSnapStartAddress.Row(), aSnapStartAddress.Col(),
3520  aSnapStartAddress.Row(), aSnapStartAddress.Tab(), true /*bHiddenAsZero*/);
3521  const tools::Long nLeftDiff(aRectFull.Left() - aRectReduced.Left());
3522  const tools::Long nTopDiff(aRectFull.Top() - aRectReduced.Top());
3523  if (pObj && (abs(nLeftDiff) > 1 || abs(nTopDiff) > 1))
3524  {
3525  bNeedsRestore = true;
3526  pObj->NbcMove(Size(nLeftDiff, nTopDiff));
3527  }
3528 
3529  // tdf#137033 In case the shape is anchored "To Cell (resize with cell)" hiding rows or
3530  // columns inside the snap rect has not only changed size of the shape but rotate and shear
3531  // angle too. We resize the shape to full size. That will recover the original angles too.
3532  if (rShape.bResizeWithCell && pObjData && pObj)
3533  {
3534  // Get original size from anchor
3535  const Point aSnapStartOffset = pObjData->maStartOffset;
3536  // In case of 'resize with cell' maEnd and maEndOffset should be valid.
3537  const ScAddress aSnapEndAddress(pObjData->maEnd);
3538  const Point aSnapEndOffset = pObjData->maEndOffset;
3539  const tools::Rectangle aStartCellRect = pDoc->GetMMRect(
3540  aSnapStartAddress.Col(), aSnapStartAddress.Row(), aSnapStartAddress.Col(),
3541  aSnapStartAddress.Row(), aSnapStartAddress.Tab(), false /*bHiddenAsZero*/);
3542  const tools::Rectangle aEndCellRect = pDoc->GetMMRect(
3543  aSnapEndAddress.Col(), aSnapEndAddress.Row(), aSnapEndAddress.Col(),
3544  aSnapEndAddress.Row(), aSnapEndAddress.Tab(), false /*bHiddenAsZero*/);
3545  if (bNegativePage)
3546  {
3547  aRectFull.SetLeft(aEndCellRect.Right() - aSnapEndOffset.X());
3548  aRectFull.SetRight(aStartCellRect.Right() - aSnapStartOffset.X());
3549  }
3550  else
3551  {
3552  aRectFull.SetLeft(aStartCellRect.Left() + aSnapStartOffset.X());
3553  aRectFull.SetRight(aEndCellRect.Left() + aSnapEndOffset.X());
3554  }
3555  aRectFull.SetTop(aStartCellRect.Top() + aSnapStartOffset.Y());
3556  aRectFull.SetBottom(aEndCellRect.Top() + aSnapEndOffset.Y());
3557  aRectReduced = pObjData->getShapeRect();
3558  if(abs(aRectFull.getWidth() - aRectReduced.getWidth()) > 1
3559  || abs(aRectFull.getHeight() - aRectReduced.getHeight()) > 1)
3560  {
3561  bNeedsRestore = true;
3562  Fraction aScaleWidth(aRectFull.getWidth(), aRectReduced.getWidth());
3563  if (!aScaleWidth.IsValid())
3564  aScaleWidth = Fraction(1.0);
3565  Fraction aScaleHeight(aRectFull.getHeight(), aRectReduced.getHeight());
3566  if (!aScaleHeight.IsValid())
3567  aScaleHeight = Fraction(1.0);
3568  pObj->NbcResize(pObj->GetRelativePos(), aScaleWidth, aScaleHeight);
3569  }
3570  }
3571 
3572  // We only write the end address if we want the shape to resize with the cell
3573  if ( rShape.bResizeWithCell &&
3574  rShape.xShape->getShapeType() != "com.sun.star.drawing.CaptionShape" )
3575  {
3576  OUString sEndAddress;
3577  ScRangeStringConverter::GetStringFromAddress(sEndAddress, rShape.aEndAddress, pDoc, FormulaGrammar::CONV_OOO);
3579  OUStringBuffer sBuffer;
3581  sBuffer, rShape.nEndX);
3582  AddAttribute(XML_NAMESPACE_TABLE, XML_END_X, sBuffer.makeStringAndClear());
3584  sBuffer, rShape.nEndY);
3585  AddAttribute(XML_NAMESPACE_TABLE, XML_END_Y, sBuffer.makeStringAndClear());
3586  }
3587 
3588  // Correct above calculated reference point for some cases:
3589  // a) For a RTL-sheet translate from matrix is not suitable, because the shape
3590  // from xml (which is always LTR) is not mirrored to negative page but shifted.
3591  // b) In case of horizontal mirrored, 'resize with cell' anchored custom shape, translate
3592  // has wrong values. FixMe: Why is translate wrong?
3593  // c) Measure lines do not use transformation matrix but use start and end point directly.
3594  ScDrawObjData* pNRObjData = nullptr;
3595  if (pObj && bNegativePage
3596  && rShape.xShape->getShapeType() == "com.sun.star.drawing.MeasureShape")
3597  {
3598  // inverse of shift when import
3599  tools::Rectangle aSnapRect = pObj->GetSnapRect();
3600  aPoint.X = aSnapRect.Left() + aSnapRect.Right() - aPoint.X;
3601  }
3602  else if (pObj && (pNRObjData = ScDrawLayer::GetNonRotatedObjData(pObj))
3603  && ((rShape.bResizeWithCell && pObj->GetObjIdentifier() == OBJ_CUSTOMSHAPE
3604  && static_cast<SdrObjCustomShape*>(pObj)->IsMirroredX())
3605  || bNegativePage))
3606  {
3607  //In these cases we set reference Point = matrix translate - startOffset.
3608  awt::Point aMatrixTranslate = rShape.xShape->getPosition();
3609  aPoint.X = aMatrixTranslate.X - pNRObjData->maStartOffset.X();
3610  aPoint.Y = aMatrixTranslate.Y - pNRObjData->maStartOffset.Y();
3611  }
3612 
3613  ExportShape(rShape.xShape, &aPoint);
3614 
3615  // Restore object geometry
3616  if (bNeedsRestore && pObj && pGeoData)
3617  pObj->SetGeoData(*pGeoData);
3618  }
3619  }
3620 }
3621 
3623 {
3624  ScMyTableShapes* pTableShapes(pSharedData->GetTableShapes());
3625  if (!pTableShapes || (*pTableShapes)[nCurrentTable].empty())
3626  return;
3627 
3628  OSL_ENSURE(pTableShapes->size() > static_cast<size_t>(nCurrentTable), "wrong Table");
3629  SvXMLElementExport aShapesElem(*this, XML_NAMESPACE_TABLE, XML_SHAPES, true, false);
3630  for (const auto& rxShape : (*pTableShapes)[nCurrentTable])
3631  {
3632  if (rxShape.is())
3633  {
3634  if (pDoc->IsNegativePage(static_cast<SCTAB>(nCurrentTable)))
3635  {
3636  // RTL-mirroring refers to snap rectangle, not to logic rectangle, therefore cannot use
3637  // getPosition() and getSize(), but need property "FrameRect" from rxShape or
3638  // GetSnapRect() from associated SdrObject.
3639  uno::Reference<beans::XPropertySet> xShapeProp(rxShape, uno::UNO_QUERY);
3640  awt::Rectangle aFrameRect;
3641  if (xShapeProp.is() && (xShapeProp->getPropertyValue("FrameRect") >>= aFrameRect))
3642  {
3643  // file format uses shape in LTR mode. newLeft = - oldRight = - (oldLeft + width).
3644  // newTranslate = oldTranslate - refPoint, oldTranslate from transformation matrix,
3645  // calculated in XMLShapeExport::exportShape common for all modules.
3646  // oldTranslate.X = oldLeft ==> refPoint.X = 2 * oldLeft + width
3647  awt::Point aRefPoint;
3648  aRefPoint.X = 2 * aFrameRect.X + aFrameRect.Width - 1;
3649  aRefPoint.Y = 0;
3650  ExportShape(rxShape, &aRefPoint);
3651  }
3652  // else should not happen
3653  }
3654  else
3655  ExportShape(rxShape, nullptr);
3656  }
3657  }
3658  (*pTableShapes)[nCurrentTable].clear();
3659 }
3660 
3661 void ScXMLExport::WriteAreaLink( const ScMyCell& rMyCell )
3662 {
3663  if( !rMyCell.bHasAreaLink )
3664  return;
3665 
3666  const ScMyAreaLink& rAreaLink = rMyCell.aAreaLink;
3671  if( !rAreaLink.sFilterOptions.isEmpty() )
3673  AddAttribute( XML_NAMESPACE_TABLE, XML_LAST_COLUMN_SPANNED, OUString::number(rAreaLink.GetColCount()) );
3674  AddAttribute( XML_NAMESPACE_TABLE, XML_LAST_ROW_SPANNED, OUString::number(rAreaLink.GetRowCount()) );
3675  if( rAreaLink.nRefresh )
3676  {
3677  OUStringBuffer sValue;
3679  static_cast<double>(rAreaLink.nRefresh) / 86400 );
3680  AddAttribute( XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, sValue.makeStringAndClear() );
3681  }
3682  SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_CELL_RANGE_SOURCE, true, true );
3683 }
3684 
3685 void ScXMLExport::exportAnnotationMeta( const uno::Reference < drawing::XShape >& xShape)
3686 {
3687  ScPostIt* pNote = pCurrentCell->pNote;
3688 
3689  if (!pNote)
3690  return;
3691 
3692  // TODO : notes
3693  //is it still useful, as this call back is only called from ScXMLExport::WriteAnnotation
3694  // and should be in sync with pCurrentCell
3696  uno::Reference<drawing::XShape> xCurrentShape( pNoteCaption->getUnoShape(), uno::UNO_QUERY );
3697  if (xCurrentShape.get()!=xShape.get())
3698  return;
3699 
3700  const OUString& sAuthor(pNote->GetAuthor());
3701  if (!sAuthor.isEmpty())
3702  {
3703  SvXMLElementExport aCreatorElem( *this, XML_NAMESPACE_DC,
3704  XML_CREATOR, true,
3705  false );
3706  Characters(sAuthor);
3707  }
3708 
3709  const OUString& aDate(pNote->GetDate());
3710  if (pDoc)
3711  {
3712  SvNumberFormatter* pNumForm = pDoc->GetFormatTable();
3713  double fDate;
3714  sal_uInt32 nfIndex = pNumForm->GetFormatIndex(NF_DATE_SYS_DDMMYYYY, LANGUAGE_SYSTEM);
3715  if (pNumForm->IsNumberFormat(aDate, nfIndex, fDate))
3716  {
3717  OUStringBuffer sBuf;
3718  GetMM100UnitConverter().convertDateTime(sBuf, fDate,true);
3719  SvXMLElementExport aDateElem( *this, XML_NAMESPACE_DC,
3720  XML_DATE, true,
3721  false );
3722  Characters(sBuf.makeStringAndClear());
3723  }
3724  else
3725  {
3726  SvXMLElementExport aDateElem( *this, XML_NAMESPACE_META,
3727  XML_DATE_STRING, true,
3728  false );
3729  Characters(aDate);
3730  }
3731  }
3732  else
3733  {
3734  SvXMLElementExport aDateElem( *this, XML_NAMESPACE_META,
3735  XML_DATE_STRING, true,
3736  false );
3737  Characters(aDate);
3738  }
3739 }
3740 
3742 {
3743  ScPostIt* pNote = pDoc->GetNote(rMyCell.maCellAddress);
3744  if (!pNote)
3745  return;
3746 
3747  if (pNote->IsCaptionShown())
3749 
3750  pCurrentCell = &rMyCell;
3751 
3752  SdrCaptionObj* pNoteCaption = pNote->GetOrCreateCaption(rMyCell.maCellAddress);
3753  if (pNoteCaption)
3754  {
3755  uno::Reference<drawing::XShape> xShape( pNoteCaption->getUnoShape(), uno::UNO_QUERY );
3756  if (xShape.is())
3757  GetShapeExport()->exportShape(xShape, SEF_DEFAULT|XMLShapeExportFlags::ANNOTATION);
3758  }
3759 
3760  pCurrentCell = nullptr;
3761 }
3762 
3764 {
3765  if( !(rMyCell.bHasDetectiveObj || rMyCell.bHasDetectiveOp) )
3766  return;
3767 
3768  const ScMyDetectiveObjVec& rObjVec = rMyCell.aDetectiveObjVec;
3769  const ScMyDetectiveOpVec& rOpVec = rMyCell.aDetectiveOpVec;
3770  sal_Int32 nObjCount(rObjVec.size());
3771  sal_Int32 nOpCount(rOpVec.size());
3772  if( !(nObjCount || nOpCount) )
3773  return;
3774 
3775  SvXMLElementExport aDetElem( *this, XML_NAMESPACE_TABLE, XML_DETECTIVE, true, true );
3776  OUString sString;
3777  for(const auto& rObj : rObjVec)
3778  {
3779  if (rObj.eObjType != SC_DETOBJ_CIRCLE)
3780  {
3781  if( (rObj.eObjType == SC_DETOBJ_ARROW) || (rObj.eObjType == SC_DETOBJ_TOOTHERTAB))
3782  {
3783  ScRangeStringConverter::GetStringFromRange( sString, rObj.aSourceRange, pDoc, FormulaGrammar::CONV_OOO );
3785  }
3786  ScXMLConverter::GetStringFromDetObjType( sString, rObj.eObjType );
3788  if( rObj.bHasError )
3790  }
3791  else
3793  SvXMLElementExport aRangeElem( *this, XML_NAMESPACE_TABLE, XML_HIGHLIGHTED_RANGE, true, true );
3794  }
3795  for(const auto& rOp : rOpVec)
3796  {
3797  OUString sOpString;
3798  ScXMLConverter::GetStringFromDetOpType( sOpString, rOp.eOpType );
3799  AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, sOpString );
3800  AddAttribute( XML_NAMESPACE_TABLE, XML_INDEX, OUString::number(rOp.nIndex) );
3801  SvXMLElementExport aRangeElem( *this, XML_NAMESPACE_TABLE, XML_OPERATION, true, true );
3802  }
3803 }
3804 
3805 void ScXMLExport::SetRepeatAttribute(sal_Int32 nEqualCellCount, bool bIncProgress)
3806 {
3807  // nEqualCellCount is additional cells, so the attribute value is nEqualCellCount+1
3808  if (nEqualCellCount > 0)
3809  {
3810  sal_Int32 nTemp(nEqualCellCount + 1);
3811  OUString sOUEqualCellCount(OUString::number(nTemp));
3812  AddAttribute(sAttrColumnsRepeated, sOUEqualCellCount);
3813  if (bIncProgress)
3814  IncrementProgressBar(false, nEqualCellCount);
3815  }
3816 }
3817 
3819 {
3820  return rCell.maBaseCell.meType == CELLTYPE_EDIT;
3821 }
3822 
3823 bool ScXMLExport::IsCellEqual (const ScMyCell& aCell1, const ScMyCell& aCell2)
3824 {
3825  bool bIsEqual = false;
3826  if( !aCell1.bIsMergedBase && !aCell2.bIsMergedBase &&
3827  aCell1.bIsCovered == aCell2.bIsCovered &&
3828  !aCell1.bIsMatrixBase && !aCell2.bIsMatrixBase &&
3829  aCell1.bIsMatrixCovered == aCell2.bIsMatrixCovered &&
3830  aCell1.bHasAnnotation == aCell2.bHasAnnotation &&
3831  !aCell1.bHasShape && !aCell2.bHasShape &&
3832  aCell1.bHasAreaLink == aCell2.bHasAreaLink &&
3833  !aCell1.bHasDetectiveObj && !aCell2.bHasDetectiveObj)
3834  {
3835  if( (aCell1.bHasAreaLink &&
3836  (aCell1.aAreaLink.GetColCount() == 1) &&
3837  (aCell2.aAreaLink.GetColCount() == 1) &&
3838  aCell1.aAreaLink.Compare( aCell2.aAreaLink ) ) ||
3839  !aCell1.bHasAreaLink )
3840  {
3841  if (!aCell1.bHasAnnotation)
3842  {
3843  if ((((aCell1.nStyleIndex == aCell2.nStyleIndex) && (aCell1.bIsAutoStyle == aCell2.bIsAutoStyle)) ||
3844  ((aCell1.nStyleIndex == aCell2.nStyleIndex) && (aCell1.nStyleIndex == -1))) &&
3845  aCell1.nValidationIndex == aCell2.nValidationIndex &&
3846  aCell1.nType == aCell2.nType)
3847  {
3848  switch ( aCell1.nType )
3849  {
3850  case table::CellContentType_EMPTY :
3851  {
3852  bIsEqual = true;
3853  }
3854  break;
3855  case table::CellContentType_VALUE :
3856  {
3857  // #i29101# number format may be different from column default styles,
3858  // but can lead to different value types, so it must also be compared
3859  bIsEqual = (aCell1.nNumberFormat == aCell2.nNumberFormat) &&
3860  (aCell1.maBaseCell.mfValue == aCell2.maBaseCell.mfValue);
3861  }
3862  break;
3863  case table::CellContentType_TEXT :
3864  {
3865  if (IsEditCell(aCell1) || IsEditCell(aCell2))
3866  bIsEqual = false;
3867  else
3868  {
3869  bIsEqual = (aCell1.maBaseCell.getString(pDoc) == aCell2.maBaseCell.getString(pDoc));
3870  }
3871  }
3872  break;
3873  case table::CellContentType_FORMULA :
3874  {
3875  bIsEqual = false;
3876  }
3877  break;
3878  default :
3879  {
3880  bIsEqual = false;
3881  }
3882  break;
3883  }
3884  }
3885  }
3886  }
3887  }
3888  return bIsEqual;
3889 }
3890 
3891 void ScXMLExport::WriteCalculationSettings(const uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc)
3892 {
3893  uno::Reference<beans::XPropertySet> xPropertySet(xSpreadDoc, uno::UNO_QUERY);
3894  if (!xPropertySet.is())
3895  return;
3896 
3897  bool bCalcAsShown (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_CALCASSHOWN) ));
3898  bool bIgnoreCase (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_IGNORECASE) ));
3899  bool bLookUpLabels (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_LOOKUPLABELS) ));
3900  bool bMatchWholeCell (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_MATCHWHOLE) ));
3901  bool bUseRegularExpressions (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_REGEXENABLED) ));
3902  bool bUseWildcards (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_WILDCARDSENABLED) ));
3903  if (bUseWildcards && bUseRegularExpressions)
3904  bUseRegularExpressions = false; // mutually exclusive, wildcards take precedence
3905  bool bIsIterationEnabled (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_ITERENABLED) ));
3906  sal_uInt16 nYear2000 (pDoc ? pDoc->GetDocOptions().GetYear2000() : 0);
3907  sal_Int32 nIterationCount(100);
3908  xPropertySet->getPropertyValue( SC_UNO_ITERCOUNT ) >>= nIterationCount;
3909  double fIterationEpsilon = 0;
3910  xPropertySet->getPropertyValue( SC_UNO_ITEREPSILON ) >>= fIterationEpsilon;
3911  util::Date aNullDate;
3912  xPropertySet->getPropertyValue( SC_UNO_NULLDATE ) >>= aNullDate;
3913  if (!(bCalcAsShown || bIgnoreCase || !bLookUpLabels || !bMatchWholeCell || !bUseRegularExpressions ||
3914  bUseWildcards ||
3915  bIsIterationEnabled || nIterationCount != 100 || !::rtl::math::approxEqual(fIterationEpsilon, 0.001) ||
3916  aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899 || nYear2000 != 1930))
3917  return;
3918 
3919  if (bIgnoreCase)
3921  if (bCalcAsShown)
3923  if (!bMatchWholeCell)
3925  if (!bLookUpLabels)
3927  if (!bUseRegularExpressions)
3929  if (bUseWildcards)
3931  if (nYear2000 != 1930)
3932  {
3933  AddAttribute(XML_NAMESPACE_TABLE, XML_NULL_YEAR, OUString::number(nYear2000));
3934  }
3935  SvXMLElementExport aCalcSettings(*this, XML_NAMESPACE_TABLE, XML_CALCULATION_SETTINGS, true, true);
3936  {
3937  if (aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899)
3938  {
3939  OUStringBuffer sDate;
3940  SvXMLUnitConverter::convertDateTime(sDate, 0.0, aNullDate);
3941  AddAttribute(XML_NAMESPACE_TABLE, XML_DATE_VALUE, sDate.makeStringAndClear());
3942  SvXMLElementExport aElemNullDate(*this, XML_NAMESPACE_TABLE, XML_NULL_DATE, true, true);
3943  }
3944  if (bIsIterationEnabled || nIterationCount != 100 || !::rtl::math::approxEqual(fIterationEpsilon, 0.001))
3945  {
3946  if (bIsIterationEnabled)
3948  if (nIterationCount != 100)
3949  {
3950  AddAttribute(XML_NAMESPACE_TABLE, XML_STEPS, OUString::number(nIterationCount));
3951  }
3952  if (!::rtl::math::approxEqual(fIterationEpsilon, 0.001))
3953  {
3954  OUStringBuffer sBuffer;
3956  fIterationEpsilon);
3957  AddAttribute(XML_NAMESPACE_TABLE, XML_MAXIMUM_DIFFERENCE, sBuffer.makeStringAndClear());
3958  }
3959  SvXMLElementExport aElemIteration(*this, XML_NAMESPACE_TABLE, XML_ITERATION, true, true);
3960  }
3961  }
3962 }
3963 
3965 {
3966  uno::Reference <sheet::XSheetLinkable> xLinkable (xCurrentTable, uno::UNO_QUERY);
3967  if (!(xLinkable.is() && GetModel().is()))
3968  return;
3969 
3970  sheet::SheetLinkMode nMode (xLinkable->getLinkMode());
3971  if (nMode == sheet::SheetLinkMode_NONE)
3972  return;
3973 
3974  OUString sLink (xLinkable->getLinkUrl());
3975  uno::Reference <beans::XPropertySet> xProps (GetModel(), uno::UNO_QUERY);
3976  if (!xProps.is())
3977  return;
3978 
3979  uno::Reference <container::XIndexAccess> xIndex(xProps->getPropertyValue(SC_UNO_SHEETLINKS), uno::UNO_QUERY);
3980  if (!xIndex.is())
3981  return;
3982 
3983  sal_Int32 nCount(xIndex->getCount());
3984  if (!nCount)
3985  return;
3986 
3987  bool bFound(false);
3988  uno::Reference <beans::XPropertySet> xLinkProps;
3989  for (sal_Int32 i = 0; (i < nCount) && !bFound; ++i)
3990  {
3991  xLinkProps.set(xIndex->getByIndex(i), uno::UNO_QUERY);
3992  if (xLinkProps.is())
3993  {
3994  OUString sNewLink;
3995  if (xLinkProps->getPropertyValue(SC_UNONAME_LINKURL) >>= sNewLink)
3996  bFound = sLink == sNewLink;
3997  }
3998  }
3999  if (!(bFound && xLinkProps.is()))
4000  return;
4001 
4002  OUString sFilter;
4003  OUString sFilterOptions;
4004  OUString sTableName (xLinkable->getLinkSheetName());
4005  sal_Int32 nRefresh(0);
4006  xLinkProps->getPropertyValue(SC_UNONAME_FILTER) >>= sFilter;
4007  xLinkProps->getPropertyValue(SC_UNONAME_FILTOPT) >>= sFilterOptions;
4008  xLinkProps->getPropertyValue(SC_UNONAME_REFDELAY) >>= nRefresh;
4009  if (sLink.isEmpty())
4010  return;
4011 
4014  if (!sTableName.isEmpty())
4016  if (!sFilter.isEmpty())
4018  if (!sFilterOptions.isEmpty())
4020  if (nMode != sheet::SheetLinkMode_NORMAL)
4022  if( nRefresh )
4023  {
4024  OUStringBuffer sBuffer;
4026  static_cast<double>(nRefresh) / 86400 );
4027  AddAttribute( XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, sBuffer.makeStringAndClear() );
4028  }
4029  SvXMLElementExport aSourceElem(*this, XML_NAMESPACE_TABLE, XML_TABLE_SOURCE, true, true);
4030 }
4031 
4032 // core implementation
4034 {
4035  if (!(pDoc && pDoc->IsScenario(static_cast<SCTAB>(nCurrentTable))))
4036  return;
4037 
4038  OUString sComment;
4039  Color aColor;
4040  ScScenarioFlags nFlags;
4041  pDoc->GetScenarioData(static_cast<SCTAB>(nCurrentTable), sComment, aColor, nFlags);
4042  if (!(nFlags & ScScenarioFlags::ShowFrame))
4044  OUStringBuffer aBuffer;
4045  ::sax::Converter::convertColor(aBuffer, aColor);
4046  AddAttribute(XML_NAMESPACE_TABLE, XML_BORDER_COLOR, aBuffer.makeStringAndClear());
4047  if (!(nFlags & ScScenarioFlags::TwoWay))
4049  if (!(nFlags & ScScenarioFlags::Attrib))
4051  if (nFlags & ScScenarioFlags::Value)
4053  if (nFlags & ScScenarioFlags::Protected)
4056  pDoc->IsActiveScenario(static_cast<SCTAB>(nCurrentTable)));
4057  AddAttribute(XML_NAMESPACE_TABLE, XML_IS_ACTIVE, aBuffer.makeStringAndClear());
4058  const ScRangeList* pRangeList = pDoc->GetScenarioRanges(static_cast<SCTAB>(nCurrentTable));
4059  OUString sRangeListStr;
4060  ScRangeStringConverter::GetStringFromRangeList( sRangeListStr, pRangeList, pDoc, FormulaGrammar::CONV_OOO );
4062  if (!sComment.isEmpty())
4064  SvXMLElementExport aElem(*this, XML_NAMESPACE_TABLE, XML_SCENARIO, true, true);
4065 }
4066 
4067 void ScXMLExport::WriteTheLabelRanges( const uno::Reference< sheet::XSpreadsheetDocument >& xSpreadDoc )
4068 {
4069  uno::Reference< beans::XPropertySet > xDocProp( xSpreadDoc, uno::UNO_QUERY );
4070  if( !xDocProp.is() ) return;
4071 
4072  sal_Int32 nCount(0);
4073  uno::Reference< container::XIndexAccess > xColRangesIAccess(xDocProp->getPropertyValue( SC_UNO_COLLABELRNG ), uno::UNO_QUERY);
4074  if( xColRangesIAccess.is() )
4075  nCount += xColRangesIAccess->getCount();
4076 
4077  uno::Reference< container::XIndexAccess > xRowRangesIAccess(xDocProp->getPropertyValue( SC_UNO_ROWLABELRNG ), uno::UNO_QUERY);
4078  if( xRowRangesIAccess.is() )
4079  nCount += xRowRangesIAccess->getCount();
4080 
4081  if( nCount )
4082  {
4083  SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_LABEL_RANGES, true, true );
4084  WriteLabelRanges( xColRangesIAccess, true );
4085  WriteLabelRanges( xRowRangesIAccess, false );
4086  }
4087 }
4088 
4089 void ScXMLExport::WriteLabelRanges( const uno::Reference< container::XIndexAccess >& xRangesIAccess, bool bColumn )
4090 {
4091  if( !xRangesIAccess.is() ) return;
4092 
4093  sal_Int32 nCount(xRangesIAccess->getCount());
4094  for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
4095  {
4096  uno::Reference< sheet::XLabelRange > xRange(xRangesIAccess->getByIndex( nIndex ), uno::UNO_QUERY);
4097  if( xRange.is() )
4098  {
4099  OUString sRangeStr;
4100  table::CellRangeAddress aCellRange( xRange->getLabelArea() );
4101  ScRangeStringConverter::GetStringFromRange( sRangeStr, aCellRange, pDoc, FormulaGrammar::CONV_OOO );
4103  aCellRange = xRange->getDataArea();
4104  ScRangeStringConverter::GetStringFromRange( sRangeStr, aCellRange, pDoc, FormulaGrammar::CONV_OOO );
4107  SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_LABEL_RANGE, true, true );
4108  }
4109  }
4110 }
4111 
4113 {
4114  if (!pDoc)
4115  return;
4116  ScRangeName* pNamedRanges = pDoc->GetRangeName();
4117  WriteNamedRange(pNamedRanges);
4118 }
4119 
4121 {
4122  if (!pDoc)
4123  return;
4124 
4126  // Export this only for 1.2 extended and above.
4127  return;
4128 
4130  auto& rDataSources = rDataMapper.getDataSources();
4131 
4132  if (rDataSources.empty())
4133  return;
4134 
4135  SvXMLElementExport aMappings(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_MAPPINGS, true, true);
4136  for (const auto& itr : rDataSources)
4137  {
4138  AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, itr.getURL());
4139  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_PROVIDER, itr.getProvider());
4143 
4144  SvXMLElementExport aMapping(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_MAPPING, true, true);
4145  // Add the data transformations
4146  WriteExternalDataTransformations(itr.getDataTransformation());
4147  }
4148 }
4149 
4150 void ScXMLExport::WriteExternalDataTransformations(const std::vector<std::shared_ptr<sc::DataTransformation>>& aDataTransformations)
4151 {
4152  SvXMLElementExport aTransformations(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_TRANSFORMATIONS, true, true);
4153  for (auto& itr : aDataTransformations)
4154  {
4155  sc::TransformationType aTransformationType = itr->getTransformationType();
4156 
4157  switch(aTransformationType)
4158  {
4160  {
4161  // Delete Columns Transformation
4162  std::shared_ptr<sc::ColumnRemoveTransformation> aDeleteTransformation = std::dynamic_pointer_cast<sc::ColumnRemoveTransformation>(itr);
4163  std::set<SCCOL> aColumns = aDeleteTransformation->getColumns();
4164  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_REMOVE_TRANSFORMATION, true, true);
4165  for(auto& col : aColumns)
4166  {
4167  // Add Columns
4168  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4169  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4170  }
4171  }
4172  break;
4174  {
4175  std::shared_ptr<sc::SplitColumnTransformation> aSplitTransformation = std::dynamic_pointer_cast<sc::SplitColumnTransformation>(itr);
4176 
4177  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(aSplitTransformation->getColumn()));
4178  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_SEPARATOR, OUString::number(aSplitTransformation->getSeparator()));
4179  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_SPLIT_TRANSFORMATION, true, true);
4180  }
4181  break;
4183  {
4184  // Merge Transformation
4185  std::shared_ptr<sc::MergeColumnTransformation> aMergeTransformation = std::dynamic_pointer_cast<sc::MergeColumnTransformation>(itr);
4186  std::set<SCCOL> aColumns = aMergeTransformation->getColumns();
4187 
4188  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MERGE_STRING, aMergeTransformation->getMergeString());
4189  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_MERGE_TRANSFORMATION, true, true);
4190 
4191  for(auto& col : aColumns)
4192  {
4193  // Columns
4194  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4195  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4196  }
4197  }
4198  break;
4200  {
4201  // Sort Transformation
4202  std::shared_ptr<sc::SortTransformation> aSortTransformation = std::dynamic_pointer_cast<sc::SortTransformation>(itr);
4203  ScSortParam aSortParam = aSortTransformation->getSortParam();
4205  const sc::DataStream* pStrm = rMgr.getDataStream();
4206  if (!pStrm)
4207  // No data stream.
4208  return;
4209 
4210  // Streamed range
4211  ScRange aRange = pStrm->GetRange();
4212 
4213  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_SORT_TRANSFORMATION, true, true);
4214 
4215  writeSort(*this, aSortParam, aRange, pDoc);
4216  }
4217  break;
4219  {
4220  // Text Transformation
4221  std::shared_ptr<sc::TextTransformation> aTextTransformation = std::dynamic_pointer_cast<sc::TextTransformation>(itr);
4222 
4223  sc::TEXT_TRANSFORM_TYPE aTextTransformType = aTextTransformation->getTextTransformationType();
4224 
4225  switch ( aTextTransformType )
4226  {
4229  break;
4232  break;
4235  break;
4238  break;
4239  }
4240 
4241  std::set<SCCOL> aColumns = aTextTransformation->getColumns();
4242 
4243  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_TEXT_TRANSFORMATION, true, true);
4244 
4245  for(auto& col : aColumns)
4246  {
4247  // Columns
4248  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4249  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4250  }
4251  }
4252  break;
4254  {
4255  // Aggregate Transformation
4256  std::shared_ptr<sc::AggregateFunction> aAggregateFunction = std::dynamic_pointer_cast<sc::AggregateFunction>(itr);
4257  std::set<SCCOL> aColumns = aAggregateFunction->getColumns();
4258 
4259  sc::AGGREGATE_FUNCTION aAggregateType = aAggregateFunction->getAggregateType();
4260 
4261  switch (aAggregateType)
4262  {
4265  break;
4268  break;
4271  break;
4274  break;
4275  }
4276 
4278 
4279  for(auto& col : aColumns)
4280  {
4281  // Columns
4282  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4283  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4284  }
4285  }
4286  break;
4288  {
4289  // Number Transformation
4290  std::shared_ptr<sc::NumberTransformation> aNumberTransformation = std::dynamic_pointer_cast<sc::NumberTransformation>(itr);
4291 
4292  sc::NUMBER_TRANSFORM_TYPE aNumberTransformType = aNumberTransformation->getNumberTransformationType();
4293 
4294  switch ( aNumberTransformType )
4295  {
4298  break;
4301  break;
4304  break;
4307  break;
4310  break;
4313  break;
4316  break;
4319  break;
4322  break;
4325  break;
4328  break;
4331  break;
4334  break;
4335  }
4336 
4337  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_PRECISION, OUString::number(aNumberTransformation->getPrecision()));
4338  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_NUMBER_TRANSFORMATION, true, true);
4339 
4340  std::set<SCCOL> aColumns = aNumberTransformation->getColumn();
4341  for(auto& col : aColumns)
4342  {
4343  // Columns
4344  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4345  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4346  }
4347  }
4348  break;
4350  {
4351  // Replace Null Transformation
4352  std::shared_ptr<sc::ReplaceNullTransformation> aReplaceNullTransformation = std::dynamic_pointer_cast<sc::ReplaceNullTransformation>(itr);
4353  std::set<SCCOL> aColumns = aReplaceNullTransformation->getColumn();
4354 
4355  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_REPLACE_STRING, aReplaceNullTransformation->getReplaceString());
4357 
4358  for(auto& col : aColumns)
4359  {
4360  // Columns
4361  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4362  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4363  }
4364  }
4365  break;
4367  {
4368  // Number Transformation
4369  std::shared_ptr<sc::DateTimeTransformation> aDateTimeTransformation = std::dynamic_pointer_cast<sc::DateTimeTransformation>(itr);
4370 
4371  sc::DATETIME_TRANSFORMATION_TYPE aDateTimeTransformationType = aDateTimeTransformation->getDateTimeTransformationType();
4372 
4373  switch ( aDateTimeTransformationType )
4374  {
4377  break;
4380  break;
4383  break;
4386  break;
4389  break;
4392  break;
4395  break;
4398  break;
4401  break;