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