Version 7.5.1.1, tag libreoffice-7.5.1.1
[LibreOffice.git] / sc / source / filter / xml / xmlimprt.cxx
blob467b8820db5557667fc3720ac9c53a3b4ffa74d3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
22 #include <osl/diagnose.h>
24 #include <svl/numformat.hxx>
26 #include <xmloff/namespacemap.hxx>
27 #include <xmloff/xmlnamespace.hxx>
28 #include <xmloff/xmlictxt.hxx>
29 #include <xmloff/xmlmetai.hxx>
30 #include <sfx2/objsh.hxx>
31 #include <unotools/streamwrap.hxx>
32 #include <xmloff/xmlscripti.hxx>
33 #include <xmloff/XMLFontStylesContext.hxx>
34 #include <xmloff/DocumentSettingsContext.hxx>
35 #include <xmloff/xmluconv.hxx>
36 #include <xmloff/numehelp.hxx>
37 #include <xmloff/xmltoken.hxx>
38 #include <xmloff/xmlerror.hxx>
39 #include <xmloff/ProgressBarHelper.hxx>
40 #include <svx/svdpage.hxx>
42 #include <svl/languageoptions.hxx>
43 #include <editeng/editstat.hxx>
44 #include <formula/errorcodes.hxx>
45 #include <vcl/svapp.hxx>
47 #include <appluno.hxx>
48 #include "xmlimprt.hxx"
49 #include "importcontext.hxx"
50 #include <document.hxx>
51 #include <docsh.hxx>
52 #include <docuno.hxx>
53 #include "xmlbodyi.hxx"
54 #include "xmlstyli.hxx"
55 #include <ViewSettingsSequenceDefines.hxx>
56 #include <userdat.hxx>
58 #include <compiler.hxx>
60 #include "XMLConverter.hxx"
61 #include "XMLDetectiveContext.hxx"
62 #include "XMLTableShapeImportHelper.hxx"
63 #include "XMLChangeTrackingImportHelper.hxx"
64 #include <chgviset.hxx>
65 #include "XMLStylesImportHelper.hxx"
66 #include <sheetdata.hxx>
67 #include <rangeutl.hxx>
68 #include <formulaparserpool.hxx>
69 #include <externalrefmgr.hxx>
70 #include <editutil.hxx>
71 #include "editattributemap.hxx"
72 #include <documentimport.hxx>
73 #include "pivotsource.hxx"
74 #include <unonames.hxx>
75 #include <numformat.hxx>
76 #include <sizedev.hxx>
77 #include <scdll.hxx>
78 #include "xmlstyle.hxx"
80 #include <comphelper/base64.hxx>
81 #include <comphelper/extract.hxx>
82 #include <comphelper/propertysequence.hxx>
83 #include <comphelper/processfactory.hxx>
85 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
86 #include <com/sun/star/frame/XModel.hpp>
87 #include <com/sun/star/io/IOException.hpp>
88 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
89 #include <com/sun/star/document/XActionLockable.hpp>
90 #include <com/sun/star/util/MalformedNumberFormatException.hpp>
91 #include <com/sun/star/util/NumberFormat.hpp>
92 #include <com/sun/star/util/XNumberFormatTypes.hpp>
93 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
94 #include <com/sun/star/sheet/NamedRangeFlag.hpp>
95 #include <com/sun/star/sheet/XLabelRanges.hpp>
96 #include <com/sun/star/io/XSeekable.hpp>
97 #include <com/sun/star/beans/XPropertySet.hpp>
98 #include <com/sun/star/sheet/XSheetCellRangeContainer.hpp>
99 #include <cellsuno.hxx>
101 #include <memory>
102 #include <utility>
104 constexpr OUStringLiteral SC_LOCALE = u"Locale";
105 constexpr OUStringLiteral SC_CURRENCYSYMBOL = u"CurrencySymbol";
106 constexpr OUStringLiteral SC_REPEAT_ROW = u"repeat-row";
107 constexpr OUStringLiteral SC_FILTER = u"filter";
108 constexpr OUStringLiteral SC_PRINT_RANGE = u"print-range";
110 using namespace com::sun::star;
111 using namespace ::xmloff::token;
112 using namespace ::formula;
114 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
115 Calc_XMLOasisImporter_get_implementation(
116 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
118 return cppu::acquire(
119 new ScXMLImport(
120 context,
121 "com.sun.star.comp.Calc.XMLOasisImporter",
122 SvXMLImportFlags::ALL,
123 { "com.sun.star.comp.Calc.XMLOasisImporter" } ));
126 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
127 Calc_XMLOasisMetaImporter_get_implementation(
128 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
130 return cppu::acquire(
131 new ScXMLImport(
132 context,
133 "com.sun.star.comp.Calc.XMLOasisMetaImporter",
134 SvXMLImportFlags::META,
135 { "com.sun.star.comp.Calc.XMLOasisMetaImporter" } ));
138 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
139 Calc_XMLOasisStylesImporter_get_implementation(
140 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
142 return cppu::acquire(
143 new ScXMLImport(
144 context,
145 "com.sun.star.comp.Calc.XMLOasisStylesImporter",
146 SvXMLImportFlags::STYLES|SvXMLImportFlags::AUTOSTYLES|SvXMLImportFlags::MASTERSTYLES|SvXMLImportFlags::FONTDECLS,
147 { "com.sun.star.comp.Calc.XMLOasisStylesImporter" } ));
150 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
151 Calc_XMLOasisContentImporter_get_implementation(
152 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
154 return cppu::acquire(new ScXMLImport(
155 context,
156 "com.sun.star.comp.Calc.XMLOasisContentImporter",
157 SvXMLImportFlags::AUTOSTYLES|SvXMLImportFlags::CONTENT|SvXMLImportFlags::SCRIPTS|SvXMLImportFlags::FONTDECLS,
158 uno::Sequence< OUString > { "com.sun.star.comp.Calc.XMLOasisContentImporter" }));
162 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
163 Calc_XMLOasisSettingsImporter_get_implementation(
164 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
166 return cppu::acquire(
167 new ScXMLImport(
168 context,
169 "com.sun.star.comp.Calc.XMLOasisSettingsImporter",
170 SvXMLImportFlags::SETTINGS,
171 { "com.sun.star.comp.Calc.XMLOasisSettingsImporter" } ));
174 namespace {
176 // NB: virtually inherit so we can multiply inherit properly
177 // in ScXMLFlatDocContext_Impl
178 class ScXMLDocContext_Impl : public virtual SvXMLImportContext
180 protected:
181 ScXMLImport& GetScImport() { return static_cast<ScXMLImport&>(GetImport()); }
183 public:
184 ScXMLDocContext_Impl( ScXMLImport& rImport );
186 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL
187 createFastChildContext( sal_Int32 nElement,
188 const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList ) override;
193 ScXMLDocContext_Impl::ScXMLDocContext_Impl( ScXMLImport& rImport ) :
194 SvXMLImportContext( rImport )
198 namespace {
200 // context for flat file xml format
201 class ScXMLFlatDocContext_Impl
202 : public ScXMLDocContext_Impl, public SvXMLMetaDocumentContext
204 public:
206 ScXMLFlatDocContext_Impl( ScXMLImport& i_rImport,
207 const uno::Reference<document::XDocumentProperties>& i_xDocProps);
209 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL
210 createFastChildContext( sal_Int32 nElement,
211 const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList ) override;
216 ScXMLFlatDocContext_Impl::ScXMLFlatDocContext_Impl( ScXMLImport& i_rImport,
217 const uno::Reference<document::XDocumentProperties>& i_xDocProps) :
218 SvXMLImportContext(i_rImport),
219 ScXMLDocContext_Impl(i_rImport),
220 SvXMLMetaDocumentContext(i_rImport, i_xDocProps)
224 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
225 ScXMLFlatDocContext_Impl::createFastChildContext( sal_Int32 nElement,
226 const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
228 if ( nElement == XML_ELEMENT( OFFICE, XML_META ) )
229 return SvXMLMetaDocumentContext::createFastChildContext( nElement, xAttrList );
230 else
231 return ScXMLDocContext_Impl::createFastChildContext( nElement, xAttrList );
234 namespace {
236 class ScXMLBodyContext_Impl : public ScXMLImportContext
238 public:
239 ScXMLBodyContext_Impl( ScXMLImport& rImport );
241 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL
242 createFastChildContext( sal_Int32 nElement,
243 const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList ) override;
248 ScXMLBodyContext_Impl::ScXMLBodyContext_Impl( ScXMLImport& rImport ) :
249 ScXMLImportContext( rImport )
253 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
254 ScXMLBodyContext_Impl::createFastChildContext( sal_Int32 /*nElement*/,
255 const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
257 sax_fastparser::FastAttributeList *pAttribList =
258 &sax_fastparser::castToFastAttributeList( xAttrList );
259 return GetScImport().CreateBodyContext( pAttribList );
262 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
263 ScXMLDocContext_Impl::createFastChildContext( sal_Int32 nElement,
264 const uno::Reference< xml::sax::XFastAttributeList > & /*xAttrList*/ )
266 SvXMLImportContext *pContext(nullptr);
268 switch( nElement )
270 case XML_ELEMENT( OFFICE, XML_BODY ):
271 if (GetScImport().getImportFlags() & SvXMLImportFlags::CONTENT)
272 pContext = new ScXMLBodyContext_Impl( GetScImport() );
273 break;
274 case XML_ELEMENT( OFFICE, XML_SCRIPTS ):
275 if (GetScImport().getImportFlags() & SvXMLImportFlags::SCRIPTS)
276 pContext = GetScImport().CreateScriptContext();
277 break;
278 case XML_ELEMENT( OFFICE, XML_SETTINGS ):
279 if (GetScImport().getImportFlags() & SvXMLImportFlags::SETTINGS)
280 pContext = new XMLDocumentSettingsContext(GetScImport());
281 break;
282 case XML_ELEMENT(OFFICE, XML_STYLES):
283 if (GetScImport().getImportFlags() & SvXMLImportFlags::STYLES)
284 pContext = GetScImport().CreateStylesContext( false);
285 break;
286 case XML_ELEMENT(OFFICE, XML_AUTOMATIC_STYLES):
287 if (GetScImport().getImportFlags() & SvXMLImportFlags::AUTOSTYLES)
288 pContext = GetScImport().CreateStylesContext( true);
289 break;
290 case XML_ELEMENT(OFFICE, XML_FONT_FACE_DECLS):
291 if (GetScImport().getImportFlags() & SvXMLImportFlags::FONTDECLS)
292 pContext = GetScImport().CreateFontDeclsContext();
293 break;
294 case XML_ELEMENT(OFFICE, XML_MASTER_STYLES):
295 if (GetScImport().getImportFlags() & SvXMLImportFlags::MASTERSTYLES)
296 pContext = new ScXMLMasterStylesContext( GetImport() );
297 break;
298 case XML_ELEMENT(OFFICE, XML_META):
299 SAL_INFO("sc", "XML_ELEMENT(OFFICE, XML_META): should not have come here, maybe document is invalid?");
300 break;
303 return pContext;
307 void ScXMLImport::SetPostProcessData( sc::ImportPostProcessData* p )
309 mpPostProcessData = p;
312 sc::PivotTableSources& ScXMLImport::GetPivotTableSources()
314 if (!mpPivotSources)
315 mpPivotSources.reset(new sc::PivotTableSources);
317 return *mpPivotSources;
320 SvXMLImportContext *ScXMLImport::CreateFastContext( sal_Int32 nElement,
321 const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
323 SvXMLImportContext *pContext = nullptr;
325 switch( nElement )
327 case XML_ELEMENT( OFFICE, XML_DOCUMENT_STYLES ):
328 case XML_ELEMENT( OFFICE, XML_DOCUMENT_CONTENT ):
329 case XML_ELEMENT( OFFICE, XML_DOCUMENT_SETTINGS ):
330 pContext = new ScXMLDocContext_Impl( *this );
331 break;
333 case XML_ELEMENT( OFFICE, XML_DOCUMENT_META ):
334 pContext = CreateMetaContext(nElement);
335 break;
337 case XML_ELEMENT( OFFICE, XML_DOCUMENT ):
339 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
340 GetModel(), uno::UNO_QUERY_THROW);
341 // flat OpenDocument file format
342 pContext = new ScXMLFlatDocContext_Impl( *this,
343 xDPS->getDocumentProperties());
344 break;
349 return pContext;
352 ScXMLImport::ScXMLImport(
353 const css::uno::Reference< css::uno::XComponentContext >& rContext,
354 OUString const & implementationName, SvXMLImportFlags nImportFlag,
355 const css::uno::Sequence< OUString > & sSupportedServiceNames)
356 : SvXMLImport( rContext, implementationName, nImportFlag, sSupportedServiceNames ),
357 pDoc( nullptr ),
358 mpPostProcessData(nullptr),
359 aTables(*this),
360 nSolarMutexLocked(0),
361 nProgressCount(0),
362 nPrevCellType(0),
363 bLoadDoc( true ),
364 bNullDateSetted(false),
365 bSelfImportingXMLSet(false),
366 mbLockSolarMutex(true),
367 mbImportStyles(true),
368 mbHasNewCondFormatData(false)
370 pStylesImportHelper.reset(new ScMyStylesImportHelper(*this));
372 xScPropHdlFactory = new XMLScPropHdlFactory;
373 xCellStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScCellStylesProperties, xScPropHdlFactory, false);
374 xColumnStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScColumnStylesProperties, xScPropHdlFactory, false);
375 xRowStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScRowStylesImportProperties, xScPropHdlFactory, false);
376 xTableStylesPropertySetMapper = new XMLPropertySetMapper(aXMLScTableStylesImportProperties, xScPropHdlFactory, false);
378 // #i66550# needed for 'presentation:event-listener' element for URLs in shapes
379 GetNamespaceMap().Add(
380 GetXMLToken( XML_NP_PRESENTATION ),
381 GetXMLToken( XML_N_PRESENTATION ),
382 XML_NAMESPACE_PRESENTATION );
385 ScXMLImport::~ScXMLImport() noexcept
387 pChangeTrackingImportHelper.reset();
388 pNumberFormatAttributesExportHelper.reset();
389 pStyleNumberFormats.reset();
390 pStylesImportHelper.reset();
392 m_aMyNamedExpressions.clear();
393 maMyLabelRanges.clear();
394 maValidations.clear();
395 pDetectiveOpArray.reset();
397 //call SvXMLImport dtor contents before deleting pSolarMutexGuard
398 cleanup();
400 pSolarMutexGuard.reset();
403 void ScXMLImport::initialize( const css::uno::Sequence<css::uno::Any>& aArguments )
405 SvXMLImport::initialize(aArguments);
407 uno::Reference<beans::XPropertySet> xInfoSet = getImportInfo();
408 if (!xInfoSet.is())
409 return;
411 uno::Reference<beans::XPropertySetInfo> xInfoSetInfo = xInfoSet->getPropertySetInfo();
412 if (!xInfoSetInfo.is())
413 return;
415 if (xInfoSetInfo->hasPropertyByName(SC_UNO_ODS_LOCK_SOLAR_MUTEX))
416 xInfoSet->getPropertyValue(SC_UNO_ODS_LOCK_SOLAR_MUTEX) >>= mbLockSolarMutex;
418 if (xInfoSetInfo->hasPropertyByName(SC_UNO_ODS_IMPORT_STYLES))
419 xInfoSet->getPropertyValue(SC_UNO_ODS_IMPORT_STYLES) >>= mbImportStyles;
422 SvXMLImportContext *ScXMLImport::CreateFontDeclsContext()
424 XMLFontStylesContext *pFSContext = new XMLFontStylesContext(
425 *this, osl_getThreadTextEncoding());
426 SetFontDecls(pFSContext);
427 SvXMLImportContext* pContext = pFSContext;
428 return pContext;
431 SvXMLImportContext *ScXMLImport::CreateStylesContext( bool bIsAutoStyle )
433 SvXMLImportContext* pContext = new XMLTableStylesContext(
434 *this, bIsAutoStyle);
436 if (bIsAutoStyle)
437 SetAutoStyles(static_cast<SvXMLStylesContext*>(pContext));
438 else
439 SetStyles(static_cast<SvXMLStylesContext*>(pContext));
441 return pContext;
444 SvXMLImportContext *ScXMLImport::CreateBodyContext(const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList)
446 return new ScXMLBodyContext(*this, rAttrList);
449 SvXMLImportContext *ScXMLImport::CreateMetaContext(
450 const sal_Int32 /*nElement*/ )
452 SvXMLImportContext* pContext = nullptr;
454 if (getImportFlags() & SvXMLImportFlags::META)
456 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
457 GetModel(), uno::UNO_QUERY_THROW);
458 uno::Reference<document::XDocumentProperties> const xDocProps(
459 (IsStylesOnlyMode()) ? nullptr : xDPS->getDocumentProperties());
460 pContext = new SvXMLMetaDocumentContext(*this, xDocProps);
463 return pContext;
466 SvXMLImportContext *ScXMLImport::CreateScriptContext()
468 SvXMLImportContext* pContext = nullptr;
470 if( !(IsStylesOnlyMode()) )
472 pContext = new XMLScriptContext( *this, GetModel() );
475 return pContext;
478 void ScXMLImport::SetStatistics(const uno::Sequence<beans::NamedValue> & i_rStats)
480 static const char* s_stats[] =
481 { "TableCount", "CellCount", "ObjectCount", nullptr };
483 SvXMLImport::SetStatistics(i_rStats);
485 sal_uInt64 nCount(0);
486 for (const auto& rStat : i_rStats) {
487 for (const char** pStat = s_stats; *pStat != nullptr; ++pStat) {
488 if (rStat.Name.equalsAscii(*pStat)) {
489 sal_Int32 val = 0;
490 if (rStat.Value >>= val) {
491 nCount += val;
492 } else {
493 OSL_FAIL("ScXMLImport::SetStatistics: invalid entry");
499 if (nCount)
501 GetProgressBarHelper()->SetReference(nCount);
502 GetProgressBarHelper()->SetValue(0);
506 ScDocumentImport& ScXMLImport::GetDoc()
508 return *mpDocImport;
511 sal_Int16 ScXMLImport::GetCellType(const char* rStrValue, const sal_Int32 nStrLength)
513 sal_Int16 nCellType = util::NumberFormat::UNDEFINED;
514 if (rStrValue != nullptr)
516 switch (rStrValue[0])
518 case 'b':
519 if (nStrLength == 7 && !strcmp(rStrValue, "boolean"))
520 nCellType = util::NumberFormat::LOGICAL;
521 break;
522 case 'c':
523 if (nStrLength == 8 && !strcmp(rStrValue, "currency"))
524 nCellType = util::NumberFormat::CURRENCY;
525 break;
526 case 'd':
527 if (nStrLength == 4 && !strcmp(rStrValue, "date"))
528 nCellType = util::NumberFormat::DATETIME;
529 break;
530 case 'f':
531 if (nStrLength == 5 && !strcmp(rStrValue, "float"))
532 nCellType = util::NumberFormat::NUMBER;
533 break;
534 case 'p':
535 if (nStrLength == 10 && !strcmp(rStrValue, "percentage"))
536 nCellType = util::NumberFormat::PERCENT;
537 break;
538 case 's':
539 if (nStrLength == 6 && !strcmp(rStrValue, "string"))
540 nCellType = util::NumberFormat::TEXT;
541 break;
542 case 't':
543 if (nStrLength == 4 && !strcmp(rStrValue, "time"))
544 nCellType = util::NumberFormat::TIME;
545 break;
549 return nCellType;
552 XMLShapeImportHelper* ScXMLImport::CreateShapeImport()
554 return new XMLTableShapeImportHelper(*this);
557 bool ScXMLImport::GetValidation(const OUString& sName, ScMyImportValidation& aValidation)
559 auto aItr = std::find_if(maValidations.begin(), maValidations.end(),
560 [&sName](const ScMyImportValidation& rValidation) { return rValidation.sName == sName; });
561 if (aItr != maValidations.end())
563 // source position must be set as string,
564 // so sBaseCellAddress no longer has to be converted here
565 aValidation = *aItr;
566 return true;
568 return false;
571 void ScXMLImport::AddNamedExpression(SCTAB nTab, ScMyNamedExpression aNamedExp)
573 SheetNamedExpMap::iterator itr = m_SheetNamedExpressions.find(nTab);
574 if (itr == m_SheetNamedExpressions.end())
576 // No chain exists for this sheet. Create one.
577 ::std::pair<SheetNamedExpMap::iterator, bool> r =
578 m_SheetNamedExpressions.insert(std::make_pair(nTab, ScMyNamedExpressions()));
579 if (!r.second)
580 // insertion failed.
581 return;
583 itr = r.first;
585 ScMyNamedExpressions& r = itr->second;
586 r.push_back(std::move(aNamedExp));
589 ScXMLChangeTrackingImportHelper* ScXMLImport::GetChangeTrackingImportHelper()
591 if (!pChangeTrackingImportHelper)
592 pChangeTrackingImportHelper.reset(new ScXMLChangeTrackingImportHelper());
593 return pChangeTrackingImportHelper.get();
596 void ScXMLImport::InsertStyles()
598 GetStyles()->CopyStylesToDoc(true);
600 // if content is going to be loaded with the same import, set bLatinDefaultStyle flag now
601 if ( getImportFlags() & SvXMLImportFlags::CONTENT )
602 ExamineDefaultStyle();
605 void ScXMLImport::ExamineDefaultStyle()
607 if (pDoc)
609 // #i62435# after inserting the styles, check if the default style has a latin-script-only
610 // number format (then, value cells can be pre-initialized with western script type)
612 const ScPatternAttr* pDefPattern = pDoc->GetDefPattern();
613 if (pDefPattern && sc::NumFmtUtil::isLatinScript(*pDefPattern, *pDoc))
614 mpDocImport->setDefaultNumericScript(SvtScriptType::LATIN);
618 void ScXMLImport::SetChangeTrackingViewSettings(const css::uno::Sequence<css::beans::PropertyValue>& rChangeProps)
620 if (!pDoc)
621 return;
623 if (!rChangeProps.hasElements())
624 return;
626 ScXMLImport::MutexGuard aGuard(*this);
627 sal_Int16 nTemp16(0);
628 ScChangeViewSettings aViewSettings;
629 for (const auto& rChangeProp : rChangeProps)
631 OUString sName(rChangeProp.Name);
632 if (sName == "ShowChanges")
633 aViewSettings.SetShowChanges(::cppu::any2bool(rChangeProp.Value));
634 else if (sName == "ShowAcceptedChanges")
635 aViewSettings.SetShowAccepted(::cppu::any2bool(rChangeProp.Value));
636 else if (sName == "ShowRejectedChanges")
637 aViewSettings.SetShowRejected(::cppu::any2bool(rChangeProp.Value));
638 else if (sName == "ShowChangesByDatetime")
639 aViewSettings.SetHasDate(::cppu::any2bool(rChangeProp.Value));
640 else if (sName == "ShowChangesByDatetimeMode")
642 if (rChangeProp.Value >>= nTemp16)
643 aViewSettings.SetTheDateMode(static_cast<SvxRedlinDateMode>(nTemp16));
645 else if (sName == "ShowChangesByDatetimeFirstDatetime")
647 util::DateTime aDateTime;
648 if (rChangeProp.Value >>= aDateTime)
650 aViewSettings.SetTheFirstDateTime(::DateTime(aDateTime));
653 else if (sName == "ShowChangesByDatetimeSecondDatetime")
655 util::DateTime aDateTime;
656 if (rChangeProp.Value >>= aDateTime)
658 aViewSettings.SetTheLastDateTime(::DateTime(aDateTime));
661 else if (sName == "ShowChangesByAuthor")
662 aViewSettings.SetHasAuthor(::cppu::any2bool(rChangeProp.Value));
663 else if (sName == "ShowChangesByAuthorName")
665 OUString sOUName;
666 if (rChangeProp.Value >>= sOUName)
668 aViewSettings.SetTheAuthorToShow(sOUName);
671 else if (sName == "ShowChangesByComment")
672 aViewSettings.SetHasComment(::cppu::any2bool(rChangeProp.Value));
673 else if (sName == "ShowChangesByCommentText")
675 OUString sOUComment;
676 if (rChangeProp.Value >>= sOUComment)
678 aViewSettings.SetTheComment(sOUComment);
681 else if (sName == "ShowChangesByRanges")
682 aViewSettings.SetHasRange(::cppu::any2bool(rChangeProp.Value));
683 else if (sName == "ShowChangesByRangesList")
685 OUString sRanges;
686 if ((rChangeProp.Value >>= sRanges) && !sRanges.isEmpty())
688 ScRangeList aRangeList;
689 ScRangeStringConverter::GetRangeListFromString(
690 aRangeList, sRanges, *pDoc, FormulaGrammar::CONV_OOO);
691 aViewSettings.SetTheRangeList(aRangeList);
695 pDoc->SetChangeViewSettings(aViewSettings);
698 void ScXMLImport::SetViewSettings(const uno::Sequence<beans::PropertyValue>& aViewProps)
700 sal_Int32 nHeight(0);
701 sal_Int32 nLeft(0);
702 sal_Int32 nTop(0);
703 sal_Int32 nWidth(0);
704 for (const auto& rViewProp : aViewProps)
706 OUString sName(rViewProp.Name);
707 if (sName == "VisibleAreaHeight")
708 rViewProp.Value >>= nHeight;
709 else if (sName == "VisibleAreaLeft")
710 rViewProp.Value >>= nLeft;
711 else if (sName == "VisibleAreaTop")
712 rViewProp.Value >>= nTop;
713 else if (sName == "VisibleAreaWidth")
714 rViewProp.Value >>= nWidth;
715 else if (sName == "TrackedChangesViewSettings")
717 uno::Sequence<beans::PropertyValue> aChangeProps;
718 if(rViewProp.Value >>= aChangeProps)
719 SetChangeTrackingViewSettings(aChangeProps);
722 if (!(nHeight && nWidth && GetModel().is()))
723 return;
725 ScModelObj* pDocObj(comphelper::getFromUnoTunnel<ScModelObj>( GetModel() ));
726 if (!pDocObj)
727 return;
729 SfxObjectShell* pEmbeddedObj = pDocObj->GetEmbeddedObject();
730 if (pEmbeddedObj)
732 tools::Rectangle aRect{ nLeft, nTop };
733 aRect.setWidth( nWidth );
734 aRect.setHeight( nHeight );
735 pEmbeddedObj->SetVisArea(aRect);
739 void ScXMLImport::SetConfigurationSettings(const uno::Sequence<beans::PropertyValue>& aConfigProps)
741 if (!GetModel().is())
742 return;
744 uno::Reference <lang::XMultiServiceFactory> xMultiServiceFactory(GetModel(), uno::UNO_QUERY);
745 if (!xMultiServiceFactory.is())
746 return;
748 sal_Int32 nCount(aConfigProps.getLength());
749 css::uno::Sequence<css::beans::PropertyValue> aFilteredProps(nCount);
750 auto pFilteredProps = aFilteredProps.getArray();
751 sal_Int32 nFilteredPropsLen = 0;
752 for (sal_Int32 i = nCount - 1; i >= 0; --i)
754 if (aConfigProps[i].Name == "TrackedChangesProtectionKey")
756 OUString sKey;
757 if (aConfigProps[i].Value >>= sKey)
759 uno::Sequence<sal_Int8> aPass;
760 ::comphelper::Base64::decode(aPass, sKey);
761 if (aPass.hasElements())
763 if (pDoc->GetChangeTrack())
764 pDoc->GetChangeTrack()->SetProtection(aPass);
765 else
767 std::set<OUString> aUsers;
768 std::unique_ptr<ScChangeTrack> pTrack( new ScChangeTrack(*pDoc, std::move(aUsers)) );
769 pTrack->SetProtection(aPass);
770 pDoc->SetChangeTrack(std::move(pTrack));
775 // store the following items for later use (after document is loaded)
776 else if ((aConfigProps[i].Name == "VBACompatibilityMode") || (aConfigProps[i].Name == "ScriptConfiguration"))
778 uno::Reference< beans::XPropertySet > xImportInfo = getImportInfo();
779 if (xImportInfo.is())
781 uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = xImportInfo->getPropertySetInfo();
782 if (xPropertySetInfo.is() && xPropertySetInfo->hasPropertyByName(aConfigProps[i].Name))
783 xImportInfo->setPropertyValue( aConfigProps[i].Name, aConfigProps[i].Value );
786 if (aConfigProps[i].Name != "LinkUpdateMode")
788 pFilteredProps[nFilteredPropsLen++] = aConfigProps[i];
791 aFilteredProps.realloc(nFilteredPropsLen);
792 uno::Reference <uno::XInterface> xInterface = xMultiServiceFactory->createInstance("com.sun.star.comp.SpreadsheetSettings");
793 uno::Reference <beans::XPropertySet> xProperties(xInterface, uno::UNO_QUERY);
794 if (xProperties.is())
795 SvXMLUnitConverter::convertPropertySet(xProperties, aFilteredProps);
798 sal_Int32 ScXMLImport::SetCurrencySymbol(const sal_Int32 nKey, std::u16string_view rCurrency)
800 uno::Reference <util::XNumberFormatsSupplier> xNumberFormatsSupplier(GetNumberFormatsSupplier());
801 if (xNumberFormatsSupplier.is())
803 uno::Reference <util::XNumberFormats> xLocalNumberFormats(xNumberFormatsSupplier->getNumberFormats());
804 if (xLocalNumberFormats.is())
806 OUString sFormatString;
809 uno::Reference <beans::XPropertySet> xProperties(xLocalNumberFormats->getByKey(nKey));
810 if (xProperties.is())
812 lang::Locale aLocale;
813 if (GetDocument() && (xProperties->getPropertyValue(SC_LOCALE) >>= aLocale))
816 ScXMLImport::MutexGuard aGuard(*this);
817 LocaleDataWrapper aLocaleData( comphelper::getProcessComponentContext(), LanguageTag( aLocale) );
818 sFormatString = "#" +
819 aLocaleData.getNumThousandSep() +
820 "##0" +
821 aLocaleData.getNumDecimalSep() +
822 "00 [$" +
823 rCurrency +
824 "]";
826 sal_Int32 nNewKey = xLocalNumberFormats->queryKey(sFormatString, aLocale, true);
827 if (nNewKey == -1)
828 nNewKey = xLocalNumberFormats->addNew(sFormatString, aLocale);
829 return nNewKey;
833 catch ( const util::MalformedNumberFormatException& rException )
835 OUString sErrorMessage ="Error in Formatstring " +
836 sFormatString + " at position " +
837 OUString::number(rException.CheckPos);
838 uno::Sequence<OUString> aSeq { sErrorMessage };
839 uno::Reference<xml::sax::XLocator> xLocator;
840 SetError(XMLERROR_API | XMLERROR_FLAG_ERROR, aSeq, rException.Message, xLocator);
844 return nKey;
847 bool ScXMLImport::IsCurrencySymbol(const sal_Int32 nNumberFormat, std::u16string_view sCurrentCurrency, std::u16string_view sBankSymbol)
849 uno::Reference <util::XNumberFormatsSupplier> xNumberFormatsSupplier(GetNumberFormatsSupplier());
850 if (xNumberFormatsSupplier.is())
852 uno::Reference <util::XNumberFormats> xLocalNumberFormats(xNumberFormatsSupplier->getNumberFormats());
853 if (xLocalNumberFormats.is())
857 uno::Reference <beans::XPropertySet> xNumberPropertySet(xLocalNumberFormats->getByKey(nNumberFormat));
858 if (xNumberPropertySet.is())
860 OUString sTemp;
861 if ( xNumberPropertySet->getPropertyValue(SC_CURRENCYSYMBOL) >>= sTemp)
863 if (sCurrentCurrency == sTemp)
864 return true;
865 // A release that saved an unknown currency may have
866 // saved the currency symbol of the number format
867 // instead of an ISO code bank symbol. In another
868 // release we may have a match for that. In this case
869 // sCurrentCurrency is the ISO code obtained through
870 // XMLNumberFormatAttributesExportHelper::GetCellType()
871 // and sBankSymbol is the currency symbol.
872 if (sCurrentCurrency.size() == 3 && sBankSymbol == sTemp)
873 return true;
874 // #i61657# This may be a legacy currency symbol that changed in the meantime.
875 if (SvNumberFormatter::GetLegacyOnlyCurrencyEntry( sCurrentCurrency, sBankSymbol) != nullptr)
876 return true;
877 // In the rare case that sCurrentCurrency is not the
878 // currency symbol, but a matching ISO code
879 // abbreviation instead that was obtained through
880 // XMLNumberFormatAttributesExportHelper::GetCellType(),
881 // check with the number format's symbol. This happens,
882 // for example, in the es_BO locale, where a legacy
883 // B$,BOB matched B$->BOP, which leads to
884 // sCurrentCurrency being BOP, and the previous call
885 // with BOP,BOB didn't find an entry, but B$,BOB will.
886 return SvNumberFormatter::GetLegacyOnlyCurrencyEntry( sTemp, sBankSymbol) != nullptr;
890 catch ( uno::Exception& )
892 OSL_FAIL("Numberformat not found");
896 return false;
899 void ScXMLImport::SetType(const uno::Reference <beans::XPropertySet>& rProperties,
900 sal_Int32& rNumberFormat,
901 const sal_Int16 nCellType,
902 std::u16string_view rCurrency)
904 if (!mbImportStyles)
905 return;
907 if ((nCellType == util::NumberFormat::TEXT) || (nCellType == util::NumberFormat::UNDEFINED))
908 return;
910 if (rNumberFormat == -1)
911 rProperties->getPropertyValue( SC_UNONAME_NUMFMT ) >>= rNumberFormat;
912 OSL_ENSURE(rNumberFormat != -1, "no NumberFormat");
913 bool bIsStandard;
914 // sCurrentCurrency may be the ISO code abbreviation if the currency
915 // symbol matches such, or if no match found the symbol itself!
916 OUString sCurrentCurrency;
917 sal_Int32 nCurrentCellType(
918 GetNumberFormatAttributesExportHelper()->GetCellType(
919 rNumberFormat, sCurrentCurrency, bIsStandard) & ~util::NumberFormat::DEFINED);
920 // If the (numeric) cell type (number, currency, date, time, boolean)
921 // is different from the format type then for some combinations we may
922 // have to apply a format, e.g. in case the generator deduced format
923 // from type and did not apply a format but we don't keep a dedicated
924 // type internally. Specifically this is necessary if the cell type is
925 // not number but the format type is (i.e. General). Currency cells
926 // need extra attention, see calls of ScXMLImport::IsCurrencySymbol()
927 // and description within there and ScXMLImport::SetCurrencySymbol().
928 if ((nCellType != nCurrentCellType) &&
929 (nCellType != util::NumberFormat::NUMBER) &&
930 (bIsStandard || (nCellType == util::NumberFormat::CURRENCY)))
932 if (!xNumberFormats.is())
934 uno::Reference <util::XNumberFormatsSupplier> xNumberFormatsSupplier(GetNumberFormatsSupplier());
935 if (xNumberFormatsSupplier.is())
936 xNumberFormats.set(xNumberFormatsSupplier->getNumberFormats());
938 if (xNumberFormats.is())
942 uno::Reference < beans::XPropertySet> xNumberFormatProperties(xNumberFormats->getByKey(rNumberFormat));
943 if (xNumberFormatProperties.is())
945 if (nCellType != util::NumberFormat::CURRENCY)
947 lang::Locale aLocale;
948 if ( xNumberFormatProperties->getPropertyValue(SC_LOCALE) >>= aLocale )
950 if (!xNumberFormatTypes.is())
951 xNumberFormatTypes.set(uno::Reference <util::XNumberFormatTypes>(xNumberFormats, uno::UNO_QUERY));
952 rProperties->setPropertyValue( SC_UNONAME_NUMFMT, uno::Any(xNumberFormatTypes->getStandardFormat(nCellType, aLocale)) );
955 else if (!rCurrency.empty() && !sCurrentCurrency.isEmpty())
957 if (sCurrentCurrency != rCurrency)
958 if (!IsCurrencySymbol(rNumberFormat, sCurrentCurrency, rCurrency))
959 rProperties->setPropertyValue( SC_UNONAME_NUMFMT, uno::Any(SetCurrencySymbol(rNumberFormat, rCurrency)));
963 catch ( uno::Exception& )
965 OSL_FAIL("Numberformat not found");
969 else
971 if ((nCellType == util::NumberFormat::CURRENCY) && !rCurrency.empty() && !sCurrentCurrency.isEmpty() &&
972 sCurrentCurrency != rCurrency && !IsCurrencySymbol(rNumberFormat, sCurrentCurrency, rCurrency))
973 rProperties->setPropertyValue( SC_UNONAME_NUMFMT, uno::Any(SetCurrencySymbol(rNumberFormat, rCurrency)));
977 void ScXMLImport::SetStyleToRanges()
979 if (!mbImportStyles)
980 return;
982 if (!sPrevStyleName.isEmpty())
984 uno::Reference <beans::XPropertySet> xProperties (xSheetCellRanges, uno::UNO_QUERY);
985 if (xProperties.is())
987 XMLTableStylesContext *pStyles(static_cast<XMLTableStylesContext *>(GetAutoStyles()));
988 XMLTableStyleContext* pStyle = nullptr;
989 if ( pStyles )
990 pStyle = const_cast<XMLTableStyleContext*>(static_cast<const XMLTableStyleContext *>(pStyles->FindStyleChildContext(
991 XmlStyleFamily::TABLE_CELL, sPrevStyleName, true)));
992 if (pStyle)
994 pStyle->FillPropertySet(xProperties);
995 // here needs to be the cond format import method
996 sal_Int32 nNumberFormat(pStyle->GetNumberFormat());
997 SetType(xProperties, nNumberFormat, nPrevCellType, sPrevCurrency);
999 css::uno::Any aAny = xProperties->getPropertyValue("FormatID");
1000 sal_uInt64 nKey = 0;
1001 if ((aAny >>= nKey) && nKey)
1003 ScFormatSaveData* pFormatSaveData = comphelper::getFromUnoTunnel<ScModelObj>(GetModel())->GetFormatSaveData();
1004 pFormatSaveData->maIDToName.insert(std::pair<sal_uInt64, OUString>(nKey, sPrevStyleName));
1007 // store first cell of first range for each style, once per sheet
1008 uno::Sequence<table::CellRangeAddress> aAddresses(xSheetCellRanges->getRangeAddresses());
1009 pStyle->ApplyCondFormat(aAddresses);
1010 if ( aAddresses.hasElements() )
1012 const table::CellRangeAddress& rRange = aAddresses[0];
1013 if ( rRange.Sheet != pStyle->GetLastSheet() )
1015 ScSheetSaveData* pSheetData = comphelper::getFromUnoTunnel<ScModelObj>(GetModel())->GetSheetSaveData();
1016 pSheetData->AddCellStyle( sPrevStyleName,
1017 ScAddress( static_cast<SCCOL>(rRange.StartColumn), static_cast<SCROW>(rRange.StartRow), static_cast<SCTAB>(rRange.Sheet) ) );
1018 pStyle->SetLastSheet(rRange.Sheet);
1022 else
1024 xProperties->setPropertyValue(SC_UNONAME_CELLSTYL, uno::Any(GetStyleDisplayName( XmlStyleFamily::TABLE_CELL, sPrevStyleName )));
1025 sal_Int32 nNumberFormat(GetStyleNumberFormats()->GetStyleNumberFormat(sPrevStyleName));
1026 bool bInsert(nNumberFormat == -1);
1027 SetType(xProperties, nNumberFormat, nPrevCellType, sPrevCurrency);
1028 if (bInsert)
1029 GetStyleNumberFormats()->AddStyleNumberFormat(sPrevStyleName, nNumberFormat);
1033 if (GetModel().is())
1035 uno::Reference <lang::XMultiServiceFactory> xMultiServiceFactory(GetModel(), uno::UNO_QUERY);
1036 if (xMultiServiceFactory.is())
1037 xSheetCellRanges.set(uno::Reference <sheet::XSheetCellRangeContainer>(
1038 xMultiServiceFactory->createInstance("com.sun.star.sheet.SheetCellRanges"),
1039 uno::UNO_QUERY));
1041 OSL_ENSURE(xSheetCellRanges.is(), "didn't get SheetCellRanges");
1044 void ScXMLImport::SetStyleToRanges(const ScRangeList& rRanges, const OUString* pStyleName,
1045 const sal_Int16 nCellType, const OUString* pCurrency)
1047 if (!mbImportStyles)
1048 return;
1050 if (sPrevStyleName.isEmpty())
1052 nPrevCellType = nCellType;
1053 if (pStyleName)
1054 sPrevStyleName = *pStyleName;
1055 if (pCurrency)
1056 sPrevCurrency = *pCurrency;
1057 else if (!sPrevCurrency.isEmpty())
1058 sPrevCurrency.clear();
1060 else if ((nCellType != nPrevCellType) ||
1061 ((pStyleName && *pStyleName != sPrevStyleName) ||
1062 (!pStyleName && !sPrevStyleName.isEmpty())) ||
1063 ((pCurrency && *pCurrency != sPrevCurrency) ||
1064 (!pCurrency && !sPrevCurrency.isEmpty())))
1066 SetStyleToRanges();
1067 nPrevCellType = nCellType;
1068 if (pStyleName)
1069 sPrevStyleName = *pStyleName;
1070 else if(!sPrevStyleName.isEmpty())
1071 sPrevStyleName.clear();
1072 if (pCurrency)
1073 sPrevCurrency = *pCurrency;
1074 else if(!sPrevCurrency.isEmpty())
1075 sPrevCurrency.clear();
1078 if (!xSheetCellRanges.is() && GetModel().is())
1080 uno::Reference <lang::XMultiServiceFactory> xMultiServiceFactory(GetModel(), uno::UNO_QUERY);
1081 if (xMultiServiceFactory.is())
1082 xSheetCellRanges.set(uno::Reference <sheet::XSheetCellRangeContainer>(xMultiServiceFactory->createInstance("com.sun.star.sheet.SheetCellRanges"), uno::UNO_QUERY));
1083 OSL_ENSURE(xSheetCellRanges.is(), "didn't get SheetCellRanges");
1086 static_cast<ScCellRangesObj*>(xSheetCellRanges.get())->SetNewRanges(rRanges);
1089 bool ScXMLImport::SetNullDateOnUnitConverter()
1091 if (!bNullDateSetted)
1092 bNullDateSetted = GetMM100UnitConverter().setNullDate(GetModel());
1093 OSL_ENSURE(bNullDateSetted, "could not set the null date");
1094 return bNullDateSetted;
1097 XMLNumberFormatAttributesExportHelper* ScXMLImport::GetNumberFormatAttributesExportHelper()
1099 if (!pNumberFormatAttributesExportHelper)
1100 pNumberFormatAttributesExportHelper.reset(new XMLNumberFormatAttributesExportHelper(GetNumberFormatsSupplier()));
1101 return pNumberFormatAttributesExportHelper.get();
1104 ScMyStyleNumberFormats* ScXMLImport::GetStyleNumberFormats()
1106 if (!pStyleNumberFormats)
1107 pStyleNumberFormats.reset(new ScMyStyleNumberFormats);
1108 return pStyleNumberFormats.get();
1111 void ScXMLImport::SetStylesToRangesFinished()
1113 SetStyleToRanges();
1114 sPrevStyleName.clear();
1117 // XImporter
1118 void SAL_CALL ScXMLImport::setTargetDocument( const css::uno::Reference< css::lang::XComponent >& xDoc )
1120 ScXMLImport::MutexGuard aGuard(*this);
1121 SvXMLImport::setTargetDocument( xDoc );
1123 uno::Reference<frame::XModel> xModel(xDoc, uno::UNO_QUERY);
1124 pDoc = ScXMLConverter::GetScDocument( xModel );
1125 OSL_ENSURE( pDoc, "ScXMLImport::setTargetDocument - no ScDocument!" );
1126 if (!pDoc)
1127 throw lang::IllegalArgumentException();
1129 if (ScDocShell* pDocSh = static_cast<ScDocShell*>(pDoc->GetDocumentShell()))
1130 pDocSh->SetInitialLinkUpdate( pDocSh->GetMedium());
1132 mpDocImport.reset(new ScDocumentImport(*pDoc));
1133 mpComp.reset(new ScCompiler(*pDoc, ScAddress(), formula::FormulaGrammar::GRAM_ODFF));
1135 uno::Reference<document::XActionLockable> xActionLockable(xDoc, uno::UNO_QUERY);
1136 if (xActionLockable.is())
1137 xActionLockable->addActionLock();
1140 // css::xml::sax::XDocumentHandler
1141 void SAL_CALL ScXMLImport::startDocument()
1143 ScXMLImport::MutexGuard aGuard(*this);
1144 SvXMLImport::startDocument();
1145 if (pDoc && !pDoc->IsImportingXML())
1147 comphelper::getFromUnoTunnel<ScModelObj>(GetModel())->BeforeXMLLoading();
1148 bSelfImportingXMLSet = true;
1151 // if content and styles are loaded with separate imports,
1152 // set bLatinDefaultStyle flag at the start of the content import
1153 SvXMLImportFlags nFlags = getImportFlags();
1154 if ( ( nFlags & SvXMLImportFlags::CONTENT ) && !( nFlags & SvXMLImportFlags::STYLES ) )
1155 ExamineDefaultStyle();
1157 if (getImportFlags() & SvXMLImportFlags::CONTENT)
1159 if (GetModel().is())
1161 // store initial namespaces, to find the ones that were added from the file later
1162 ScSheetSaveData* pSheetData = comphelper::getFromUnoTunnel<ScModelObj>(GetModel())->GetSheetSaveData();
1163 const SvXMLNamespaceMap& rNamespaces = GetNamespaceMap();
1164 pSheetData->StoreInitialNamespaces(rNamespaces);
1168 uno::Reference< beans::XPropertySet > const xImportInfo( getImportInfo() );
1169 uno::Reference< beans::XPropertySetInfo > const xPropertySetInfo(
1170 xImportInfo.is() ? xImportInfo->getPropertySetInfo() : nullptr);
1171 if (xPropertySetInfo.is())
1173 OUString const sOrganizerMode(
1174 "OrganizerMode");
1175 if (xPropertySetInfo->hasPropertyByName(sOrganizerMode))
1177 bool bStyleOnly(false);
1178 if (xImportInfo->getPropertyValue(sOrganizerMode) >>= bStyleOnly)
1180 bLoadDoc = !bStyleOnly;
1185 UnlockSolarMutex();
1188 sal_Int32 ScXMLImport::GetRangeType(std::u16string_view sRangeType)
1190 sal_Int32 nRangeType(0);
1191 OUStringBuffer sBuffer;
1192 size_t i = 0;
1193 while (i <= sRangeType.size())
1195 if ((i == sRangeType.size()) || (sRangeType[i] == ' '))
1197 OUString sTemp = sBuffer.makeStringAndClear();
1198 if (sTemp == "repeat-column")
1199 nRangeType |= sheet::NamedRangeFlag::COLUMN_HEADER;
1200 else if (sTemp == SC_REPEAT_ROW)
1201 nRangeType |= sheet::NamedRangeFlag::ROW_HEADER;
1202 else if (sTemp == SC_FILTER)
1203 nRangeType |= sheet::NamedRangeFlag::FILTER_CRITERIA;
1204 else if (sTemp == SC_PRINT_RANGE)
1205 nRangeType |= sheet::NamedRangeFlag::PRINT_AREA;
1207 else if (i < sRangeType.size())
1208 sBuffer.append(sRangeType[i]);
1209 ++i;
1211 return nRangeType;
1214 void ScXMLImport::SetLabelRanges()
1216 if (maMyLabelRanges.empty())
1217 return;
1219 uno::Reference <beans::XPropertySet> xPropertySet (GetModel(), uno::UNO_QUERY);
1220 if (!xPropertySet.is())
1221 return;
1223 uno::Any aColAny = xPropertySet->getPropertyValue(SC_UNO_COLLABELRNG);
1224 uno::Any aRowAny = xPropertySet->getPropertyValue(SC_UNO_ROWLABELRNG);
1226 uno::Reference< sheet::XLabelRanges > xColRanges;
1227 uno::Reference< sheet::XLabelRanges > xRowRanges;
1229 if ( !(( aColAny >>= xColRanges ) && ( aRowAny >>= xRowRanges )) )
1230 return;
1232 table::CellRangeAddress aLabelRange;
1233 table::CellRangeAddress aDataRange;
1235 for (const auto& rLabelRange : maMyLabelRanges)
1237 sal_Int32 nOffset1(0);
1238 sal_Int32 nOffset2(0);
1239 FormulaGrammar::AddressConvention eConv = FormulaGrammar::CONV_OOO;
1241 assert(pDoc);
1242 if (ScRangeStringConverter::GetRangeFromString( aLabelRange, rLabelRange.sLabelRangeStr, *pDoc, eConv, nOffset1 ) &&
1243 ScRangeStringConverter::GetRangeFromString( aDataRange, rLabelRange.sDataRangeStr, *pDoc, eConv, nOffset2 ))
1245 if ( rLabelRange.bColumnOrientation )
1246 xColRanges->addNew( aLabelRange, aDataRange );
1247 else
1248 xRowRanges->addNew( aLabelRange, aDataRange );
1252 maMyLabelRanges.clear();
1255 namespace {
1257 class RangeNameInserter
1259 ScDocument& mrDoc;
1260 ScRangeName& mrRangeName;
1261 SCTAB mnTab;
1263 public:
1264 RangeNameInserter(ScDocument& rDoc, ScRangeName& rRangeName, SCTAB nTab) :
1265 mrDoc(rDoc), mrRangeName(rRangeName), mnTab(nTab) {}
1267 void operator() (const ScMyNamedExpression& p) const
1269 using namespace formula;
1271 const OUString& aType = p.sRangeType;
1272 sal_uInt32 nUnoType = ScXMLImport::GetRangeType(aType);
1274 ScRangeData::Type nNewType = ScRangeData::Type::Name;
1275 if ( nUnoType & sheet::NamedRangeFlag::FILTER_CRITERIA ) nNewType |= ScRangeData::Type::Criteria;
1276 if ( nUnoType & sheet::NamedRangeFlag::PRINT_AREA ) nNewType |= ScRangeData::Type::PrintArea;
1277 if ( nUnoType & sheet::NamedRangeFlag::COLUMN_HEADER ) nNewType |= ScRangeData::Type::ColHeader;
1278 if ( nUnoType & sheet::NamedRangeFlag::ROW_HEADER ) nNewType |= ScRangeData::Type::RowHeader;
1280 // Insert a new name.
1281 ScAddress aPos;
1282 sal_Int32 nOffset = 0;
1283 bool bSuccess = ScRangeStringConverter::GetAddressFromString(
1284 aPos, p.sBaseCellAddress, mrDoc, FormulaGrammar::CONV_OOO, nOffset);
1286 if (!bSuccess)
1288 SAL_WARN("sc.filter", "No conversion from table:base-cell-address '" << p.sBaseCellAddress
1289 << "' for name '" << p.sName << "' on sheet " << mnTab);
1290 // Do not lose the defined name. Relative addressing in
1291 // content/expression, if any, will be broken though.
1292 // May had happened due to tdf#150312.
1293 aPos.SetTab(mnTab < 0 ? 0 : mnTab);
1294 bSuccess = true;
1297 if (bSuccess)
1299 OUString aContent = p.sContent;
1300 if (!p.bIsExpression)
1301 ScXMLConverter::ConvertCellRangeAddress(aContent);
1303 ScRangeData* pData = new ScRangeData(
1304 mrDoc, p.sName, aContent, aPos, nNewType, p.eGrammar);
1305 mrRangeName.insert(pData);
1312 void ScXMLImport::SetNamedRanges()
1314 if (m_aMyNamedExpressions.empty())
1315 return;
1317 if (!pDoc)
1318 return;
1320 // Insert the namedRanges
1321 ScRangeName* pRangeNames = pDoc->GetRangeName();
1322 ::std::for_each(m_aMyNamedExpressions.begin(), m_aMyNamedExpressions.end(),
1323 RangeNameInserter(*pDoc, *pRangeNames, -1));
1326 void ScXMLImport::SetSheetNamedRanges()
1328 if (!pDoc)
1329 return;
1331 for (auto const& itr : m_SheetNamedExpressions)
1333 const SCTAB nTab = itr.first;
1334 ScRangeName* pRangeNames = pDoc->GetRangeName(nTab);
1335 if (!pRangeNames)
1336 continue;
1338 const ScMyNamedExpressions& rNames = itr.second;
1339 ::std::for_each(rNames.begin(), rNames.end(), RangeNameInserter(*pDoc, *pRangeNames, nTab));
1343 void ScXMLImport::SetStringRefSyntaxIfMissing()
1345 if (!pDoc)
1346 return;
1348 ScCalcConfig aCalcConfig = pDoc->GetCalcConfig();
1350 // Has any string ref syntax been imported?
1351 // If not, we need to take action
1352 if ( !aCalcConfig.mbHasStringRefSyntax )
1354 aCalcConfig.meStringRefAddressSyntax = formula::FormulaGrammar::CONV_A1_XL_A1;
1355 pDoc->SetCalcConfig(aCalcConfig);
1359 void SAL_CALL ScXMLImport::endDocument()
1361 ScXMLImport::MutexGuard aGuard(*this);
1362 if (getImportFlags() & SvXMLImportFlags::CONTENT)
1364 if (GetModel().is())
1366 mpDocImport->finalize();
1368 uno::Reference<document::XViewDataSupplier> xViewDataSupplier(GetModel(), uno::UNO_QUERY);
1369 if (xViewDataSupplier.is())
1371 uno::Reference<container::XIndexAccess> xIndexAccess(xViewDataSupplier->getViewData());
1372 if (xIndexAccess.is() && xIndexAccess->getCount() > 0)
1374 uno::Sequence< beans::PropertyValue > aSeq;
1375 if (xIndexAccess->getByIndex(0) >>= aSeq)
1377 for (const auto& rProp : std::as_const(aSeq))
1379 OUString sName(rProp.Name);
1380 if (sName == SC_ACTIVETABLE)
1382 OUString sTabName;
1383 if(rProp.Value >>= sTabName)
1385 SCTAB nTab(0);
1386 if (pDoc->GetTable(sTabName, nTab))
1388 pDoc->SetVisibleTab(nTab);
1389 break;
1397 SetLabelRanges();
1398 SetNamedRanges();
1399 SetSheetNamedRanges();
1400 SetStringRefSyntaxIfMissing();
1401 if (mpPivotSources)
1402 // Process pivot table sources after the named ranges have been set.
1403 mpPivotSources->process();
1405 GetProgressBarHelper()->End(); // make room for subsequent SfxProgressBars
1406 if (pDoc)
1408 pDoc->CompileXML();
1410 // After CompileXML, links must be completely changed to the new URLs.
1411 // Otherwise, hasExternalFile for API wouldn't work (#i116940#),
1412 // and typing a new formula would create a second link with the same "real" file name.
1413 if (pDoc->HasExternalRefManager())
1414 pDoc->GetExternalRefManager()->updateAbsAfterLoad();
1417 // If the stream contains cells outside of the current limits, the styles can't be re-created,
1418 // so stream copying is disabled then.
1419 if (pDoc && GetModel().is() && !pDoc->HasRangeOverflow())
1421 // set "valid stream" flags after loading (before UpdateRowHeights, so changed formula results
1422 // in UpdateRowHeights can already clear the flags again)
1423 ScSheetSaveData* pSheetData = comphelper::getFromUnoTunnel<ScModelObj>(GetModel())->GetSheetSaveData();
1425 SCTAB nTabCount = pDoc->GetTableCount();
1426 for (SCTAB nTab=0; nTab<nTabCount; ++nTab)
1428 pDoc->SetDrawPageSize(nTab);
1429 if (!pSheetData->IsSheetBlocked( nTab ))
1430 pDoc->SetStreamValid( nTab, true );
1434 // There are rows with optimal height which need to be updated
1435 if (pDoc && !maRecalcRowRanges.empty())
1437 bool bLockHeight = pDoc->IsAdjustHeightLocked();
1438 if (bLockHeight)
1440 pDoc->UnlockAdjustHeight();
1443 ScSizeDeviceProvider aProv(static_cast<ScDocShell*>(pDoc->GetDocumentShell()));
1444 ScDocRowHeightUpdater aUpdater(*pDoc, aProv.GetDevice(), aProv.GetPPTX(), aProv.GetPPTY(), &maRecalcRowRanges);
1445 aUpdater.update();
1447 if (bLockHeight)
1449 pDoc->LockAdjustHeight();
1453 // Initialize and set position and size of objects
1454 if (pDoc && pDoc->GetDrawLayer())
1456 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
1457 SCTAB nTabCount = pDoc->GetTableCount();
1458 for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
1460 const SdrPage* pPage = pDrawLayer->GetPage(nTab);
1461 if (!pPage)
1462 continue;
1463 bool bNegativePage = pDoc->IsNegativePage(nTab);
1464 const size_t nCount = pPage->GetObjCount();
1465 for (size_t i = 0; i < nCount; ++i)
1467 SdrObject* pObj = pPage->GetObj(i);
1468 ScDrawObjData* pData
1469 = ScDrawLayer::GetObjDataTab(pObj, nTab);
1470 // Existence of pData means, that it is a cell anchored object
1471 if (pData)
1473 // Finish and correct import based on full size (no hidden row/col) and LTR
1474 pDrawLayer->InitializeCellAnchoredObj(pObj, *pData);
1475 // Adapt object to hidden row/col and RTL
1476 pDrawLayer->RecalcPos(pObj, *pData, bNegativePage,
1477 true /*bUpdateNoteCaptionPos*/);
1483 aTables.FixupOLEs();
1485 if (GetModel().is())
1487 uno::Reference<document::XActionLockable> xActionLockable(GetModel(), uno::UNO_QUERY);
1488 if (xActionLockable.is())
1489 xActionLockable->removeActionLock();
1491 SvXMLImport::endDocument();
1493 if (pDoc)
1495 pDoc->BroadcastUno(SfxHint(SfxHintId::ScClearCache));
1498 if(pDoc && bSelfImportingXMLSet)
1499 comphelper::getFromUnoTunnel<ScModelObj>(GetModel())->AfterXMLLoading();
1502 // XEventListener
1503 void ScXMLImport::DisposingModel()
1505 SvXMLImport::DisposingModel();
1506 pDoc = nullptr;
1509 ScXMLImport::MutexGuard::MutexGuard(ScXMLImport& rImport) :
1510 mrImport(rImport)
1512 mrImport.LockSolarMutex();
1515 ScXMLImport::MutexGuard::~MutexGuard()
1517 mrImport.UnlockSolarMutex();
1520 void ScXMLImport::LockSolarMutex()
1522 // #i62677# When called from DocShell/Wrapper, the SolarMutex is already locked,
1523 // so there's no need to allocate (and later delete) the SolarMutexGuard.
1524 if (!mbLockSolarMutex)
1526 DBG_TESTSOLARMUTEX();
1527 return;
1530 if (nSolarMutexLocked == 0)
1532 OSL_ENSURE(!pSolarMutexGuard, "Solar Mutex is locked");
1533 pSolarMutexGuard.reset(new SolarMutexGuard());
1535 ++nSolarMutexLocked;
1538 void ScXMLImport::UnlockSolarMutex()
1540 if (nSolarMutexLocked > 0)
1542 nSolarMutexLocked--;
1543 if (nSolarMutexLocked == 0)
1545 OSL_ENSURE(pSolarMutexGuard, "Solar Mutex is always unlocked");
1546 pSolarMutexGuard.reset();
1551 sal_Int32 ScXMLImport::GetByteOffset() const
1553 sal_Int32 nOffset = -1;
1554 uno::Reference<xml::sax::XLocator> xLocator = GetLocator();
1555 uno::Reference<io::XSeekable> xSeek( xLocator, uno::UNO_QUERY ); //! should use different interface
1556 if ( xSeek.is() )
1557 nOffset = static_cast<sal_Int32>(xSeek->getPosition());
1558 return nOffset;
1561 void ScXMLImport::SetRangeOverflowType(ErrCode nType)
1563 // #i31130# Overflow is stored in the document, because the ScXMLImport object
1564 // isn't available in ScXMLImportWrapper::ImportFromComponent when using the
1565 // OOo->Oasis transformation.
1567 if ( pDoc )
1568 pDoc->SetRangeOverflowType( nType );
1571 void ScXMLImport::ProgressBarIncrement()
1573 nProgressCount++;
1574 if (nProgressCount > 100)
1576 GetProgressBarHelper()->Increment(nProgressCount);
1577 nProgressCount = 0;
1581 void ScXMLImport::ExtractFormulaNamespaceGrammar(
1582 OUString& rFormula, OUString& rFormulaNmsp, FormulaGrammar::Grammar& reGrammar,
1583 const OUString& rAttrValue, bool bRestrictToExternalNmsp ) const
1585 // parse the attribute value, extract namespace ID, literal namespace, and formula string
1586 rFormulaNmsp.clear();
1587 sal_uInt16 nNsId = GetNamespaceMap().GetKeyByQName(rAttrValue, nullptr, &rFormula, &rFormulaNmsp, SvXMLNamespaceMap::QNameMode::AttrValue);
1589 // check if we have an ODF formula namespace
1590 if( !bRestrictToExternalNmsp ) switch( nNsId )
1592 case XML_NAMESPACE_OOOC:
1593 rFormulaNmsp.clear(); // remove namespace string for built-in grammar
1594 reGrammar = FormulaGrammar::GRAM_PODF;
1595 return;
1596 case XML_NAMESPACE_OF:
1597 rFormulaNmsp.clear(); // remove namespace string for built-in grammar
1598 reGrammar = FormulaGrammar::GRAM_ODFF;
1599 return;
1602 /* Find default grammar for formulas without namespace. There may be
1603 documents in the wild that stored no namespace in ODF 1.0/1.1. Use
1604 GRAM_PODF then (old style ODF 1.0/1.1 formulas). The default for ODF
1605 1.2 and later without namespace is GRAM_ODFF (OpenFormula). */
1606 FormulaGrammar::Grammar eDefaultGrammar =
1607 (GetDocument()->GetStorageGrammar() == FormulaGrammar::GRAM_PODF) ?
1608 FormulaGrammar::GRAM_PODF : FormulaGrammar::GRAM_ODFF;
1610 /* Check if we have no namespace at all. The value XML_NAMESPACE_NONE
1611 indicates that there is no colon. If the first character of the
1612 attribute value is the equality sign, the value XML_NAMESPACE_UNKNOWN
1613 indicates that there is a colon somewhere in the formula string. */
1614 if( (nNsId == XML_NAMESPACE_NONE) || ((nNsId == XML_NAMESPACE_UNKNOWN) && (rAttrValue.toChar() == '=')) )
1616 rFormula = rAttrValue; // return entire string as formula
1617 reGrammar = eDefaultGrammar;
1618 return;
1621 /* Check if a namespace URL could be resolved from the attribute value.
1622 Use that namespace only, if the Calc document knows an associated
1623 external formula parser. This prevents that the range operator in
1624 conjunction with defined names is confused as namespaces prefix, e.g.
1625 in the expression 'table:A1' where 'table' is a named reference. */
1626 if( ((nNsId & XML_NAMESPACE_UNKNOWN_FLAG) != 0) && !rFormulaNmsp.isEmpty() &&
1627 GetDocument()->GetFormulaParserPool().hasFormulaParser( rFormulaNmsp ) )
1629 reGrammar = FormulaGrammar::GRAM_EXTERNAL;
1630 return;
1633 /* All attempts failed (e.g. no namespace and no leading equality sign, or
1634 an invalid namespace prefix), continue with the entire attribute value. */
1635 rFormula = rAttrValue;
1636 rFormulaNmsp.clear(); // remove any namespace string
1637 reGrammar = eDefaultGrammar;
1640 FormulaError ScXMLImport::GetFormulaErrorConstant( const OUString& rStr ) const
1642 if (!mpComp)
1643 return FormulaError::NONE;
1645 return mpComp->GetErrorConstant(rStr);
1648 ScEditEngineDefaulter* ScXMLImport::GetEditEngine()
1650 if (!mpEditEngine)
1652 mpEditEngine.reset(new ScEditEngineDefaulter(pDoc->GetEnginePool()));
1653 mpEditEngine->SetRefMapMode(MapMode(MapUnit::Map100thMM));
1654 mpEditEngine->SetEditTextObjectPool(pDoc->GetEditPool());
1655 mpEditEngine->SetUpdateLayout(false);
1656 mpEditEngine->EnableUndo(false);
1657 mpEditEngine->SetControlWord(mpEditEngine->GetControlWord() & ~EEControlBits::ALLOWBIGOBJS);
1659 return mpEditEngine.get();
1662 const ScXMLEditAttributeMap& ScXMLImport::GetEditAttributeMap() const
1664 if (!mpEditAttrMap)
1665 mpEditAttrMap.reset(new ScXMLEditAttributeMap);
1666 return *mpEditAttrMap;
1669 void ScXMLImport::NotifyContainsEmbeddedFont()
1671 if (pDoc)
1672 pDoc->SetEmbedFonts(true);
1675 ScMyImpDetectiveOpArray* ScXMLImport::GetDetectiveOpArray()
1677 if (!pDetectiveOpArray)
1678 pDetectiveOpArray.reset(new ScMyImpDetectiveOpArray());
1679 return pDetectiveOpArray.get();
1682 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportFODS(SvStream &rStream)
1684 ScDLL::Init();
1686 SfxObjectShellLock xDocSh(new ScDocShell);
1687 xDocSh->DoInitNew();
1688 uno::Reference<frame::XModel> xModel(xDocSh->GetModel());
1690 uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(comphelper::getProcessServiceFactory());
1691 uno::Reference<io::XInputStream> xStream(new ::utl::OSeekableInputStreamWrapper(rStream));
1692 uno::Reference<uno::XInterface> xInterface(xMultiServiceFactory->createInstance("com.sun.star.comp.Writer.XmlFilterAdaptor"), uno::UNO_SET_THROW);
1694 css::uno::Sequence<OUString> aUserData
1696 "com.sun.star.comp.filter.OdfFlatXml",
1698 "com.sun.star.comp.Calc.XMLOasisImporter",
1699 "com.sun.star.comp.Calc.XMLOasisExporter",
1702 "true"
1704 uno::Sequence<beans::PropertyValue> aAdaptorArgs(comphelper::InitPropertySequence(
1706 { "UserData", uno::Any(aUserData) },
1707 }));
1708 css::uno::Sequence<uno::Any> aOuterArgs{ uno::Any(aAdaptorArgs) };
1710 uno::Reference<lang::XInitialization> xInit(xInterface, uno::UNO_QUERY_THROW);
1711 xInit->initialize(aOuterArgs);
1713 uno::Reference<document::XImporter> xImporter(xInterface, uno::UNO_QUERY_THROW);
1714 uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
1716 { "InputStream", uno::Any(xStream) },
1717 { "URL", uno::Any(OUString("private:stream")) },
1718 }));
1719 xImporter->setTargetDocument(xModel);
1721 uno::Reference<document::XFilter> xFilter(xInterface, uno::UNO_QUERY_THROW);
1722 //SetLoading hack because the document properties will be re-initted
1723 //by the xml filter and during the init, while it's considered uninitialized,
1724 //setting a property will inform the document it's modified, which attempts
1725 //to update the properties, which throws cause the properties are uninitialized
1726 xDocSh->SetLoading(SfxLoadedFlags::NONE);
1727 bool ret = xFilter->filter(aArgs);
1728 xDocSh->SetLoading(SfxLoadedFlags::ALL);
1730 xDocSh->DoClose();
1732 return ret;
1735 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportXLSX(SvStream &rStream)
1737 ScDLL::Init();
1739 SfxObjectShellLock xDocSh(new ScDocShell);
1740 xDocSh->DoInitNew();
1741 uno::Reference<frame::XModel> xModel(xDocSh->GetModel());
1743 uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(comphelper::getProcessServiceFactory());
1744 uno::Reference<io::XInputStream> xStream(new utl::OSeekableInputStreamWrapper(rStream));
1746 uno::Reference<document::XFilter> xFilter(xMultiServiceFactory->createInstance("com.sun.star.comp.oox.xls.ExcelFilter"), uno::UNO_QUERY_THROW);
1748 uno::Reference<document::XImporter> xImporter(xFilter, uno::UNO_QUERY_THROW);
1749 uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
1751 { "InputStream", uno::Any(xStream) },
1752 { "InputMode", uno::Any(true) },
1753 }));
1754 xImporter->setTargetDocument(xModel);
1756 //SetLoading hack because the document properties will be re-initted
1757 //by the xml filter and during the init, while it's considered uninitialized,
1758 //setting a property will inform the document it's modified, which attempts
1759 //to update the properties, which throws cause the properties are uninitialized
1760 xDocSh->SetLoading(SfxLoadedFlags::NONE);
1761 bool ret = false;
1764 ret = xFilter->filter(aArgs);
1766 catch (const css::io::IOException&)
1769 catch (const css::lang::WrappedTargetRuntimeException&)
1772 xDocSh->SetLoading(SfxLoadedFlags::ALL);
1774 xDocSh->DoClose();
1776 return ret;
1779 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */