1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include "precompiled_svtools.hxx" 25 26 #include "cellvalueconversion.hxx" 27 28 /** === begin UNO includes === **/ 29 #include <com/sun/star/util/XNumberFormatter.hpp> 30 #include <com/sun/star/util/XNumberFormatsSupplier.hpp> 31 #include <com/sun/star/beans/XPropertySet.hpp> 32 #include <com/sun/star/util/Date.hpp> 33 #include <com/sun/star/util/DateTime.hpp> 34 #include <com/sun/star/util/Time.hpp> 35 #include <com/sun/star/util/XNumberFormatTypes.hpp> 36 #include <com/sun/star/util/NumberFormat.hpp> 37 /** === end UNO includes === **/ 38 39 #include <comphelper/componentcontext.hxx> 40 #include <rtl/math.hxx> 41 #include <rtl/strbuf.hxx> 42 #include <tools/date.hxx> 43 #include <tools/time.hxx> 44 #include <tools/diagnose_ex.h> 45 #include <unotools/syslocale.hxx> 46 47 #include <boost/shared_ptr.hpp> 48 #include <hash_map> 49 50 //...................................................................................................................... 51 namespace svt 52 { 53 //...................................................................................................................... 54 55 /** === begin UNO using === **/ 56 using ::com::sun::star::uno::Any; 57 using ::com::sun::star::util::XNumberFormatter; 58 using ::com::sun::star::uno::UNO_QUERY_THROW; 59 using ::com::sun::star::util::XNumberFormatsSupplier; 60 using ::com::sun::star::beans::XPropertySet; 61 using ::com::sun::star::uno::UNO_SET_THROW; 62 using ::com::sun::star::uno::Exception; 63 using ::com::sun::star::util::DateTime; 64 using ::com::sun::star::uno::TypeClass; 65 using ::com::sun::star::util::XNumberFormatTypes; 66 using ::com::sun::star::uno::Reference; 67 using ::com::sun::star::uno::Sequence; 68 using ::com::sun::star::uno::makeAny; 69 using ::com::sun::star::uno::Type; 70 using ::com::sun::star::uno::TypeClass_BYTE; 71 using ::com::sun::star::uno::TypeClass_SHORT; 72 using ::com::sun::star::uno::TypeClass_UNSIGNED_SHORT; 73 using ::com::sun::star::uno::TypeClass_LONG; 74 using ::com::sun::star::uno::TypeClass_UNSIGNED_LONG; 75 using ::com::sun::star::uno::TypeClass_HYPER; 76 /** === end UNO using === **/ 77 namespace NumberFormat = ::com::sun::star::util::NumberFormat; 78 79 typedef ::com::sun::star::util::Time UnoTime; 80 typedef ::com::sun::star::util::Date UnoDate; 81 82 //================================================================================================================== 83 //= helper 84 //================================================================================================================== 85 namespace 86 { 87 //-------------------------------------------------------------------------------------------------------------- lcl_convertDateToDays(long const i_day,long const i_month,long const i_year)88 double lcl_convertDateToDays( long const i_day, long const i_month, long const i_year ) 89 { 90 long const nNullDateDays = ::Date::DateToDays( 1, 1, 1900 ); 91 long const nValueDateDays = ::Date::DateToDays( i_day, i_month, i_year ); 92 93 return nValueDateDays - nNullDateDays; 94 } 95 96 //-------------------------------------------------------------------------------------------------------------- lcl_convertTimeToDays(long const i_hours,long const i_minutes,long const i_seconds,long const i_100thSeconds)97 double lcl_convertTimeToDays( long const i_hours, long const i_minutes, long const i_seconds, long const i_100thSeconds ) 98 { 99 return Time( i_hours, i_minutes, i_seconds, i_100thSeconds ).GetTimeInDays(); 100 } 101 } 102 103 //================================================================================================================== 104 //= IValueNormalization 105 //================================================================================================================== 106 class SAL_NO_VTABLE IValueNormalization 107 { 108 public: ~IValueNormalization()109 virtual ~IValueNormalization() { } 110 111 /** converts the given <code>Any</code> into a <code>double</code> value to be fed into a number formatter 112 */ 113 virtual double convertToDouble( Any const & i_value ) const = 0; 114 115 /** returns the format key to be used for formatting values 116 */ 117 virtual ::sal_Int32 getFormatKey() const = 0; 118 }; 119 120 typedef ::boost::shared_ptr< IValueNormalization > PValueNormalization; 121 typedef ::std::hash_map< ::rtl::OUString, PValueNormalization, ::rtl::OUStringHash > NormalizerCache; 122 123 //================================================================================================================== 124 //= CellValueConversion_Data 125 //================================================================================================================== 126 struct CellValueConversion_Data 127 { 128 ::comphelper::ComponentContext const aContext; 129 Reference< XNumberFormatter > xNumberFormatter; 130 bool bAttemptedFormatterCreation; 131 NormalizerCache aNormalizers; 132 CellValueConversion_Datasvt::CellValueConversion_Data133 CellValueConversion_Data( ::comphelper::ComponentContext const & i_context ) 134 :aContext( i_context ) 135 ,xNumberFormatter() 136 ,bAttemptedFormatterCreation( false ) 137 ,aNormalizers() 138 { 139 } 140 }; 141 142 //================================================================================================================== 143 //= StandardFormatNormalizer 144 //================================================================================================================== 145 class StandardFormatNormalizer : public IValueNormalization 146 { 147 protected: StandardFormatNormalizer(Reference<XNumberFormatter> const & i_formatter,::sal_Int32 const i_numberFormatType)148 StandardFormatNormalizer( Reference< XNumberFormatter > const & i_formatter, ::sal_Int32 const i_numberFormatType ) 149 :m_nFormatKey( 0 ) 150 { 151 try 152 { 153 ENSURE_OR_THROW( i_formatter.is(), "StandardFormatNormalizer: no formatter!" ); 154 Reference< XNumberFormatsSupplier > const xSupplier( i_formatter->getNumberFormatsSupplier(), UNO_SET_THROW ); 155 Reference< XNumberFormatTypes > const xTypes( xSupplier->getNumberFormats(), UNO_QUERY_THROW ); 156 m_nFormatKey = xTypes->getStandardFormat( i_numberFormatType, SvtSysLocale().GetLocale() ); 157 } 158 catch( const Exception& ) 159 { 160 DBG_UNHANDLED_EXCEPTION(); 161 } 162 } 163 getFormatKey() const164 virtual ::sal_Int32 getFormatKey() const 165 { 166 return m_nFormatKey; 167 } 168 169 private: 170 ::sal_Int32 m_nFormatKey; 171 }; 172 173 //================================================================================================================== 174 //= DoubleNormalization 175 //================================================================================================================== 176 class DoubleNormalization : public StandardFormatNormalizer 177 { 178 public: DoubleNormalization(Reference<XNumberFormatter> const & i_formatter)179 DoubleNormalization( Reference< XNumberFormatter > const & i_formatter ) 180 :StandardFormatNormalizer( i_formatter, NumberFormat::NUMBER ) 181 { 182 } 183 convertToDouble(Any const & i_value) const184 virtual double convertToDouble( Any const & i_value ) const 185 { 186 double returnValue(0); 187 ::rtl::math::setNan( &returnValue ); 188 OSL_VERIFY( i_value >>= returnValue ); 189 return returnValue; 190 } 191 ~DoubleNormalization()192 virtual ~DoubleNormalization() { } 193 }; 194 195 //================================================================================================================== 196 //= IntegerNormalization 197 //================================================================================================================== 198 class IntegerNormalization : public StandardFormatNormalizer 199 { 200 public: IntegerNormalization(Reference<XNumberFormatter> const & i_formatter)201 IntegerNormalization( Reference< XNumberFormatter > const & i_formatter ) 202 :StandardFormatNormalizer( i_formatter, NumberFormat::NUMBER ) 203 { 204 } 205 ~IntegerNormalization()206 virtual ~IntegerNormalization() {} 207 convertToDouble(Any const & i_value) const208 virtual double convertToDouble( Any const & i_value ) const 209 { 210 sal_Int64 value( 0 ); 211 OSL_VERIFY( i_value >>= value ); 212 return value; 213 } 214 }; 215 216 //================================================================================================================== 217 //= BooleanNormalization 218 //================================================================================================================== 219 class BooleanNormalization : public StandardFormatNormalizer 220 { 221 public: BooleanNormalization(Reference<XNumberFormatter> const & i_formatter)222 BooleanNormalization( Reference< XNumberFormatter > const & i_formatter ) 223 :StandardFormatNormalizer( i_formatter, NumberFormat::LOGICAL ) 224 { 225 } 226 ~BooleanNormalization()227 virtual ~BooleanNormalization() {} 228 convertToDouble(Any const & i_value) const229 virtual double convertToDouble( Any const & i_value ) const 230 { 231 bool value( false ); 232 OSL_VERIFY( i_value >>= value ); 233 return value ? 1 : 0; 234 } 235 }; 236 237 //================================================================================================================== 238 //= DateTimeNormalization 239 //================================================================================================================== 240 class DateTimeNormalization : public StandardFormatNormalizer 241 { 242 public: DateTimeNormalization(Reference<XNumberFormatter> const & i_formatter)243 DateTimeNormalization( Reference< XNumberFormatter > const & i_formatter ) 244 :StandardFormatNormalizer( i_formatter, NumberFormat::DATETIME ) 245 { 246 } 247 ~DateTimeNormalization()248 virtual ~DateTimeNormalization() {} 249 convertToDouble(Any const & i_value) const250 virtual double convertToDouble( Any const & i_value ) const 251 { 252 double returnValue(0); 253 ::rtl::math::setNan( &returnValue ); 254 255 // extract actual UNO value 256 DateTime aDateTimeValue; 257 ENSURE_OR_RETURN( i_value >>= aDateTimeValue, "allowed for DateTime values only", returnValue ); 258 259 // date part 260 returnValue = lcl_convertDateToDays( aDateTimeValue.Day, aDateTimeValue.Month, aDateTimeValue.Year ); 261 262 // time part 263 returnValue += lcl_convertTimeToDays( 264 aDateTimeValue.Hours, aDateTimeValue.Minutes, aDateTimeValue.Seconds, aDateTimeValue.HundredthSeconds ); 265 266 // done 267 return returnValue; 268 } 269 }; 270 271 //================================================================================================================== 272 //= DateNormalization 273 //================================================================================================================== 274 class DateNormalization : public StandardFormatNormalizer 275 { 276 public: DateNormalization(Reference<XNumberFormatter> const & i_formatter)277 DateNormalization( Reference< XNumberFormatter > const & i_formatter ) 278 :StandardFormatNormalizer( i_formatter, NumberFormat::DATE ) 279 { 280 } 281 ~DateNormalization()282 virtual ~DateNormalization() {} 283 convertToDouble(Any const & i_value) const284 virtual double convertToDouble( Any const & i_value ) const 285 { 286 double returnValue(0); 287 ::rtl::math::setNan( &returnValue ); 288 289 // extract 290 UnoDate aDateValue; 291 ENSURE_OR_RETURN( i_value >>= aDateValue, "allowed for Date values only", returnValue ); 292 293 // convert 294 returnValue = lcl_convertDateToDays( aDateValue.Day, aDateValue.Month, aDateValue.Year ); 295 296 // done 297 return returnValue; 298 } 299 }; 300 301 //================================================================================================================== 302 //= TimeNormalization 303 //================================================================================================================== 304 class TimeNormalization : public StandardFormatNormalizer 305 { 306 public: TimeNormalization(Reference<XNumberFormatter> const & i_formatter)307 TimeNormalization( Reference< XNumberFormatter > const & i_formatter ) 308 :StandardFormatNormalizer( i_formatter, NumberFormat::TIME ) 309 { 310 } 311 ~TimeNormalization()312 virtual ~TimeNormalization() {} 313 convertToDouble(Any const & i_value) const314 virtual double convertToDouble( Any const & i_value ) const 315 { 316 double returnValue(0); 317 ::rtl::math::setNan( &returnValue ); 318 319 // extract 320 UnoTime aTimeValue; 321 ENSURE_OR_RETURN( i_value >>= aTimeValue, "allowed for Time values only", returnValue ); 322 323 // convert 324 returnValue += lcl_convertTimeToDays( 325 aTimeValue.Hours, aTimeValue.Minutes, aTimeValue.Seconds, aTimeValue.HundredthSeconds ); 326 327 // done 328 return returnValue; 329 } 330 }; 331 332 //================================================================================================================== 333 //= operations 334 //================================================================================================================== 335 namespace 336 { 337 //-------------------------------------------------------------------------------------------------------------- lcl_ensureNumberFormatter(CellValueConversion_Data & io_data)338 bool lcl_ensureNumberFormatter( CellValueConversion_Data & io_data ) 339 { 340 if ( io_data.bAttemptedFormatterCreation ) 341 return io_data.xNumberFormatter.is(); 342 io_data.bAttemptedFormatterCreation = true; 343 344 try 345 { 346 // a number formatter 347 Reference< XNumberFormatter > const xFormatter( 348 io_data.aContext.createComponent( "com.sun.star.util.NumberFormatter" ), UNO_QUERY_THROW ); 349 350 // a supplier of number formats 351 Sequence< Any > aInitArgs(1); 352 aInitArgs[0] <<= SvtSysLocale().GetLocale(); 353 354 Reference< XNumberFormatsSupplier > const xSupplier( 355 io_data.aContext.createComponentWithArguments( "com.sun.star.util.NumberFormatsSupplier", aInitArgs ), 356 UNO_QUERY_THROW 357 ); 358 359 // ensure a NullDate we will assume later on 360 UnoDate const aNullDate( 1, 1, 1900 ); 361 Reference< XPropertySet > const xFormatSettings( xSupplier->getNumberFormatSettings(), UNO_SET_THROW ); 362 xFormatSettings->setPropertyValue( ::rtl::OUString::createFromAscii( "NullDate" ), makeAny( aNullDate ) ); 363 364 // knit 365 xFormatter->attachNumberFormatsSupplier( xSupplier ); 366 367 // done 368 io_data.xNumberFormatter = xFormatter; 369 } 370 catch( const Exception& ) 371 { 372 DBG_UNHANDLED_EXCEPTION(); 373 } 374 375 return io_data.xNumberFormatter.is(); 376 } 377 378 //-------------------------------------------------------------------------------------------------------------- lcl_getValueNormalizer(CellValueConversion_Data & io_data,Type const & i_valueType,PValueNormalization & o_formatter)379 bool lcl_getValueNormalizer( CellValueConversion_Data & io_data, Type const & i_valueType, 380 PValueNormalization & o_formatter ) 381 { 382 NormalizerCache::const_iterator pos = io_data.aNormalizers.find( i_valueType.getTypeName() ); 383 if ( pos == io_data.aNormalizers.end() ) 384 { 385 // never encountered this type before 386 o_formatter.reset(); 387 388 ::rtl::OUString const sTypeName( i_valueType.getTypeName() ); 389 TypeClass const eTypeClass = i_valueType.getTypeClass(); 390 391 if ( sTypeName.equals( ::cppu::UnoType< DateTime >::get().getTypeName() ) ) 392 { 393 o_formatter.reset( new DateTimeNormalization( io_data.xNumberFormatter ) ); 394 } 395 else if ( sTypeName.equals( ::cppu::UnoType< UnoDate >::get().getTypeName() ) ) 396 { 397 o_formatter.reset( new DateNormalization( io_data.xNumberFormatter ) ); 398 } 399 else if ( sTypeName.equals( ::cppu::UnoType< UnoTime >::get().getTypeName() ) ) 400 { 401 o_formatter.reset( new TimeNormalization( io_data.xNumberFormatter ) ); 402 } 403 else if ( sTypeName.equals( ::cppu::UnoType< ::sal_Bool >::get().getTypeName() ) ) 404 { 405 o_formatter.reset( new BooleanNormalization( io_data.xNumberFormatter ) ); 406 } 407 else if ( sTypeName.equals( ::cppu::UnoType< double >::get().getTypeName() ) 408 || sTypeName.equals( ::cppu::UnoType< float >::get().getTypeName() ) 409 ) 410 { 411 o_formatter.reset( new DoubleNormalization( io_data.xNumberFormatter ) ); 412 } 413 else if ( ( eTypeClass == TypeClass_BYTE ) 414 || ( eTypeClass == TypeClass_SHORT ) 415 || ( eTypeClass == TypeClass_UNSIGNED_SHORT ) 416 || ( eTypeClass == TypeClass_LONG ) 417 || ( eTypeClass == TypeClass_UNSIGNED_LONG ) 418 || ( eTypeClass == TypeClass_HYPER ) 419 ) 420 { 421 o_formatter.reset( new IntegerNormalization( io_data.xNumberFormatter ) ); 422 } 423 else 424 { 425 #if OSL_DEBUG_LEVEL > 0 426 ::rtl::OStringBuffer message( "lcl_getValueNormalizer: unsupported type '" ); 427 message.append( ::rtl::OUStringToOString( sTypeName, RTL_TEXTENCODING_ASCII_US ) ); 428 message.append( "'!" ); 429 OSL_ENSURE( false, message.getStr() ); 430 #endif 431 } 432 io_data.aNormalizers[ sTypeName ] = o_formatter; 433 } 434 else 435 o_formatter = pos->second; 436 437 return !!o_formatter; 438 } 439 } 440 441 //================================================================================================================== 442 //= CellValueConversion 443 //================================================================================================================== 444 //------------------------------------------------------------------------------------------------------------------ CellValueConversion(::comphelper::ComponentContext const & i_context)445 CellValueConversion::CellValueConversion( ::comphelper::ComponentContext const & i_context ) 446 :m_pData( new CellValueConversion_Data( i_context ) ) 447 { 448 } 449 450 //------------------------------------------------------------------------------------------------------------------ ~CellValueConversion()451 CellValueConversion::~CellValueConversion() 452 { 453 } 454 455 //------------------------------------------------------------------------------------------------------------------ convertToString(const Any & i_value)456 ::rtl::OUString CellValueConversion::convertToString( const Any& i_value ) 457 { 458 ::rtl::OUString sStringValue; 459 if ( !i_value.hasValue() ) 460 return sStringValue; 461 462 if ( ! ( i_value >>= sStringValue ) ) 463 { 464 if ( lcl_ensureNumberFormatter( *m_pData ) ) 465 { 466 PValueNormalization pNormalizer; 467 if ( lcl_getValueNormalizer( *m_pData, i_value.getValueType(), pNormalizer ) ) 468 { 469 try 470 { 471 double const formatterCompliantValue = pNormalizer->convertToDouble( i_value ); 472 sal_Int32 const formatKey = pNormalizer->getFormatKey(); 473 sStringValue = m_pData->xNumberFormatter->convertNumberToString( 474 formatKey, formatterCompliantValue ); 475 } 476 catch( const Exception& ) 477 { 478 DBG_UNHANDLED_EXCEPTION(); 479 } 480 } 481 } 482 } 483 484 return sStringValue; 485 } 486 487 //...................................................................................................................... 488 } // namespace svt 489 //...................................................................................................................... 490