1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
> ()),
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());
78 bIsStandard
= aItr
->bIsStandard
;
79 sCurrency
= aItr
->sCurrency
;
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
);
94 void XMLNumberFormatAttributesExportHelper::WriteAttributes(SvXMLExport
& rXMLExport
,
95 const sal_Int16 nTypeKey
,
97 const OUString
& rCurrency
,
100 bool bWasSetTypeAttribute
= false;
101 switch(nTypeKey
& ~util::NumberFormat::DEFINED
)
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;
112 case util::NumberFormat::PERCENT
:
114 if (!bWasSetTypeAttribute
)
116 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_VALUE_TYPE
, XML_PERCENTAGE
);
117 bWasSetTypeAttribute
= true;
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
);
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
);
139 case util::NumberFormat::DATE
:
140 case util::NumberFormat::DATETIME
:
142 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_VALUE_TYPE
, XML_DATE
);
145 if ( rXMLExport
.SetNullDateOnUnitConverter() )
147 OUStringBuffer sBuffer
;
148 rXMLExport
.GetMM100UnitConverter().convertDateTime(sBuffer
, rValue
);
149 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_DATE_VALUE
, sBuffer
.makeStringAndClear());
154 case util::NumberFormat::TIME
:
156 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_VALUE_TYPE
, XML_TIME
);
159 OUStringBuffer sBuffer
;
160 ::sax::Converter::convertDuration(sBuffer
, rValue
);
161 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_TIME_VALUE
, sBuffer
.makeStringAndClear());
165 case util::NumberFormat::LOGICAL
:
167 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_VALUE_TYPE
, XML_BOOLEAN
);
170 double fTempValue
= rValue
;
171 if (::rtl::math::approxEqual( fTempValue
, 1.0 ))
173 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_BOOLEAN_VALUE
, XML_TRUE
);
179 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_BOOLEAN_VALUE
, XML_FALSE
);
183 OUString
sValue( ::rtl::math::doubleToUString(
185 rtl_math_StringFormat_Automatic
,
186 rtl_math_DecimalPlaces_Max
, '.',
188 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_BOOLEAN_VALUE
, sValue
);
194 case util::NumberFormat::TEXT
:
196 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_VALUE_TYPE
, XML_FLOAT
);
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
);
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
;
229 if ( sCurrencySymbol
.getLength() == 1 && sCurrencySymbol
.toChar() == NfCurrencyEntry::GetEuroSymbol() )
230 sCurrencySymbol
= "EUR";
236 catch ( uno::Exception
& )
238 OSL_FAIL("Numberformat not found");
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
)
264 catch ( uno::Exception
& )
266 OSL_FAIL("Numberformat not found");
273 void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(SvXMLExport
& rXMLExport
,
274 const sal_Int32 nNumberFormat
, const double& rValue
, bool bExportValue
)
277 sal_Int16 nTypeKey
= GetCellType(nNumberFormat
, bIsStandard
, rXMLExport
.GetNumberFormatsSupplier());
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
;
313 if ( rCurrencySymbol
.getLength() == 1 && rCurrencySymbol
.toChar() == NfCurrencyEntry::GetEuroSymbol() )
314 rCurrencySymbol
= "EUR";
320 catch ( uno::Exception
& )
322 OSL_FAIL("Numberformat not found");
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
)
348 catch ( uno::Exception
& )
350 OSL_FAIL("Numberformat not found");
356 void XMLNumberFormatAttributesExportHelper::WriteAttributes(
357 const sal_Int16 nTypeKey
,
358 const double& rValue
,
359 const OUString
& rCurrency
,
360 bool bExportValue
, sal_uInt16 nNamespace
)
365 bool bWasSetTypeAttribute
= false;
366 OUString sAttrValType
= m_pExport
->GetNamespaceMap().GetQNameByKey( nNamespace
, GetXMLToken(XML_VALUE_TYPE
));
367 switch(nTypeKey
& ~util::NumberFormat::DEFINED
)
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;
378 case util::NumberFormat::PERCENT
:
380 if (!bWasSetTypeAttribute
)
382 m_pExport
->AddAttribute(sAttrValType
, XML_PERCENTAGE
);
383 bWasSetTypeAttribute
= true;
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
);
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
);
405 case util::NumberFormat::DATE
:
406 case util::NumberFormat::DATETIME
:
408 m_pExport
->AddAttribute(sAttrValType
, XML_DATE
);
411 if ( m_pExport
->SetNullDateOnUnitConverter() )
413 OUStringBuffer sBuffer
;
414 m_pExport
->GetMM100UnitConverter().convertDateTime(sBuffer
, rValue
);
415 m_pExport
->AddAttribute(m_sAttrDateValue
, sBuffer
.makeStringAndClear());
420 case util::NumberFormat::TIME
:
422 m_pExport
->AddAttribute(sAttrValType
, XML_TIME
);
425 OUStringBuffer sBuffer
;
426 ::sax::Converter::convertDuration(sBuffer
, rValue
);
427 m_pExport
->AddAttribute(m_sAttrTimeValue
, sBuffer
.makeStringAndClear());
431 case util::NumberFormat::LOGICAL
:
433 m_pExport
->AddAttribute(sAttrValType
, XML_BOOLEAN
);
436 double fTempValue
= rValue
;
437 if (::rtl::math::approxEqual( fTempValue
, 1.0 ))
439 m_pExport
->AddAttribute(m_sAttrBooleanValue
, XML_TRUE
);
445 m_pExport
->AddAttribute(m_sAttrBooleanValue
, XML_FALSE
);
449 OUString
sValue( ::rtl::math::doubleToUString(
451 rtl_math_StringFormat_Automatic
,
452 rtl_math_DecimalPlaces_Max
, '.',
454 m_pExport
->AddAttribute(m_sAttrBooleanValue
, sValue
);
460 case util::NumberFormat::TEXT
:
462 m_pExport
->AddAttribute(sAttrValType
, XML_FLOAT
);
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
);
475 void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(
476 const sal_Int32 nNumberFormat
, const double& rValue
, bool bExportValue
,
477 sal_uInt16 nNamespace
, bool bExportCurrencySymbol
)
483 sal_Int16 nTypeKey
= GetCellType(nNumberFormat
, sCurrency
, bIsStandard
);
484 if(!bExportCurrencySymbol
)
487 WriteAttributes(nTypeKey
, rValue
, sCurrency
, bExportValue
, nNamespace
);
490 OSL_FAIL("no SvXMLExport given");
494 void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(
495 const OUString
& rValue
, std::u16string_view rCharacters
,
497 sal_uInt16 nNamespace
)
501 m_pExport
->AddAttribute(nNamespace
, XML_VALUE_TYPE
, XML_STRING
);
502 if (bExportValue
&& !rValue
.isEmpty() && (rValue
!= rCharacters
))
503 m_pExport
->AddAttribute(m_sAttrStringValue
, rValue
);
506 OSL_FAIL("no SvXMLExport given");
510 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */