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