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