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/xmlnmspe.hxx>
73 #include <xmloff/xmluconv.hxx>
74 #include <xmloff/nmspmap.hxx>
75 #include <xmloff/families.hxx>
76 #include <xmloff/numehelp.hxx>
77 #include <xmloff/txtparae.hxx>
78 #include <editeng/autokernitem.hxx>
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/svdobj.hxx>
118 #include <svx/svdocapt.hxx>
119 #include <svtools/miscopt.hxx>
120 #include <vcl/svapp.hxx>
121 
123 #include <com/sun/star/beans/XPropertySet.hpp>
124 #include <com/sun/star/container/XNamed.hpp>
125 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
126 #include <com/sun/star/form/XFormsSupplier2.hpp>
127 #include <com/sun/star/io/XActiveDataSource.hpp>
128 #include <com/sun/star/io/XSeekable.hpp>
129 #include <com/sun/star/sheet/XUsedAreaCursor.hpp>
130 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
131 #include <com/sun/star/sheet/XPrintAreas.hpp>
132 #include <com/sun/star/sheet/XUniqueCellFormatRangesSupplier.hpp>
133 #include <com/sun/star/sheet/XLabelRange.hpp>
134 #include <com/sun/star/sheet/NamedRangeFlag.hpp>
135 #include <com/sun/star/sheet/XSheetCellCursor.hpp>
136 #include <com/sun/star/sheet/XSheetCellRanges.hpp>
137 #include <com/sun/star/sheet/XSheetLinkable.hpp>
138 #include <com/sun/star/sheet/GlobalSheetSettings.hpp>
139 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
140 #include <com/sun/star/table/XColumnRowRange.hpp>
141 #include <com/sun/star/util/XProtectable.hpp>
142 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
143 #include <com/sun/star/chart2/XChartDocument.hpp>
144 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
145 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
146 
147 #include <com/sun/star/document/XDocumentProperties.hpp>
148 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
149 
150 #include "XMLCodeNameProvider.hxx"
151 
152 #include <sfx2/linkmgr.hxx>
153 #include <sfx2/objsh.hxx>
154 
155 #include <memory>
156 #include <vector>
158 
159 namespace com::sun::star::uno { class XComponentContext; }
160 
161 
162 
164 #define SC_LAYERID "LayerID"
165 
166 #define SC_VIEWCHANGES_COUNT 13
167 #define SC_SHOW_CHANGES 0
168 #define SC_SHOW_ACCEPTED_CHANGES 1
169 #define SC_SHOW_REJECTED_CHANGES 2
170 #define SC_SHOW_CHANGES_BY_DATETIME 3
171 #define SC_SHOW_CHANGES_BY_DATETIME_MODE 4
172 #define SC_SHOW_CHANGES_BY_DATETIME_FIRST_DATETIME 5
173 #define SC_SHOW_CHANGES_BY_DATETIME_SECOND_DATETIME 6
174 #define SC_SHOW_CHANGES_BY_AUTHOR 7
175 #define SC_SHOW_CHANGES_BY_AUTHOR_NAME 8
176 #define SC_SHOW_CHANGES_BY_COMMENT 9
177 #define SC_SHOW_CHANGES_BY_COMMENT_TEXT 10
178 #define SC_SHOW_CHANGES_BY_RANGES 11
179 #define SC_SHOW_CHANGES_BY_RANGES_LIST 12
180 
181 using namespace formula;
182 using namespace com::sun::star;
183 using namespace xmloff::token;
184 using ::std::vector;
185 using ::com::sun::star::uno::UNO_QUERY;
186 
187 namespace
188 {
189 OUString lcl_RangeSequenceToString(
190  const uno::Sequence< OUString > & rRanges,
191  const uno::Reference< chart2::data::XRangeXMLConversion > & xFormatConverter )
192 {
193  OUStringBuffer aResult;
194  const sal_Int32 nMaxIndex( rRanges.getLength() - 1 );
195  const sal_Unicode cSep(' ');
196  for( sal_Int32 i=0; i<=nMaxIndex; ++i )
197  {
198  OUString aRange( rRanges[i] );
199  if( xFormatConverter.is())
200  aRange = xFormatConverter->convertRangeToXML( aRange );
201  aResult.append( aRange );
202  if( i < nMaxIndex )
203  aResult.append( cSep );
204  }
205  return aResult.makeStringAndClear();
206 }
207 
208 OUString lcl_GetFormattedString(ScDocument* pDoc, const ScRefCellValue& rCell, const ScAddress& rAddr)
209 {
210  // return text/edit cell string content, with line feeds in edit cells
211 
212  if (!pDoc)
213  return EMPTY_OUSTRING;
214 
215  switch (rCell.meType)
216  {
217  case CELLTYPE_STRING:
218  {
219  OUString aStr;
220  Color* pColor;
221  SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
222 
223  sal_uInt32 nFormat = pDoc->GetNumberFormat(rAddr);
224  ScCellFormat::GetString(rCell, nFormat, aStr, &pColor, *pFormatter, pDoc);
225  return aStr;
226  }
227  case CELLTYPE_EDIT:
228  {
229  const EditTextObject* pData = rCell.mpEditText;
230  if (!pData)
231  return EMPTY_OUSTRING;
232 
233  EditEngine& rEngine = pDoc->GetEditEngine();
234  rEngine.SetText(*pData);
235  return rEngine.GetText();
236  }
237  break;
238  default:
239  ;
240  }
241 
242  return EMPTY_OUSTRING;
243 }
244 
245 } // anonymous namespace
246 
247 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
248 Calc_XMLExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
249 {
250  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLExporter", SvXMLExportFlags::ALL));
251 }
252 
253 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
254 Calc_XMLMetaExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
255 {
256  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLMetaExporter", SvXMLExportFlags::META));
257 }
258 
259 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
260 Calc_XMLStylesExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
261 {
262  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLStylesExporter", SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS));
263 }
264 
265 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
266 Calc_XMLContentExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
267 {
268  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLContentExporter", SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::FONTDECLS));
269 }
270 
271 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
272 Calc_XMLSettingsExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
273 {
274  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLSettingsExporter", SvXMLExportFlags::SETTINGS));
275 }
276 
277 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
278 Calc_XMLOasisExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
279 {
280  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisExporter", SvXMLExportFlags::ALL|SvXMLExportFlags::OASIS));
281 }
282 
283 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
284 Calc_XMLOasisMetaExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
285 {
286  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisMetaExporter", SvXMLExportFlags::META|SvXMLExportFlags::OASIS));
287 }
288 
289 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
290 Calc_XMLOasisStylesExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
291 {
292  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisStylesExporter", SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::OASIS));
293 }
294 
295 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
296 Calc_XMLOasisContentExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
297 {
298  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisContentExporter", SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::OASIS));
299 }
300 
301 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
302 Calc_XMLOasisSettingsExporter_get_implementation(css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const &)
303 {
304  return cppu::acquire(new ScXMLExport(context, "com.sun.star.comp.Calc.XMLOasisSettingsExporter", SvXMLExportFlags::SETTINGS|SvXMLExportFlags::OASIS));
305 }
306 
307 namespace {
308 
309 class ScXMLShapeExport : public XMLShapeExport
310 {
311 public:
312  explicit ScXMLShapeExport(SvXMLExport& rExp) : XMLShapeExport(rExp) {}
313 
315  virtual void onExport( const uno::Reference < drawing::XShape >& xShape ) override;
316 };
317 
318 }
319 
320 void ScXMLShapeExport::onExport( const uno::Reference < drawing::XShape >& xShape )
321 {
322  uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
323  if( xShapeProp.is() )
324  {
325  sal_Int16 nLayerID = 0;
326  if( (xShapeProp->getPropertyValue( SC_LAYERID ) >>= nLayerID) && (SdrLayerID(nLayerID) == SC_LAYER_BACK) )
327  GetExport().AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_BACKGROUND, XML_TRUE);
328  }
329 }
330 
332 {
333  css::uno::Reference<css::sheet::XGlobalSheetSettings> xProperties =
334  css::sheet::GlobalSheetSettings::create( comphelper::getProcessComponentContext() );
335  const FieldUnit eFieldUnit = static_cast<FieldUnit>(xProperties->getMetric());
336  return SvXMLUnitConverter::GetMeasureUnit(eFieldUnit);
337 }
338 
339 const OUStringLiteral gsLayerID( SC_LAYERID );
340 
342  const css::uno::Reference< css::uno::XComponentContext >& rContext,
343  OUString const & implementationName, SvXMLExportFlags nExportFlag)
344 : SvXMLExport(
345  rContext, implementationName, GetMeasureUnit(), XML_SPREADSHEET, nExportFlag ),
346  pDoc(nullptr),
347  nSourceStreamPos(0),
348  aTableStyles(),
349  pCurrentCell(nullptr),
350  nOpenRow(-1),
351  nProgressCount(0),
352  nCurrentTable(0),
353  bHasRowHeader(false),
354  bRowHeaderOpen(false)
355 {
356  if (getExportFlags() & SvXMLExportFlags::CONTENT)
357  {
360  pColumnStyles.reset( new ScColumnStyles() );
361  pRowStyles.reset( new ScRowStyles() );
362  pRowFormatRanges.reset( new ScRowFormatRanges() );
365  mpCellsItr.reset(new ScMyNotEmptyCellsIterator(*this));
366  pDefaults.reset( new ScMyDefaultStyles );
367  }
368  pCellStyles.reset( new ScFormatRangeStyles() );
369 
370  // document is not set here - create ScChangeTrackingExportHelper later
371 
382 
383  GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_CELL, XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME,
385  GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_COLUMN, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_NAME,
387  GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_ROW, XML_STYLE_FAMILY_TABLE_ROW_STYLES_NAME,
389  GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_TABLE, XML_STYLE_FAMILY_TABLE_TABLE_STYLES_NAME,
391 
392  if( !(getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT)) )
393  return;
394 
395  // This name is reserved for the external ref cache tables. This
396  // should not conflict with user-defined styles since this name is
397  // used for a table style which is not available in the UI.
398  sExternalRefTabStyleName = "ta_extref";
399  GetAutoStylePool()->RegisterName(XmlStyleFamily::TABLE_TABLE, sExternalRefTabStyleName);
400 
413 }
414 
416 {
417  pGroupColumns.reset();
418  pGroupRows.reset();
419  pColumnStyles.reset();
420  pRowStyles.reset();
421  pCellStyles.reset();
422  pRowFormatRanges.reset();
423  pMergedRangesContainer.reset();
424  pValidationsContainer.reset();
426  pDefaults.reset();
428 }
429 
430 void ScXMLExport::SetSourceStream( const uno::Reference<io::XInputStream>& xNewStream )
431 {
432  xSourceStream = xNewStream;
433 
434  if ( !xSourceStream.is() )
435  return;
436 
437  // make sure it's a plain UTF-8 stream as written by OOo itself
438 
439  const char pXmlHeader[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
440  sal_Int32 nLen = strlen(pXmlHeader);
441 
442  uno::Sequence<sal_Int8> aFileStart(nLen);
443  sal_Int32 nRead = xSourceStream->readBytes( aFileStart, nLen );
444 
445  if ( nRead != nLen || memcmp( aFileStart.getConstArray(), pXmlHeader, nLen ) != 0 )
446  {
447  // invalid - ignore stream, save normally
448  xSourceStream.clear();
449  }
450  else
451  {
452  // keep track of the bytes already read
453  nSourceStreamPos = nRead;
454 
455  const ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(GetModel())->GetSheetSaveData();
456  if (pSheetData)
457  {
458  // add the loaded namespaces to the name space map
459 
460  if ( !pSheetData->AddLoadedNamespaces( GetNamespaceMap_() ) )
461  {
462  // conflicts in the namespaces - ignore the stream, save normally
463  xSourceStream.clear();
464  }
465  }
466  }
467 }
468 
469 sal_Int32 ScXMLExport::GetNumberFormatStyleIndex(sal_Int32 nNumFmt) const
470 {
471  NumberFormatIndexMap::const_iterator itr = aNumFmtIndexMap.find(nNumFmt);
472  if (itr == aNumFmtIndexMap.end())
473  return -1;
474 
475  return itr->second;
476 }
477 
478 void ScXMLExport::CollectSharedData(SCTAB& nTableCount, sal_Int32& nShapesCount)
479 {
480  if (!GetModel().is())
481  return;
482 
483  uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc(GetModel(), uno::UNO_QUERY);
484  if (!xSpreadDoc.is())
485  return;
486 
487  uno::Reference<container::XIndexAccess> xIndex(xSpreadDoc->getSheets(), uno::UNO_QUERY);
488  if (!xIndex.is())
489  return;
490 
491  nTableCount = xIndex->getCount();
492  if (!pSharedData)
493  pSharedData.reset(new ScMySharedData(nTableCount));
494 
495  pCellStyles->AddNewTable(nTableCount - 1);
496 
497  for (SCTAB nTable = 0; nTable < nTableCount; ++nTable)
498  {
499  nCurrentTable = sal::static_int_cast<sal_uInt16>(nTable);
500  uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xIndex->getByIndex(nTable), uno::UNO_QUERY);
501  if (!xDrawPageSupplier.is())
502  continue;
503 
504  uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage());
505  ScMyDrawPage aDrawPage;
506  aDrawPage.bHasForms = false;
507  aDrawPage.xDrawPage.set(xDrawPage);
508  pSharedData->AddDrawPage(aDrawPage, nTable);
509  if (!xDrawPage.is())
510  continue;
511 
512  sal_Int32 nShapes = xDrawPage->getCount();
513  for (sal_Int32 nShape = 0; nShape < nShapes; ++nShape)
514  {
515  uno::Reference<drawing::XShape> xShape(xDrawPage->getByIndex(nShape), uno::UNO_QUERY);
516  if (!xShape.is())
517  continue;
518 
519  uno::Reference<beans::XPropertySet> xShapeProp(xShape, uno::UNO_QUERY);
520  if (!xShapeProp.is())
521  continue;
522 
523  sal_Int16 nLayerID = 0;
524  bool bExtracted = xShapeProp->getPropertyValue(gsLayerID) >>= nLayerID;
525  if (!bExtracted)
526  continue;
527 
528  if ((SdrLayerID(nLayerID) == SC_LAYER_INTERN) || (SdrLayerID(nLayerID) == SC_LAYER_HIDDEN))
529  {
530  CollectInternalShape(xShape);
531  continue;
532  }
533 
534  ++nShapesCount;
535 
536  SvxShape* pShapeImp = comphelper::getUnoTunnelImplementation<SvxShape>(xShape);
537  if (!pShapeImp)
538  continue;
539 
540  SdrObject* pSdrObj = pShapeImp->GetSdrObject();
541  if (!pSdrObj)
542  continue;
543 
544  if (ScDrawObjData *pAnchor = ScDrawLayer::GetNonRotatedObjData(pSdrObj))
545  {
546  ScMyShape aMyShape;
547  aMyShape.aAddress = pAnchor->maStart;
548  SAL_WARN_IF(aMyShape.aAddress.Tab() != nTable, "sc", "not anchored to current sheet!");
549  aMyShape.aAddress.SetTab(nTable);
550  aMyShape.aEndAddress = pAnchor->maEnd;
551  aMyShape.aEndAddress.SetTab( nTable );
552  aMyShape.nEndX = pAnchor->maEndOffset.X();
553  aMyShape.nEndY = pAnchor->maEndOffset.Y();
554  aMyShape.xShape = xShape;
555  aMyShape.bResizeWithCell = ScDrawLayer::IsResizeWithCell(*pSdrObj);
556  pSharedData->AddNewShape(aMyShape);
557  pSharedData->SetLastColumn(nTable, pAnchor->maStart.Col());
558  pSharedData->SetLastRow(nTable, pAnchor->maStart.Row());
559  }
560  else
561  pSharedData->AddTableShape(nTable, xShape);
562  }
563  }
564 }
565 
567 {
568  // #i84077# To avoid compiler warnings about uninitialized aShapeItr,
569  // it's initialized using this dummy list. The iterator contains shapes
570  // from all sheets, so it can't be declared inside the nTable loop where
571  // it is used.
572  ScMyShapeList aDummyInitList;
573 
574  pSharedData->SortShapesContainer();
575  pSharedData->SortNoteShapes();
576  const ScMyShapeList* pShapeList(nullptr);
577  ScMyShapeList::const_iterator aShapeItr = aDummyInitList.end();
578  if (pSharedData->GetShapesContainer())
579  {
580  pShapeList = &pSharedData->GetShapesContainer()->GetShapes();
581  aShapeItr = pShapeList->begin();
582  }
583  if (pSharedData->HasDrawPage())
584  {
585  for (SCTAB nTable = 0; nTable < nTableCount; ++nTable)
586  {
587  uno::Reference<drawing::XDrawPage> xDrawPage(pSharedData->GetDrawPage(nTable));
588 
589  if (xDrawPage.is())
590  {
591  GetShapeExport()->seekShapes(xDrawPage);
592  uno::Reference< form::XFormsSupplier2 > xFormsSupplier( xDrawPage, uno::UNO_QUERY );
593  if( xFormsSupplier.is() && xFormsSupplier->hasForms() )
594  {
595  GetFormExport()->examineForms(xDrawPage);
596  pSharedData->SetDrawPageHasForms(nTable, true);
597  }
598  ScMyTableShapes* pTableShapes(pSharedData->GetTableShapes());
599  if (pTableShapes)
600  {
601  for (const auto& rxShape : (*pTableShapes)[nTable])
602  {
603  GetShapeExport()->collectShapeAutoStyles(rxShape);
604  IncrementProgressBar(false);
605  }
606  }
607  if (pShapeList)
608  {
609  ScMyShapeList::const_iterator aEndItr(pShapeList->end());
610  while ( aShapeItr != aEndItr && ( aShapeItr->aAddress.Tab() == nTable ) )
611  {
612  GetShapeExport()->collectShapeAutoStyles(aShapeItr->xShape);
613  IncrementProgressBar(false);
614  ++aShapeItr;
615  }
616  }
617  if (pSharedData->GetNoteShapes())
618  {
619  const ScMyNoteShapeList& rNoteShapes = pSharedData->GetNoteShapes()->GetNotes();
620  for (const auto& rNoteShape : rNoteShapes)
621  {
622  if ( rNoteShape.aPos.Tab() == nTable )
623  GetShapeExport()->collectShapeAutoStyles(rNoteShape.xShape);
624  }
625  }
626  }
627  }
628  }
629  pSharedData->SortNoteShapes(); // sort twice, because some more shapes are added
630 }
631 
633 {
634  sal_Int32 nCellCount(pDoc ? pDoc->GetCellCount() : 0);
635  SCTAB nTableCount(0);
636  sal_Int32 nShapesCount(0);
637  GetAutoStylePool()->ClearEntries();
638  CollectSharedData(nTableCount, nShapesCount);
639 
640  uno::Sequence<beans::NamedValue> stats
641  {
642  { "TableCount", uno::makeAny(static_cast<sal_Int32>(nTableCount)) },
643  { "CellCount", uno::makeAny(nCellCount) },
644  { "ObjectCount", uno::makeAny(nShapesCount) }
645  };
646 
647  // update document statistics at the model
648  uno::Reference<document::XDocumentPropertiesSupplier> xPropSup(GetModel(),
649  uno::UNO_QUERY_THROW);
650  uno::Reference<document::XDocumentProperties> xDocProps(
651  xPropSup->getDocumentProperties());
652  if (xDocProps.is()) {
653  xDocProps->setDocumentStatistics(stats);
654  }
655 
656  // export document properties
658 }
659 
661 {
662  GetFontAutoStylePool(); // make sure the pool is created
664 }
665 
666 table::CellRangeAddress ScXMLExport::GetEndAddress(const uno::Reference<sheet::XSpreadsheet>& xTable)
667 {
668  table::CellRangeAddress aCellAddress;
669  uno::Reference<sheet::XSheetCellCursor> xCursor(xTable->createCursor());
670  uno::Reference<sheet::XUsedAreaCursor> xUsedArea (xCursor, uno::UNO_QUERY);
671  uno::Reference<sheet::XCellRangeAddressable> xCellAddress (xCursor, uno::UNO_QUERY);
672  if (xUsedArea.is() && xCellAddress.is())
673  {
674  xUsedArea->gotoEndOfUsedArea(true);
675  aCellAddress = xCellAddress->getRangeAddress();
676  }
677  return aCellAddress;
678 }
679 
681 {
682  if (pDoc->GetLinkManager())
683  {
684  const sfx2::SvBaseLinks& rLinks = pDoc->GetLinkManager()->GetLinks();
685  for (const auto & rLink : rLinks)
686  {
687  ScAreaLink *pLink = dynamic_cast<ScAreaLink*>(rLink.get());
688  if (pLink)
689  {
690  ScMyAreaLink aAreaLink;
691  aAreaLink.aDestRange = pLink->GetDestArea();
692  aAreaLink.sSourceStr = pLink->GetSource();
693  aAreaLink.sFilter = pLink->GetFilter();
694  aAreaLink.sFilterOptions = pLink->GetOptions();
695  aAreaLink.sURL = pLink->GetFile();
696  aAreaLink.nRefresh = pLink->GetRefreshDelay();
697  rAreaLinks.AddNewAreaLink( aAreaLink );
698  }
699  }
700  }
701  rAreaLinks.Sort();
702 }
703 
704 // core implementation
706 {
707  if (!pDoc)
708  return;
709 
710  ScDetOpList* pOpList(pDoc->GetDetOpList());
711  if( !pOpList )
712  return;
713 
714  size_t nCount = pOpList->Count();
715  for (size_t nIndex = 0; nIndex < nCount; ++nIndex )
716  {
717  const ScDetOpData& rDetData = pOpList->GetObject( nIndex);
718  const ScAddress& rDetPos = rDetData.GetPos();
719  SCTAB nTab = rDetPos.Tab();
720  if ( nTab < pDoc->GetTableCount() )
721  {
722  rDetOp.AddOperation( rDetData.GetOperation(), rDetPos, static_cast<sal_uInt32>( nIndex) );
723 
724  // cells with detective operations are written even if empty
725  pSharedData->SetLastColumn( nTab, rDetPos.Col() );
726  pSharedData->SetLastRow( nTab, rDetPos.Row() );
727  }
728  }
729  rDetOp.Sort();
730 }
731 
732 void ScXMLExport::WriteSingleColumn(const sal_Int32 nRepeatColumns, const sal_Int32 nStyleIndex,
733  const sal_Int32 nIndex, const bool bIsAutoStyle, const bool bIsVisible)
734 {
735  CheckAttrList();
736  AddAttribute(sAttrStyleName, pColumnStyles->GetStyleNameByIndex(nStyleIndex));
737  if (!bIsVisible)
739  if (nRepeatColumns > 1)
740  {
741  OUString sOUEndCol(OUString::number(nRepeatColumns));
743  }
744  if (nIndex != -1)
745  AddAttribute(XML_NAMESPACE_TABLE, XML_DEFAULT_CELL_STYLE_NAME, pCellStyles->GetStyleNameByIndex(nIndex, bIsAutoStyle));
746  SvXMLElementExport aElemC(*this, sElemCol, true, true);
747 }
748 
749 void ScXMLExport::WriteColumn(const sal_Int32 nColumn, const sal_Int32 nRepeatColumns,
750  const sal_Int32 nStyleIndex, const bool bIsVisible)
751 {
752  sal_Int32 nRepeat(1);
753  sal_Int32 nPrevIndex(pDefaults->GetColDefaults()[nColumn].nIndex);
754  bool bPrevAutoStyle(pDefaults->GetColDefaults()[nColumn].bIsAutoStyle);
755  for (sal_Int32 i = nColumn + 1; i < nColumn + nRepeatColumns; ++i)
756  {
757  if ((pDefaults->GetColDefaults()[i].nIndex != nPrevIndex) ||
758  (pDefaults->GetColDefaults()[i].bIsAutoStyle != bPrevAutoStyle))
759  {
760  WriteSingleColumn(nRepeat, nStyleIndex, nPrevIndex, bPrevAutoStyle, bIsVisible);
761  nPrevIndex = pDefaults->GetColDefaults()[i].nIndex;
762  bPrevAutoStyle = pDefaults->GetColDefaults()[i].bIsAutoStyle;
763  nRepeat = 1;
764  }
765  else
766  ++nRepeat;
767  }
768  WriteSingleColumn(nRepeat, nStyleIndex, nPrevIndex, bPrevAutoStyle, bIsVisible);
769 }
770 
772 {
774 }
775 
777 {
779 }
780 
781 void ScXMLExport::ExportColumns(const sal_Int32 nTable, const ScRange& aColumnHeaderRange, const bool bHasColumnHeader)
782 {
783  sal_Int32 nColsRepeated (1);
784  sal_Int32 nIndex;
785  sal_Int32 nPrevColumn(0);
786  bool bPrevIsVisible (true);
787  bool bWasHeader (false);
788  bool bIsClosed (true);
789  sal_Int32 nPrevIndex (-1);
790  sal_Int32 nColumn;
791  for (nColumn = 0; nColumn <= pSharedData->GetLastColumn(nTable); ++nColumn)
792  {
793  CheckAttrList();
794  bool bIsVisible(true);
795  nIndex = pColumnStyles->GetStyleNameIndex(nTable, nColumn, bIsVisible);
796 
797  const bool bIsHeader = bHasColumnHeader && (aColumnHeaderRange.aStart.Col() <= nColumn) && (nColumn <= aColumnHeaderRange.aEnd.Col());
798  if (bIsHeader != bWasHeader)
799  {
800  if (bIsHeader)
801  {
802  if (nColumn > 0)
803  {
804  WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
805  if (pGroupColumns->IsGroupEnd(nColumn - 1))
806  pGroupColumns->CloseGroups(nColumn - 1);
807  }
808  bPrevIsVisible = bIsVisible;
809  nPrevIndex = nIndex;
810  nPrevColumn = nColumn;
811  nColsRepeated = 1;
812  if(pGroupColumns->IsGroupStart(nColumn))
813  pGroupColumns->OpenGroups(nColumn);
815  bWasHeader = true;
816  bIsClosed = false;
817  }
818  else
819  {
820  WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
822  if (pGroupColumns->IsGroupEnd(nColumn - 1))
823  pGroupColumns->CloseGroups(nColumn - 1);
824  if(pGroupColumns->IsGroupStart(nColumn))
825  pGroupColumns->OpenGroups(nColumn);
826  bPrevIsVisible = bIsVisible;
827  nPrevIndex = nIndex;
828  nPrevColumn = nColumn;
829  nColsRepeated = 1;
830  bWasHeader = false;
831  bIsClosed = true;
832  }
833  }
834  else if (nColumn == 0)
835  {
836  if (pGroupColumns->IsGroupStart(nColumn))
837  pGroupColumns->OpenGroups(nColumn);
838  bPrevIsVisible = bIsVisible;
839  nPrevIndex = nIndex;
840  }
841  else if ((bIsVisible == bPrevIsVisible) && (nIndex == nPrevIndex) &&
842  !pGroupColumns->IsGroupStart(nColumn) && !pGroupColumns->IsGroupEnd(nColumn - 1))
843  ++nColsRepeated;
844  else
845  {
846  WriteColumn(nPrevColumn, nColsRepeated, nPrevIndex, bPrevIsVisible);
847  if (pGroupColumns->IsGroupEnd(nColumn - 1))
848  {
849  if (bIsHeader)
851  pGroupColumns->CloseGroups(nColumn - 1);
852  if (bIsHeader)
854  }
855  if (pGroupColumns->IsGroupStart(nColumn))
856  {
857  if (bIsHeader)
859  pGroupColumns->OpenGroups(nColumn);
860  if (bIsHeader)
862  }
863  bPrevIsVisible = bIsVisible;
864  nPrevIndex = nIndex;
865  nPrevColumn = nColumn;
866  nColsRepeated = 1;
867  }
868  }
869  assert(nPrevIndex >= 0 && "coverity#1438402");
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, "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, const OUString& 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, "font-name");
978  break;
980  handleFont(rPropStates, p, xMapper, "font-name-asian");
981  break;
983  handleFont(rPropStates, p, xMapper, "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, "text-underline-style", 0);
1019  if (nIndexStyle == -1 || nIndexStyle > nEntryCount)
1020  break;
1021 
1022  sal_Int32 nIndexWidth = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-underline-width", 0);
1023  if (nIndexWidth == -1 || nIndexWidth > nEntryCount)
1024  break;
1025 
1026  sal_Int32 nIndexType = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-underline-type", 0);
1027  if (nIndexType == -1 || nIndexType > nEntryCount)
1028  break;
1029 
1030  sal_Int32 nIndexColor = xMapper->FindEntryIndex("CharUnderlineColor", XML_NAMESPACE_STYLE, "text-underline-color");
1031  if (nIndexColor == -1 || nIndexColor > nEntryCount)
1032  break;
1033 
1034  sal_Int32 nIndexHasColor = xMapper->FindEntryIndex("CharUnderlineHasColor", XML_NAMESPACE_STYLE, "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, "text-overline-style", 0);
1055  if (nIndexStyle == -1 || nIndexStyle > nEntryCount)
1056  break;
1057 
1058  sal_Int32 nIndexWidth = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-overline-width", 0);
1059  if (nIndexWidth == -1 || nIndexWidth > nEntryCount)
1060  break;
1061 
1062  sal_Int32 nIndexType = xMapper->GetEntryIndex(XML_NAMESPACE_STYLE, "text-overline-type", 0);
1063  if (nIndexType == -1 || nIndexType > nEntryCount)
1064  break;
1065 
1066  sal_Int32 nIndexColor = xMapper->FindEntryIndex("CharOverlineColor", XML_NAMESPACE_STYLE, "text-overline-color");
1067  if (nIndexColor == -1 || nIndexColor > nEntryCount)
1068  break;
1069 
1070  sal_Int32 nIndexHasColor = xMapper->FindEntryIndex("CharOverlineHasColor", XML_NAMESPACE_STYLE, "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, "text-position");
1168  if (nIndexEsc == -1 || nIndexEsc > nEntryCount)
1169  break;
1170 
1171  sal_Int32 nIndexEscHeight = xMapper->FindEntryIndex("CharEscapementHeight", XML_NAMESPACE_STYLE, "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, "language", 0);
1206  nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_FO, "country", 0);
1207  nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_FO, "script", 0);
1208  nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "rfc-language-tag", 0);
1209  break;
1210  case EE_CHAR_LANGUAGE_CJK:
1211  nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "language-asian", 0);
1212  nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "country-asian", 0);
1213  nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "script-asian", 0);
1214  nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "rfc-language-tag-asian", 0);
1215  break;
1216  case EE_CHAR_LANGUAGE_CTL:
1217  nIndexLanguage = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "language-complex", 0);
1218  nIndexCountry = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "country-complex", 0);
1219  nIndexScript = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "script-complex", 0);
1220  nIndexTag = xMapper->GetEntryIndex( XML_NAMESPACE_STYLE, "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  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  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  {
2651  GetPageExport()->exportAutoStyles();
2652  }
2653 
2654  // #i30251#; only write Text Styles once
2655 
2656  if ((getExportFlags() & SvXMLExportFlags::CONTENT) || (getExportFlags() & SvXMLExportFlags::MASTERSTYLES))
2657  GetTextParagraphExport()->exportTextAutoStyles();
2658 }
2659 
2661 {
2662  GetPageExport()->exportMasterStyles( true );
2663 }
2664 
2665 void ScXMLExport::CollectInternalShape( uno::Reference< drawing::XShape > const & xShape )
2666 {
2667  // detective objects and notes
2668  SvxShape* pShapeImp = comphelper::getUnoTunnelImplementation<SvxShape>( xShape );
2669  if( !pShapeImp )
2670  return;
2671 
2672  SdrObject* pObject = pShapeImp->GetSdrObject();
2673  if( !pObject )
2674  return;
2675 
2676  // collect note caption objects from all layers (internal or hidden)
2677  if( ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( pObject, static_cast< SCTAB >( nCurrentTable ) ) )
2678  {
2679  if(pDoc->GetNote(pCaptData->maStart))
2680  {
2681  pSharedData->AddNoteObj( xShape, pCaptData->maStart );
2682 
2683  // #i60851# When the file is saved while editing a new note,
2684  // the cell is still empty -> last column/row must be updated
2685  OSL_ENSURE( pCaptData->maStart.Tab() == nCurrentTable, "invalid table in object data" );
2686  pSharedData->SetLastColumn( nCurrentTable, pCaptData->maStart.Col() );
2687  pSharedData->SetLastRow( nCurrentTable, pCaptData->maStart.Row() );
2688  }
2689  }
2690  // other objects from internal layer only (detective)
2691  else if( pObject->GetLayer() == SC_LAYER_INTERN )
2692  {
2693  ScDetectiveFunc aDetFunc( pDoc, static_cast<SCTAB>(nCurrentTable) );
2694  ScAddress aPosition;
2695  ScRange aSourceRange;
2696  bool bRedLine;
2697  ScDetectiveObjType eObjType = aDetFunc.GetDetectiveObjectType(
2698  pObject, nCurrentTable, aPosition, aSourceRange, bRedLine );
2699  pSharedData->GetDetectiveObjContainer()->AddObject( eObjType, static_cast<SCTAB>(nCurrentTable), aPosition, aSourceRange, bRedLine );
2700  }
2701 }
2702 
2703 bool ScXMLExport::GetMerged (const table::CellRangeAddress* pCellAddress,
2704  const uno::Reference <sheet::XSpreadsheet>& xTable)
2705 {
2706  bool bReady(false);
2707  sal_Int32 nRow(pCellAddress->StartRow);
2708  sal_Int32 nCol(pCellAddress->StartColumn);
2709  sal_Int32 nEndRow(pCellAddress->EndRow);
2710  sal_Int32 nEndCol(pCellAddress->EndColumn);
2711  bool bRowInc(nEndRow > nRow);
2712  while(!bReady && nRow <= nEndRow && nCol <= nEndCol)
2713  {
2714  uno::Reference<sheet::XSheetCellRange> xSheetCellRange(xTable->getCellRangeByPosition(nCol, nRow, nCol, nRow), uno::UNO_QUERY);
2715  if (xSheetCellRange.is())
2716  {
2717  uno::Reference<sheet::XSheetCellCursor> xCursor(xTable->createCursorByRange(xSheetCellRange));
2718  if(xCursor.is())
2719  {
2720  uno::Reference<sheet::XCellRangeAddressable> xCellAddress (xCursor, uno::UNO_QUERY);
2721  xCursor->collapseToMergedArea();
2722  table::CellRangeAddress aCellAddress2(xCellAddress->getRangeAddress());
2723  ScRange aScRange( aCellAddress2.StartColumn, aCellAddress2.StartRow, aCellAddress2.Sheet,
2724  aCellAddress2.EndColumn, aCellAddress2.EndRow, aCellAddress2.Sheet );
2725 
2726  if ((aScRange.aEnd.Row() > nRow ||
2727  aScRange.aEnd.Col() > nCol) &&
2728  aScRange.aStart.Row() == nRow &&
2729  aScRange.aStart.Col() == nCol)
2730  {
2731  pMergedRangesContainer->AddRange(aScRange);
2732  pSharedData->SetLastColumn(aScRange.aEnd.Tab(), aScRange.aEnd.Col());
2733  pSharedData->SetLastRow(aScRange.aEnd.Tab(), aScRange.aEnd.Row());
2734  }
2735  else
2736  bReady = true;
2737  }
2738  }
2739  if (!bReady)
2740  {
2741  if (bRowInc)
2742  ++nRow;
2743  else
2744  ++nCol;
2745  }
2746  }
2747  OSL_ENSURE(!(!bReady && nEndRow > nRow && nEndCol > nCol), "should not be possible");
2748  return !bReady;
2749 }
2750 
2752  ScRange& aCellAddress, bool& bIsFirst) const
2753 {
2754  bIsFirst = false;
2755 
2756  ScRange aMatrixRange;
2757 
2758  if (pDoc && pDoc->GetMatrixFormulaRange(aCell, aMatrixRange))
2759  {
2760  aCellAddress = aMatrixRange;
2761  if ((aCellAddress.aStart.Col() == aCell.Col() && aCellAddress.aStart.Row() == aCell.Row()) &&
2762  (aCellAddress.aEnd.Col() > aCell.Col() || aCellAddress.aEnd.Row() > aCell.Row()))
2763  {
2764  bIsFirst = true;
2765  return true;
2766  }
2767  else if (aCellAddress.aStart.Col() != aCell.Col() || aCellAddress.aStart.Row() != aCell.Row() ||
2768  aCellAddress.aEnd.Col() != aCell.Col() || aCellAddress.aEnd.Row()!= aCell.Row())
2769  return true;
2770  else
2771  {
2772  bIsFirst = true;
2773  return true;
2774  }
2775  }
2776 
2777  return false;
2778 }
2779 
2780 void ScXMLExport::WriteTable(sal_Int32 nTable, const uno::Reference<sheet::XSpreadsheet>& xTable)
2781 {
2782  if (!xTable.is())
2783  return;
2784 
2785  xCurrentTable.set(xTable);
2786  uno::Reference<container::XNamed> xName (xTable, uno::UNO_QUERY );
2787  if (!xName.is())
2788  return;
2789 
2790  nCurrentTable = sal::static_int_cast<sal_uInt16>( nTable );
2791  OUString sOUTableName(xName->getName());
2792  AddAttribute(sAttrName, sOUTableName);
2794 
2795  uno::Reference<util::XProtectable> xProtectable (xTable, uno::UNO_QUERY);
2796  ScTableProtection* pProtect = nullptr;
2797  if (xProtectable.is() && xProtectable->isProtected())
2798  {
2800  if (pDoc)
2801  {
2802  pProtect = pDoc->GetTabProtection(nTable);
2803  if (pProtect)
2804  {
2805  OUStringBuffer aBuffer;
2807  if (pProtect->hasPasswordHash(PASSHASH_SHA1))
2808  {
2810  pProtect->getPasswordHash(PASSHASH_SHA1));
2811  eHashUsed = PASSHASH_SHA1;
2812  }
2813  else if (pProtect->hasPasswordHash(PASSHASH_SHA256))
2814  {
2816  pProtect->getPasswordHash(PASSHASH_SHA256));
2817  eHashUsed = PASSHASH_SHA256;
2818  }
2819  else if (pProtect->hasPasswordHash(PASSHASH_XL, PASSHASH_SHA1))
2820  {
2821  // Double-hash this by SHA1 on top of the legacy xls hash.
2822  uno::Sequence<sal_Int8> aHash = pProtect->getPasswordHash(PASSHASH_XL, PASSHASH_SHA1);
2823  ::comphelper::Base64::encode(aBuffer, aHash);
2824  eHashUsed = PASSHASH_XL;
2825  }
2826  if (!aBuffer.isEmpty())
2827  {
2828  AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
2830  {
2831  if (eHashUsed == PASSHASH_XL)
2832  {
2838  }
2839  else if (eHashUsed == PASSHASH_SHA1)
2840  {
2843  }
2844  else if (eHashUsed == PASSHASH_SHA256)
2845  {
2848  }
2849  }
2850  }
2851  }
2852  }
2853  }
2854  OUString sPrintRanges;
2855  ScRange aColumnHeaderRange;
2856  bool bHasColumnHeader;
2857  GetColumnRowHeader(bHasColumnHeader, aColumnHeaderRange, bHasRowHeader, aRowHeaderRange, sPrintRanges);
2858  if( !sPrintRanges.isEmpty() )
2860  else if (pDoc && !pDoc->IsPrintEntireSheet(static_cast<SCTAB>(nTable)))
2862  SvXMLElementExport aElemT(*this, sElemTab, true, true);
2863 
2864  if (pProtect && pProtect->isProtected() && getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2865  {
2870 
2875 
2880 
2881  OUString aElemName = GetNamespaceMap().GetQNameByKey(
2883 
2884  SvXMLElementExport aElemProtected(*this, aElemName, true, true);
2885  }
2886 
2887  CheckAttrList();
2888 
2889  if ( pDoc && pDoc->GetSheetEvents( static_cast<SCTAB>(nTable) ) &&
2891  {
2892  // store sheet events
2893  uno::Reference<document::XEventsSupplier> xSupplier(xTable, uno::UNO_QUERY);
2894  uno::Reference<container::XNameAccess> xEvents = xSupplier->getEvents();
2895  GetEventExport().ExportExt( xEvents );
2896  }
2897 
2898  WriteTableSource();
2899  WriteScenario();
2900  uno::Reference<drawing::XDrawPage> xDrawPage;
2901  if (pSharedData->HasForm(nTable, xDrawPage) && xDrawPage.is())
2902  {
2903  ::xmloff::OOfficeFormsExport aForms(*this);
2904  GetFormExport()->exportForms( xDrawPage );
2905  bool bRet(GetFormExport()->seekPage( xDrawPage ));
2906  OSL_ENSURE( bRet, "OFormLayerXMLExport::seekPage failed!" );
2907  }
2908  if (pSharedData->HasDrawPage())
2909  {
2910  GetShapeExport()->seekShapes(pSharedData->GetDrawPage(nTable));
2911  WriteTableShapes();
2912  }
2913  table::CellRangeAddress aRange(GetEndAddress(xTable));
2914  pSharedData->SetLastColumn(nTable, aRange.EndColumn);
2915  pSharedData->SetLastRow(nTable, aRange.EndRow);
2916  mpCellsItr->SetCurrentTable(static_cast<SCTAB>(nTable), xCurrentTable);
2917  pGroupColumns->NewTable();
2918  pGroupRows->NewTable();
2920  if (bHasColumnHeader)
2921  pSharedData->SetLastColumn(nTable, aColumnHeaderRange.aEnd.Col());
2922  bRowHeaderOpen = false;
2923  if (bHasRowHeader)
2924  pSharedData->SetLastRow(nTable, aRowHeaderRange.aEnd.Row());
2925  pDefaults->FillDefaultStyles(nTable, pSharedData->GetLastRow(nTable),
2926  pSharedData->GetLastColumn(nTable), pCellStyles.get(), pDoc);
2927  pRowFormatRanges->SetColDefaults(&pDefaults->GetColDefaults());
2928  pCellStyles->SetColDefaults(&pDefaults->GetColDefaults());
2929  ExportColumns(nTable, aColumnHeaderRange, bHasColumnHeader);
2930  bool bIsFirst(true);
2931  sal_Int32 nEqualCells(0);
2932  ScMyCell aCell;
2933  ScMyCell aPrevCell;
2934  while (mpCellsItr->GetNext(aCell, pCellStyles.get()))
2935  {
2936  if (bIsFirst)
2937  {
2938  ExportFormatRanges(0, 0, aCell.maCellAddress.Col()-1, aCell.maCellAddress.Row(), nTable);
2939  aPrevCell = aCell;
2940  bIsFirst = false;
2941  }
2942  else
2943  {
2944  if ((aPrevCell.maCellAddress.Row() == aCell.maCellAddress.Row()) &&
2945  (aPrevCell.maCellAddress.Col() + nEqualCells + 1 == aCell.maCellAddress.Col()))
2946  {
2947  if(IsCellEqual(aPrevCell, aCell))
2948  ++nEqualCells;
2949  else
2950  {
2951  WriteCell(aPrevCell, nEqualCells);
2952  nEqualCells = 0;
2953  aPrevCell = aCell;
2954  }
2955  }
2956  else
2957  {
2958  WriteCell(aPrevCell, nEqualCells);
2959  ExportFormatRanges(aPrevCell.maCellAddress.Col() + nEqualCells + 1, aPrevCell.maCellAddress.Row(),
2960  aCell.maCellAddress.Col()-1, aCell.maCellAddress.Row(), nTable);
2961  nEqualCells = 0;
2962  aPrevCell = aCell;
2963  }
2964  }
2965  }
2966  if (!bIsFirst)
2967  {
2968  WriteCell(aPrevCell, nEqualCells);
2969  ExportFormatRanges(aPrevCell.maCellAddress.Col() + nEqualCells + 1, aPrevCell.maCellAddress.Row(),
2970  pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
2971  }
2972  else
2973  ExportFormatRanges(0, 0, pSharedData->GetLastColumn(nTable), pSharedData->GetLastRow(nTable), nTable);
2974 
2975  CloseRow(pSharedData->GetLastRow(nTable));
2976 
2977  if (!pDoc)
2978  return;
2979 
2980  // Export sheet-local named ranges.
2981  ScRangeName* pRangeName = pDoc->GetRangeName(nTable);
2982  if (pRangeName && !pRangeName->empty())
2983  {
2984  WriteNamedRange(pRangeName);
2985  }
2986 
2988  {
2989  //export new conditional format information
2990  ExportConditionalFormat(nTable);
2991  }
2992 }
2993 
2994 namespace {
2995 
2996 void writeContent(
2997  ScXMLExport& rExport, const OUString& rStyleName, const OUString& rContent, const SvxFieldData* pField )
2998 {
2999  std::unique_ptr<SvXMLElementExport> pElem;
3000  if (!rStyleName.isEmpty())
3001  {
3002  // Formatted section with automatic style.
3003  rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME, rStyleName);
3004  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3005  XML_NAMESPACE_TEXT, GetXMLToken(XML_SPAN));
3006  pElem.reset(new SvXMLElementExport(rExport, aElemName, false, false));
3007  }
3008 
3009  if (pField)
3010  {
3011  // Write a field item.
3012  OUString aFieldVal = ScEditUtil::GetCellFieldValue(*pField, rExport.GetDocument(), nullptr);
3013  switch (pField->GetClassId())
3014  {
3015  case text::textfield::Type::URL:
3016  {
3017  // <text:a xlink:href="url" xlink:type="simple">value</text:a>
3018 
3019  const SvxURLField* pURLField = static_cast<const SvxURLField*>(pField);
3020  const OUString& aURL = pURLField->GetURL();
3021  rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, rExport.GetRelativeReference(aURL));
3022  rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, "simple");
3023  const OUString& aTargetFrame = pURLField->GetTargetFrame();
3024  if (!aTargetFrame.isEmpty())
3025  rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_TARGET_FRAME_NAME, aTargetFrame);
3026 
3027  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3028  XML_NAMESPACE_TEXT, GetXMLToken(XML_A));
3029  SvXMLElementExport aElem(rExport, aElemName, false, false);
3030  rExport.Characters(aFieldVal);
3031  }
3032  break;
3034  {
3035  // <text:date style:data-style-name="N2" text:date-value="YYYY-MM-DD">value</text:date>
3036 
3037  Date aDate(Date::SYSTEM);
3038  OUStringBuffer aBuf;
3039  sal_Int32 nVal = aDate.GetYear();
3040  aBuf.append(nVal);
3041  aBuf.append('-');
3042  nVal = aDate.GetMonth();
3043  if (nVal < 10)
3044  aBuf.append('0');
3045  aBuf.append(nVal);
3046  aBuf.append('-');
3047  nVal = aDate.GetDay();
3048  if (nVal < 10)
3049  aBuf.append('0');
3050  aBuf.append(nVal);
3051  rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_DATA_STYLE_NAME, "N2");
3052  rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_DATE_VALUE, aBuf.makeStringAndClear());
3053 
3054  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3055  XML_NAMESPACE_TEXT, GetXMLToken(XML_DATE));
3056  SvXMLElementExport aElem(rExport, aElemName, false, false);
3057  rExport.Characters(aFieldVal);
3058  }
3059  break;
3060  case text::textfield::Type::DOCINFO_TITLE:
3061  {
3062  // <text:title>value</text:title>
3063 
3064  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3065  XML_NAMESPACE_TEXT, GetXMLToken(XML_TITLE));
3066  SvXMLElementExport aElem(rExport, aElemName, false, false);
3067  rExport.Characters(aFieldVal);
3068  }
3069  break;
3071  {
3072  // <text:sheet-name>value</text:sheet-name>
3073 
3074  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3075  XML_NAMESPACE_TEXT, GetXMLToken(XML_SHEET_NAME));
3076  SvXMLElementExport aElem(rExport, aElemName, false, false);
3077  rExport.Characters(aFieldVal);
3078  }
3079  break;
3080  default:
3081  rExport.Characters(aFieldVal);
3082  }
3083  }
3084  else
3085  rExport.Characters(rContent);
3086 }
3087 
3088 void flushParagraph(
3089  ScXMLExport& rExport, const OUString& rParaText,
3091  const ScXMLEditAttributeMap& rAttrMap,
3092  std::vector<editeng::Section>::const_iterator it, std::vector<editeng::Section>::const_iterator const & itEnd )
3093 {
3094  OUString aElemName = rExport.GetNamespaceMap().GetQNameByKey(
3095  XML_NAMESPACE_TEXT, GetXMLToken(XML_P));
3096  SvXMLElementExport aElemP(rExport, aElemName, false, false);
3097 
3098  for (; it != itEnd; ++it)
3099  {
3100  const editeng::Section& rSec = *it;
3101 
3102  OUString aContent(rParaText.copy(rSec.mnStart, rSec.mnEnd - rSec.mnStart));
3103 
3104  std::vector<XMLPropertyState> aPropStates;
3105  const SvxFieldData* pField = toXMLPropertyStates(aPropStates, rSec.maAttributes, xMapper, rAttrMap);
3106  OUString aStyleName = xStylePool->Find(XmlStyleFamily::TEXT_TEXT, OUString(), aPropStates);
3107  writeContent(rExport, aStyleName, aContent, pField);
3108  }
3109 }
3110 
3111 }
3112 
3113 void ScXMLExport::WriteCell(ScMyCell& aCell, sal_Int32 nEqualCellCount)
3114 {
3115  // nEqualCellCount is the number of additional cells
3116  SetRepeatAttribute(nEqualCellCount, (aCell.nType != table::CellContentType_EMPTY));
3117 
3118  if (aCell.nStyleIndex != -1)
3119  AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(aCell.nStyleIndex, aCell.bIsAutoStyle));
3120  if (aCell.nValidationIndex > -1)
3122  const bool bIsFirstMatrixCell(aCell.bIsMatrixBase);
3123  if (bIsFirstMatrixCell)
3124  {
3125  SCCOL nColumns( aCell.aMatrixRange.aEnd.Col() - aCell.aMatrixRange.aStart.Col() + 1 );
3126  SCROW nRows( aCell.aMatrixRange.aEnd.Row() - aCell.aMatrixRange.aStart.Row() + 1 );
3129  }
3130  bool bIsEmpty(false);
3131  switch (aCell.nType)
3132  {
3133  case table::CellContentType_EMPTY :
3134  {
3135  bIsEmpty = true;
3136  }
3137  break;
3138  case table::CellContentType_VALUE :
3139  {
3141  aCell.nNumberFormat, aCell.maBaseCell.mfValue);
3144  aCell.nNumberFormat, aCell.maBaseCell.mfValue, false, XML_NAMESPACE_CALC_EXT, false);
3145  }
3146  break;
3147  case table::CellContentType_TEXT :
3148  {
3149  OUString sFormattedString(lcl_GetFormattedString(pDoc, aCell.maBaseCell, aCell.maCellAddress));
3150  OUString sCellString = aCell.maBaseCell.getString(pDoc);
3152  sCellString, sFormattedString);
3155  sCellString, sFormattedString, false, XML_NAMESPACE_CALC_EXT);
3156  }
3157  break;
3158  case table::CellContentType_FORMULA :
3159  {
3160  if (aCell.maBaseCell.meType == CELLTYPE_FORMULA)
3161  {
3162  const bool bIsMatrix(bIsFirstMatrixCell || aCell.bIsMatrixCovered);
3163  ScFormulaCell* pFormulaCell = aCell.maBaseCell.mpFormula;
3164  if (!bIsMatrix || bIsFirstMatrixCell)
3165  {
3166  if (!mpCompileFormulaCxt)
3167  {
3169  mpCompileFormulaCxt.reset(new sc::CompileFormulaContext(pDoc, eGrammar));
3170  }
3171 
3172  OUString aFormula = pFormulaCell->GetFormula(*mpCompileFormulaCxt);
3173  sal_uInt16 nNamespacePrefix =
3175 
3176  if (!bIsMatrix)
3177  {
3178  AddAttribute(sAttrFormula, GetNamespaceMap().GetQNameByKey(nNamespacePrefix, aFormula, false));
3179  }
3180  else
3181  {
3182  AddAttribute(sAttrFormula, GetNamespaceMap().GetQNameByKey(nNamespacePrefix, aFormula.copy(1, aFormula.getLength()-2), false));
3183  }
3184  }
3185  if (pFormulaCell->GetErrCode() != FormulaError::NONE)
3186  {
3190  {
3191  //export calcext:value-type="error"
3193  }
3194  }
3195  else if (pFormulaCell->IsValue())
3196  {
3197  bool bIsStandard;
3198  OUString sCurrency;
3199  GetNumberFormatAttributesExportHelper()->GetCellType(aCell.nNumberFormat, sCurrency, bIsStandard);
3200  if (pDoc)
3201  {
3203  aCell.nNumberFormat, pDoc->GetValue(aCell.maCellAddress));
3205  {
3207  aCell.nNumberFormat, pDoc->GetValue(aCell.maCellAddress), false, XML_NAMESPACE_CALC_EXT, false );
3208  }
3209  }
3210  }
3211  else
3212  {
3213  if (!aCell.maBaseCell.getString(pDoc).isEmpty())
3214  {
3218  {
3220  }
3221  }
3222  }
3223  }
3224  }
3225  break;
3226  default:
3227  break;
3228  }
3229  OUString* pCellString(&sElemCell);
3230  if (aCell.bIsCovered)
3231  {
3232  pCellString = &sElemCoveredCell;
3233  }
3234  else
3235  {
3236  if (aCell.bIsMergedBase)
3237  {
3238  SCCOL nColumns( aCell.aMergeRange.aEnd.Col() - aCell.aMergeRange.aStart.Col() + 1 );
3239  SCROW nRows( aCell.aMergeRange.aEnd.Row() - aCell.aMergeRange.aStart.Row() + 1 );
3240  AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED, OUString::number(nColumns));
3241  AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED, OUString::number(nRows));
3242  }
3243  }
3244  SvXMLElementExport aElemC(*this, *pCellString, true, true);
3245  CheckAttrList();
3246  WriteAreaLink(aCell);
3247  WriteAnnotation(aCell);
3248  WriteDetective(aCell);
3249 
3250  if (!bIsEmpty)
3251  {
3252  if (aCell.maBaseCell.meType == CELLTYPE_EDIT)
3253  {
3255  }
3257  {
3259  }
3260  else
3261  {
3262  SvXMLElementExport aElemP(*this, sElemP, true, false);
3263 
3264  OUString aParaStr =
3266 
3267  bool bPrevCharWasSpace = true;
3268  GetTextParagraphExport()->exportCharacterData(aParaStr, bPrevCharWasSpace);
3269  }
3270  }
3271  WriteShapes(aCell);
3272  if (!bIsEmpty)
3273  IncrementProgressBar(false);
3274 }
3275 
3277 {
3278  rtl::Reference<XMLPropertySetMapper> xMapper = GetTextParagraphExport()->GetTextPropMapper()->getPropertySetMapper();
3280  const ScXMLEditAttributeMap& rAttrMap = GetEditAttributeMap();
3281 
3282  // Get raw paragraph texts first.
3283  std::vector<OUString> aParaTexts;
3284  sal_Int32 nParaCount = pText->GetParagraphCount();
3285  aParaTexts.reserve(nParaCount);
3286  for (sal_Int32 i = 0; i < nParaCount; ++i)
3287  aParaTexts.push_back(pText->GetText(i));
3288 
3289  // Get all section data and iterate through them.
3290  std::vector<editeng::Section> aAttrs;
3291  pText->GetAllSections(aAttrs);
3292  std::vector<editeng::Section>::const_iterator itSec = aAttrs.begin(), itSecEnd = aAttrs.end();
3293  std::vector<editeng::Section>::const_iterator itPara = itSec;
3294  sal_Int32 nCurPara = 0; // current paragraph
3295  for (; itSec != itSecEnd; ++itSec)
3296  {
3297  const editeng::Section& rSec = *itSec;
3298  if (nCurPara == rSec.mnParagraph)
3299  // Still in the same paragraph.
3300  continue;
3301 
3302  // Start of a new paragraph. Flush the old paragraph.
3303  flushParagraph(*this, aParaTexts[nCurPara], xMapper, xStylePool, rAttrMap, itPara, itSec);
3304  nCurPara = rSec.mnParagraph;
3305  itPara = itSec;
3306  }
3307 
3308  flushParagraph(*this, aParaTexts[nCurPara], xMapper, xStylePool, rAttrMap, itPara, itSecEnd);
3309 }
3310 
3312 {
3314 
3315  OUString aResStr = pCell->GetResultString().getString();
3316  const sal_Unicode* p = aResStr.getStr();
3317  const sal_Unicode* pEnd = p + static_cast<size_t>(aResStr.getLength());
3318  const sal_Unicode* pPara = p; // paragraph head.
3319  for (; p != pEnd; ++p)
3320  {
3321  if (*p != '\n')
3322  continue;
3323 
3324  // flush the paragraph.
3325  OUString aContent;
3326  if (*pPara == '\n')
3327  ++pPara;
3328  if (p > pPara)
3329  aContent = OUString(pPara, p-pPara);
3330 
3331  SvXMLElementExport aElem(*this, aElemName, false, false);
3332  Characters(aContent);
3333 
3334  pPara = p;
3335  }
3336 
3337  OUString aContent;
3338  if (*pPara == '\n')
3339  ++pPara;
3340  if (pEnd > pPara)
3341  aContent = OUString(pPara, pEnd-pPara);
3342 
3343  SvXMLElementExport aElem(*this, aElemName, false, false);
3344  Characters(aContent);
3345 }
3346 
3347 void ScXMLExport::ExportShape(const uno::Reference < drawing::XShape >& xShape, awt::Point* pPoint)
3348 {
3349  uno::Reference < beans::XPropertySet > xShapeProps ( xShape, uno::UNO_QUERY );
3350  bool bIsChart( false );
3351  OUString sPropCLSID ("CLSID");
3352  if (xShapeProps.is())
3353  {
3354  sal_Int32 nZOrder = 0;
3355  if (xShapeProps->getPropertyValue("ZOrder") >>= nZOrder)
3356  {
3357  AddAttribute(XML_NAMESPACE_DRAW, XML_ZINDEX, OUString::number(nZOrder));
3358  }
3359  uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xShapeProps->getPropertySetInfo();
3360  if( xPropSetInfo->hasPropertyByName( sPropCLSID ) )
3361  {
3362  OUString sCLSID;
3363  if (xShapeProps->getPropertyValue( sPropCLSID ) >>= sCLSID)
3364  {
3365  if ( sCLSID.equalsIgnoreAsciiCase(GetChartExport()->getChartCLSID()) )
3366  {
3367  // we have a chart
3368  OUString sRanges;
3369  if ( pDoc )
3370  {
3371  OUString aChartName;
3372  xShapeProps->getPropertyValue( "PersistName" ) >>= aChartName;
3374  if (pCollection)
3375  {
3376  ScChartListener* pListener = pCollection->findByName(aChartName);
3377  if (pListener)
3378  {
3379  const ScRangeListRef& rRangeList = pListener->GetRangeList();
3380  if ( rRangeList.is() )
3381  {
3382  ScRangeStringConverter::GetStringFromRangeList( sRanges, rRangeList.get(), pDoc, FormulaGrammar::CONV_OOO );
3383  if ( !sRanges.isEmpty() )
3384  {
3385  bIsChart = true;
3386  SvXMLAttributeList* pAttrList = new SvXMLAttributeList();
3387  pAttrList->AddAttribute(
3389  GetShapeExport()->exportShape( xShape, SEF_DEFAULT, pPoint, pAttrList );
3390  }
3391  }
3392  }
3393  }
3394  }
3395 
3396  if ( sRanges.isEmpty() )
3397  {
3398  uno::Reference< frame::XModel > xChartModel;
3399  if( ( xShapeProps->getPropertyValue( "Model" ) >>= xChartModel ) &&
3400  xChartModel.is())
3401  {
3402  uno::Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY );
3403  uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartModel, uno::UNO_QUERY );
3404  if( xChartDoc.is() && xReceiver.is() &&
3405  ! xChartDoc->hasInternalDataProvider())
3406  {
3407  // we have a chart that gets its data from Calc
3408  bIsChart = true;
3409  uno::Sequence< OUString > aRepresentations(
3410  xReceiver->getUsedRangeRepresentations());
3411  SvXMLAttributeList* pAttrList = nullptr;
3412  if(aRepresentations.hasElements())
3413  {
3414  // add the ranges used by the chart to the shape
3415  // element to be able to start listening after
3416  // load (when the chart is not yet loaded)
3417  uno::Reference< chart2::data::XRangeXMLConversion > xRangeConverter( xChartDoc->getDataProvider(), uno::UNO_QUERY );
3418  sRanges = lcl_RangeSequenceToString( aRepresentations, xRangeConverter );
3419  pAttrList = new SvXMLAttributeList();
3420  pAttrList->AddAttribute(
3422  }
3423  GetShapeExport()->exportShape(xShape, SEF_DEFAULT, pPoint, pAttrList);
3424  }
3425  }
3426  }
3427  }
3428  }
3429  }
3430  }
3431  if (!bIsChart)
3432  {
3433  OUString sHlink;
3434  try
3435  {
3436  uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );
3437  if ( xProps.is() )
3438  xProps->getPropertyValue( SC_UNONAME_HYPERLINK ) >>= sHlink;
3439  }
3440  catch ( const beans::UnknownPropertyException& )
3441  {
3442  // no hyperlink property
3443  }
3444 
3445  std::unique_ptr< SvXMLElementExport > pDrawA;
3446  // enclose shapes with <draw:a> element only if sHlink contains something
3447  if ( !sHlink.isEmpty() )
3448  {
3449  // need to get delete the attributes that are pre-loaded
3450  // for the shape export ( otherwise they will become
3451  // attributes of the draw:a element ) This *shouldn't*
3452  // affect performance adversely as there are only a
3453  // couple of attributes involved
3454  uno::Reference< xml::sax::XAttributeList > xSaveAttribs( new SvXMLAttributeList( GetAttrList() ) );
3455  ClearAttrList();
3456  // Add Hlink
3459  pDrawA.reset( new SvXMLElementExport( *this, XML_NAMESPACE_DRAW, XML_A, false, false ) );
3460  // Attribute list has been cleared by previous operation
3461  // re-add pre-loaded attributes
3462  AddAttributeList( xSaveAttribs );
3463  }
3464  GetShapeExport()->exportShape(xShape, SEF_DEFAULT, pPoint);
3465  }
3466  IncrementProgressBar(false);
3467 }
3468 
3470 {
3471  if( !(rMyCell.bHasShape && !rMyCell.aShapeList.empty() && pDoc) )
3472  return;
3473 
3474  awt::Point aPoint;
3475  tools::Rectangle aRect = pDoc->GetMMRect(rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(),
3476  rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(), rMyCell.maCellAddress.Tab());
3477  bool bNegativePage = pDoc->IsNegativePage(rMyCell.maCellAddress.Tab());
3478  if (bNegativePage)
3479  aPoint.X = aRect.Right();
3480  else
3481  aPoint.X = aRect.Left();
3482  aPoint.Y = aRect.Top();
3483  for (const auto& rShape : rMyCell.aShapeList)
3484  {
3485  if (rShape.xShape.is())
3486  {
3487  if (bNegativePage)
3488  aPoint.X = 2 * rShape.xShape->getPosition().X + rShape.xShape->getSize().Width - aPoint.X;
3489 
3490  // We only write the end address if we want the shape to resize with the cell
3491  if ( rShape.bResizeWithCell &&
3492  rShape.xShape->getShapeType() != "com.sun.star.drawing.CaptionShape" )
3493  {
3494  OUString sEndAddress;
3495  ScRangeStringConverter::GetStringFromAddress(sEndAddress, rShape.aEndAddress, pDoc, FormulaGrammar::CONV_OOO);
3497  OUStringBuffer sBuffer;
3499  sBuffer, rShape.nEndX);
3500  AddAttribute(XML_NAMESPACE_TABLE, XML_END_X, sBuffer.makeStringAndClear());
3502  sBuffer, rShape.nEndY);
3503  AddAttribute(XML_NAMESPACE_TABLE, XML_END_Y, sBuffer.makeStringAndClear());
3504  }
3505  ExportShape(rShape.xShape, &aPoint);
3506  }
3507  }
3508 }
3509 
3511 {
3512  ScMyTableShapes* pTableShapes(pSharedData->GetTableShapes());
3513  if (!(pTableShapes && !(*pTableShapes)[nCurrentTable].empty()))
3514  return;
3515 
3516  OSL_ENSURE(pTableShapes->size() > static_cast<size_t>(nCurrentTable), "wrong Table");
3517  SvXMLElementExport aShapesElem(*this, XML_NAMESPACE_TABLE, XML_SHAPES, true, false);
3518  for (const auto& rxShape : (*pTableShapes)[nCurrentTable])
3519  {
3520  if (rxShape.is())
3521  {
3522  if (pDoc->IsNegativePage(static_cast<SCTAB>(nCurrentTable)))
3523  {
3524  awt::Point aPoint(rxShape->getPosition());
3525  awt::Size aSize(rxShape->getSize());
3526  aPoint.X += aPoint.X + aSize.Width;
3527  aPoint.Y = 0;
3528  ExportShape(rxShape, &aPoint);
3529  }
3530  else
3531  ExportShape(rxShape, nullptr);
3532  }
3533  }
3534  (*pTableShapes)[nCurrentTable].clear();
3535 }
3536 
3537 void ScXMLExport::WriteAreaLink( const ScMyCell& rMyCell )
3538 {
3539  if( !rMyCell.bHasAreaLink )
3540  return;
3541 
3542  const ScMyAreaLink& rAreaLink = rMyCell.aAreaLink;
3547  if( !rAreaLink.sFilterOptions.isEmpty() )
3549  OUStringBuffer sValue;
3550  AddAttribute( XML_NAMESPACE_TABLE, XML_LAST_COLUMN_SPANNED, OUString::number(rAreaLink.GetColCount()) );
3551  AddAttribute( XML_NAMESPACE_TABLE, XML_LAST_ROW_SPANNED, OUString::number(rAreaLink.GetRowCount()) );
3552  if( rAreaLink.nRefresh )
3553  {
3555  static_cast<double>(rAreaLink.nRefresh) / 86400 );
3556  AddAttribute( XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, sValue.makeStringAndClear() );
3557  }
3558  SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_CELL_RANGE_SOURCE, true, true );
3559 }
3560 
3561 void ScXMLExport::exportAnnotationMeta( const uno::Reference < drawing::XShape >& xShape)
3562 {
3563  ScPostIt* pNote = pCurrentCell->pNote;
3564 
3565  if (!pNote)
3566  return;
3567 
3568  // TODO : notes
3569  //is it still useful, as this call back is only called from ScXMLExport::WriteAnnotation
3570  // and should be in sync with pCurrentCell
3572  uno::Reference<drawing::XShape> xCurrentShape( pNoteCaption->getUnoShape(), uno::UNO_QUERY );
3573  if (xCurrentShape.get()!=xShape.get())
3574  return;
3575 
3576  const OUString& sAuthor(pNote->GetAuthor());
3577  if (!sAuthor.isEmpty())
3578  {
3579  SvXMLElementExport aCreatorElem( *this, XML_NAMESPACE_DC,
3580  XML_CREATOR, true,
3581  false );
3582  Characters(sAuthor);
3583  }
3584 
3585  const OUString& aDate(pNote->GetDate());
3586  if (pDoc)
3587  {
3588  SvNumberFormatter* pNumForm = pDoc->GetFormatTable();
3589  double fDate;
3590  sal_uInt32 nfIndex = pNumForm->GetFormatIndex(NF_DATE_SYS_DDMMYYYY, LANGUAGE_SYSTEM);
3591  if (pNumForm->IsNumberFormat(aDate, nfIndex, fDate))
3592  {
3593  OUStringBuffer sBuf;
3594  GetMM100UnitConverter().convertDateTime(sBuf, fDate,true);
3595  SvXMLElementExport aDateElem( *this, XML_NAMESPACE_DC,
3596  XML_DATE, true,
3597  false );
3598  Characters(sBuf.makeStringAndClear());
3599  }
3600  else
3601  {
3602  SvXMLElementExport aDateElem( *this, XML_NAMESPACE_META,
3603  XML_DATE_STRING, true,
3604  false );
3605  Characters(aDate);
3606  }
3607  }
3608  else
3609  {
3610  SvXMLElementExport aDateElem( *this, XML_NAMESPACE_META,
3611  XML_DATE_STRING, true,
3612  false );
3613  Characters(aDate);
3614  }
3615 }
3616 
3618 {
3619  ScPostIt* pNote = pDoc->GetNote(rMyCell.maCellAddress);
3620  if (!pNote)
3621  return;
3622 
3623  if (pNote->IsCaptionShown())
3625 
3626  pCurrentCell = &rMyCell;
3627 
3628  SdrCaptionObj* pNoteCaption = pNote->GetOrCreateCaption(rMyCell.maCellAddress);
3629  if (pNoteCaption)
3630  {
3631  uno::Reference<drawing::XShape> xShape( pNoteCaption->getUnoShape(), uno::UNO_QUERY );
3632  if (xShape.is())
3633  GetShapeExport()->exportShape(xShape, SEF_DEFAULT|XMLShapeExportFlags::ANNOTATION);
3634  }
3635 
3636  pCurrentCell = nullptr;
3637 }
3638 
3640 {
3641  if( !(rMyCell.bHasDetectiveObj || rMyCell.bHasDetectiveOp) )
3642  return;
3643 
3644  const ScMyDetectiveObjVec& rObjVec = rMyCell.aDetectiveObjVec;
3645  const ScMyDetectiveOpVec& rOpVec = rMyCell.aDetectiveOpVec;
3646  sal_Int32 nObjCount(rObjVec.size());
3647  sal_Int32 nOpCount(rOpVec.size());
3648  if( !(nObjCount || nOpCount) )
3649  return;
3650 
3651  SvXMLElementExport aDetElem( *this, XML_NAMESPACE_TABLE, XML_DETECTIVE, true, true );
3652  OUString sString;
3653  for(const auto& rObj : rObjVec)
3654  {
3655  if (rObj.eObjType != SC_DETOBJ_CIRCLE)
3656  {
3657  if( (rObj.eObjType == SC_DETOBJ_ARROW) || (rObj.eObjType == SC_DETOBJ_TOOTHERTAB))
3658  {
3659  ScRangeStringConverter::GetStringFromRange( sString, rObj.aSourceRange, pDoc, FormulaGrammar::CONV_OOO );
3661  }
3662  ScXMLConverter::GetStringFromDetObjType( sString, rObj.eObjType );
3664  if( rObj.bHasError )
3666  }
3667  else
3669  SvXMLElementExport aRangeElem( *this, XML_NAMESPACE_TABLE, XML_HIGHLIGHTED_RANGE, true, true );
3670  }
3671  for(const auto& rOp : rOpVec)
3672  {
3673  OUString sOpString;
3674  ScXMLConverter::GetStringFromDetOpType( sOpString, rOp.eOpType );
3675  AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, sOpString );
3676  AddAttribute( XML_NAMESPACE_TABLE, XML_INDEX, OUString::number(rOp.nIndex) );
3677  SvXMLElementExport aRangeElem( *this, XML_NAMESPACE_TABLE, XML_OPERATION, true, true );
3678  }
3679 }
3680 
3681 void ScXMLExport::SetRepeatAttribute(sal_Int32 nEqualCellCount, bool bIncProgress)
3682 {
3683  // nEqualCellCount is additional cells, so the attribute value is nEqualCellCount+1
3684  if (nEqualCellCount > 0)
3685  {
3686  sal_Int32 nTemp(nEqualCellCount + 1);
3687  OUString sOUEqualCellCount(OUString::number(nTemp));
3688  AddAttribute(sAttrColumnsRepeated, sOUEqualCellCount);
3689  if (bIncProgress)
3690  IncrementProgressBar(false, nEqualCellCount);
3691  }
3692 }
3693 
3695 {
3696  return rCell.maBaseCell.meType == CELLTYPE_EDIT;
3697 }
3698 
3699 bool ScXMLExport::IsCellEqual (const ScMyCell& aCell1, const ScMyCell& aCell2)
3700 {
3701  bool bIsEqual = false;
3702  if( !aCell1.bIsMergedBase && !aCell2.bIsMergedBase &&
3703  aCell1.bIsCovered == aCell2.bIsCovered &&
3704  !aCell1.bIsMatrixBase && !aCell2.bIsMatrixBase &&
3705  aCell1.bIsMatrixCovered == aCell2.bIsMatrixCovered &&
3706  aCell1.bHasAnnotation == aCell2.bHasAnnotation &&
3707  !aCell1.bHasShape && !aCell2.bHasShape &&
3708  aCell1.bHasAreaLink == aCell2.bHasAreaLink &&
3709  !aCell1.bHasDetectiveObj && !aCell2.bHasDetectiveObj)
3710  {
3711  if( (aCell1.bHasAreaLink &&
3712  (aCell1.aAreaLink.GetColCount() == 1) &&
3713  (aCell2.aAreaLink.GetColCount() == 1) &&
3714  aCell1.aAreaLink.Compare( aCell2.aAreaLink ) ) ||
3715  !aCell1.bHasAreaLink )
3716  {
3717  if (!aCell1.bHasAnnotation)
3718  {
3719  if ((((aCell1.nStyleIndex == aCell2.nStyleIndex) && (aCell1.bIsAutoStyle == aCell2.bIsAutoStyle)) ||
3720  ((aCell1.nStyleIndex == aCell2.nStyleIndex) && (aCell1.nStyleIndex == -1))) &&
3721  aCell1.nValidationIndex == aCell2.nValidationIndex &&
3722  aCell1.nType == aCell2.nType)
3723  {
3724  switch ( aCell1.nType )
3725  {
3726  case table::CellContentType_EMPTY :
3727  {
3728  bIsEqual = true;
3729  }
3730  break;
3731  case table::CellContentType_VALUE :
3732  {
3733  // #i29101# number format may be different from column default styles,
3734  // but can lead to different value types, so it must also be compared
3735  bIsEqual = (aCell1.nNumberFormat == aCell2.nNumberFormat) &&
3736  (aCell1.maBaseCell.mfValue == aCell2.maBaseCell.mfValue);
3737  }
3738  break;
3739  case table::CellContentType_TEXT :
3740  {
3741  if (IsEditCell(aCell1) || IsEditCell(aCell2))
3742  bIsEqual = false;
3743  else
3744  {
3745  bIsEqual = (aCell1.maBaseCell.getString(pDoc) == aCell2.maBaseCell.getString(pDoc));
3746  }
3747  }
3748  break;
3749  case table::CellContentType_FORMULA :
3750  {
3751  bIsEqual = false;
3752  }
3753  break;
3754  default :
3755  {
3756  bIsEqual = false;
3757  }
3758  break;
3759  }
3760  }
3761  }
3762  }
3763  }
3764  return bIsEqual;
3765 }
3766 
3767 void ScXMLExport::WriteCalculationSettings(const uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc)
3768 {
3769  uno::Reference<beans::XPropertySet> xPropertySet(xSpreadDoc, uno::UNO_QUERY);
3770  if (!xPropertySet.is())
3771  return;
3772 
3773  bool bCalcAsShown (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_CALCASSHOWN) ));
3774  bool bIgnoreCase (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_IGNORECASE) ));
3775  bool bLookUpLabels (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_LOOKUPLABELS) ));
3776  bool bMatchWholeCell (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_MATCHWHOLE) ));
3777  bool bUseRegularExpressions (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_REGEXENABLED) ));
3778  bool bUseWildcards (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_WILDCARDSENABLED) ));
3779  if (bUseWildcards && bUseRegularExpressions)
3780  bUseRegularExpressions = false; // mutually exclusive, wildcards take precedence
3781  bool bIsIterationEnabled (::cppu::any2bool( xPropertySet->getPropertyValue(SC_UNO_ITERENABLED) ));
3782  sal_uInt16 nYear2000 (pDoc ? pDoc->GetDocOptions().GetYear2000() : 0);
3783  sal_Int32 nIterationCount(100);
3784  xPropertySet->getPropertyValue( SC_UNO_ITERCOUNT ) >>= nIterationCount;
3785  double fIterationEpsilon = 0;
3786  xPropertySet->getPropertyValue( SC_UNO_ITEREPSILON ) >>= fIterationEpsilon;
3787  util::Date aNullDate;
3788  xPropertySet->getPropertyValue( SC_UNO_NULLDATE ) >>= aNullDate;
3789  if (!(bCalcAsShown || bIgnoreCase || !bLookUpLabels || !bMatchWholeCell || !bUseRegularExpressions ||
3790  bUseWildcards ||
3791  bIsIterationEnabled || nIterationCount != 100 || !::rtl::math::approxEqual(fIterationEpsilon, 0.001) ||
3792  aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899 || nYear2000 != 1930))
3793  return;
3794 
3795  if (bIgnoreCase)
3797  if (bCalcAsShown)
3799  if (!bMatchWholeCell)
3801  if (!bLookUpLabels)
3803  if (!bUseRegularExpressions)
3805  if (bUseWildcards)
3807  if (nYear2000 != 1930)
3808  {
3809  AddAttribute(XML_NAMESPACE_TABLE, XML_NULL_YEAR, OUString::number(nYear2000));
3810  }
3811  SvXMLElementExport aCalcSettings(*this, XML_NAMESPACE_TABLE, XML_CALCULATION_SETTINGS, true, true);
3812  {
3813  if (aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899)
3814  {
3815  OUStringBuffer sDate;
3816  SvXMLUnitConverter::convertDateTime(sDate, 0.0, aNullDate);
3817  AddAttribute(XML_NAMESPACE_TABLE, XML_DATE_VALUE, sDate.makeStringAndClear());
3818  SvXMLElementExport aElemNullDate(*this, XML_NAMESPACE_TABLE, XML_NULL_DATE, true, true);
3819  }
3820  if (bIsIterationEnabled || nIterationCount != 100 || !::rtl::math::approxEqual(fIterationEpsilon, 0.001))
3821  {
3822  OUStringBuffer sBuffer;
3823  if (bIsIterationEnabled)
3825  if (nIterationCount != 100)
3826  {
3827  AddAttribute(XML_NAMESPACE_TABLE, XML_STEPS, OUString::number(nIterationCount));
3828  }
3829  if (!::rtl::math::approxEqual(fIterationEpsilon, 0.001))
3830  {
3832  fIterationEpsilon);
3833  AddAttribute(XML_NAMESPACE_TABLE, XML_MAXIMUM_DIFFERENCE, sBuffer.makeStringAndClear());
3834  }
3835  SvXMLElementExport aElemIteration(*this, XML_NAMESPACE_TABLE, XML_ITERATION, true, true);
3836  }
3837  }
3838 }
3839 
3841 {
3842  uno::Reference <sheet::XSheetLinkable> xLinkable (xCurrentTable, uno::UNO_QUERY);
3843  if (!(xLinkable.is() && GetModel().is()))
3844  return;
3845 
3846  sheet::SheetLinkMode nMode (xLinkable->getLinkMode());
3847  if (nMode == sheet::SheetLinkMode_NONE)
3848  return;
3849 
3850  OUString sLink (xLinkable->getLinkUrl());
3851  uno::Reference <beans::XPropertySet> xProps (GetModel(), uno::UNO_QUERY);
3852  if (!xProps.is())
3853  return;
3854 
3855  uno::Reference <container::XIndexAccess> xIndex(xProps->getPropertyValue(SC_UNO_SHEETLINKS), uno::UNO_QUERY);
3856  if (!xIndex.is())
3857  return;
3858 
3859  sal_Int32 nCount(xIndex->getCount());
3860  if (!nCount)
3861  return;
3862 
3863  bool bFound(false);
3864  uno::Reference <beans::XPropertySet> xLinkProps;
3865  for (sal_Int32 i = 0; (i < nCount) && !bFound; ++i)
3866  {
3867  xLinkProps.set(xIndex->getByIndex(i), uno::UNO_QUERY);
3868  if (xLinkProps.is())
3869  {
3870  OUString sNewLink;
3871  if (xLinkProps->getPropertyValue(SC_UNONAME_LINKURL) >>= sNewLink)
3872  bFound = sLink == sNewLink;
3873  }
3874  }
3875  if (!(bFound && xLinkProps.is()))
3876  return;
3877 
3878  OUString sFilter;
3879  OUString sFilterOptions;
3880  OUString sTableName (xLinkable->getLinkSheetName());
3881  sal_Int32 nRefresh(0);
3882  xLinkProps->getPropertyValue(SC_UNONAME_FILTER) >>= sFilter;
3883  xLinkProps->getPropertyValue(SC_UNONAME_FILTOPT) >>= sFilterOptions;
3884  xLinkProps->getPropertyValue(SC_UNONAME_REFDELAY) >>= nRefresh;
3885  if (sLink.isEmpty())
3886  return;
3887 
3890  if (!sTableName.isEmpty())
3892  if (!sFilter.isEmpty())
3894  if (!sFilterOptions.isEmpty())
3896  if (nMode != sheet::SheetLinkMode_NORMAL)
3898  if( nRefresh )
3899  {
3900  OUStringBuffer sBuffer;
3902  static_cast<double>(nRefresh) / 86400 );
3903  AddAttribute( XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, sBuffer.makeStringAndClear() );
3904  }
3905  SvXMLElementExport aSourceElem(*this, XML_NAMESPACE_TABLE, XML_TABLE_SOURCE, true, true);
3906 }
3907 
3908 // core implementation
3910 {
3911  if (!(pDoc && pDoc->IsScenario(static_cast<SCTAB>(nCurrentTable))))
3912  return;
3913 
3914  OUString sComment;
3915  Color aColor;
3916  ScScenarioFlags nFlags;
3917  pDoc->GetScenarioData(static_cast<SCTAB>(nCurrentTable), sComment, aColor, nFlags);
3918  if (!(nFlags & ScScenarioFlags::ShowFrame))
3920  OUStringBuffer aBuffer;
3921  ::sax::Converter::convertColor(aBuffer, aColor);
3922  AddAttribute(XML_NAMESPACE_TABLE, XML_BORDER_COLOR, aBuffer.makeStringAndClear());
3923  if (!(nFlags & ScScenarioFlags::TwoWay))
3925  if (!(nFlags & ScScenarioFlags::Attrib))
3927  if (nFlags & ScScenarioFlags::Value)
3929  if (nFlags & ScScenarioFlags::Protected)
3932  pDoc->IsActiveScenario(static_cast<SCTAB>(nCurrentTable)));
3933  AddAttribute(XML_NAMESPACE_TABLE, XML_IS_ACTIVE, aBuffer.makeStringAndClear());
3934  const ScRangeList* pRangeList = pDoc->GetScenarioRanges(static_cast<SCTAB>(nCurrentTable));
3935  OUString sRangeListStr;
3936  ScRangeStringConverter::GetStringFromRangeList( sRangeListStr, pRangeList, pDoc, FormulaGrammar::CONV_OOO );
3938  if (!sComment.isEmpty())
3940  SvXMLElementExport aElem(*this, XML_NAMESPACE_TABLE, XML_SCENARIO, true, true);
3941 }
3942 
3943 void ScXMLExport::WriteTheLabelRanges( const uno::Reference< sheet::XSpreadsheetDocument >& xSpreadDoc )
3944 {
3945  uno::Reference< beans::XPropertySet > xDocProp( xSpreadDoc, uno::UNO_QUERY );
3946  if( !xDocProp.is() ) return;
3947 
3948  sal_Int32 nCount(0);
3949  uno::Reference< container::XIndexAccess > xColRangesIAccess(xDocProp->getPropertyValue( SC_UNO_COLLABELRNG ), uno::UNO_QUERY);
3950  if( xColRangesIAccess.is() )
3951  nCount += xColRangesIAccess->getCount();
3952 
3953  uno::Reference< container::XIndexAccess > xRowRangesIAccess(xDocProp->getPropertyValue( SC_UNO_ROWLABELRNG ), uno::UNO_QUERY);
3954  if( xRowRangesIAccess.is() )
3955  nCount += xRowRangesIAccess->getCount();
3956 
3957  if( nCount )
3958  {
3959  SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_LABEL_RANGES, true, true );
3960  WriteLabelRanges( xColRangesIAccess, true );
3961  WriteLabelRanges( xRowRangesIAccess, false );
3962  }
3963 }
3964 
3965 void ScXMLExport::WriteLabelRanges( const uno::Reference< container::XIndexAccess >& xRangesIAccess, bool bColumn )
3966 {
3967  if( !xRangesIAccess.is() ) return;
3968 
3969  sal_Int32 nCount(xRangesIAccess->getCount());
3970  for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
3971  {
3972  uno::Reference< sheet::XLabelRange > xRange(xRangesIAccess->getByIndex( nIndex ), uno::UNO_QUERY);
3973  if( xRange.is() )
3974  {
3975  OUString sRangeStr;
3976  table::CellRangeAddress aCellRange( xRange->getLabelArea() );
3977  ScRangeStringConverter::GetStringFromRange( sRangeStr, aCellRange, pDoc, FormulaGrammar::CONV_OOO );
3979  aCellRange = xRange->getDataArea();
3980  ScRangeStringConverter::GetStringFromRange( sRangeStr, aCellRange, pDoc, FormulaGrammar::CONV_OOO );
3983  SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_LABEL_RANGE, true, true );
3984  }
3985  }
3986 }
3987 
3989 {
3990  if (!pDoc)
3991  return;
3992  ScRangeName* pNamedRanges = pDoc->GetRangeName();
3993  WriteNamedRange(pNamedRanges);
3994 }
3995 
3997 {
3998  if (!pDoc)
3999  return;
4000 
4002  // Export this only for 1.2 extended and above.
4003  return;
4004 
4006  auto& rDataSources = rDataMapper.getDataSources();
4007 
4008  if (rDataSources.empty())
4009  return;
4010 
4011  SvXMLElementExport aMappings(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_MAPPINGS, true, true);
4012  for (const auto& itr : rDataSources)
4013  {
4014  AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, itr.getURL());
4015  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_PROVIDER, itr.getProvider());
4019 
4020  SvXMLElementExport aMapping(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_MAPPING, true, true);
4021  // Add the data transformations
4022  WriteExternalDataTransformations(itr.getDataTransformation());
4023  }
4024 }
4025 
4026 void ScXMLExport::WriteExternalDataTransformations(const std::vector<std::shared_ptr<sc::DataTransformation>>& aDataTransformations)
4027 {
4028  SvXMLElementExport aTransformations(*this, XML_NAMESPACE_CALC_EXT, XML_DATA_TRANSFORMATIONS, true, true);
4029  for (auto& itr : aDataTransformations)
4030  {
4031  sc::TransformationType aTransformationType = itr->getTransformationType();
4032 
4033  switch(aTransformationType)
4034  {
4036  {
4037  // Delete Columns Transformation
4038  std::shared_ptr<sc::ColumnRemoveTransformation> aDeleteTransformation = std::dynamic_pointer_cast<sc::ColumnRemoveTransformation>(itr);
4039  std::set<SCCOL> aColumns = aDeleteTransformation->getColumns();
4040  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_REMOVE_TRANSFORMATION, true, true);
4041  for(auto& col : aColumns)
4042  {
4043  // Add Columns
4044  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4045  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4046  }
4047  }
4048  break;
4050  {
4051  std::shared_ptr<sc::SplitColumnTransformation> aSplitTransformation = std::dynamic_pointer_cast<sc::SplitColumnTransformation>(itr);
4052 
4053  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(aSplitTransformation->getColumn()));
4054  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_SEPARATOR, OUString::number(aSplitTransformation->getSeparator()));
4055  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_SPLIT_TRANSFORMATION, true, true);
4056  }
4057  break;
4059  {
4060  // Merge Transformation
4061  std::shared_ptr<sc::MergeColumnTransformation> aMergeTransformation = std::dynamic_pointer_cast<sc::MergeColumnTransformation>(itr);
4062  std::set<SCCOL> aColumns = aMergeTransformation->getColumns();
4063 
4064  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_MERGE_STRING, aMergeTransformation->getMergeString());
4065  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_MERGE_TRANSFORMATION, true, true);
4066 
4067  for(auto& col : aColumns)
4068  {
4069  // Columns
4070  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4071  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4072  }
4073  }
4074  break;
4076  {
4077  // Sort Transformation
4078  std::shared_ptr<sc::SortTransformation> aSortTransformation = std::dynamic_pointer_cast<sc::SortTransformation>(itr);
4079  ScSortParam aSortParam = aSortTransformation->getSortParam();
4081  const sc::DataStream* pStrm = rMgr.getDataStream();
4082  if (!pStrm)
4083  // No data stream.
4084  return;
4085 
4086  // Streamed range
4087  ScRange aRange = pStrm->GetRange();
4088 
4089  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_SORT_TRANSFORMATION, true, true);
4090 
4091  writeSort(*this, aSortParam, aRange, pDoc);
4092  }
4093  break;
4095  {
4096  // Text Transformation
4097  std::shared_ptr<sc::TextTransformation> aTextTransformation = std::dynamic_pointer_cast<sc::TextTransformation>(itr);
4098 
4099  sc::TEXT_TRANSFORM_TYPE aTextTransformType = aTextTransformation->getTextTransformationType();
4100 
4101  switch ( aTextTransformType )
4102  {
4105  break;
4108  break;
4111  break;
4114  break;
4115  }
4116 
4117  std::set<SCCOL> aColumns = aTextTransformation->getColumns();
4118 
4119  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_TEXT_TRANSFORMATION, true, true);
4120 
4121  for(auto& col : aColumns)
4122  {
4123  // Columns
4124  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4125  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4126  }
4127  }
4128  break;
4130  {
4131  // Aggregate Transformation
4132  std::shared_ptr<sc::AggregateFunction> aAggregateFunction = std::dynamic_pointer_cast<sc::AggregateFunction>(itr);
4133  std::set<SCCOL> aColumns = aAggregateFunction->getColumns();
4134 
4135  sc::AGGREGATE_FUNCTION aAggregateType = aAggregateFunction->getAggregateType();
4136 
4137  switch (aAggregateType)
4138  {
4141  break;
4144  break;
4147  break;
4150  break;
4151  }
4152 
4154 
4155  for(auto& col : aColumns)
4156  {
4157  // Columns
4158  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4159  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4160  }
4161  }
4162  break;
4164  {
4165  // Number Transformation
4166  std::shared_ptr<sc::NumberTransformation> aNumberTransformation = std::dynamic_pointer_cast<sc::NumberTransformation>(itr);
4167 
4168  sc::NUMBER_TRANSFORM_TYPE aNumberTransformType = aNumberTransformation->getNumberTransformationType();
4169 
4170  switch ( aNumberTransformType )
4171  {
4174  break;
4177  break;
4180  break;
4183  break;
4186  break;
4189  break;
4192  break;
4195  break;
4198  break;
4201  break;
4204  break;
4207  break;
4210  break;
4211  }
4212 
4213  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_PRECISION, OUString::number(aNumberTransformation->getPrecision()));
4214  SvXMLElementExport aTransformation(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN_NUMBER_TRANSFORMATION, true, true);
4215 
4216  std::set<SCCOL> aColumns = aNumberTransformation->getColumn();
4217  for(auto& col : aColumns)
4218  {
4219  // Columns
4220  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4221  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4222  }
4223  }
4224  break;
4226  {
4227  // Replace Null Transformation
4228  std::shared_ptr<sc::ReplaceNullTransformation> aReplaceNullTransformation = std::dynamic_pointer_cast<sc::ReplaceNullTransformation>(itr);
4229  std::set<SCCOL> aColumns = aReplaceNullTransformation->getColumn();
4230 
4231  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_REPLACE_STRING, aReplaceNullTransformation->getReplaceString());
4233 
4234  for(auto& col : aColumns)
4235  {
4236  // Columns
4237  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4238  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4239  }
4240  }
4241  break;
4243  {
4244  // Number Transformation
4245  std::shared_ptr<sc::DateTimeTransformation> aDateTimeTransformation = std::dynamic_pointer_cast<sc::DateTimeTransformation>(itr);
4246 
4247  sc::DATETIME_TRANSFORMATION_TYPE aDateTimeTransformationType = aDateTimeTransformation->getDateTimeTransformationType();
4248 
4249  switch ( aDateTimeTransformationType )
4250  {
4253  break;
4256  break;
4259  break;
4262  break;
4265  break;
4268  break;
4271  break;
4274  break;
4277  break;
4280  break;
4283  break;
4286  break;
4289  break;
4292  break;
4295  break;
4298  break;
4301  break;
4304  break;
4305  }
4306 
4308 
4309  std::set<SCCOL> aColumns = aDateTimeTransformation->getColumn();
4310  for(auto& col : aColumns)
4311  {
4312  // Columns
4313  AddAttribute(XML_NAMESPACE_CALC_EXT, XML_COLUMN, OUString::number(col));
4314  SvXMLElementExport aCol(*this, XML_NAMESPACE_CALC_EXT, XML_COLUMN, true, true);
4315  }
4316  }
4317  break;
4318  default:
4319  break;
4320  }
4321  }
4322 }
4323 
4325 {
4326  if (!pDoc)
4327  return;
4328 
4329  SvtMiscOptions aMiscOptions;
4330  if (!aMiscOptions.IsExperimentalMode())
4331  // Export this only in experimental mode.
4332  return;
4333 
4335  // Export this only for 1.2 extended and above.
4336  return;
4337 
4339  const sc::DataStream* pStrm = rMgr.getDataStream();
4340  if (!pStrm)
4341  // No data stream.
4342  return;
4343 
4344  // Source URL
4346 
4347  // Streamed range
4348  ScRange aRange = pStrm->GetRange();
4349  OUString aRangeStr;
4351  aRangeStr, aRange, pDoc, formula::FormulaGrammar::CONV_OOO);
4353 
4354  // Empty line refresh option.
4356 
4357  // New data insertion position. Either top of bottom. Default to bottom.
4358  xmloff::token::XMLTokenEnum eInsertPosition = XML_BOTTOM;
4359  if (pStrm->GetMove() == sc::DataStream::MOVE_DOWN)
4360  eInsertPosition = XML_TOP;
4361 
4363 
4365 }
4366 
4368 {
4369  //write a global or local ScRangeName
4370  SvXMLElementExport aElemNEs(*this, XML_NAMESPACE_TABLE, XML_NAMED_EXPRESSIONS, true, true);
4371  for (const auto& rxEntry : *pRangeName)
4372  {
4373  AddAttribute(sAttrName, rxEntry.second->GetName());
4374 
4375  OUString sBaseCellAddress;
4376  rxEntry.second->ValidateTabRefs();
4377  ScRangeStringConverter::GetStringFromAddress( sBaseCellAddress, rxEntry.second->GetPos(), pDoc,
4378  FormulaGrammar::CONV_OOO, ' ', false, ScRefFlags::ADDR_ABS_3D);
4380 
4381  OUString sSymbol;
4382  rxEntry.second->GetSymbol(sSymbol, pDoc->GetStorageGrammar());
4383  OUString sTempSymbol(sSymbol);
4384  ScRange aRange;
4385  if (rxEntry.second->IsReference(aRange))
4386  {
4387 
4388  OUString sContent(sTempSymbol.copy(1, sTempSymbol.getLength() -2 ));
4390 
4391  sal_Int32 nRangeType = rxEntry.second->GetUnoType();