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 OUStringLiteral
gsStandardFormat(u
"StandardFormat");
42 constexpr OUStringLiteral
gsType(u
"Type");
43 constexpr OUStringLiteral
gsCurrencySymbol(u
"CurrencySymbol");
44 constexpr OUStringLiteral
gsCurrencyAbbreviation(u
"CurrencyAbbreviation");
46 XMLNumberFormatAttributesExportHelper::XMLNumberFormatAttributesExportHelper(
47 css::uno::Reference
< css::util::XNumberFormatsSupplier
> const & xTempNumberFormatsSupplier
)
48 : xNumberFormats(xTempNumberFormatsSupplier
.is() ? xTempNumberFormatsSupplier
->getNumberFormats() : css::uno::Reference
< css::util::XNumberFormats
> ()),
54 XMLNumberFormatAttributesExportHelper::XMLNumberFormatAttributesExportHelper(
55 css::uno::Reference
< css::util::XNumberFormatsSupplier
> const & xTempNumberFormatsSupplier
,
56 SvXMLExport
& rTempExport
)
57 : xNumberFormats(xTempNumberFormatsSupplier
.is() ? xTempNumberFormatsSupplier
->getNumberFormats() : css::uno::Reference
< css::util::XNumberFormats
> ()),
58 pExport(&rTempExport
),
59 sAttrValue(rTempExport
.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE
, GetXMLToken(XML_VALUE
))),
60 sAttrDateValue(rTempExport
.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE
, GetXMLToken(XML_DATE_VALUE
))),
61 sAttrTimeValue(rTempExport
.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE
, GetXMLToken(XML_TIME_VALUE
))),
62 sAttrBooleanValue(rTempExport
.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE
, GetXMLToken(XML_BOOLEAN_VALUE
))),
63 sAttrStringValue(rTempExport
.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE
, GetXMLToken(XML_STRING_VALUE
))),
64 sAttrCurrency(rTempExport
.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE
, GetXMLToken(XML_CURRENCY
))),
69 XMLNumberFormatAttributesExportHelper::~XMLNumberFormatAttributesExportHelper()
73 sal_Int16
XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat
, OUString
& sCurrency
, bool& bIsStandard
)
75 XMLNumberFormat
aFormat(nNumberFormat
);
76 XMLNumberFormatSet::iterator
aItr(aNumberFormats
.find(aFormat
));
77 XMLNumberFormatSet::iterator
aEndItr(aNumberFormats
.end());
80 bIsStandard
= aItr
->bIsStandard
;
81 sCurrency
= aItr
->sCurrency
;
86 aFormat
.nType
= GetCellType(nNumberFormat
, bIsStandard
);
87 aFormat
.bIsStandard
= bIsStandard
;
88 if ((aFormat
.nType
& ~util::NumberFormat::DEFINED
) == util::NumberFormat::CURRENCY
)
89 if (GetCurrencySymbol(nNumberFormat
, aFormat
.sCurrency
))
90 sCurrency
= aFormat
.sCurrency
;
91 aNumberFormats
.insert(aFormat
);
96 void XMLNumberFormatAttributesExportHelper::WriteAttributes(SvXMLExport
& rXMLExport
,
97 const sal_Int16 nTypeKey
,
99 const OUString
& rCurrency
,
102 bool bWasSetTypeAttribute
= false;
103 switch(nTypeKey
& ~util::NumberFormat::DEFINED
)
106 case util::NumberFormat::NUMBER
:
107 case util::NumberFormat::SCIENTIFIC
:
108 case util::NumberFormat::FRACTION
:
110 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_VALUE_TYPE
, XML_FLOAT
);
111 bWasSetTypeAttribute
= true;
114 case util::NumberFormat::PERCENT
:
116 if (!bWasSetTypeAttribute
)
118 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_VALUE_TYPE
, XML_PERCENTAGE
);
119 bWasSetTypeAttribute
= true;
123 case util::NumberFormat::CURRENCY
:
125 if (!bWasSetTypeAttribute
)
127 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_VALUE_TYPE
, XML_CURRENCY
);
128 if (!rCurrency
.isEmpty())
129 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_CURRENCY
, rCurrency
);
134 OUString
sValue( ::rtl::math::doubleToUString( rValue
,
135 rtl_math_StringFormat_Automatic
,
136 rtl_math_DecimalPlaces_Max
, '.', true));
137 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_VALUE
, sValue
);
141 case util::NumberFormat::DATE
:
142 case util::NumberFormat::DATETIME
:
144 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_VALUE_TYPE
, XML_DATE
);
147 if ( rXMLExport
.SetNullDateOnUnitConverter() )
149 OUStringBuffer sBuffer
;
150 rXMLExport
.GetMM100UnitConverter().convertDateTime(sBuffer
, rValue
);
151 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_DATE_VALUE
, sBuffer
.makeStringAndClear());
156 case util::NumberFormat::TIME
:
158 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_VALUE_TYPE
, XML_TIME
);
161 OUStringBuffer sBuffer
;
162 ::sax::Converter::convertDuration(sBuffer
, rValue
);
163 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_TIME_VALUE
, sBuffer
.makeStringAndClear());
167 case util::NumberFormat::LOGICAL
:
169 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_VALUE_TYPE
, XML_BOOLEAN
);
172 double fTempValue
= rValue
;
173 if (::rtl::math::approxEqual( fTempValue
, 1.0 ))
175 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_BOOLEAN_VALUE
, XML_TRUE
);
181 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_BOOLEAN_VALUE
, XML_FALSE
);
185 OUString
sValue( ::rtl::math::doubleToUString(
187 rtl_math_StringFormat_Automatic
,
188 rtl_math_DecimalPlaces_Max
, '.',
190 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_BOOLEAN_VALUE
, sValue
);
196 case util::NumberFormat::TEXT
:
198 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_VALUE_TYPE
, XML_FLOAT
);
201 OUString
sValue( ::rtl::math::doubleToUString( rValue
,
202 rtl_math_StringFormat_Automatic
,
203 rtl_math_DecimalPlaces_Max
, '.', true));
204 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_VALUE
, sValue
);
211 bool XMLNumberFormatAttributesExportHelper::GetCurrencySymbol(const sal_Int32 nNumberFormat
, OUString
& sCurrencySymbol
,
212 uno::Reference
<util::XNumberFormatsSupplier
> const & xNumberFormatsSupplier
)
214 if (xNumberFormatsSupplier
.is())
216 uno::Reference
<util::XNumberFormats
> xNumberFormats(xNumberFormatsSupplier
->getNumberFormats());
217 if (xNumberFormats
.is())
221 uno::Reference
<beans::XPropertySet
> xNumberPropertySet(xNumberFormats
->getByKey(nNumberFormat
));
222 if ( xNumberPropertySet
->getPropertyValue(gsCurrencySymbol
) >>= sCurrencySymbol
)
224 OUString sCurrencyAbbreviation
;
225 if ( xNumberPropertySet
->getPropertyValue(gsCurrencyAbbreviation
) >>= sCurrencyAbbreviation
)
227 if ( !sCurrencyAbbreviation
.isEmpty())
228 sCurrencySymbol
= sCurrencyAbbreviation
;
231 if ( sCurrencySymbol
.getLength() == 1 && sCurrencySymbol
.toChar() == NfCurrencyEntry::GetEuroSymbol() )
232 sCurrencySymbol
= "EUR";
238 catch ( uno::Exception
& )
240 OSL_FAIL("Numberformat not found");
248 sal_Int16
XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat
, bool& bIsStandard
,
249 uno::Reference
<util::XNumberFormatsSupplier
> const & xNumberFormatsSupplier
)
251 if (xNumberFormatsSupplier
.is())
253 uno::Reference
<util::XNumberFormats
> xNumberFormats(xNumberFormatsSupplier
->getNumberFormats());
254 if (xNumberFormats
.is())
258 uno::Reference
<beans::XPropertySet
> xNumberPropertySet(xNumberFormats
->getByKey(nNumberFormat
));
259 xNumberPropertySet
->getPropertyValue(gsStandardFormat
) >>= bIsStandard
;
260 sal_Int16 nNumberType
= sal_Int16();
261 if ( xNumberPropertySet
->getPropertyValue(gsType
) >>= nNumberType
)
266 catch ( uno::Exception
& )
268 OSL_FAIL("Numberformat not found");
275 void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(SvXMLExport
& rXMLExport
,
276 const sal_Int32 nNumberFormat
, const double& rValue
, bool bExportValue
)
279 sal_Int16 nTypeKey
= GetCellType(nNumberFormat
, bIsStandard
, rXMLExport
.GetNumberFormatsSupplier());
281 if ((nTypeKey
& ~util::NumberFormat::DEFINED
) == util::NumberFormat::CURRENCY
)
282 GetCurrencySymbol(nNumberFormat
, sCurrency
, rXMLExport
.GetNumberFormatsSupplier());
283 WriteAttributes(rXMLExport
, nTypeKey
, rValue
, sCurrency
, bExportValue
);
286 void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(SvXMLExport
& rXMLExport
,
287 const OUString
& rValue
, const OUString
& rCharacters
,
288 bool bExportValue
, bool bExportTypeAttribute
)
290 if (bExportTypeAttribute
)
291 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_VALUE_TYPE
, XML_STRING
);
292 if (bExportValue
&& !rValue
.isEmpty() && (rValue
!= rCharacters
))
293 rXMLExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_STRING_VALUE
, rValue
);
296 bool XMLNumberFormatAttributesExportHelper::GetCurrencySymbol(const sal_Int32 nNumberFormat
, OUString
& rCurrencySymbol
)
298 if (!xNumberFormats
.is() && pExport
&& pExport
->GetNumberFormatsSupplier().is())
299 xNumberFormats
.set(pExport
->GetNumberFormatsSupplier()->getNumberFormats());
301 if (xNumberFormats
.is())
305 uno::Reference
<beans::XPropertySet
> xNumberPropertySet(xNumberFormats
->getByKey(nNumberFormat
));
306 if ( xNumberPropertySet
->getPropertyValue(gsCurrencySymbol
) >>= rCurrencySymbol
)
308 OUString sCurrencyAbbreviation
;
309 if ( xNumberPropertySet
->getPropertyValue(gsCurrencyAbbreviation
) >>= sCurrencyAbbreviation
)
311 if ( !sCurrencyAbbreviation
.isEmpty())
312 rCurrencySymbol
= sCurrencyAbbreviation
;
315 if ( rCurrencySymbol
.getLength() == 1 && rCurrencySymbol
.toChar() == NfCurrencyEntry::GetEuroSymbol() )
316 rCurrencySymbol
= "EUR";
322 catch ( uno::Exception
& )
324 OSL_FAIL("Numberformat not found");
330 sal_Int16
XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat
, bool& bIsStandard
)
332 if (!xNumberFormats
.is() && pExport
&& pExport
->GetNumberFormatsSupplier().is())
333 xNumberFormats
.set(pExport
->GetNumberFormatsSupplier()->getNumberFormats());
335 if (xNumberFormats
.is())
339 uno::Reference
<beans::XPropertySet
> xNumberPropertySet(xNumberFormats
->getByKey(nNumberFormat
));
340 if (xNumberPropertySet
.is())
342 xNumberPropertySet
->getPropertyValue(gsStandardFormat
) >>= bIsStandard
;
343 sal_Int16 nNumberType
= sal_Int16();
344 if ( xNumberPropertySet
->getPropertyValue(gsType
) >>= nNumberType
)
350 catch ( uno::Exception
& )
352 OSL_FAIL("Numberformat not found");
358 void XMLNumberFormatAttributesExportHelper::WriteAttributes(
359 const sal_Int16 nTypeKey
,
360 const double& rValue
,
361 const OUString
& rCurrency
,
362 bool bExportValue
, sal_uInt16 nNamespace
)
367 bool bWasSetTypeAttribute
= false;
368 OUString sAttrValType
= pExport
->GetNamespaceMap().GetQNameByKey( nNamespace
, GetXMLToken(XML_VALUE_TYPE
));
369 switch(nTypeKey
& ~util::NumberFormat::DEFINED
)
372 case util::NumberFormat::NUMBER
:
373 case util::NumberFormat::SCIENTIFIC
:
374 case util::NumberFormat::FRACTION
:
376 pExport
->AddAttribute(sAttrValType
, XML_FLOAT
);
377 bWasSetTypeAttribute
= true;
380 case util::NumberFormat::PERCENT
:
382 if (!bWasSetTypeAttribute
)
384 pExport
->AddAttribute(sAttrValType
, XML_PERCENTAGE
);
385 bWasSetTypeAttribute
= true;
389 case util::NumberFormat::CURRENCY
:
391 if (!bWasSetTypeAttribute
)
393 pExport
->AddAttribute(sAttrValType
, XML_CURRENCY
);
394 if (!rCurrency
.isEmpty())
395 pExport
->AddAttribute(sAttrCurrency
, rCurrency
);
400 OUString
sValue( ::rtl::math::doubleToUString( rValue
,
401 rtl_math_StringFormat_Automatic
,
402 rtl_math_DecimalPlaces_Max
, '.', true));
403 pExport
->AddAttribute(sAttrValue
, sValue
);
407 case util::NumberFormat::DATE
:
408 case util::NumberFormat::DATETIME
:
410 pExport
->AddAttribute(sAttrValType
, XML_DATE
);
413 if ( pExport
->SetNullDateOnUnitConverter() )
415 OUStringBuffer sBuffer
;
416 pExport
->GetMM100UnitConverter().convertDateTime(sBuffer
, rValue
);
417 pExport
->AddAttribute(sAttrDateValue
, sBuffer
.makeStringAndClear());
422 case util::NumberFormat::TIME
:
424 pExport
->AddAttribute(sAttrValType
, XML_TIME
);
427 OUStringBuffer sBuffer
;
428 ::sax::Converter::convertDuration(sBuffer
, rValue
);
429 pExport
->AddAttribute(sAttrTimeValue
, sBuffer
.makeStringAndClear());
433 case util::NumberFormat::LOGICAL
:
435 pExport
->AddAttribute(sAttrValType
, XML_BOOLEAN
);
438 double fTempValue
= rValue
;
439 if (::rtl::math::approxEqual( fTempValue
, 1.0 ))
441 pExport
->AddAttribute(sAttrBooleanValue
, XML_TRUE
);
447 pExport
->AddAttribute(sAttrBooleanValue
, XML_FALSE
);
451 OUString
sValue( ::rtl::math::doubleToUString(
453 rtl_math_StringFormat_Automatic
,
454 rtl_math_DecimalPlaces_Max
, '.',
456 pExport
->AddAttribute(sAttrBooleanValue
, sValue
);
462 case util::NumberFormat::TEXT
:
464 pExport
->AddAttribute(sAttrValType
, XML_FLOAT
);
467 OUString
sValue( ::rtl::math::doubleToUString( rValue
,
468 rtl_math_StringFormat_Automatic
,
469 rtl_math_DecimalPlaces_Max
, '.', true));
470 pExport
->AddAttribute(sAttrValue
, sValue
);
477 void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(
478 const sal_Int32 nNumberFormat
, const double& rValue
, bool bExportValue
,
479 sal_uInt16 nNamespace
, bool bExportCurrencySymbol
)
485 sal_Int16 nTypeKey
= GetCellType(nNumberFormat
, sCurrency
, bIsStandard
);
486 if(!bExportCurrencySymbol
)
489 WriteAttributes(nTypeKey
, rValue
, sCurrency
, bExportValue
, nNamespace
);
492 OSL_FAIL("no SvXMLExport given");
496 void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(
497 const OUString
& rValue
, const OUString
& rCharacters
,
499 sal_uInt16 nNamespace
)
503 pExport
->AddAttribute(nNamespace
, XML_VALUE_TYPE
, XML_STRING
);
504 if (bExportValue
&& !rValue
.isEmpty() && (rValue
!= rCharacters
))
505 pExport
->AddAttribute(sAttrStringValue
, rValue
);
508 OSL_FAIL("no SvXMLExport given");
512 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */