1*e1f63238SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*e1f63238SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*e1f63238SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*e1f63238SAndrew Rist * distributed with this work for additional information 6*e1f63238SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*e1f63238SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*e1f63238SAndrew Rist * "License"); you may not use this file except in compliance 9*e1f63238SAndrew Rist * with the License. You may obtain a copy of the License at 10*e1f63238SAndrew Rist * 11*e1f63238SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*e1f63238SAndrew Rist * 13*e1f63238SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*e1f63238SAndrew Rist * software distributed under the License is distributed on an 15*e1f63238SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*e1f63238SAndrew Rist * KIND, either express or implied. See the License for the 17*e1f63238SAndrew Rist * specific language governing permissions and limitations 18*e1f63238SAndrew Rist * under the License. 19*e1f63238SAndrew Rist * 20*e1f63238SAndrew Rist *************************************************************/ 21*e1f63238SAndrew Rist 22*e1f63238SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_basic.hxx" 26cdf0e10cSrcweir #include <tools/errcode.hxx> 27cdf0e10cSrcweir #include <basic/sbx.hxx> 28cdf0e10cSrcweir #include "sbxconv.hxx" 29cdf0e10cSrcweir 30cdf0e10cSrcweir #include "unotools/syslocale.hxx" 31cdf0e10cSrcweir 32cdf0e10cSrcweir #if defined ( UNX ) 33cdf0e10cSrcweir #include <stdlib.h> 34cdf0e10cSrcweir #endif 35cdf0e10cSrcweir 36cdf0e10cSrcweir #ifndef _APP_HXX //autogen 37cdf0e10cSrcweir #include <vcl/svapp.hxx> 38cdf0e10cSrcweir #endif 39cdf0e10cSrcweir #include <math.h> 40cdf0e10cSrcweir #include <string.h> 41cdf0e10cSrcweir #include <ctype.h> 42cdf0e10cSrcweir 43cdf0e10cSrcweir #include "sbxres.hxx" 44cdf0e10cSrcweir #include <basic/sbxbase.hxx> 45cdf0e10cSrcweir #include <basic/sbxform.hxx> 46cdf0e10cSrcweir #include <svtools/svtools.hrc> 47cdf0e10cSrcweir 48cdf0e10cSrcweir #include "basrid.hxx" 49cdf0e10cSrcweir #include "runtime.hxx" 50cdf0e10cSrcweir 51cdf0e10cSrcweir #include <svl/zforlist.hxx> 52cdf0e10cSrcweir #include <comphelper/processfactory.hxx> 53cdf0e10cSrcweir 54cdf0e10cSrcweir 55cdf0e10cSrcweir void ImpGetIntntlSep( sal_Unicode& rcDecimalSep, sal_Unicode& rcThousandSep ) 56cdf0e10cSrcweir { 57cdf0e10cSrcweir SvtSysLocale aSysLocale; 58cdf0e10cSrcweir const LocaleDataWrapper& rData = aSysLocale.GetLocaleData(); 59cdf0e10cSrcweir rcDecimalSep = rData.getNumDecimalSep().GetBuffer()[0]; 60cdf0e10cSrcweir rcThousandSep = rData.getNumThousandSep().GetBuffer()[0]; 61cdf0e10cSrcweir } 62cdf0e10cSrcweir 63cdf0e10cSrcweir // Scannen eines Strings nach BASIC-Konventionen 64cdf0e10cSrcweir // Dies entspricht den ueblichen Konventionen, nur dass der Exponent 65cdf0e10cSrcweir // auch ein D sein darf, was den Datentyp auf SbxDOUBLE festlegt. 66cdf0e10cSrcweir // Die Routine versucht, den Datentyp so klein wie moeglich zu gestalten. 67cdf0e10cSrcweir // Das ganze gibt auch noch einen Konversionsfehler, wenn der Datentyp 68cdf0e10cSrcweir // Fixed ist und das ganze nicht hineinpasst! 69cdf0e10cSrcweir 70cdf0e10cSrcweir SbxError ImpScan( const ::rtl::OUString& rWSrc, double& nVal, SbxDataType& rType, 71cdf0e10cSrcweir sal_uInt16* pLen, sal_Bool bAllowIntntl, sal_Bool bOnlyIntntl ) 72cdf0e10cSrcweir { 73cdf0e10cSrcweir ::rtl::OString aBStr( ::rtl::OUStringToOString( rWSrc, RTL_TEXTENCODING_ASCII_US ) ); 74cdf0e10cSrcweir 75cdf0e10cSrcweir // Bei International Komma besorgen 76cdf0e10cSrcweir char cIntntlComma, cIntntl1000; 77cdf0e10cSrcweir char cNonIntntlComma = '.'; 78cdf0e10cSrcweir 79cdf0e10cSrcweir sal_Unicode cDecimalSep, cThousandSep = 0; 80cdf0e10cSrcweir if( bAllowIntntl || bOnlyIntntl ) 81cdf0e10cSrcweir { 82cdf0e10cSrcweir ImpGetIntntlSep( cDecimalSep, cThousandSep ); 83cdf0e10cSrcweir cIntntlComma = (char)cDecimalSep; 84cdf0e10cSrcweir cIntntl1000 = (char)cThousandSep; 85cdf0e10cSrcweir } 86cdf0e10cSrcweir // Sonst einfach auch auf . setzen 87cdf0e10cSrcweir else 88cdf0e10cSrcweir { 89cdf0e10cSrcweir cIntntlComma = cNonIntntlComma; 90cdf0e10cSrcweir cIntntl1000 = cNonIntntlComma; // Unschaedlich machen 91cdf0e10cSrcweir } 92cdf0e10cSrcweir // Nur International -> IntnlComma uebernehmen 93cdf0e10cSrcweir if( bOnlyIntntl ) 94cdf0e10cSrcweir { 95cdf0e10cSrcweir cNonIntntlComma = cIntntlComma; 96cdf0e10cSrcweir cIntntl1000 = (char)cThousandSep; 97cdf0e10cSrcweir } 98cdf0e10cSrcweir 99cdf0e10cSrcweir const char* pStart = aBStr.getStr(); 100cdf0e10cSrcweir const char* p = pStart; 101cdf0e10cSrcweir char buf[ 80 ], *q = buf; 102cdf0e10cSrcweir sal_Bool bRes = sal_True; 103cdf0e10cSrcweir sal_Bool bMinus = sal_False; 104cdf0e10cSrcweir nVal = 0; 105cdf0e10cSrcweir SbxDataType eScanType = SbxSINGLE; 106cdf0e10cSrcweir // Whitespace wech 107cdf0e10cSrcweir while( *p &&( *p == ' ' || *p == '\t' ) ) p++; 108cdf0e10cSrcweir // Zahl? Dann einlesen und konvertieren. 109cdf0e10cSrcweir if( *p == '-' ) 110cdf0e10cSrcweir p++, bMinus = sal_True; 111cdf0e10cSrcweir if( isdigit( *p ) ||( (*p == cNonIntntlComma || *p == cIntntlComma || 112cdf0e10cSrcweir *p == cIntntl1000) && isdigit( *(p+1 ) ) ) ) 113cdf0e10cSrcweir { 114cdf0e10cSrcweir short exp = 0; // >0: Exponentteil 115cdf0e10cSrcweir short comma = 0; // >0: Nachkomma 116cdf0e10cSrcweir short ndig = 0; // Anzahl Ziffern 117cdf0e10cSrcweir short ncdig = 0; // Anzahl Ziffern nach Komma 118cdf0e10cSrcweir ByteString aSearchStr( "0123456789DEde" ); 119cdf0e10cSrcweir // Kommas ergaenzen 120cdf0e10cSrcweir aSearchStr += cNonIntntlComma; 121cdf0e10cSrcweir if( cIntntlComma != cNonIntntlComma ) 122cdf0e10cSrcweir aSearchStr += cIntntlComma; 123cdf0e10cSrcweir if( bOnlyIntntl ) 124cdf0e10cSrcweir aSearchStr += cIntntl1000; 125cdf0e10cSrcweir const char* pSearchStr = aSearchStr.GetBuffer(); 126cdf0e10cSrcweir while( strchr( pSearchStr, *p ) && *p ) 127cdf0e10cSrcweir { 128cdf0e10cSrcweir // 1000er-Trenner ueberlesen 129cdf0e10cSrcweir if( bOnlyIntntl && *p == cIntntl1000 ) 130cdf0e10cSrcweir { 131cdf0e10cSrcweir p++; 132cdf0e10cSrcweir continue; 133cdf0e10cSrcweir } 134cdf0e10cSrcweir 135cdf0e10cSrcweir // Komma oder Exponent? 136cdf0e10cSrcweir if( *p == cNonIntntlComma || *p == cIntntlComma ) 137cdf0e10cSrcweir { 138cdf0e10cSrcweir // Immer '.' einfuegen, damit atof funktioniert 139cdf0e10cSrcweir p++; 140cdf0e10cSrcweir if( ++comma > 1 ) 141cdf0e10cSrcweir continue; 142cdf0e10cSrcweir else 143cdf0e10cSrcweir *q++ = '.'; 144cdf0e10cSrcweir } 145cdf0e10cSrcweir else if( strchr( "DdEe", *p ) ) 146cdf0e10cSrcweir { 147cdf0e10cSrcweir if( ++exp > 1 ) 148cdf0e10cSrcweir { 149cdf0e10cSrcweir p++; continue; 150cdf0e10cSrcweir } 151cdf0e10cSrcweir if( toupper( *p ) == 'D' ) 152cdf0e10cSrcweir eScanType = SbxDOUBLE; 153cdf0e10cSrcweir *q++ = 'E'; p++; 154cdf0e10cSrcweir // Vorzeichen hinter Exponent? 155cdf0e10cSrcweir if( *p == '+' ) 156cdf0e10cSrcweir p++; 157cdf0e10cSrcweir else 158cdf0e10cSrcweir if( *p == '-' ) 159cdf0e10cSrcweir *q++ = *p++; 160cdf0e10cSrcweir } 161cdf0e10cSrcweir else 162cdf0e10cSrcweir { 163cdf0e10cSrcweir *q++ = *p++; 164cdf0e10cSrcweir if( comma && !exp ) ncdig++; 165cdf0e10cSrcweir } 166cdf0e10cSrcweir if( !exp ) ndig++; 167cdf0e10cSrcweir } 168cdf0e10cSrcweir *q = 0; 169cdf0e10cSrcweir // Komma, Exponent mehrfach vorhanden? 170cdf0e10cSrcweir if( comma > 1 || exp > 1 ) 171cdf0e10cSrcweir bRes = sal_False; 172cdf0e10cSrcweir // Kann auf Integer gefaltet werden? 173cdf0e10cSrcweir if( !comma && !exp ) 174cdf0e10cSrcweir { 175cdf0e10cSrcweir if( nVal >= SbxMININT && nVal <= SbxMAXINT ) 176cdf0e10cSrcweir eScanType = SbxINTEGER; 177cdf0e10cSrcweir else if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG ) 178cdf0e10cSrcweir eScanType = SbxLONG; 179cdf0e10cSrcweir } 180cdf0e10cSrcweir 181cdf0e10cSrcweir nVal = atof( buf ); 182cdf0e10cSrcweir ndig = ndig - comma; 183cdf0e10cSrcweir // zu viele Zahlen fuer SINGLE? 184cdf0e10cSrcweir if( ndig > 15 || ncdig > 6 ) 185cdf0e10cSrcweir eScanType = SbxDOUBLE; 186cdf0e10cSrcweir 187cdf0e10cSrcweir // Typkennung? 188cdf0e10cSrcweir if( strchr( "%!&#", *p ) && *p ) p++; 189cdf0e10cSrcweir } 190cdf0e10cSrcweir // Hex/Oktalzahl? Einlesen und konvertieren: 191cdf0e10cSrcweir else if( *p == '&' ) 192cdf0e10cSrcweir { 193cdf0e10cSrcweir p++; 194cdf0e10cSrcweir eScanType = SbxLONG; 195cdf0e10cSrcweir const char *cmp = "0123456789ABCDEF"; 196cdf0e10cSrcweir char base = 16; 197cdf0e10cSrcweir char ndig = 8; 198cdf0e10cSrcweir char xch = *p++; 199cdf0e10cSrcweir switch( toupper( xch ) ) 200cdf0e10cSrcweir { 201cdf0e10cSrcweir case 'O': cmp = "01234567"; base = 8; ndig = 11; break; 202cdf0e10cSrcweir case 'H': break; 203cdf0e10cSrcweir default : bRes = sal_False; 204cdf0e10cSrcweir } 205cdf0e10cSrcweir long l = 0; 206cdf0e10cSrcweir int i; 207cdf0e10cSrcweir while( isalnum( *p ) ) 208cdf0e10cSrcweir { 209cdf0e10cSrcweir char ch = sal::static_int_cast< char >( toupper( *p ) ); 210cdf0e10cSrcweir p++; 211cdf0e10cSrcweir if( strchr( cmp, ch ) ) *q++ = ch; 212cdf0e10cSrcweir else bRes = sal_False; 213cdf0e10cSrcweir } 214cdf0e10cSrcweir *q = 0; 215cdf0e10cSrcweir for( q = buf; *q; q++ ) 216cdf0e10cSrcweir { 217cdf0e10cSrcweir i =( *q & 0xFF ) - '0'; 218cdf0e10cSrcweir if( i > 9 ) i -= 7; 219cdf0e10cSrcweir l =( l * base ) + i; 220cdf0e10cSrcweir if( !ndig-- ) 221cdf0e10cSrcweir bRes = sal_False; 222cdf0e10cSrcweir } 223cdf0e10cSrcweir if( *p == '&' ) p++; 224cdf0e10cSrcweir nVal = (double) l; 225cdf0e10cSrcweir if( l >= SbxMININT && l <= SbxMAXINT ) 226cdf0e10cSrcweir eScanType = SbxINTEGER; 227cdf0e10cSrcweir } 228cdf0e10cSrcweir else if ( SbiRuntime::isVBAEnabled() ) 229cdf0e10cSrcweir { 230cdf0e10cSrcweir OSL_TRACE("Reporting error converting"); 231cdf0e10cSrcweir return SbxERR_CONVERSION; 232cdf0e10cSrcweir } 233cdf0e10cSrcweir if( pLen ) 234cdf0e10cSrcweir *pLen = (sal_uInt16) ( p - pStart ); 235cdf0e10cSrcweir if( !bRes ) 236cdf0e10cSrcweir return SbxERR_CONVERSION; 237cdf0e10cSrcweir if( bMinus ) 238cdf0e10cSrcweir nVal = -nVal; 239cdf0e10cSrcweir rType = eScanType; 240cdf0e10cSrcweir return SbxERR_OK; 241cdf0e10cSrcweir } 242cdf0e10cSrcweir 243cdf0e10cSrcweir // Schnittstelle fuer CDbl im Basic 244cdf0e10cSrcweir SbxError SbxValue::ScanNumIntnl( const String& rSrc, double& nVal, sal_Bool bSingle ) 245cdf0e10cSrcweir { 246cdf0e10cSrcweir SbxDataType t; 247cdf0e10cSrcweir sal_uInt16 nLen = 0; 248cdf0e10cSrcweir SbxError nRetError = ImpScan( rSrc, nVal, t, &nLen, 249cdf0e10cSrcweir /*bAllowIntntl*/sal_False, /*bOnlyIntntl*/sal_True ); 250cdf0e10cSrcweir // Komplett gelesen? 251cdf0e10cSrcweir if( nRetError == SbxERR_OK && nLen != rSrc.Len() ) 252cdf0e10cSrcweir nRetError = SbxERR_CONVERSION; 253cdf0e10cSrcweir 254cdf0e10cSrcweir if( bSingle ) 255cdf0e10cSrcweir { 256cdf0e10cSrcweir SbxValues aValues( nVal ); 257cdf0e10cSrcweir nVal = (double)ImpGetSingle( &aValues ); // Hier Error bei Overflow 258cdf0e10cSrcweir } 259cdf0e10cSrcweir return nRetError; 260cdf0e10cSrcweir } 261cdf0e10cSrcweir 262cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////// 263cdf0e10cSrcweir 264cdf0e10cSrcweir static double roundArray[] = { 265cdf0e10cSrcweir 5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6, 0.5e-7, 266cdf0e10cSrcweir 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14,0.5e-15 }; 267cdf0e10cSrcweir 268cdf0e10cSrcweir /*************************************************************************** 269cdf0e10cSrcweir |* 270cdf0e10cSrcweir |* void myftoa( double, char *, short, short, sal_Bool, sal_Bool ) 271cdf0e10cSrcweir |* 272cdf0e10cSrcweir |* Beschreibung: Konversion double --> ASCII 273cdf0e10cSrcweir |* Parameter: double die Zahl. 274cdf0e10cSrcweir |* char * der Zielpuffer 275cdf0e10cSrcweir |* short Anzahl Nachkommastellen 276cdf0e10cSrcweir |* short Weite des Exponenten( 0=kein E ) 277cdf0e10cSrcweir |* sal_Bool sal_True: mit 1000er Punkten 278cdf0e10cSrcweir |* sal_Bool sal_True: formatfreie Ausgabe 279cdf0e10cSrcweir |* 280cdf0e10cSrcweir ***************************************************************************/ 281cdf0e10cSrcweir 282cdf0e10cSrcweir static void myftoa( double nNum, char * pBuf, short nPrec, short nExpWidth, 283cdf0e10cSrcweir sal_Bool bPt, sal_Bool bFix, sal_Unicode cForceThousandSep = 0 ) 284cdf0e10cSrcweir { 285cdf0e10cSrcweir 286cdf0e10cSrcweir short nExp = 0; // Exponent 287cdf0e10cSrcweir short nDig = nPrec + 1; // Anzahl Digits in Zahl 288cdf0e10cSrcweir short nDec; // Anzahl Vorkommastellen 289cdf0e10cSrcweir register int i, digit; 290cdf0e10cSrcweir 291cdf0e10cSrcweir // Komma besorgen 292cdf0e10cSrcweir sal_Unicode cDecimalSep, cThousandSep; 293cdf0e10cSrcweir ImpGetIntntlSep( cDecimalSep, cThousandSep ); 294cdf0e10cSrcweir if( cForceThousandSep ) 295cdf0e10cSrcweir cThousandSep = cForceThousandSep; 296cdf0e10cSrcweir 297cdf0e10cSrcweir // Exponentberechnung: 298cdf0e10cSrcweir nExp = 0; 299cdf0e10cSrcweir if( nNum > 0.0 ) 300cdf0e10cSrcweir { 301cdf0e10cSrcweir while( nNum < 1.0 ) nNum *= 10.0, nExp--; 302cdf0e10cSrcweir while( nNum >= 10.0 ) nNum /= 10.0, nExp++; 303cdf0e10cSrcweir } 304cdf0e10cSrcweir if( !bFix && !nExpWidth ) 305cdf0e10cSrcweir nDig = nDig + nExp; 306cdf0e10cSrcweir else if( bFix && !nPrec ) 307cdf0e10cSrcweir nDig = nExp + 1; 308cdf0e10cSrcweir 309cdf0e10cSrcweir // Zahl runden: 310cdf0e10cSrcweir if( (nNum += roundArray [( nDig > 16 ) ? 16 : nDig] ) >= 10.0 ) 311cdf0e10cSrcweir { 312cdf0e10cSrcweir nNum = 1.0; 313cdf0e10cSrcweir ++nExp; 314cdf0e10cSrcweir if( !nExpWidth ) ++nDig; 315cdf0e10cSrcweir } 316cdf0e10cSrcweir 317cdf0e10cSrcweir // Bestimmung der Vorkommastellen: 318cdf0e10cSrcweir if( !nExpWidth ) 319cdf0e10cSrcweir { 320cdf0e10cSrcweir if( nExp < 0 ) 321cdf0e10cSrcweir { 322cdf0e10cSrcweir // #41691: Auch bei bFix eine 0 spendieren 323cdf0e10cSrcweir *pBuf++ = '0'; 324cdf0e10cSrcweir if( nPrec ) *pBuf++ = (char)cDecimalSep; 325cdf0e10cSrcweir i = -nExp - 1; 326cdf0e10cSrcweir if( nDig <= 0 ) i = nPrec; 327cdf0e10cSrcweir while( i-- ) *pBuf++ = '0'; 328cdf0e10cSrcweir nDec = 0; 329cdf0e10cSrcweir } 330cdf0e10cSrcweir else 331cdf0e10cSrcweir nDec = nExp+1; 332cdf0e10cSrcweir } 333cdf0e10cSrcweir else 334cdf0e10cSrcweir nDec = 1; 335cdf0e10cSrcweir 336cdf0e10cSrcweir // Zahl ausgeben: 337cdf0e10cSrcweir if( nDig > 0 ) 338cdf0e10cSrcweir { 339cdf0e10cSrcweir for( i = 0 ; ; ++i ) 340cdf0e10cSrcweir { 341cdf0e10cSrcweir if( i < 16 ) 342cdf0e10cSrcweir { 343cdf0e10cSrcweir digit = (int) nNum; 344cdf0e10cSrcweir *pBuf++ = sal::static_int_cast< char >(digit + '0'); 345cdf0e10cSrcweir nNum =( nNum - digit ) * 10.0; 346cdf0e10cSrcweir } else 347cdf0e10cSrcweir *pBuf++ = '0'; 348cdf0e10cSrcweir if( --nDig == 0 ) break; 349cdf0e10cSrcweir if( nDec ) 350cdf0e10cSrcweir { 351cdf0e10cSrcweir nDec--; 352cdf0e10cSrcweir if( !nDec ) 353cdf0e10cSrcweir *pBuf++ = (char)cDecimalSep; 354cdf0e10cSrcweir else if( !(nDec % 3 ) && bPt ) 355cdf0e10cSrcweir *pBuf++ = (char)cThousandSep; 356cdf0e10cSrcweir } 357cdf0e10cSrcweir } 358cdf0e10cSrcweir } 359cdf0e10cSrcweir 360cdf0e10cSrcweir // Exponent ausgeben: 361cdf0e10cSrcweir if( nExpWidth ) 362cdf0e10cSrcweir { 363cdf0e10cSrcweir if( nExpWidth < 3 ) nExpWidth = 3; 364cdf0e10cSrcweir nExpWidth -= 2; 365cdf0e10cSrcweir *pBuf++ = 'E'; 366cdf0e10cSrcweir *pBuf++ =( nExp < 0 ) ?( (nExp = -nExp ), '-' ) : '+'; 367cdf0e10cSrcweir while( nExpWidth > 3 ) *pBuf++ = '0', nExpWidth--; 368cdf0e10cSrcweir if( nExp >= 100 || nExpWidth == 3 ) 369cdf0e10cSrcweir { 370cdf0e10cSrcweir *pBuf++ = sal::static_int_cast< char >(nExp/100 + '0'); 371cdf0e10cSrcweir nExp %= 100; 372cdf0e10cSrcweir } 373cdf0e10cSrcweir if( nExp/10 || nExpWidth >= 2 ) 374cdf0e10cSrcweir *pBuf++ = sal::static_int_cast< char >(nExp/10 + '0'); 375cdf0e10cSrcweir *pBuf++ = sal::static_int_cast< char >(nExp%10 + '0'); 376cdf0e10cSrcweir } 377cdf0e10cSrcweir *pBuf = 0; 378cdf0e10cSrcweir } 379cdf0e10cSrcweir 380cdf0e10cSrcweir // Die Zahl wird unformatiert mit der angegebenen Anzahl NK-Stellen 381cdf0e10cSrcweir // aufbereitet. Evtl. wird ein Minus vorangestellt. 382cdf0e10cSrcweir // Diese Routine ist public, weil sie auch von den Put-Funktionen 383cdf0e10cSrcweir // der Klasse SbxImpSTRING verwendet wird. 384cdf0e10cSrcweir 385cdf0e10cSrcweir #ifdef _MSC_VER 386cdf0e10cSrcweir #pragma optimize( "", off ) 387cdf0e10cSrcweir #pragma warning(disable: 4748) // "... because optimizations are disabled ..." 388cdf0e10cSrcweir #endif 389cdf0e10cSrcweir 390cdf0e10cSrcweir void ImpCvtNum( double nNum, short nPrec, ::rtl::OUString& rRes, sal_Bool bCoreString ) 391cdf0e10cSrcweir { 392cdf0e10cSrcweir char *q; 393cdf0e10cSrcweir char cBuf[ 40 ], *p = cBuf; 394cdf0e10cSrcweir 395cdf0e10cSrcweir sal_Unicode cDecimalSep, cThousandSep; 396cdf0e10cSrcweir ImpGetIntntlSep( cDecimalSep, cThousandSep ); 397cdf0e10cSrcweir if( bCoreString ) 398cdf0e10cSrcweir cDecimalSep = '.'; 399cdf0e10cSrcweir 400cdf0e10cSrcweir if( nNum < 0.0 ) { 401cdf0e10cSrcweir nNum = -nNum; 402cdf0e10cSrcweir *p++ = '-'; 403cdf0e10cSrcweir } 404cdf0e10cSrcweir double dMaxNumWithoutExp = (nPrec == 6) ? 1E6 : 1E14; 405cdf0e10cSrcweir myftoa( nNum, p, nPrec,( nNum &&( nNum < 1E-1 || nNum > dMaxNumWithoutExp ) ) ? 4:0, 406cdf0e10cSrcweir sal_False, sal_True, cDecimalSep ); 407cdf0e10cSrcweir // Trailing Zeroes weg: 408cdf0e10cSrcweir for( p = cBuf; *p &&( *p != 'E' ); p++ ) {} 409cdf0e10cSrcweir q = p; p--; 410cdf0e10cSrcweir while( nPrec && *p == '0' ) nPrec--, p--; 411cdf0e10cSrcweir if( *p == cDecimalSep ) p--; 412cdf0e10cSrcweir while( *q ) *++p = *q++; 413cdf0e10cSrcweir *++p = 0; 414cdf0e10cSrcweir rRes = ::rtl::OUString::createFromAscii( cBuf ); 415cdf0e10cSrcweir } 416cdf0e10cSrcweir 417cdf0e10cSrcweir #ifdef _MSC_VER 418cdf0e10cSrcweir #pragma optimize( "", on ) 419cdf0e10cSrcweir #endif 420cdf0e10cSrcweir 421cdf0e10cSrcweir sal_Bool ImpConvStringExt( ::rtl::OUString& rSrc, SbxDataType eTargetType ) 422cdf0e10cSrcweir { 423cdf0e10cSrcweir // Merken, ob ueberhaupt was geaendert wurde 424cdf0e10cSrcweir sal_Bool bChanged = sal_False; 425cdf0e10cSrcweir ::rtl::OUString aNewString; 426cdf0e10cSrcweir 427cdf0e10cSrcweir // Nur Spezial-F�lle behandeln, als Default tun wir nichts 428cdf0e10cSrcweir switch( eTargetType ) 429cdf0e10cSrcweir { 430cdf0e10cSrcweir // Bei Fliesskomma International beruecksichtigen 431cdf0e10cSrcweir case SbxSINGLE: 432cdf0e10cSrcweir case SbxDOUBLE: 433cdf0e10cSrcweir case SbxCURRENCY: 434cdf0e10cSrcweir { 435cdf0e10cSrcweir ::rtl::OString aBStr( ::rtl::OUStringToOString( rSrc, RTL_TEXTENCODING_ASCII_US ) ); 436cdf0e10cSrcweir 437cdf0e10cSrcweir // Komma besorgen 438cdf0e10cSrcweir sal_Unicode cDecimalSep, cThousandSep; 439cdf0e10cSrcweir ImpGetIntntlSep( cDecimalSep, cThousandSep ); 440cdf0e10cSrcweir aNewString = rSrc; 441cdf0e10cSrcweir 442cdf0e10cSrcweir // Ersetzen, wenn DecimalSep kein '.' (nur den ersten) 443cdf0e10cSrcweir if( cDecimalSep != (sal_Unicode)'.' ) 444cdf0e10cSrcweir { 445cdf0e10cSrcweir sal_Int32 nPos = aNewString.indexOf( cDecimalSep ); 446cdf0e10cSrcweir if( nPos != -1 ) 447cdf0e10cSrcweir { 448cdf0e10cSrcweir sal_Unicode* pStr = (sal_Unicode*)aNewString.getStr(); 449cdf0e10cSrcweir pStr[nPos] = (sal_Unicode)'.'; 450cdf0e10cSrcweir bChanged = sal_True; 451cdf0e10cSrcweir } 452cdf0e10cSrcweir } 453cdf0e10cSrcweir break; 454cdf0e10cSrcweir } 455cdf0e10cSrcweir 456cdf0e10cSrcweir // Bei sal_Bool sal_True und sal_False als String pruefen 457cdf0e10cSrcweir case SbxBOOL: 458cdf0e10cSrcweir { 459cdf0e10cSrcweir if( rSrc.equalsIgnoreAsciiCaseAscii( "true" ) ) 460cdf0e10cSrcweir { 461cdf0e10cSrcweir aNewString = ::rtl::OUString::valueOf( (sal_Int32)SbxTRUE ); 462cdf0e10cSrcweir bChanged = sal_True; 463cdf0e10cSrcweir } 464cdf0e10cSrcweir else 465cdf0e10cSrcweir if( rSrc.equalsIgnoreAsciiCaseAscii( "false" ) ) 466cdf0e10cSrcweir { 467cdf0e10cSrcweir aNewString = ::rtl::OUString::valueOf( (sal_Int32)SbxFALSE ); 468cdf0e10cSrcweir bChanged = sal_True; 469cdf0e10cSrcweir } 470cdf0e10cSrcweir break; 471cdf0e10cSrcweir } 472cdf0e10cSrcweir default: break; 473cdf0e10cSrcweir } 474cdf0e10cSrcweir // String bei Aenderung uebernehmen 475cdf0e10cSrcweir if( bChanged ) 476cdf0e10cSrcweir rSrc = aNewString; 477cdf0e10cSrcweir return bChanged; 478cdf0e10cSrcweir } 479cdf0e10cSrcweir 480cdf0e10cSrcweir 481cdf0e10cSrcweir // Formatierte Zahlenausgabe 482cdf0e10cSrcweir // Der Returnwert ist die Anzahl Zeichen, die aus dem 483cdf0e10cSrcweir // Format verwendt wurden. 484cdf0e10cSrcweir 485cdf0e10cSrcweir #ifdef _old_format_code_ 486cdf0e10cSrcweir // lasse diesen Code vorl"aufig drin, zum 'abgucken' 487cdf0e10cSrcweir // der bisherigen Implementation 488cdf0e10cSrcweir 489cdf0e10cSrcweir static sal_uInt16 printfmtnum( double nNum, XubString& rRes, const XubString& rWFmt ) 490cdf0e10cSrcweir { 491cdf0e10cSrcweir const String& rFmt = rWFmt; 492cdf0e10cSrcweir char cFill = ' '; // Fuellzeichen 493cdf0e10cSrcweir char cPre = 0; // Startzeichen( evtl. "$" ) 494cdf0e10cSrcweir short nExpDig= 0; // Anzahl Exponentstellen 495cdf0e10cSrcweir short nPrec = 0; // Anzahl Nachkommastellen 496cdf0e10cSrcweir short nWidth = 0; // Zahlenweite gesamnt 497cdf0e10cSrcweir short nLen; // Laenge konvertierte Zahl 498cdf0e10cSrcweir sal_Bool bPoint = sal_False; // sal_True: mit 1000er Kommas 499cdf0e10cSrcweir sal_Bool bTrail = sal_False; // sal_True, wenn folgendes Minus 500cdf0e10cSrcweir sal_Bool bSign = sal_False; // sal_True: immer mit Vorzeichen 501cdf0e10cSrcweir sal_Bool bNeg = sal_False; // sal_True: Zahl ist negativ 502cdf0e10cSrcweir char cBuf [1024]; // Zahlenpuffer 503cdf0e10cSrcweir char * p; 504cdf0e10cSrcweir const char* pFmt = rFmt; 505cdf0e10cSrcweir rRes.Erase(); 506cdf0e10cSrcweir // $$ und ** abfangen. Einfach wird als Zeichen ausgegeben. 507cdf0e10cSrcweir if( *pFmt == '$' ) 508cdf0e10cSrcweir if( *++pFmt != '$' ) rRes += '$'; 509cdf0e10cSrcweir if( *pFmt == '*' ) 510cdf0e10cSrcweir if( *++pFmt != '*' ) rRes += '*'; 511cdf0e10cSrcweir 512cdf0e10cSrcweir switch( *pFmt++ ) 513cdf0e10cSrcweir { 514cdf0e10cSrcweir case 0: 515cdf0e10cSrcweir break; 516cdf0e10cSrcweir case '+': 517cdf0e10cSrcweir bSign = sal_True; nWidth++; break; 518cdf0e10cSrcweir case '*': 519cdf0e10cSrcweir nWidth++; cFill = '*'; 520cdf0e10cSrcweir if( *pFmt == '$' ) nWidth++, pFmt++, cPre = '$'; 521cdf0e10cSrcweir break; 522cdf0e10cSrcweir case '$': 523cdf0e10cSrcweir nWidth++; cPre = '$'; break; 524cdf0e10cSrcweir case '#': 525cdf0e10cSrcweir case '.': 526cdf0e10cSrcweir case ',': 527cdf0e10cSrcweir pFmt--; break; 528cdf0e10cSrcweir } 529cdf0e10cSrcweir // Vorkomma: 530cdf0e10cSrcweir for( ;; ) 531cdf0e10cSrcweir { 532cdf0e10cSrcweir while( *pFmt == '#' ) pFmt++, nWidth++; 533cdf0e10cSrcweir // 1000er Kommas? 534cdf0e10cSrcweir if( *pFmt == ',' ) 535cdf0e10cSrcweir { 536cdf0e10cSrcweir nWidth++; pFmt++; bPoint = sal_True; 537cdf0e10cSrcweir } else break; 538cdf0e10cSrcweir } 539cdf0e10cSrcweir // Nachkomma: 540cdf0e10cSrcweir if( *pFmt == '.' ) 541cdf0e10cSrcweir { 542cdf0e10cSrcweir while( *++pFmt == '#' ) nPrec++; 543cdf0e10cSrcweir nWidth += nPrec + 1; 544cdf0e10cSrcweir } 545cdf0e10cSrcweir // Exponent: 546cdf0e10cSrcweir while( *pFmt == '^' ) 547cdf0e10cSrcweir pFmt++, nExpDig++, nWidth++; 548cdf0e10cSrcweir // Folgendes Minus: 549cdf0e10cSrcweir if( !bSign && *pFmt == '-' ) 550cdf0e10cSrcweir pFmt++, bTrail = sal_True; 551cdf0e10cSrcweir 552cdf0e10cSrcweir // Zahl konvertieren: 553cdf0e10cSrcweir if( nPrec > 15 ) nPrec = 15; 554cdf0e10cSrcweir if( nNum < 0.0 ) nNum = -nNum, bNeg = sal_True; 555cdf0e10cSrcweir p = cBuf; 556cdf0e10cSrcweir if( bSign ) *p++ = bNeg ? '-' : '+'; 557cdf0e10cSrcweir myftoa( nNum, p, nPrec, nExpDig, bPoint, sal_False ); 558cdf0e10cSrcweir nLen = strlen( cBuf ); 559cdf0e10cSrcweir 560cdf0e10cSrcweir // Ueberlauf? 561cdf0e10cSrcweir if( cPre ) nLen++; 562cdf0e10cSrcweir if( nLen > nWidth ) rRes += '%'; 563cdf0e10cSrcweir else { 564cdf0e10cSrcweir nWidth -= nLen; 565cdf0e10cSrcweir while( nWidth-- ) rRes += (xub_Unicode)cFill; 566cdf0e10cSrcweir if( cPre ) rRes += (xub_Unicode)cPre; 567cdf0e10cSrcweir } 568cdf0e10cSrcweir rRes += (xub_Unicode*)&(cBuf[0]); 569cdf0e10cSrcweir if( bTrail ) 570cdf0e10cSrcweir rRes += bNeg ? '-' : ' '; 571cdf0e10cSrcweir 572cdf0e10cSrcweir return (sal_uInt16) ( pFmt - (const char*) rFmt ); 573cdf0e10cSrcweir } 574cdf0e10cSrcweir 575cdf0e10cSrcweir #endif //_old_format_code_ 576cdf0e10cSrcweir 577cdf0e10cSrcweir static sal_uInt16 printfmtstr( const XubString& rStr, XubString& rRes, const XubString& rFmt ) 578cdf0e10cSrcweir { 579cdf0e10cSrcweir const xub_Unicode* pStr = rStr.GetBuffer(); 580cdf0e10cSrcweir const xub_Unicode* pFmtStart = rFmt.GetBuffer(); 581cdf0e10cSrcweir const xub_Unicode* pFmt = pFmtStart; 582cdf0e10cSrcweir rRes.Erase(); 583cdf0e10cSrcweir switch( *pFmt ) 584cdf0e10cSrcweir { 585cdf0e10cSrcweir case '!': 586cdf0e10cSrcweir rRes += *pStr++; pFmt++; break; 587cdf0e10cSrcweir case '\\': 588cdf0e10cSrcweir do 589cdf0e10cSrcweir { 590cdf0e10cSrcweir rRes += *pStr ? *pStr++ : static_cast< xub_Unicode >(' '); 591cdf0e10cSrcweir pFmt++; 592cdf0e10cSrcweir } while( *pFmt != '\\' ); 593cdf0e10cSrcweir rRes += *pStr ? *pStr++ : static_cast< xub_Unicode >(' '); 594cdf0e10cSrcweir pFmt++; break; 595cdf0e10cSrcweir case '&': 596cdf0e10cSrcweir rRes = rStr; 597cdf0e10cSrcweir pFmt++; break; 598cdf0e10cSrcweir default: 599cdf0e10cSrcweir rRes = rStr; 600cdf0e10cSrcweir break; 601cdf0e10cSrcweir } 602cdf0e10cSrcweir return (sal_uInt16) ( pFmt - pFmtStart ); 603cdf0e10cSrcweir } 604cdf0e10cSrcweir 605cdf0e10cSrcweir ///////////////////////////////////////////////////////////////////////// 606cdf0e10cSrcweir 607cdf0e10cSrcweir sal_Bool SbxValue::Scan( const XubString& rSrc, sal_uInt16* pLen ) 608cdf0e10cSrcweir { 609cdf0e10cSrcweir SbxError eRes = SbxERR_OK; 610cdf0e10cSrcweir if( !CanWrite() ) 611cdf0e10cSrcweir eRes = SbxERR_PROP_READONLY; 612cdf0e10cSrcweir else 613cdf0e10cSrcweir { 614cdf0e10cSrcweir double n; 615cdf0e10cSrcweir SbxDataType t; 616cdf0e10cSrcweir eRes = ImpScan( rSrc, n, t, pLen ); 617cdf0e10cSrcweir if( eRes == SbxERR_OK ) 618cdf0e10cSrcweir { 619cdf0e10cSrcweir if( !IsFixed() ) 620cdf0e10cSrcweir SetType( t ); 621cdf0e10cSrcweir PutDouble( n ); 622cdf0e10cSrcweir } 623cdf0e10cSrcweir } 624cdf0e10cSrcweir if( eRes ) 625cdf0e10cSrcweir { 626cdf0e10cSrcweir SetError( eRes ); return sal_False; 627cdf0e10cSrcweir } 628cdf0e10cSrcweir else 629cdf0e10cSrcweir return sal_True; 630cdf0e10cSrcweir } 631cdf0e10cSrcweir 632cdf0e10cSrcweir 633cdf0e10cSrcweir ResMgr* implGetResMgr( void ) 634cdf0e10cSrcweir { 635cdf0e10cSrcweir static ResMgr* pResMgr = NULL; 636cdf0e10cSrcweir if( !pResMgr ) 637cdf0e10cSrcweir { 638cdf0e10cSrcweir ::com::sun::star::lang::Locale aLocale = Application::GetSettings().GetUILocale(); 639cdf0e10cSrcweir pResMgr = ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(sb), aLocale ); 640cdf0e10cSrcweir } 641cdf0e10cSrcweir return pResMgr; 642cdf0e10cSrcweir } 643cdf0e10cSrcweir 644cdf0e10cSrcweir class SbxValueFormatResId : public ResId 645cdf0e10cSrcweir { 646cdf0e10cSrcweir public: 647cdf0e10cSrcweir SbxValueFormatResId( sal_uInt16 nId ) 648cdf0e10cSrcweir : ResId( nId, *implGetResMgr() ) 649cdf0e10cSrcweir {} 650cdf0e10cSrcweir }; 651cdf0e10cSrcweir 652cdf0e10cSrcweir 653cdf0e10cSrcweir enum VbaFormatType 654cdf0e10cSrcweir { 655cdf0e10cSrcweir VBA_FORMAT_TYPE_OFFSET, // standard number format 656cdf0e10cSrcweir VBA_FORMAT_TYPE_USERDEFINED, // user defined number format 657cdf0e10cSrcweir VBA_FORMAT_TYPE_NULL 658cdf0e10cSrcweir }; 659cdf0e10cSrcweir 660cdf0e10cSrcweir struct VbaFormatInfo 661cdf0e10cSrcweir { 662cdf0e10cSrcweir VbaFormatType meType; 663cdf0e10cSrcweir const char* mpVbaFormat; // Format string in vba 664cdf0e10cSrcweir NfIndexTableOffset meOffset; // SvNumberFormatter format index, if meType = VBA_FORMAT_TYPE_OFFSET 665cdf0e10cSrcweir const char* mpOOoFormat; // if meType = VBA_FORMAT_TYPE_USERDEFINED 666cdf0e10cSrcweir }; 667cdf0e10cSrcweir 668cdf0e10cSrcweir #define VBA_FORMAT_OFFSET( pcUtf8, eOffset ) \ 669cdf0e10cSrcweir { VBA_FORMAT_TYPE_OFFSET, pcUtf8, eOffset, 0 } 670cdf0e10cSrcweir 671cdf0e10cSrcweir #define VBA_FORMAT_USERDEFINED( pcUtf8, pcDefinedUtf8 ) \ 672cdf0e10cSrcweir { VBA_FORMAT_TYPE_USERDEFINED, pcUtf8, NF_NUMBER_STANDARD, pcDefinedUtf8 } 673cdf0e10cSrcweir 674cdf0e10cSrcweir static VbaFormatInfo pFormatInfoTable[] = 675cdf0e10cSrcweir { 676cdf0e10cSrcweir VBA_FORMAT_OFFSET( "Long Date", NF_DATE_SYSTEM_LONG ), 677cdf0e10cSrcweir VBA_FORMAT_USERDEFINED( "Medium Date", "DD-MMM-YY" ), 678cdf0e10cSrcweir VBA_FORMAT_OFFSET( "Short Date", NF_DATE_SYSTEM_SHORT ), 679cdf0e10cSrcweir VBA_FORMAT_USERDEFINED( "Long Time", "H:MM:SS AM/PM" ), 680cdf0e10cSrcweir VBA_FORMAT_OFFSET( "Medium Time", NF_TIME_HHMMAMPM ), 681cdf0e10cSrcweir VBA_FORMAT_OFFSET( "Short Time", NF_TIME_HHMM ), 682cdf0e10cSrcweir VBA_FORMAT_OFFSET( "ddddd", NF_DATE_SYSTEM_SHORT ), 683cdf0e10cSrcweir VBA_FORMAT_OFFSET( "dddddd", NF_DATE_SYSTEM_LONG ), 684cdf0e10cSrcweir VBA_FORMAT_USERDEFINED( "ttttt", "H:MM:SS AM/PM" ), 685cdf0e10cSrcweir VBA_FORMAT_OFFSET( "ww", NF_DATE_WW ), 686cdf0e10cSrcweir { VBA_FORMAT_TYPE_NULL, 0, NF_INDEX_TABLE_ENTRIES, 0 } 687cdf0e10cSrcweir }; 688cdf0e10cSrcweir 689cdf0e10cSrcweir VbaFormatInfo* getFormatInfo( const String& rFmt ) 690cdf0e10cSrcweir { 691cdf0e10cSrcweir VbaFormatInfo* pInfo = NULL; 692cdf0e10cSrcweir sal_Int16 i = 0; 693cdf0e10cSrcweir while( (pInfo = pFormatInfoTable + i )->mpVbaFormat != NULL ) 694cdf0e10cSrcweir { 695cdf0e10cSrcweir if( rFmt.EqualsIgnoreCaseAscii( pInfo->mpVbaFormat ) ) 696cdf0e10cSrcweir break; 697cdf0e10cSrcweir i++; 698cdf0e10cSrcweir } 699cdf0e10cSrcweir return pInfo; 700cdf0e10cSrcweir } 701cdf0e10cSrcweir 702cdf0e10cSrcweir #define VBAFORMAT_GENERALDATE "General Date" 703cdf0e10cSrcweir #define VBAFORMAT_C "c" 704cdf0e10cSrcweir #define VBAFORMAT_N "n" 705cdf0e10cSrcweir #define VBAFORMAT_NN "nn" 706cdf0e10cSrcweir #define VBAFORMAT_W "w" 707cdf0e10cSrcweir #define VBAFORMAT_Y "y" 708cdf0e10cSrcweir #define VBAFORMAT_LOWERCASE "<" 709cdf0e10cSrcweir #define VBAFORMAT_UPPERCASE ">" 710cdf0e10cSrcweir 711cdf0e10cSrcweir // From methods1.cxx 712cdf0e10cSrcweir sal_Int16 implGetWeekDay( double aDate, bool bFirstDayParam = false, sal_Int16 nFirstDay = 0 ); 713cdf0e10cSrcweir // from methods.cxx 714cdf0e10cSrcweir sal_Int16 implGetMinute( double dDate ); 715cdf0e10cSrcweir sal_Int16 implGetDateYear( double aDate ); 716cdf0e10cSrcweir sal_Bool implDateSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay, double& rdRet ); 717cdf0e10cSrcweir 718cdf0e10cSrcweir void SbxValue::Format( XubString& rRes, const XubString* pFmt ) const 719cdf0e10cSrcweir { 720cdf0e10cSrcweir short nComma = 0; 721cdf0e10cSrcweir double d = 0; 722cdf0e10cSrcweir 723cdf0e10cSrcweir // pflin, It is better to use SvNumberFormatter to handle the date/time/number format. 724cdf0e10cSrcweir // the SvNumberFormatter output is mostly compatible with 725cdf0e10cSrcweir // VBA output besides the OOo-basic output 726cdf0e10cSrcweir if( pFmt && !SbxBasicFormater::isBasicFormat( *pFmt ) ) 727cdf0e10cSrcweir { 728cdf0e10cSrcweir String aStr = GetString(); 729cdf0e10cSrcweir 730cdf0e10cSrcweir if( pFmt->EqualsIgnoreCaseAscii( VBAFORMAT_LOWERCASE ) ) 731cdf0e10cSrcweir { 732cdf0e10cSrcweir rRes = aStr.ToLowerAscii(); 733cdf0e10cSrcweir return; 734cdf0e10cSrcweir } 735cdf0e10cSrcweir if( pFmt->EqualsIgnoreCaseAscii( VBAFORMAT_UPPERCASE ) ) 736cdf0e10cSrcweir { 737cdf0e10cSrcweir rRes = aStr.ToUpperAscii(); 738cdf0e10cSrcweir return; 739cdf0e10cSrcweir } 740cdf0e10cSrcweir 741cdf0e10cSrcweir LanguageType eLangType = GetpApp()->GetSettings().GetLanguage(); 742cdf0e10cSrcweir com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > 743cdf0e10cSrcweir xFactory = comphelper::getProcessServiceFactory(); 744cdf0e10cSrcweir SvNumberFormatter aFormatter( xFactory, eLangType ); 745cdf0e10cSrcweir 746cdf0e10cSrcweir sal_uInt32 nIndex; 747cdf0e10cSrcweir xub_StrLen nCheckPos = 0; 748cdf0e10cSrcweir short nType; 749cdf0e10cSrcweir double nNumber; 750cdf0e10cSrcweir Color* pCol; 751cdf0e10cSrcweir 752cdf0e10cSrcweir sal_Bool bSuccess = aFormatter.IsNumberFormat( aStr, nIndex, nNumber ); 753cdf0e10cSrcweir 754cdf0e10cSrcweir // number format, use SvNumberFormatter to handle it. 755cdf0e10cSrcweir if( bSuccess ) 756cdf0e10cSrcweir { 757cdf0e10cSrcweir String aFmtStr = *pFmt; 758cdf0e10cSrcweir VbaFormatInfo* pInfo = getFormatInfo( aFmtStr ); 759cdf0e10cSrcweir if( pInfo && pInfo->meType != VBA_FORMAT_TYPE_NULL ) 760cdf0e10cSrcweir { 761cdf0e10cSrcweir if( pInfo->meType == VBA_FORMAT_TYPE_OFFSET ) 762cdf0e10cSrcweir { 763cdf0e10cSrcweir nIndex = aFormatter.GetFormatIndex( pInfo->meOffset, eLangType ); 764cdf0e10cSrcweir } 765cdf0e10cSrcweir else 766cdf0e10cSrcweir { 767cdf0e10cSrcweir aFmtStr.AssignAscii( pInfo->mpOOoFormat ); 768cdf0e10cSrcweir aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType ); 769cdf0e10cSrcweir } 770cdf0e10cSrcweir aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol ); 771cdf0e10cSrcweir } 772cdf0e10cSrcweir else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_GENERALDATE ) 773cdf0e10cSrcweir || aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_C )) 774cdf0e10cSrcweir { 775cdf0e10cSrcweir if( nNumber <=-1.0 || nNumber >= 1.0 ) 776cdf0e10cSrcweir { 777cdf0e10cSrcweir // short date 778cdf0e10cSrcweir nIndex = aFormatter.GetFormatIndex( NF_DATE_SYSTEM_SHORT, eLangType ); 779cdf0e10cSrcweir aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol ); 780cdf0e10cSrcweir 781cdf0e10cSrcweir // long time 782cdf0e10cSrcweir if( floor( nNumber ) != nNumber ) 783cdf0e10cSrcweir { 784cdf0e10cSrcweir aFmtStr.AssignAscii( "H:MM:SS AM/PM" ); 785cdf0e10cSrcweir aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType ); 786cdf0e10cSrcweir String aTime; 787cdf0e10cSrcweir aFormatter.GetOutputString( nNumber, nIndex, aTime, &pCol ); 788cdf0e10cSrcweir rRes.AppendAscii(" "); 789cdf0e10cSrcweir rRes += aTime; 790cdf0e10cSrcweir } 791cdf0e10cSrcweir } 792cdf0e10cSrcweir else 793cdf0e10cSrcweir { 794cdf0e10cSrcweir // long time only 795cdf0e10cSrcweir aFmtStr.AssignAscii( "H:MM:SS AM/PM" ); 796cdf0e10cSrcweir aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType ); 797cdf0e10cSrcweir aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol ); 798cdf0e10cSrcweir } 799cdf0e10cSrcweir } 800cdf0e10cSrcweir else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_N ) 801cdf0e10cSrcweir || aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_NN )) 802cdf0e10cSrcweir { 803cdf0e10cSrcweir sal_Int32 nMin = implGetMinute( nNumber ); 804cdf0e10cSrcweir if( nMin < 10 && aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_NN ) ) 805cdf0e10cSrcweir { 806cdf0e10cSrcweir // Minute in two digits 807cdf0e10cSrcweir sal_Unicode* p = rRes.AllocBuffer( 2 ); 808cdf0e10cSrcweir *p++ = '0'; 809cdf0e10cSrcweir *p = sal_Unicode( '0' + nMin ); 810cdf0e10cSrcweir } 811cdf0e10cSrcweir else 812cdf0e10cSrcweir { 813cdf0e10cSrcweir rRes = String::CreateFromInt32( nMin ); 814cdf0e10cSrcweir } 815cdf0e10cSrcweir } 816cdf0e10cSrcweir else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_W )) 817cdf0e10cSrcweir { 818cdf0e10cSrcweir sal_Int32 nWeekDay = implGetWeekDay( nNumber ); 819cdf0e10cSrcweir rRes = String::CreateFromInt32( nWeekDay ); 820cdf0e10cSrcweir } 821cdf0e10cSrcweir else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_Y )) 822cdf0e10cSrcweir { 823cdf0e10cSrcweir sal_Int16 nYear = implGetDateYear( nNumber ); 824cdf0e10cSrcweir double dBaseDate; 825cdf0e10cSrcweir implDateSerial( nYear, 1, 1, dBaseDate ); 826cdf0e10cSrcweir sal_Int32 nYear32 = 1 + sal_Int32( nNumber - dBaseDate ); 827cdf0e10cSrcweir rRes = String::CreateFromInt32( nYear32 ); 828cdf0e10cSrcweir } 829cdf0e10cSrcweir else 830cdf0e10cSrcweir { 831cdf0e10cSrcweir aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType ); 832cdf0e10cSrcweir aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol ); 833cdf0e10cSrcweir } 834cdf0e10cSrcweir 835cdf0e10cSrcweir return; 836cdf0e10cSrcweir } 837cdf0e10cSrcweir } 838cdf0e10cSrcweir 839cdf0e10cSrcweir SbxDataType eType = GetType(); 840cdf0e10cSrcweir switch( eType ) 841cdf0e10cSrcweir { 842cdf0e10cSrcweir case SbxCHAR: 843cdf0e10cSrcweir case SbxBYTE: 844cdf0e10cSrcweir case SbxINTEGER: 845cdf0e10cSrcweir case SbxUSHORT: 846cdf0e10cSrcweir case SbxLONG: 847cdf0e10cSrcweir case SbxULONG: 848cdf0e10cSrcweir case SbxINT: 849cdf0e10cSrcweir case SbxUINT: 850cdf0e10cSrcweir case SbxNULL: // #45929 NULL mit durchschummeln 851cdf0e10cSrcweir nComma = 0; goto cvt; 852cdf0e10cSrcweir case SbxSINGLE: 853cdf0e10cSrcweir nComma = 6; goto cvt; 854cdf0e10cSrcweir case SbxDOUBLE: 855cdf0e10cSrcweir nComma = 14; 856cdf0e10cSrcweir 857cdf0e10cSrcweir cvt: 858cdf0e10cSrcweir if( eType != SbxNULL ) 859cdf0e10cSrcweir d = GetDouble(); 860cdf0e10cSrcweir 861cdf0e10cSrcweir // #45355 weiterer Einsprungpunkt fuer isnumeric-String 862cdf0e10cSrcweir cvt2: 863cdf0e10cSrcweir if( pFmt ) 864cdf0e10cSrcweir { 865cdf0e10cSrcweir // hole die 'statischen' Daten f"ur Sbx 866cdf0e10cSrcweir SbxAppData* pData = GetSbxData_Impl(); 867cdf0e10cSrcweir 868cdf0e10cSrcweir LanguageType eLangType = GetpApp()->GetSettings().GetLanguage(); 869cdf0e10cSrcweir if( pData->pBasicFormater ) 870cdf0e10cSrcweir { 871cdf0e10cSrcweir if( pData->eBasicFormaterLangType != eLangType ) 872cdf0e10cSrcweir { 873cdf0e10cSrcweir delete pData->pBasicFormater; 874cdf0e10cSrcweir pData->pBasicFormater = NULL; 875cdf0e10cSrcweir } 876cdf0e10cSrcweir } 877cdf0e10cSrcweir pData->eBasicFormaterLangType = eLangType; 878cdf0e10cSrcweir 879cdf0e10cSrcweir // falls bisher noch kein BasicFormater-Objekt 880cdf0e10cSrcweir // existiert, so erzeuge dieses 881cdf0e10cSrcweir if( !pData->pBasicFormater ) 882cdf0e10cSrcweir { 883cdf0e10cSrcweir SvtSysLocale aSysLocale; 884cdf0e10cSrcweir const LocaleDataWrapper& rData = aSysLocale.GetLocaleData(); 885cdf0e10cSrcweir sal_Unicode cComma = rData.getNumDecimalSep().GetBuffer()[0]; 886cdf0e10cSrcweir sal_Unicode c1000 = rData.getNumThousandSep().GetBuffer()[0]; 887cdf0e10cSrcweir String aCurrencyStrg = rData.getCurrSymbol(); 888cdf0e10cSrcweir 889cdf0e10cSrcweir // Initialisierung des Basic-Formater-Hilfsobjekts: 890cdf0e10cSrcweir // hole die Resourcen f"ur die vordefinierten Ausgaben 891cdf0e10cSrcweir // des Format()-Befehls, z.B. f"ur "On/Off". 892cdf0e10cSrcweir String aOnStrg = String( SbxValueFormatResId( 893cdf0e10cSrcweir STR_BASICKEY_FORMAT_ON ) ); 894cdf0e10cSrcweir String aOffStrg = String( SbxValueFormatResId( 895cdf0e10cSrcweir STR_BASICKEY_FORMAT_OFF) ); 896cdf0e10cSrcweir String aYesStrg = String( SbxValueFormatResId( 897cdf0e10cSrcweir STR_BASICKEY_FORMAT_YES) ); 898cdf0e10cSrcweir String aNoStrg = String( SbxValueFormatResId( 899cdf0e10cSrcweir STR_BASICKEY_FORMAT_NO) ); 900cdf0e10cSrcweir String aTrueStrg = String( SbxValueFormatResId( 901cdf0e10cSrcweir STR_BASICKEY_FORMAT_TRUE) ); 902cdf0e10cSrcweir String aFalseStrg = String( SbxValueFormatResId( 903cdf0e10cSrcweir STR_BASICKEY_FORMAT_FALSE) ); 904cdf0e10cSrcweir String aCurrencyFormatStrg = String( SbxValueFormatResId( 905cdf0e10cSrcweir STR_BASICKEY_FORMAT_CURRENCY) ); 906cdf0e10cSrcweir // erzeuge das Basic-Formater-Objekt 907cdf0e10cSrcweir pData->pBasicFormater 908cdf0e10cSrcweir = new SbxBasicFormater( cComma,c1000,aOnStrg,aOffStrg, 909cdf0e10cSrcweir aYesStrg,aNoStrg,aTrueStrg,aFalseStrg, 910cdf0e10cSrcweir aCurrencyStrg,aCurrencyFormatStrg ); 911cdf0e10cSrcweir } 912cdf0e10cSrcweir // Bem.: Aus Performance-Gr"unden wird nur EIN BasicFormater- 913cdf0e10cSrcweir // Objekt erzeugt und 'gespeichert', dadurch erspart man 914cdf0e10cSrcweir // sich das teure Resourcen-Laden (f"ur landesspezifische 915cdf0e10cSrcweir // vordefinierte Ausgaben, z.B. "On/Off") und die st"andige 916cdf0e10cSrcweir // String-Erzeugungs Operationen. 917cdf0e10cSrcweir // ABER: dadurch ist dieser Code NICHT multithreading f"ahig ! 918cdf0e10cSrcweir 919cdf0e10cSrcweir // hier gibt es Probleme mit ;;;Null, da diese Methode nur aufgerufen 920cdf0e10cSrcweir // wird, wenn der SbxValue eine Zahl ist !!! 921cdf0e10cSrcweir // dazu koennte: pData->pBasicFormater->BasicFormatNull( *pFmt ); aufgerufen werden ! 922cdf0e10cSrcweir if( eType != SbxNULL ) 923cdf0e10cSrcweir { 924cdf0e10cSrcweir rRes = pData->pBasicFormater->BasicFormat( d ,*pFmt ); 925cdf0e10cSrcweir } 926cdf0e10cSrcweir else 927cdf0e10cSrcweir { 928cdf0e10cSrcweir rRes = pData->pBasicFormater->BasicFormatNull( *pFmt ); 929cdf0e10cSrcweir } 930cdf0e10cSrcweir 931cdf0e10cSrcweir // Die alte Implementierung: 932cdf0e10cSrcweir //old: printfmtnum( GetDouble(), rRes, *pFmt ); 933cdf0e10cSrcweir } 934cdf0e10cSrcweir else 935cdf0e10cSrcweir { 936cdf0e10cSrcweir ::rtl::OUString aTmpString( rRes ); 937cdf0e10cSrcweir ImpCvtNum( GetDouble(), nComma, aTmpString ); 938cdf0e10cSrcweir rRes = aTmpString; 939cdf0e10cSrcweir } 940cdf0e10cSrcweir break; 941cdf0e10cSrcweir case SbxSTRING: 942cdf0e10cSrcweir if( pFmt ) 943cdf0e10cSrcweir { 944cdf0e10cSrcweir // #45355 wenn es numerisch ist, muss gewandelt werden 945cdf0e10cSrcweir if( IsNumericRTL() ) 946cdf0e10cSrcweir { 947cdf0e10cSrcweir ScanNumIntnl( GetString(), d, /*bSingle*/sal_False ); 948cdf0e10cSrcweir goto cvt2; 949cdf0e10cSrcweir } 950cdf0e10cSrcweir else 951cdf0e10cSrcweir { 952cdf0e10cSrcweir // Sonst String-Formatierung 953cdf0e10cSrcweir printfmtstr( GetString(), rRes, *pFmt ); 954cdf0e10cSrcweir } 955cdf0e10cSrcweir } 956cdf0e10cSrcweir else 957cdf0e10cSrcweir rRes = GetString(); 958cdf0e10cSrcweir break; 959cdf0e10cSrcweir default: 960cdf0e10cSrcweir rRes = GetString(); 961cdf0e10cSrcweir } 962cdf0e10cSrcweir } 963cdf0e10cSrcweir 964cdf0e10cSrcweir 965