LibreOffice Module xmloff (master) 1
numehelp.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20
21#include <xmloff/numehelp.hxx>
22
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>
34#include <rtl/math.hxx>
35#include <rtl/ustrbuf.hxx>
36#include <osl/diagnose.h>
37
38using namespace com::sun::star;
39using namespace xmloff::token;
40
41constexpr OUStringLiteral gsStandardFormat(u"StandardFormat");
42constexpr OUStringLiteral gsType(u"Type");
43constexpr OUStringLiteral gsCurrencySymbol(u"CurrencySymbol");
44constexpr OUStringLiteral gsCurrencyAbbreviation(u"CurrencyAbbreviation");
45
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)
50{
51}
52
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)))
64{
65}
66
68{
69}
70
71sal_Int16 XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat, OUString& sCurrency, bool& bIsStandard)
72{
73 XMLNumberFormat aFormat(nNumberFormat);
74 XMLNumberFormatSet::iterator aItr(m_aNumberFormats.find(aFormat));
75 XMLNumberFormatSet::iterator aEndItr(m_aNumberFormats.end());
76 if (aItr != aEndItr)
77 {
78 bIsStandard = aItr->bIsStandard;
79 sCurrency = aItr->sCurrency;
80 return aItr->nType;
81 }
82 else
83 {
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;
91 }
92}
93
95 const sal_Int16 nTypeKey,
96 const double& rValue,
97 const OUString& rCurrency,
98 bool bExportValue)
99{
100 bool bWasSetTypeAttribute = false;
101 switch(nTypeKey & ~util::NumberFormat::DEFINED)
102 {
103 case 0:
104 case util::NumberFormat::NUMBER:
105 case util::NumberFormat::SCIENTIFIC:
106 case util::NumberFormat::FRACTION:
107 {
109 bWasSetTypeAttribute = true;
110 [[fallthrough]];
111 }
112 case util::NumberFormat::PERCENT:
113 {
114 if (!bWasSetTypeAttribute)
115 {
117 bWasSetTypeAttribute = true;
118 }
119 [[fallthrough]];
120 }
121 case util::NumberFormat::CURRENCY:
122 {
123 if (!bWasSetTypeAttribute)
124 {
126 if (!rCurrency.isEmpty())
127 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_CURRENCY, rCurrency);
128 }
129
130 if (bExportValue)
131 {
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);
136 }
137 }
138 break;
139 case util::NumberFormat::DATE:
140 case util::NumberFormat::DATETIME:
141 {
143 if (bExportValue)
144 {
145 if ( rXMLExport.SetNullDateOnUnitConverter() )
146 {
147 OUStringBuffer sBuffer;
148 rXMLExport.GetMM100UnitConverter().convertDateTime(sBuffer, rValue);
149 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_DATE_VALUE, sBuffer.makeStringAndClear());
150 }
151 }
152 }
153 break;
154 case util::NumberFormat::TIME:
155 {
157 if (bExportValue)
158 {
159 OUStringBuffer sBuffer;
160 ::sax::Converter::convertDuration(sBuffer, rValue);
161 rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_TIME_VALUE, sBuffer.makeStringAndClear());
162 }
163 }
164 break;
165 case util::NumberFormat::LOGICAL:
166 {
168 if (bExportValue)
169 {
170 double fTempValue = rValue;
171 if (::rtl::math::approxEqual( fTempValue, 1.0 ))
172 {
174 }
175 else
176 {
177 if (rValue == 0.0)
178 {
180 }
181 else
182 {
183 OUString sValue( ::rtl::math::doubleToUString(
184 fTempValue,
185 rtl_math_StringFormat_Automatic,
186 rtl_math_DecimalPlaces_Max, '.',
187 true));
189 }
190 }
191 }
192 }
193 break;
194 case util::NumberFormat::TEXT:
195 {
197 if (bExportValue)
198 {
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);
203 }
204 }
205 break;
206 }
207}
208
209bool XMLNumberFormatAttributesExportHelper::GetCurrencySymbol(const sal_Int32 nNumberFormat, OUString& sCurrencySymbol,
210 uno::Reference <util::XNumberFormatsSupplier> const & xNumberFormatsSupplier)
211{
212 if (xNumberFormatsSupplier.is())
213 {
214 uno::Reference <util::XNumberFormats> xNumberFormats(xNumberFormatsSupplier->getNumberFormats());
215 if (xNumberFormats.is())
216 {
217 try
218 {
219 uno::Reference <beans::XPropertySet> xNumberPropertySet(xNumberFormats->getByKey(nNumberFormat));
220 if ( xNumberPropertySet->getPropertyValue(gsCurrencySymbol) >>= sCurrencySymbol)
221 {
222 OUString sCurrencyAbbreviation;
223 if ( xNumberPropertySet->getPropertyValue(gsCurrencyAbbreviation) >>= sCurrencyAbbreviation)
224 {
225 if ( !sCurrencyAbbreviation.isEmpty())
226 sCurrencySymbol = sCurrencyAbbreviation;
227 else
228 {
229 if ( sCurrencySymbol.getLength() == 1 && sCurrencySymbol.toChar() == NfCurrencyEntry::GetEuroSymbol() )
230 sCurrencySymbol = "EUR";
231 }
232 }
233 return true;
234 }
235 }
236 catch ( uno::Exception& )
237 {
238 OSL_FAIL("Numberformat not found");
239 }
240 }
241 }
242 return false;
243}
244
245
246sal_Int16 XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat, bool& bIsStandard,
247 uno::Reference <util::XNumberFormatsSupplier> const & xNumberFormatsSupplier)
248{
249 if (xNumberFormatsSupplier.is())
250 {
251 uno::Reference <util::XNumberFormats> xNumberFormats(xNumberFormatsSupplier->getNumberFormats());
252 if (xNumberFormats.is())
253 {
254 try
255 {
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 )
260 {
261 return nNumberType;
262 }
263 }
264 catch ( uno::Exception& )
265 {
266 OSL_FAIL("Numberformat not found");
267 }
268 }
269 }
270 return 0;
271}
272
274 const sal_Int32 nNumberFormat, const double& rValue, bool bExportValue)
275{
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);
282}
283
285 const OUString& rValue, std::u16string_view rCharacters,
286 bool bExportValue, bool bExportTypeAttribute)
287{
288 if (bExportTypeAttribute)
290 if (bExportValue && !rValue.isEmpty() && (rValue != rCharacters))
292}
293
294bool XMLNumberFormatAttributesExportHelper::GetCurrencySymbol(const sal_Int32 nNumberFormat, OUString& rCurrencySymbol)
295{
297 m_xNumberFormats.set(m_pExport->GetNumberFormatsSupplier()->getNumberFormats());
298
299 if (m_xNumberFormats.is())
300 {
301 try
302 {
303 uno::Reference <beans::XPropertySet> xNumberPropertySet(m_xNumberFormats->getByKey(nNumberFormat));
304 if ( xNumberPropertySet->getPropertyValue(gsCurrencySymbol) >>= rCurrencySymbol)
305 {
306 OUString sCurrencyAbbreviation;
307 if ( xNumberPropertySet->getPropertyValue(gsCurrencyAbbreviation) >>= sCurrencyAbbreviation)
308 {
309 if ( !sCurrencyAbbreviation.isEmpty())
310 rCurrencySymbol = sCurrencyAbbreviation;
311 else
312 {
313 if ( rCurrencySymbol.getLength() == 1 && rCurrencySymbol.toChar() == NfCurrencyEntry::GetEuroSymbol() )
314 rCurrencySymbol = "EUR";
315 }
316 }
317 return true;
318 }
319 }
320 catch ( uno::Exception& )
321 {
322 OSL_FAIL("Numberformat not found");
323 }
324 }
325 return false;
326}
327
328sal_Int16 XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat, bool& bIsStandard)
329{
331 m_xNumberFormats.set(m_pExport->GetNumberFormatsSupplier()->getNumberFormats());
332
333 if (m_xNumberFormats.is())
334 {
335 try
336 {
337 uno::Reference <beans::XPropertySet> xNumberPropertySet(m_xNumberFormats->getByKey(nNumberFormat));
338 if (xNumberPropertySet.is())
339 {
340 xNumberPropertySet->getPropertyValue(gsStandardFormat) >>= bIsStandard;
341 sal_Int16 nNumberType = sal_Int16();
342 if ( xNumberPropertySet->getPropertyValue(gsType) >>= nNumberType )
343 {
344 return nNumberType;
345 }
346 }
347 }
348 catch ( uno::Exception& )
349 {
350 OSL_FAIL("Numberformat not found");
351 }
352 }
353 return 0;
354}
355
357 const sal_Int16 nTypeKey,
358 const double& rValue,
359 const OUString& rCurrency,
360 bool bExportValue, sal_uInt16 nNamespace)
361{
362 if (!m_pExport)
363 return;
364
365 bool bWasSetTypeAttribute = false;
367 switch(nTypeKey & ~util::NumberFormat::DEFINED)
368 {
369 case 0:
370 case util::NumberFormat::NUMBER:
371 case util::NumberFormat::SCIENTIFIC:
372 case util::NumberFormat::FRACTION:
373 {
374 m_pExport->AddAttribute(sAttrValType, XML_FLOAT);
375 bWasSetTypeAttribute = true;
376 [[fallthrough]];
377 }
378 case util::NumberFormat::PERCENT:
379 {
380 if (!bWasSetTypeAttribute)
381 {
382 m_pExport->AddAttribute(sAttrValType, XML_PERCENTAGE);
383 bWasSetTypeAttribute = true;
384 }
385 [[fallthrough]];
386 }
387 case util::NumberFormat::CURRENCY:
388 {
389 if (!bWasSetTypeAttribute)
390 {
391 m_pExport->AddAttribute(sAttrValType, XML_CURRENCY);
392 if (!rCurrency.isEmpty())
394 }
395
396 if (bExportValue)
397 {
398 OUString sValue( ::rtl::math::doubleToUString( rValue,
399 rtl_math_StringFormat_Automatic,
400 rtl_math_DecimalPlaces_Max, '.', true));
402 }
403 }
404 break;
405 case util::NumberFormat::DATE:
406 case util::NumberFormat::DATETIME:
407 {
408 m_pExport->AddAttribute(sAttrValType, XML_DATE);
409 if (bExportValue)
410 {
412 {
413 OUStringBuffer sBuffer;
415 m_pExport->AddAttribute(m_sAttrDateValue, sBuffer.makeStringAndClear());
416 }
417 }
418 }
419 break;
420 case util::NumberFormat::TIME:
421 {
422 m_pExport->AddAttribute(sAttrValType, XML_TIME);
423 if (bExportValue)
424 {
425 OUStringBuffer sBuffer;
426 ::sax::Converter::convertDuration(sBuffer, rValue);
427 m_pExport->AddAttribute(m_sAttrTimeValue, sBuffer.makeStringAndClear());
428 }
429 }
430 break;
431 case util::NumberFormat::LOGICAL:
432 {
433 m_pExport->AddAttribute(sAttrValType, XML_BOOLEAN);
434 if (bExportValue)
435 {
436 double fTempValue = rValue;
437 if (::rtl::math::approxEqual( fTempValue, 1.0 ))
438 {
440 }
441 else
442 {
443 if (rValue == 0.0)
444 {
446 }
447 else
448 {
449 OUString sValue( ::rtl::math::doubleToUString(
450 fTempValue,
451 rtl_math_StringFormat_Automatic,
452 rtl_math_DecimalPlaces_Max, '.',
453 true));
455 }
456 }
457 }
458 }
459 break;
460 case util::NumberFormat::TEXT:
461 {
462 m_pExport->AddAttribute(sAttrValType, XML_FLOAT);
463 if (bExportValue)
464 {
465 OUString sValue( ::rtl::math::doubleToUString( rValue,
466 rtl_math_StringFormat_Automatic,
467 rtl_math_DecimalPlaces_Max, '.', true));
469 }
470 }
471 break;
472 }
473}
474
476 const sal_Int32 nNumberFormat, const double& rValue, bool bExportValue,
477 sal_uInt16 nNamespace, bool bExportCurrencySymbol)
478{
479 if (m_pExport)
480 {
481 bool bIsStandard;
482 OUString sCurrency;
483 sal_Int16 nTypeKey = GetCellType(nNumberFormat, sCurrency, bIsStandard);
484 if(!bExportCurrencySymbol)
485 sCurrency.clear();
486
487 WriteAttributes(nTypeKey, rValue, sCurrency, bExportValue, nNamespace);
488 }
489 else {
490 OSL_FAIL("no SvXMLExport given");
491 }
492}
493
495 const OUString& rValue, std::u16string_view rCharacters,
496 bool bExportValue,
497 sal_uInt16 nNamespace)
498{
499 if (m_pExport)
500 {
502 if (bExportValue && !rValue.isEmpty() && (rValue != rCharacters))
504 }
505 else {
506 OSL_FAIL("no SvXMLExport given");
507 }
508}
509
510/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const SvXMLNamespaceMap & GetNamespaceMap() const
Definition: xmlexp.hxx:385
void AddAttribute(sal_uInt16 nPrefix, const OUString &rName, const OUString &rValue)
Definition: xmlexp.cxx:907
css::uno::Reference< css::util::XNumberFormatsSupplier > & GetNumberFormatsSupplier()
Definition: xmlexp.hxx:413
const SvXMLUnitConverter & GetMM100UnitConverter() const
Definition: xmlexp.hxx:391
bool SetNullDateOnUnitConverter()
set null date from model to unit converter, if not already done
Definition: xmlexp.cxx:2369
OUString GetQNameByKey(sal_uInt16 nKey, const OUString &rLocalName, bool bCache=true) const
void convertDateTime(OUStringBuffer &rBuffer, const double &fDateTime, bool const bAddTimeIf0AM=false)
convert double to ISO Date Time String
Definition: xmluconv.cxx:377
static void SetNumberFormatAttributes(SvXMLExport &rXMLExport, const sal_Int32 nNumberFormat, const double &rValue, bool bExportValue=true)
Definition: numehelp.cxx:273
static bool GetCurrencySymbol(const sal_Int32 nNumberFormat, OUString &rCurrencySymbol, css::uno::Reference< css::util::XNumberFormatsSupplier > const &xNumberFormatsSupplier)
sal_Int16 GetCellType(const sal_Int32 nNumberFormat, OUString &sCurrency, bool &bIsStandard)
Definition: numehelp.cxx:71
XMLNumberFormatSet m_aNumberFormats
Definition: numehelp.hxx:72
XMLNumberFormatAttributesExportHelper(css::uno::Reference< css::util::XNumberFormatsSupplier > const &xNumberFormatsSupplier)
Definition: numehelp.cxx:46
css::uno::Reference< css::util::XNumberFormats > m_xNumberFormats
Definition: numehelp.hxx:64
static void WriteAttributes(SvXMLExport &rXMLExport, const sal_Int16 nTypeKey, const double &rValue, const OUString &rCurrencySymbol, bool bExportValue)
Definition: numehelp.cxx:94
static void convertDuration(OUStringBuffer &rBuffer, const double fTime)
Reference< XNumberFormatsSupplier > getNumberFormats(const Reference< XConnection > &_rxConn, bool _bAlloweDefault, const Reference< XComponentContext > &_rxContext)
Reference
Handling of tokens in XML:
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Definition: xmltoken.cxx:3541
constexpr OUStringLiteral gsType(u"Type")
constexpr OUStringLiteral gsCurrencySymbol(u"CurrencySymbol")
constexpr OUStringLiteral gsStandardFormat(u"StandardFormat")
constexpr OUStringLiteral gsCurrencyAbbreviation(u"CurrencyAbbreviation")
OReadStatusBarDocumentHandler::StatusBar_XML_Namespace nNamespace
sal_Int16 nType
Definition: numehelp.hxx:41
OUString sCurrency
Definition: numehelp.hxx:39
constexpr sal_uInt16 XML_NAMESPACE_OFFICE