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