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  aNumberFormats()
51 {
52 }
53 
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))),
65  aNumberFormats()
66 {
67 }
68 
70 {
71 }
72 
73 sal_Int16 XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat, OUString& sCurrency, bool& bIsStandard)
74 {
75  XMLNumberFormat aFormat(nNumberFormat);
76  XMLNumberFormatSet::iterator aItr(aNumberFormats.find(aFormat));
77  XMLNumberFormatSet::iterator aEndItr(aNumberFormats.end());
78  if (aItr != aEndItr)
79  {
80  bIsStandard = aItr->bIsStandard;
81  sCurrency = aItr->sCurrency;
82  return aItr->nType;
83  }
84  else
85  {
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);
92  return aFormat.nType;
93  }
94 }
95 
97  const sal_Int16 nTypeKey,
98  const double& rValue,
99  const OUString& rCurrency,
100  bool bExportValue)
101 {
102  bool bWasSetTypeAttribute = false;
103  switch(nTypeKey & ~util::NumberFormat::DEFINED)
104  {
105  case 0:
106  case util::NumberFormat::NUMBER:
107  case util::NumberFormat::SCIENTIFIC:
108  case util::NumberFormat::FRACTION:
109  {
111  bWasSetTypeAttribute = true;
112  [[fallthrough]];
113  }
114  case util::NumberFormat::PERCENT:
115  {
116  if (!bWasSetTypeAttribute)
117  {
119  bWasSetTypeAttribute = true;
120  }
121  [[fallthrough]];
122  }
123  case util::NumberFormat::CURRENCY:
124  {
125  if (!bWasSetTypeAttribute)
126  {
128  if (!rCurrency.isEmpty())
129  rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_CURRENCY, rCurrency);
130  }
131 
132  if (bExportValue)
133  {
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);
138  }
139  }
140  break;
141  case util::NumberFormat::DATE:
142  case util::NumberFormat::DATETIME:
143  {
145  if (bExportValue)
146  {
147  if ( rXMLExport.SetNullDateOnUnitConverter() )
148  {
149  OUStringBuffer sBuffer;
150  rXMLExport.GetMM100UnitConverter().convertDateTime(sBuffer, rValue);
151  rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_DATE_VALUE, sBuffer.makeStringAndClear());
152  }
153  }
154  }
155  break;
156  case util::NumberFormat::TIME:
157  {
159  if (bExportValue)
160  {
161  OUStringBuffer sBuffer;
162  ::sax::Converter::convertDuration(sBuffer, rValue);
163  rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_TIME_VALUE, sBuffer.makeStringAndClear());
164  }
165  }
166  break;
167  case util::NumberFormat::LOGICAL:
168  {
170  if (bExportValue)
171  {
172  double fTempValue = rValue;
173  if (::rtl::math::approxEqual( fTempValue, 1.0 ))
174  {
176  }
177  else
178  {
179  if (rValue == 0.0)
180  {
182  }
183  else
184  {
185  OUString sValue( ::rtl::math::doubleToUString(
186  fTempValue,
187  rtl_math_StringFormat_Automatic,
188  rtl_math_DecimalPlaces_Max, '.',
189  true));
191  }
192  }
193  }
194  }
195  break;
196  case util::NumberFormat::TEXT:
197  {
199  if (bExportValue)
200  {
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);
205  }
206  }
207  break;
208  }
209 }
210 
211 bool XMLNumberFormatAttributesExportHelper::GetCurrencySymbol(const sal_Int32 nNumberFormat, OUString& sCurrencySymbol,
212  uno::Reference <util::XNumberFormatsSupplier> const & xNumberFormatsSupplier)
213 {
214  if (xNumberFormatsSupplier.is())
215  {
216  uno::Reference <util::XNumberFormats> xNumberFormats(xNumberFormatsSupplier->getNumberFormats());
217  if (xNumberFormats.is())
218  {
219  try
220  {
221  uno::Reference <beans::XPropertySet> xNumberPropertySet(xNumberFormats->getByKey(nNumberFormat));
222  if ( xNumberPropertySet->getPropertyValue(gsCurrencySymbol) >>= sCurrencySymbol)
223  {
224  OUString sCurrencyAbbreviation;
225  if ( xNumberPropertySet->getPropertyValue(gsCurrencyAbbreviation) >>= sCurrencyAbbreviation)
226  {
227  if ( !sCurrencyAbbreviation.isEmpty())
228  sCurrencySymbol = sCurrencyAbbreviation;
229  else
230  {
231  if ( sCurrencySymbol.getLength() == 1 && sCurrencySymbol.toChar() == NfCurrencyEntry::GetEuroSymbol() )
232  sCurrencySymbol = "EUR";
233  }
234  }
235  return true;
236  }
237  }
238  catch ( uno::Exception& )
239  {
240  OSL_FAIL("Numberformat not found");
241  }
242  }
243  }
244  return false;
245 }
246 
247 
248 sal_Int16 XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat, bool& bIsStandard,
249  uno::Reference <util::XNumberFormatsSupplier> const & xNumberFormatsSupplier)
250 {
251  if (xNumberFormatsSupplier.is())
252  {
253  uno::Reference <util::XNumberFormats> xNumberFormats(xNumberFormatsSupplier->getNumberFormats());
254  if (xNumberFormats.is())
255  {
256  try
257  {
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 )
262  {
263  return nNumberType;
264  }
265  }
266  catch ( uno::Exception& )
267  {
268  OSL_FAIL("Numberformat not found");
269  }
270  }
271  }
272  return 0;
273 }
274 
276  const sal_Int32 nNumberFormat, const double& rValue, bool bExportValue)
277 {
278  bool bIsStandard;
279  sal_Int16 nTypeKey = GetCellType(nNumberFormat, bIsStandard, rXMLExport.GetNumberFormatsSupplier());
280  OUString sCurrency;
281  if ((nTypeKey & ~util::NumberFormat::DEFINED) == util::NumberFormat::CURRENCY)
282  GetCurrencySymbol(nNumberFormat, sCurrency, rXMLExport.GetNumberFormatsSupplier());
283  WriteAttributes(rXMLExport, nTypeKey, rValue, sCurrency, bExportValue);
284 }
285 
287  const OUString& rValue, const OUString& rCharacters,
288  bool bExportValue, bool bExportTypeAttribute)
289 {
290  if (bExportTypeAttribute)
292  if (bExportValue && !rValue.isEmpty() && (rValue != rCharacters))
294 }
295 
296 bool XMLNumberFormatAttributesExportHelper::GetCurrencySymbol(const sal_Int32 nNumberFormat, OUString& rCurrencySymbol)
297 {
298  if (!xNumberFormats.is() && pExport && pExport->GetNumberFormatsSupplier().is())
299  xNumberFormats.set(pExport->GetNumberFormatsSupplier()->getNumberFormats());
300 
301  if (xNumberFormats.is())
302  {
303  try
304  {
305  uno::Reference <beans::XPropertySet> xNumberPropertySet(xNumberFormats->getByKey(nNumberFormat));
306  if ( xNumberPropertySet->getPropertyValue(gsCurrencySymbol) >>= rCurrencySymbol)
307  {
308  OUString sCurrencyAbbreviation;
309  if ( xNumberPropertySet->getPropertyValue(gsCurrencyAbbreviation) >>= sCurrencyAbbreviation)
310  {
311  if ( !sCurrencyAbbreviation.isEmpty())
312  rCurrencySymbol = sCurrencyAbbreviation;
313  else
314  {
315  if ( rCurrencySymbol.getLength() == 1 && rCurrencySymbol.toChar() == NfCurrencyEntry::GetEuroSymbol() )
316  rCurrencySymbol = "EUR";
317  }
318  }
319  return true;
320  }
321  }
322  catch ( uno::Exception& )
323  {
324  OSL_FAIL("Numberformat not found");
325  }
326  }
327  return false;
328 }
329 
330 sal_Int16 XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat, bool& bIsStandard)
331 {
332  if (!xNumberFormats.is() && pExport && pExport->GetNumberFormatsSupplier().is())
333  xNumberFormats.set(pExport->GetNumberFormatsSupplier()->getNumberFormats());
334 
335  if (xNumberFormats.is())
336  {
337  try
338  {
339  uno::Reference <beans::XPropertySet> xNumberPropertySet(xNumberFormats->getByKey(nNumberFormat));
340  if (xNumberPropertySet.is())
341  {
342  xNumberPropertySet->getPropertyValue(gsStandardFormat) >>= bIsStandard;
343  sal_Int16 nNumberType = sal_Int16();
344  if ( xNumberPropertySet->getPropertyValue(gsType) >>= nNumberType )
345  {
346  return nNumberType;
347  }
348  }
349  }
350  catch ( uno::Exception& )
351  {
352  OSL_FAIL("Numberformat not found");
353  }
354  }
355  return 0;
356 }
357 
359  const sal_Int16 nTypeKey,
360  const double& rValue,
361  const OUString& rCurrency,
362  bool bExportValue, sal_uInt16 nNamespace)
363 {
364  if (!pExport)
365  return;
366 
367  bool bWasSetTypeAttribute = false;
368  OUString sAttrValType = pExport->GetNamespaceMap().GetQNameByKey( nNamespace, GetXMLToken(XML_VALUE_TYPE));
369  switch(nTypeKey & ~util::NumberFormat::DEFINED)
370  {
371  case 0:
372  case util::NumberFormat::NUMBER:
373  case util::NumberFormat::SCIENTIFIC:
374  case util::NumberFormat::FRACTION:
375  {
376  pExport->AddAttribute(sAttrValType, XML_FLOAT);
377  bWasSetTypeAttribute = true;
378  [[fallthrough]];
379  }
380  case util::NumberFormat::PERCENT:
381  {
382  if (!bWasSetTypeAttribute)
383  {
384  pExport->AddAttribute(sAttrValType, XML_PERCENTAGE);
385  bWasSetTypeAttribute = true;
386  }
387  [[fallthrough]];
388  }
389  case util::NumberFormat::CURRENCY:
390  {
391  if (!bWasSetTypeAttribute)
392  {
393  pExport->AddAttribute(sAttrValType, XML_CURRENCY);
394  if (!rCurrency.isEmpty())
395  pExport->AddAttribute(sAttrCurrency, rCurrency);
396  }
397 
398  if (bExportValue)
399  {
400  OUString sValue( ::rtl::math::doubleToUString( rValue,
401  rtl_math_StringFormat_Automatic,
402  rtl_math_DecimalPlaces_Max, '.', true));
403  pExport->AddAttribute(sAttrValue, sValue);
404  }
405  }
406  break;
407  case util::NumberFormat::DATE:
408  case util::NumberFormat::DATETIME:
409  {
410  pExport->AddAttribute(sAttrValType, XML_DATE);
411  if (bExportValue)
412  {
414  {
415  OUStringBuffer sBuffer;
416  pExport->GetMM100UnitConverter().convertDateTime(sBuffer, rValue);
417  pExport->AddAttribute(sAttrDateValue, sBuffer.makeStringAndClear());
418  }
419  }
420  }
421  break;
422  case util::NumberFormat::TIME:
423  {
424  pExport->AddAttribute(sAttrValType, XML_TIME);
425  if (bExportValue)
426  {
427  OUStringBuffer sBuffer;
428  ::sax::Converter::convertDuration(sBuffer, rValue);
429  pExport->AddAttribute(sAttrTimeValue, sBuffer.makeStringAndClear());
430  }
431  }
432  break;
433  case util::NumberFormat::LOGICAL:
434  {
435  pExport->AddAttribute(sAttrValType, XML_BOOLEAN);
436  if (bExportValue)
437  {
438  double fTempValue = rValue;
439  if (::rtl::math::approxEqual( fTempValue, 1.0 ))
440  {
442  }
443  else
444  {
445  if (rValue == 0.0)
446  {
448  }
449  else
450  {
451  OUString sValue( ::rtl::math::doubleToUString(
452  fTempValue,
453  rtl_math_StringFormat_Automatic,
454  rtl_math_DecimalPlaces_Max, '.',
455  true));
457  }
458  }
459  }
460  }
461  break;
462  case util::NumberFormat::TEXT:
463  {
464  pExport->AddAttribute(sAttrValType, XML_FLOAT);
465  if (bExportValue)
466  {
467  OUString sValue( ::rtl::math::doubleToUString( rValue,
468  rtl_math_StringFormat_Automatic,
469  rtl_math_DecimalPlaces_Max, '.', true));
470  pExport->AddAttribute(sAttrValue, sValue);
471  }
472  }
473  break;
474  }
475 }
476 
478  const sal_Int32 nNumberFormat, const double& rValue, bool bExportValue,
479  sal_uInt16 nNamespace, bool bExportCurrencySymbol)
480 {
481  if (pExport)
482  {
483  bool bIsStandard;
484  OUString sCurrency;
485  sal_Int16 nTypeKey = GetCellType(nNumberFormat, sCurrency, bIsStandard);
486  if(!bExportCurrencySymbol)
487  sCurrency.clear();
488 
489  WriteAttributes(nTypeKey, rValue, sCurrency, bExportValue, nNamespace);
490  }
491  else {
492  OSL_FAIL("no SvXMLExport given");
493  }
494 }
495 
497  const OUString& rValue, const OUString& rCharacters,
498  bool bExportValue,
499  sal_uInt16 nNamespace)
500 {
501  if (pExport)
502  {
504  if (bExportValue && !rValue.isEmpty() && (rValue != rCharacters))
506  }
507  else {
508  OSL_FAIL("no SvXMLExport given");
509  }
510 }
511 
512 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
exports com.sun.star.lib. util
css::uno::Reference< css::util::XNumberFormats > xNumberFormats
Definition: numehelp.hxx:63
constexpr sal_uInt16 XML_NAMESPACE_OFFICE
OUString sCurrency
Definition: numehelp.hxx:38
const SvXMLUnitConverter & GetMM100UnitConverter() const
Definition: xmlexp.hxx:394
Reference
constexpr OUStringLiteral gsType(u"Type")
Reference< XNumberFormatsSupplier > getNumberFormats(const Reference< XConnection > &_rxConn, bool _bAlloweDefault, const Reference< XComponentContext > &_rxContext)
css::uno::Any const & rValue
Definition: ImageStyle.hxx:38
void AddAttribute(sal_uInt16 nPrefix, const char *pName, const OUString &rValue)
Definition: xmlexp.cxx:909
bool SetNullDateOnUnitConverter()
set null date from model to unit converter, if not already done
Definition: xmlexp.cxx:2402
css::uno::Reference< css::util::XNumberFormatsSupplier > & GetNumberFormatsSupplier()
Definition: xmlexp.hxx:416
void convertDateTime(OUStringBuffer &rBuffer, const double &fDateTime, bool const bAddTimeIf0AM=false)
convert double to ISO Date Time String
Definition: xmluconv.cxx:317
static void SetNumberFormatAttributes(SvXMLExport &rXMLExport, const sal_Int32 nNumberFormat, const double &rValue, bool bExportValue=true)
Definition: numehelp.cxx:275
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:391
sal_Int16 nType
Definition: numehelp.hxx:40
constexpr OUStringLiteral gsCurrencyAbbreviation(u"CurrencyAbbreviation")
sal_Int16 GetCellType(const sal_Int32 nNumberFormat, OUString &sCurrency, bool &bIsStandard)
Definition: numehelp.cxx:73
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Definition: xmltoken.cxx:3405
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:96
constexpr OUStringLiteral gsCurrencySymbol(u"CurrencySymbol")
constexpr OUStringLiteral gsStandardFormat(u"StandardFormat")