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 
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>
37 
38 using namespace com::sun::star;
39 using namespace xmloff::token;
40 
41 constexpr OUStringLiteral gsStandardFormat(u"StandardFormat");
42 constexpr OUStringLiteral gsType(u"Type");
43 constexpr OUStringLiteral gsCurrencySymbol(u"CurrencySymbol");
44 constexpr OUStringLiteral gsCurrencyAbbreviation(u"CurrencyAbbreviation");
45 
47  css::uno::Reference< css::util::XNumberFormatsSupplier > const & xTempNumberFormatsSupplier)
48  : xNumberFormats(xTempNumberFormatsSupplier.is() ? xTempNumberFormatsSupplier->getNumberFormats() : css::uno::Reference< css::util::XNumberFormats > ()),
49  pExport(nullptr)
50 {
51 }
52 
54  css::uno::Reference< css::util::XNumberFormatsSupplier > const & xTempNumberFormatsSupplier,
55  SvXMLExport& rTempExport )
56 : xNumberFormats(xTempNumberFormatsSupplier.is() ? xTempNumberFormatsSupplier->getNumberFormats() : css::uno::Reference< css::util::XNumberFormats > ()),
57  pExport(&rTempExport),
58  sAttrValue(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_VALUE))),
59  sAttrDateValue(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_DATE_VALUE))),
60  sAttrTimeValue(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_TIME_VALUE))),
61  sAttrBooleanValue(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_BOOLEAN_VALUE))),
62  sAttrStringValue(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_STRING_VALUE))),
63  sAttrCurrency(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_CURRENCY)))
64 {
65 }
66 
68 {
69 }
70 
71 sal_Int16 XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat, OUString& sCurrency, bool& bIsStandard)
72 {
73  XMLNumberFormat aFormat(nNumberFormat);
74  XMLNumberFormatSet::iterator aItr(aNumberFormats.find(aFormat));
75  XMLNumberFormatSet::iterator aEndItr(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  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 
209 bool 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 
246 sal_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 
294 bool XMLNumberFormatAttributesExportHelper::GetCurrencySymbol(const sal_Int32 nNumberFormat, OUString& rCurrencySymbol)
295 {
296  if (!xNumberFormats.is() && pExport && pExport->GetNumberFormatsSupplier().is())
297  xNumberFormats.set(pExport->GetNumberFormatsSupplier()->getNumberFormats());
298 
299  if (xNumberFormats.is())
300  {
301  try
302  {
303  uno::Reference <beans::XPropertySet> xNumberPropertySet(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 
328 sal_Int16 XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat, bool& bIsStandard)
329 {
330  if (!xNumberFormats.is() && pExport && pExport->GetNumberFormatsSupplier().is())
331  xNumberFormats.set(pExport->GetNumberFormatsSupplier()->getNumberFormats());
332 
333  if (xNumberFormats.is())
334  {
335  try
336  {
337  uno::Reference <beans::XPropertySet> xNumberPropertySet(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 (!pExport)
363  return;
364 
365  bool bWasSetTypeAttribute = false;
366  OUString sAttrValType = pExport->GetNamespaceMap().GetQNameByKey( nNamespace, GetXMLToken(XML_VALUE_TYPE));
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  pExport->AddAttribute(sAttrValType, XML_FLOAT);
375  bWasSetTypeAttribute = true;
376  [[fallthrough]];
377  }
378  case util::NumberFormat::PERCENT:
379  {
380  if (!bWasSetTypeAttribute)
381  {
382  pExport->AddAttribute(sAttrValType, XML_PERCENTAGE);
383  bWasSetTypeAttribute = true;
384  }
385  [[fallthrough]];
386  }
387  case util::NumberFormat::CURRENCY:
388  {
389  if (!bWasSetTypeAttribute)
390  {
391  pExport->AddAttribute(sAttrValType, XML_CURRENCY);
392  if (!rCurrency.isEmpty())
393  pExport->AddAttribute(sAttrCurrency, rCurrency);
394  }
395 
396  if (bExportValue)
397  {
398  OUString sValue( ::rtl::math::doubleToUString( rValue,
399  rtl_math_StringFormat_Automatic,
400  rtl_math_DecimalPlaces_Max, '.', true));
401  pExport->AddAttribute(sAttrValue, sValue);
402  }
403  }
404  break;
405  case util::NumberFormat::DATE:
406  case util::NumberFormat::DATETIME:
407  {
408  pExport->AddAttribute(sAttrValType, XML_DATE);
409  if (bExportValue)
410  {
412  {
413  OUStringBuffer sBuffer;
414  pExport->GetMM100UnitConverter().convertDateTime(sBuffer, rValue);
415  pExport->AddAttribute(sAttrDateValue, sBuffer.makeStringAndClear());
416  }
417  }
418  }
419  break;
420  case util::NumberFormat::TIME:
421  {
422  pExport->AddAttribute(sAttrValType, XML_TIME);
423  if (bExportValue)
424  {
425  OUStringBuffer sBuffer;
426  ::sax::Converter::convertDuration(sBuffer, rValue);
427  pExport->AddAttribute(sAttrTimeValue, sBuffer.makeStringAndClear());
428  }
429  }
430  break;
431  case util::NumberFormat::LOGICAL:
432  {
433  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  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));
468  pExport->AddAttribute(sAttrValue, sValue);
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 (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 (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: */
exports com.sun.star.lib. util
css::uno::Reference< css::util::XNumberFormats > xNumberFormats
Definition: numehelp.hxx:64
constexpr sal_uInt16 XML_NAMESPACE_OFFICE
OUString sCurrency
Definition: numehelp.hxx:39
const SvXMLUnitConverter & GetMM100UnitConverter() const
Definition: xmlexp.hxx:400
Reference
constexpr OUStringLiteral gsType(u"Type")
Reference< XNumberFormatsSupplier > getNumberFormats(const Reference< XConnection > &_rxConn, bool _bAlloweDefault, const Reference< XComponentContext > &_rxContext)
void AddAttribute(sal_uInt16 nPrefix, const char *pName, const OUString &rValue)
Definition: xmlexp.cxx:938
bool SetNullDateOnUnitConverter()
set null date from model to unit converter, if not already done
Definition: xmlexp.cxx:2428
css::uno::Reference< css::util::XNumberFormatsSupplier > & GetNumberFormatsSupplier()
Definition: xmlexp.hxx:422
void convertDateTime(OUStringBuffer &rBuffer, const double &fDateTime, bool const bAddTimeIf0AM=false)
convert double to ISO Date Time String
Definition: xmluconv.cxx:364
static void SetNumberFormatAttributes(SvXMLExport &rXMLExport, const sal_Int32 nNumberFormat, const double &rValue, bool bExportValue=true)
Definition: numehelp.cxx:273
XMLNumberFormatAttributesExportHelper(css::uno::Reference< css::util::XNumberFormatsSupplier > const &xNumberFormatsSupplier)
Definition: numehelp.cxx:46
static void convertDuration(OUStringBuffer &rBuffer, const double fTime)
OUString GetQNameByKey(sal_uInt16 nKey, const OUString &rLocalName, bool bCache=true) const
const SvXMLNamespaceMap & GetNamespaceMap() const
Definition: xmlexp.hxx:394
sal_Int16 nType
Definition: numehelp.hxx:41
constexpr OUStringLiteral gsCurrencyAbbreviation(u"CurrencyAbbreviation")
sal_Int16 GetCellType(const sal_Int32 nNumberFormat, OUString &sCurrency, bool &bIsStandard)
Definition: numehelp.cxx:71
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Definition: xmltoken.cxx:3452
Handling of tokens in XML:
static bool GetCurrencySymbol(const sal_Int32 nNumberFormat, OUString &rCurrencySymbol, css::uno::Reference< css::util::XNumberFormatsSupplier > const &xNumberFormatsSupplier)
static void WriteAttributes(SvXMLExport &rXMLExport, const sal_Int16 nTypeKey, const double &rValue, const OUString &rCurrencySymbol, bool bExportValue)
Definition: numehelp.cxx:94
constexpr OUStringLiteral gsCurrencySymbol(u"CurrencySymbol")
constexpr OUStringLiteral gsStandardFormat(u"StandardFormat")