Version 24.2.2.2, tag libreoffice-24.2.2.2
[LibreOffice.git] / xmloff / source / style / numehelp.cxx
blobf2c3a3b2caf9b6e49c25575b96efdd4294d54108
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 .
21 #include <xmloff/numehelp.hxx>
23 #include <xmloff/namespacemap.hxx>
24 #include <xmloff/xmlnamespace.hxx>
25 #include <xmloff/xmluconv.hxx>
26 #include <xmloff/xmltoken.hxx>
27 #include <xmloff/xmlexp.hxx>
28 #include <com/sun/star/uno/Reference.h>
29 #include <rtl/ustring.hxx>
30 #include <svl/zforlist.hxx>
31 #include <com/sun/star/util/NumberFormat.hpp>
32 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
33 #include <sax/tools/converter.hxx>
34 #include <rtl/math.hxx>
35 #include <rtl/ustrbuf.hxx>
36 #include <osl/diagnose.h>
38 using namespace com::sun::star;
39 using namespace xmloff::token;
41 constexpr OUString gsStandardFormat(u"StandardFormat"_ustr);
42 constexpr OUString gsType(u"Type"_ustr);
43 constexpr OUString gsCurrencySymbol(u"CurrencySymbol"_ustr);
44 constexpr OUString gsCurrencyAbbreviation(u"CurrencyAbbreviation"_ustr);
46 XMLNumberFormatAttributesExportHelper::XMLNumberFormatAttributesExportHelper(
47 css::uno::Reference< css::util::XNumberFormatsSupplier > const & xTempNumberFormatsSupplier)
48 : m_xNumberFormats(xTempNumberFormatsSupplier.is() ? xTempNumberFormatsSupplier->getNumberFormats() : css::uno::Reference< css::util::XNumberFormats > ()),
49 m_pExport(nullptr)
53 XMLNumberFormatAttributesExportHelper::XMLNumberFormatAttributesExportHelper(
54 css::uno::Reference< css::util::XNumberFormatsSupplier > const & xTempNumberFormatsSupplier,
55 SvXMLExport& rTempExport )
56 : m_xNumberFormats(xTempNumberFormatsSupplier.is() ? xTempNumberFormatsSupplier->getNumberFormats() : css::uno::Reference< css::util::XNumberFormats > ()),
57 m_pExport(&rTempExport),
58 m_sAttrValue(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_VALUE))),
59 m_sAttrDateValue(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_DATE_VALUE))),
60 m_sAttrTimeValue(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_TIME_VALUE))),
61 m_sAttrBooleanValue(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_BOOLEAN_VALUE))),
62 m_sAttrStringValue(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_STRING_VALUE))),
63 m_sAttrCurrency(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_CURRENCY)))
67 XMLNumberFormatAttributesExportHelper::~XMLNumberFormatAttributesExportHelper()
71 sal_Int16 XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat, OUString& sCurrency, bool& bIsStandard)
73 XMLNumberFormat aFormat(nNumberFormat);
74 XMLNumberFormatSet::iterator aItr(m_aNumberFormats.find(aFormat));
75 XMLNumberFormatSet::iterator aEndItr(m_aNumberFormats.end());
76 if (aItr != aEndItr)
78 bIsStandard = aItr->bIsStandard;
79 sCurrency = aItr->sCurrency;
80 return aItr->nType;
82 else
84 aFormat.nType = GetCellType(nNumberFormat, bIsStandard);
85 aFormat.bIsStandard = bIsStandard;
86 if ((aFormat.nType & ~util::NumberFormat::DEFINED) == util::NumberFormat::CURRENCY)
87 if (GetCurrencySymbol(nNumberFormat, aFormat.sCurrency))
88 sCurrency = aFormat.sCurrency;
89 m_aNumberFormats.insert(aFormat);
90 return aFormat.nType;
94 void XMLNumberFormatAttributesExportHelper::WriteAttributes(SvXMLExport& rXMLExport,
95 const sal_Int16 nTypeKey,
96 const double& rValue,
97 const OUString& rCurrency,
98 bool bExportValue)
100 bool bWasSetTypeAttribute = false;
101 switch(nTypeKey & ~util::NumberFormat::DEFINED)
103 case 0:
104 case util::NumberFormat::NUMBER:
105 case util::NumberFormat::SCIENTIFIC:
106 case util::NumberFormat::FRACTION:
108 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT);
109 bWasSetTypeAttribute = true;
110 [[fallthrough]];
112 case util::NumberFormat::PERCENT:
114 if (!bWasSetTypeAttribute)
116 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_PERCENTAGE);
117 bWasSetTypeAttribute = true;
119 [[fallthrough]];
121 case util::NumberFormat::CURRENCY:
123 if (!bWasSetTypeAttribute)
125 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_CURRENCY);
126 if (!rCurrency.isEmpty())
127 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_CURRENCY, rCurrency);
130 if (bExportValue)
132 OUString sValue( ::rtl::math::doubleToUString( rValue,
133 rtl_math_StringFormat_Automatic,
134 rtl_math_DecimalPlaces_Max, '.', true));
135 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE, sValue);
138 break;
139 case util::NumberFormat::DATE:
140 case util::NumberFormat::DATETIME:
142 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_DATE);
143 if (bExportValue)
145 if ( rXMLExport.SetNullDateOnUnitConverter() )
147 OUStringBuffer sBuffer;
148 rXMLExport.GetMM100UnitConverter().convertDateTime(sBuffer, rValue);
149 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_DATE_VALUE, sBuffer.makeStringAndClear());
153 break;
154 case util::NumberFormat::TIME:
156 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_TIME);
157 if (bExportValue)
159 OUStringBuffer sBuffer;
160 ::sax::Converter::convertDuration(sBuffer, rValue);
161 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_TIME_VALUE, sBuffer.makeStringAndClear());
164 break;
165 case util::NumberFormat::LOGICAL:
167 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_BOOLEAN);
168 if (bExportValue)
170 double fTempValue = rValue;
171 if (::rtl::math::approxEqual( fTempValue, 1.0 ))
173 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_BOOLEAN_VALUE, XML_TRUE);
175 else
177 if (rValue == 0.0)
179 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_BOOLEAN_VALUE, XML_FALSE);
181 else
183 OUString sValue( ::rtl::math::doubleToUString(
184 fTempValue,
185 rtl_math_StringFormat_Automatic,
186 rtl_math_DecimalPlaces_Max, '.',
187 true));
188 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_BOOLEAN_VALUE, sValue);
193 break;
194 case util::NumberFormat::TEXT:
196 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT);
197 if (bExportValue)
199 OUString sValue( ::rtl::math::doubleToUString( rValue,
200 rtl_math_StringFormat_Automatic,
201 rtl_math_DecimalPlaces_Max, '.', true));
202 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE, sValue);
205 break;
209 bool XMLNumberFormatAttributesExportHelper::GetCurrencySymbol(const sal_Int32 nNumberFormat, OUString& sCurrencySymbol,
210 uno::Reference <util::XNumberFormatsSupplier> const & xNumberFormatsSupplier)
212 if (xNumberFormatsSupplier.is())
214 uno::Reference <util::XNumberFormats> xNumberFormats(xNumberFormatsSupplier->getNumberFormats());
215 if (xNumberFormats.is())
219 uno::Reference <beans::XPropertySet> xNumberPropertySet(xNumberFormats->getByKey(nNumberFormat));
220 if ( xNumberPropertySet->getPropertyValue(gsCurrencySymbol) >>= sCurrencySymbol)
222 OUString sCurrencyAbbreviation;
223 if ( xNumberPropertySet->getPropertyValue(gsCurrencyAbbreviation) >>= sCurrencyAbbreviation)
225 if ( !sCurrencyAbbreviation.isEmpty())
226 sCurrencySymbol = sCurrencyAbbreviation;
227 else
229 if ( sCurrencySymbol.getLength() == 1 && sCurrencySymbol.toChar() == NfCurrencyEntry::GetEuroSymbol() )
230 sCurrencySymbol = "EUR";
233 return true;
236 catch ( uno::Exception& )
238 OSL_FAIL("Numberformat not found");
242 return false;
246 sal_Int16 XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat, bool& bIsStandard,
247 uno::Reference <util::XNumberFormatsSupplier> const & xNumberFormatsSupplier)
249 if (xNumberFormatsSupplier.is())
251 uno::Reference <util::XNumberFormats> xNumberFormats(xNumberFormatsSupplier->getNumberFormats());
252 if (xNumberFormats.is())
256 uno::Reference <beans::XPropertySet> xNumberPropertySet(xNumberFormats->getByKey(nNumberFormat));
257 xNumberPropertySet->getPropertyValue(gsStandardFormat) >>= bIsStandard;
258 sal_Int16 nNumberType = sal_Int16();
259 if ( xNumberPropertySet->getPropertyValue(gsType) >>= nNumberType )
261 return nNumberType;
264 catch ( uno::Exception& )
266 OSL_FAIL("Numberformat not found");
270 return 0;
273 void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(SvXMLExport& rXMLExport,
274 const sal_Int32 nNumberFormat, const double& rValue, bool bExportValue)
276 bool bIsStandard;
277 sal_Int16 nTypeKey = GetCellType(nNumberFormat, bIsStandard, rXMLExport.GetNumberFormatsSupplier());
278 OUString sCurrency;
279 if ((nTypeKey & ~util::NumberFormat::DEFINED) == util::NumberFormat::CURRENCY)
280 GetCurrencySymbol(nNumberFormat, sCurrency, rXMLExport.GetNumberFormatsSupplier());
281 WriteAttributes(rXMLExport, nTypeKey, rValue, sCurrency, bExportValue);
284 void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(SvXMLExport& rXMLExport,
285 const OUString& rValue, std::u16string_view rCharacters,
286 bool bExportValue, bool bExportTypeAttribute)
288 if (bExportTypeAttribute)
289 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING);
290 if (bExportValue && !rValue.isEmpty() && (rValue != rCharacters))
291 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_STRING_VALUE, rValue);
294 bool XMLNumberFormatAttributesExportHelper::GetCurrencySymbol(const sal_Int32 nNumberFormat, OUString& rCurrencySymbol)
296 if (!m_xNumberFormats.is() && m_pExport && m_pExport->GetNumberFormatsSupplier().is())
297 m_xNumberFormats.set(m_pExport->GetNumberFormatsSupplier()->getNumberFormats());
299 if (m_xNumberFormats.is())
303 uno::Reference <beans::XPropertySet> xNumberPropertySet(m_xNumberFormats->getByKey(nNumberFormat));
304 if ( xNumberPropertySet->getPropertyValue(gsCurrencySymbol) >>= rCurrencySymbol)
306 OUString sCurrencyAbbreviation;
307 if ( xNumberPropertySet->getPropertyValue(gsCurrencyAbbreviation) >>= sCurrencyAbbreviation)
309 if ( !sCurrencyAbbreviation.isEmpty())
310 rCurrencySymbol = sCurrencyAbbreviation;
311 else
313 if ( rCurrencySymbol.getLength() == 1 && rCurrencySymbol.toChar() == NfCurrencyEntry::GetEuroSymbol() )
314 rCurrencySymbol = "EUR";
317 return true;
320 catch ( uno::Exception& )
322 OSL_FAIL("Numberformat not found");
325 return false;
328 sal_Int16 XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat, bool& bIsStandard)
330 if (!m_xNumberFormats.is() && m_pExport && m_pExport->GetNumberFormatsSupplier().is())
331 m_xNumberFormats.set(m_pExport->GetNumberFormatsSupplier()->getNumberFormats());
333 if (m_xNumberFormats.is())
337 uno::Reference <beans::XPropertySet> xNumberPropertySet(m_xNumberFormats->getByKey(nNumberFormat));
338 if (xNumberPropertySet.is())
340 xNumberPropertySet->getPropertyValue(gsStandardFormat) >>= bIsStandard;
341 sal_Int16 nNumberType = sal_Int16();
342 if ( xNumberPropertySet->getPropertyValue(gsType) >>= nNumberType )
344 return nNumberType;
348 catch ( uno::Exception& )
350 OSL_FAIL("Numberformat not found");
353 return 0;
356 void XMLNumberFormatAttributesExportHelper::WriteAttributes(
357 const sal_Int16 nTypeKey,
358 const double& rValue,
359 const OUString& rCurrency,
360 bool bExportValue, sal_uInt16 nNamespace)
362 if (!m_pExport)
363 return;
365 bool bWasSetTypeAttribute = false;
366 OUString sAttrValType = m_pExport->GetNamespaceMap().GetQNameByKey( nNamespace, GetXMLToken(XML_VALUE_TYPE));
367 switch(nTypeKey & ~util::NumberFormat::DEFINED)
369 case 0:
370 case util::NumberFormat::NUMBER:
371 case util::NumberFormat::SCIENTIFIC:
372 case util::NumberFormat::FRACTION:
374 m_pExport->AddAttribute(sAttrValType, XML_FLOAT);
375 bWasSetTypeAttribute = true;
376 [[fallthrough]];
378 case util::NumberFormat::PERCENT:
380 if (!bWasSetTypeAttribute)
382 m_pExport->AddAttribute(sAttrValType, XML_PERCENTAGE);
383 bWasSetTypeAttribute = true;
385 [[fallthrough]];
387 case util::NumberFormat::CURRENCY:
389 if (!bWasSetTypeAttribute)
391 m_pExport->AddAttribute(sAttrValType, XML_CURRENCY);
392 if (!rCurrency.isEmpty())
393 m_pExport->AddAttribute(m_sAttrCurrency, rCurrency);
396 if (bExportValue)
398 OUString sValue( ::rtl::math::doubleToUString( rValue,
399 rtl_math_StringFormat_Automatic,
400 rtl_math_DecimalPlaces_Max, '.', true));
401 m_pExport->AddAttribute(m_sAttrValue, sValue);
404 break;
405 case util::NumberFormat::DATE:
406 case util::NumberFormat::DATETIME:
408 m_pExport->AddAttribute(sAttrValType, XML_DATE);
409 if (bExportValue)
411 if ( m_pExport->SetNullDateOnUnitConverter() )
413 OUStringBuffer sBuffer;
414 m_pExport->GetMM100UnitConverter().convertDateTime(sBuffer, rValue);
415 m_pExport->AddAttribute(m_sAttrDateValue, sBuffer.makeStringAndClear());
419 break;
420 case util::NumberFormat::TIME:
422 m_pExport->AddAttribute(sAttrValType, XML_TIME);
423 if (bExportValue)
425 OUStringBuffer sBuffer;
426 ::sax::Converter::convertDuration(sBuffer, rValue);
427 m_pExport->AddAttribute(m_sAttrTimeValue, sBuffer.makeStringAndClear());
430 break;
431 case util::NumberFormat::LOGICAL:
433 m_pExport->AddAttribute(sAttrValType, XML_BOOLEAN);
434 if (bExportValue)
436 double fTempValue = rValue;
437 if (::rtl::math::approxEqual( fTempValue, 1.0 ))
439 m_pExport->AddAttribute(m_sAttrBooleanValue, XML_TRUE);
441 else
443 if (rValue == 0.0)
445 m_pExport->AddAttribute(m_sAttrBooleanValue, XML_FALSE);
447 else
449 OUString sValue( ::rtl::math::doubleToUString(
450 fTempValue,
451 rtl_math_StringFormat_Automatic,
452 rtl_math_DecimalPlaces_Max, '.',
453 true));
454 m_pExport->AddAttribute(m_sAttrBooleanValue, sValue);
459 break;
460 case util::NumberFormat::TEXT:
462 m_pExport->AddAttribute(sAttrValType, XML_FLOAT);
463 if (bExportValue)
465 OUString sValue( ::rtl::math::doubleToUString( rValue,
466 rtl_math_StringFormat_Automatic,
467 rtl_math_DecimalPlaces_Max, '.', true));
468 m_pExport->AddAttribute(m_sAttrValue, sValue);
471 break;
475 void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(
476 const sal_Int32 nNumberFormat, const double& rValue, bool bExportValue,
477 sal_uInt16 nNamespace, bool bExportCurrencySymbol)
479 if (m_pExport)
481 bool bIsStandard;
482 OUString sCurrency;
483 sal_Int16 nTypeKey = GetCellType(nNumberFormat, sCurrency, bIsStandard);
484 if(!bExportCurrencySymbol)
485 sCurrency.clear();
487 WriteAttributes(nTypeKey, rValue, sCurrency, bExportValue, nNamespace);
489 else {
490 OSL_FAIL("no SvXMLExport given");
494 void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(
495 const OUString& rValue, std::u16string_view rCharacters,
496 bool bExportValue,
497 sal_uInt16 nNamespace)
499 if (m_pExport)
501 m_pExport->AddAttribute(nNamespace, XML_VALUE_TYPE, XML_STRING);
502 if (bExportValue && !rValue.isEmpty() && (rValue != rCharacters))
503 m_pExport->AddAttribute(m_sAttrStringValue, rValue);
505 else {
506 OSL_FAIL("no SvXMLExport given");
510 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */