1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_basic.hxx" 30 31 #include <stdlib.h> 32 33 #include <basic/sbxform.hxx> 34 35 /* 36 TODO: gibt es noch irgend welche Star-Basic Besonderheiten ? 37 38 was bedeutet: * als Platzhalter 39 40 BEMERKUNG: Visual-Basic behandelt folgende (ung"ultige) Format-Strings 41 wie angezeigt: 42 43 ##0##.##0## --> ##000.000## 44 45 (diese Klasse verh"alt sich genau so). 46 */ 47 48 #include <stdio.h> // f"ur: sprintf() 49 #include <float.h> // f"ur: DBL_DIG, DBL_EPSILON 50 #include <math.h> // f"ur: floor(), fabs(), log10(), pow() 51 52 //================================================================= 53 //=========================== DEFINES ============================= 54 //================================================================= 55 56 #define _NO_DIGIT -1 57 58 #define MAX_NO_OF_EXP_DIGITS 5 59 // +4 wegen dem Wertebereich: zwischen -308 und +308 60 // +1 f"ur abschliessende 0 61 #define MAX_NO_OF_DIGITS DBL_DIG 62 #define MAX_DOUBLE_BUFFER_LENGTH MAX_NO_OF_DIGITS + 9 63 // +1 f"ur Vorzeichen 64 // +1 f"ur Ziffer vor dem Dezimal-Punkt 65 // +1 f"ur Dezimal-Punkt 66 // +2 f"ur Exponent E und Exp. Vorzeichen 67 // +3 f"ur den Wert des Exponenten 68 // +1 f"ur abschliessende 0 69 70 // Defines f"ur die Ziffern: 71 #define ASCII_0 '0' // 48 72 #define ASCII_9 '9' // 57 73 74 #define CREATE_1000SEP_CHAR '@' 75 76 #define FORMAT_SEPARATOR ';' 77 78 // vordefinierte Formate f"ur den Format$()-Befehl: 79 #define BASICFORMAT_GENERALNUMBER "General Number" 80 #define BASICFORMAT_CURRENCY "Currency" 81 #define BASICFORMAT_FIXED "Fixed" 82 #define BASICFORMAT_STANDARD "Standard" 83 #define BASICFORMAT_PERCENT "Percent" 84 #define BASICFORMAT_SCIENTIFIC "Scientific" 85 #define BASICFORMAT_YESNO "Yes/No" 86 #define BASICFORMAT_TRUEFALSE "True/False" 87 #define BASICFORMAT_ONOFF "On/Off" 88 89 #define EMPTYFORMATSTRING "" 90 91 // Bem.: Visual-Basic hat bei Floating-Point-Zahlen maximal 12 Stellen 92 // nach dem Dezimal-Punkt. 93 // Alle Format-Strings sind kompatibel zu Visual-Basic: 94 #define GENERALNUMBER_FORMAT "0.############" 95 // max. 12 Stellen in Visual-Basic ! 96 #define CURRENCY_FORMAT "@$0.00;@($0.00)" 97 #define FIXED_FORMAT "0.00" 98 #define STANDARD_FORMAT "@0.00" 99 #define PERCENT_FORMAT "0.00%" 100 #define SCIENTIFIC_FORMAT "#.00E+00" 101 // BEMERKUNG: das Zeichen @ bedeutet, das Tausender-Separatoren erzeugt 102 // weden sollen. Dies ist eine StarBasic 'Erweiterung'. 103 104 //================================================================= 105 106 // zur Bestimmung der Anzahl Stellen in dNumber 107 double get_number_of_digits( double dNumber ) 108 //double floor_log10_fabs( double dNumber ) 109 { 110 if( dNumber==0.0 ) 111 // 0 hat zumindest auch eine Stelle ! 112 return 0.0; //ehemals 1.0, jetzt 0.0 wegen #40025; 113 else 114 return floor( log10( fabs( dNumber ) ) ); 115 } 116 117 //================================================================= 118 //======================= IMPLEMENTATION ========================== 119 //================================================================= 120 121 SbxBasicFormater::SbxBasicFormater( sal_Unicode _cDecPoint, sal_Unicode _cThousandSep, 122 String _sOnStrg, 123 String _sOffStrg, 124 String _sYesStrg, 125 String _sNoStrg, 126 String _sTrueStrg, 127 String _sFalseStrg, 128 String _sCurrencyStrg, 129 String _sCurrencyFormatStrg ) 130 { 131 cDecPoint = _cDecPoint; 132 cThousandSep = _cThousandSep; 133 sOnStrg = _sOnStrg; 134 sOffStrg = _sOffStrg; 135 sYesStrg = _sYesStrg; 136 sNoStrg = _sNoStrg; 137 sTrueStrg = _sTrueStrg; 138 sFalseStrg = _sFalseStrg; 139 sCurrencyStrg = _sCurrencyStrg; 140 sCurrencyFormatStrg = _sCurrencyFormatStrg; 141 } 142 143 // Funktion zur Ausgabe eines Fehler-Textes (zum Debuggen) 144 /* 145 void SbxBasicFormater::ShowError( char * sErrMsg ) 146 { 147 // cout << "ERROR in Format$(): " << sErrMsg << endl; 148 } 149 */ 150 // verschiebt alle Zeichen des Strings, angefangen von der nStartPos, 151 // um eine Position zu gr"osseren Indizes, d.h. es wird Platz f"ur 152 // ein neues (einzuf"ugendes) Zeichen geschafft. 153 // ACHTUNG: der String MUSS gross genug sein ! 154 inline void SbxBasicFormater::ShiftString( String& sStrg, sal_uInt16 nStartPos ) 155 { 156 sStrg.Erase( nStartPos,1 ); 157 } 158 159 // Funktion um ein Zeichen an einen String anzuh"angen 160 inline void SbxBasicFormater::StrAppendChar( String& sStrg, sal_Unicode ch ) 161 { 162 sStrg.Insert( ch ); 163 } 164 165 // h"angt die "ubergebene Ziffer nDigit an den "ubergebenen String sStrg 166 // an, dabei wird "uberpr"uft ob nDigit eine g"ultige Ziffer ist, 167 // falls dies nicht der Fall ist, wird nichts gemacht. 168 void SbxBasicFormater::AppendDigit( String& sStrg, short nDigit ) 169 { 170 if( nDigit>=0 && nDigit<=9 ) 171 StrAppendChar( sStrg, (sal_Unicode)(nDigit+ASCII_0) ); 172 } 173 174 // verschiebt den Dezimal-Punkt um eine Stelle nach links 175 void SbxBasicFormater::LeftShiftDecimalPoint( String& sStrg ) 176 { 177 sal_uInt16 nPos = sStrg.Search( cDecPoint ); 178 179 if( nPos!=STRING_NOTFOUND ) 180 { 181 // vertausche Dezimal-Punkt 182 sStrg.SetChar( nPos, sStrg.GetChar( nPos - 1 ) ); 183 sStrg.SetChar( nPos-1, cDecPoint ); 184 } 185 } 186 187 // rundet in einem String die Ziffer an der angegebenen Stelle, 188 // es wird ein Flag zur"uckgeliefert, falls ein Overflow auftrat, 189 // d.h. 99.99 --> 100.00, d.h. ein Gr"ossenordung ge"andert wurde 190 // (geschieht beim Runden einer 9). 191 void SbxBasicFormater::StrRoundDigit( String& sStrg, short nPos, sal_Bool& bOverflow ) 192 { 193 // wurde ggf ein falscher Index uebergeben --> Aufruf ignorieren 194 if( nPos<0 ) 195 return; 196 197 bOverflow = sal_False; 198 // "uberspringe den Dezimalpunkt und Tausender-Trennzeichen 199 sal_Unicode c = sStrg.GetChar( nPos ); 200 if( nPos>0 && (c == cDecPoint || c == cThousandSep) ) 201 { 202 StrRoundDigit( sStrg,nPos-1,bOverflow ); 203 // AENDERUNG ab 9.3.1997: nach rekursivem Call die Methode SOFORT beenden ! 204 return; 205 } 206 // "uberspringe alle nicht-Ziffern: 207 // BEMERKUNG: 208 // in einem g"ultigen Format-String sollte die Ausgabe 209 // der Zahl an einem St"uck geschen, d.h. Sonderzeichen sollten 210 // NUR vor ODER nach der Zahl stehen und nicht mitten in der 211 // Format-Angabe f"ur die Zahl 212 while( nPos>=0 && (sStrg.GetChar( nPos )<ASCII_0 || sStrg.GetChar( nPos )>ASCII_9) ) 213 nPos--; 214 // muss ggf. noch Platz f"ur eine weitere (f"uhrende) Ziffer 215 // geschaffen werden ? 216 if( nPos==-1 ) 217 { 218 ShiftString( sStrg,0 ); 219 // f"uhrende 1 einf"ugen: z.B. 99.99 f"ur 0.0 220 sStrg.SetChar( 0, '1' ); 221 bOverflow = sal_True; 222 } 223 else 224 { 225 // ist die zu rundende Position eine Ziffer ? 226 sal_Unicode c2 = sStrg.GetChar( nPos ); 227 if( c2 >= ASCII_0 && c2 <= ASCII_9 ) 228 { 229 // muss eine 9 gerundet werden? Falls: Ja --> rekursiver Aufruf 230 if( c2 == ASCII_9 ) 231 { 232 sStrg.SetChar( nPos, '0' ); 233 StrRoundDigit( sStrg,nPos-1,bOverflow ); 234 } 235 else 236 sStrg.SetChar( nPos, c2+1 ); 237 } 238 else 239 { 240 // --> Nein, d.h. Platz f"ur Ziffer schaffen: z.B. -99.99 f"ur #0.0 241 // da gerundet wird MUSS es immer eine g"ultige Position 242 // nPos+1 geben ! 243 ShiftString( sStrg,nPos+1 ); 244 // f"uhrende 1 einf"ugen 245 sStrg.SetChar( nPos+1, '1' ); 246 bOverflow = sal_True; 247 } 248 } 249 } 250 251 // rundet in einem String die Ziffer an der angegebenen Stelle 252 void SbxBasicFormater::StrRoundDigit( String& sStrg, short nPos ) 253 { 254 sal_Bool bOverflow; 255 256 StrRoundDigit( sStrg,nPos,bOverflow ); 257 } 258 259 // parse den Formatstring von der "ubergebenen Position zur"uck 260 // und l"osche ggf. "uberf"ussige 0en, z.B. 4.50 in 0.0# 261 void SbxBasicFormater::ParseBack( String& sStrg, const String& sFormatStrg, 262 short nFormatPos ) 263 { 264 // WICHTIG: nFormatPos kann auch negativ sein, in diesem Fall Aufruf ignorieren 265 for( short i=nFormatPos; 266 i>0 && sFormatStrg.GetChar( i ) == '#' && sStrg.GetChar( (sStrg.Len()-1) ) == '0'; 267 i-- ) 268 { sStrg.Erase( sStrg.Len()-1 ); } 269 } 270 271 #ifdef _with_sprintf 272 273 /* 274 Bemerkung: 275 Zahl wird mit maximaler (sinnvollen) Genauigkeit in einen String 276 umgewandelt (mit sprintf()), dieser String wird dann im Schleifen- 277 Durchlauf nach der entsprechenden Ziffer durchsucht. 278 */ 279 // initialisiert die Daten der Klasse um einen Scan-Durchlauf durchzuf"uhren 280 void SbxBasicFormater::InitScan( double _dNum ) 281 { 282 char sBuffer[ MAX_DOUBLE_BUFFER_LENGTH ]; 283 284 dNum = _dNum; 285 InitExp( get_number_of_digits( dNum ) ); 286 // maximal 15 Nachkomma-Stellen, Format-Beispiel: -1.234000000000000E-001 287 /*int nCount =*/ sprintf( sBuffer,"%+22.15lE",dNum ); 288 sSciNumStrg.AssignAscii( sBuffer ); 289 } 290 291 void SbxBasicFormater::InitExp( double _dNewExp ) 292 { 293 char sBuffer[ MAX_DOUBLE_BUFFER_LENGTH ]; 294 // bestimme den Exponenten (kann immer GENAU durch int dargestellt werden) 295 nNumExp = (short)_dNewExp; 296 // und dessen String 297 /*int nCount =*/ sprintf( sBuffer,"%+i",nNumExp ); 298 sNumExpStrg.AssignAscii( sBuffer ); 299 // bestimme die Anzahl der Stellen im Exponenten 300 nExpExp = (short)get_number_of_digits( (double)nNumExp ); 301 } 302 303 // bestimmt die Ziffer an der angegebenen Stelle (gedacht zur Anwendung im 304 // Scan-Durchlauf) 305 short SbxBasicFormater::GetDigitAtPosScan( short nPos, sal_Bool& bFoundFirstDigit ) 306 { 307 // Versuch eine gr"ossere Ziffer zu lesen, 308 // z.B. Stelle 4 in 1.234, 309 // oder eine Ziffer ausserhalb der Aufl"osung der 310 // Zahl (double) zu lesen (z.B. max. 15 Stellen). 311 if( nPos>nNumExp || abs(nNumExp-nPos)>MAX_NO_OF_DIGITS ) 312 return _NO_DIGIT; 313 // bestimme den Index der Stelle in dem Number-String: 314 // "uberlese das Vorzeichen 315 sal_uInt16 no = 1; 316 // falls notwendig den Dezimal-Punkt "uberlesen: 317 if( nPos<nNumExp ) 318 no++; 319 no += nNumExp-nPos; 320 // Abfrage der ersten (g"ultigen) Ziffer der Zahl --> Flag setzen 321 if( nPos==nNumExp ) 322 bFoundFirstDigit = sal_True; 323 return (short)(sSciNumStrg.GetChar( no ) - ASCII_0); 324 } 325 326 short SbxBasicFormater::GetDigitAtPosExpScan( short nPos, sal_Bool& bFoundFirstDigit ) 327 { 328 // ist die abgefragte Stelle zu gross f"ur den Exponenten ? 329 if( nPos>nExpExp ) 330 return -1; 331 332 // bestimme den Index der Stelle in dem Number-String: 333 // "uberlese das Vorzeichen 334 sal_uInt16 no = 1; 335 no += nExpExp-nPos; 336 // Abfrage der ersten (g"ultigen) Ziffer der Zahl --> Flag setzen 337 if( nPos==nExpExp ) 338 bFoundFirstDigit = sal_True; 339 return (short)(sNumExpStrg.GetChar( no ) - ASCII_0); 340 } 341 342 // es kann ein Wert f"ur den Exponent angegeben werden, da ggf. die 343 // Zahl ggf. NICHT normiert (z.B. 1.2345e-03) dargestellt werden soll, 344 // sondern eventuell 123.345e-3 ! 345 short SbxBasicFormater::GetDigitAtPosExpScan( double dNewExponent, short nPos, 346 sal_Bool& bFoundFirstDigit ) 347 { 348 // neuer Exponent wurde "ubergeben, aktualisiere 349 // die tempor"aren Klassen-Variablen 350 InitExp( dNewExponent ); 351 // und jetzt die Stelle bestimmen 352 return GetDigitAtPosExpScan( nPos,bFoundFirstDigit ); 353 } 354 355 #else 356 357 /* Probleme mit der folgenden Methode: 358 359 TODO: ggf einen 'intelligenten' Peek-Parser um Rundungsfehler bei 360 double-Zahlen herauszufinden ? z.B. f"ur 0.00115 #.#e-000 361 362 Problem mit: format( 0.3345 , "0.000" ) 363 Problem mit: format( 0.00115 , "0.0000" ) 364 365 */ 366 // liefert die Ziffer an der angegebenen '10er System'-Position, 367 // d.h. positive nPos f"ur Stellen vor dem Komma und negative 368 // f"ur Stellen nach dem Komma. 369 // nPos==0 bedeutet erste Stelle vor dem Komma, also 10^0. 370 // liefert 0..9 f"ur g"ultige Ziffern und -1 f"ur nicht vorhanden, 371 // d.h. falls die "ubergebene Zahl zu klein ist 372 // (z.B. Stelle 5 bei dNumber=123). 373 // Weiter wird in dNextNumber die um die f"uhrenden Stellen 374 // (bis nPos) gek"urzte Zahl zur"uckgeliefert, z.B. 375 // GetDigitAtPos( 3434.565 , 2 , dNewNumber ) --> dNewNumber = 434.565 376 // dies kann f"ur Schleifenabarbeitung g"unstiger sein, d.h. 377 // die Zahlen immer von der gr"ossten Stelle abarbeiten/scanen. 378 // In bFoundFirstDigit wird ggf. ein Flag gesetzt wenn eine Ziffer 379 // gefunden wurde, dies wird dazu verwendet um 'Fehler' beim Parsen 202 380 // zu vermeiden, die 381 // 382 // ACHTUNG: anscheinend gibt es manchmal noch Probleme mit Rundungs-Fehlern! 383 short SbxBasicFormater::GetDigitAtPos( double dNumber, short nPos, 384 double& dNextNumber, sal_Bool& bFoundFirstDigit ) 385 // ACHTUNG: nPos kann auch negativ werden, f"ur Stellen nach dem Dezimal-Punkt 386 { 387 double dTemp = dNumber; 388 double dDigit,dPos; 389 short nMaxDigit; 390 391 // erst mal aus der Zahl eine positive Zahl machen: 392 dNumber = fabs( dNumber ); 393 dPos = (double)nPos; 394 395 // "uberpr"ufe ob Zahl zu klein f"ur angegebene Stelle ist 396 nMaxDigit = (short)get_number_of_digits( dNumber ); 397 // f"uhrende Ziffern 'l"oschen' 398 // Bem.: Fehler nur bei Zahlen gr"osser 0, d.h. bei Ziffern vor dem 399 // Dezimal-Punkt 400 if( nMaxDigit<nPos && !bFoundFirstDigit && nPos>=0 ) 401 return _NO_DIGIT; 402 // Ziffer gefunden, setze Flag: 403 bFoundFirstDigit = sal_True; 404 for( short i=nMaxDigit; i>=nPos; i-- ) 405 { 406 double dI = (double)i; 407 double dTemp1 = pow( 10.0,dI ); 408 // pr"apariere nun die gesuchte Ziffer: 409 dDigit = floor( pow( 10.0,log10( fabs( dNumber ) )-dI ) ); 410 dNumber -= dTemp1 * dDigit; 411 } 412 // Zuweisung f"ur optimierte Schleifen-Durchl"aufe 413 dNextNumber = dNumber; 414 // und zum Schluss noch die float-Rundungsungenauigkeiten heraus filtern 415 return RoundDigit( dDigit ); 416 } 417 418 // rundet eine double-Zahl zwischen 0 und 9 auf die genaue 419 // Integer-Zahl, z.B. 2.8 -> 3 und 2.2 -> 2 420 short SbxBasicFormater::RoundDigit( double dNumber ) 421 { 422 // ist der Wertebereich g"ultig ? 423 if( dNumber<0.0 || dNumber>10.0 ) 424 return -1; 425 short nTempHigh = (short)(dNumber+0.5); // ggf. floor( ) 426 return nTempHigh; 427 } 428 429 #endif 430 431 // kopiert den entsprechenden Teil des Format-Strings, falls vorhanden, 432 // und liefert diesen zur"uck. 433 // Somit wird ein neuer String erzeugt, der vom Aufrufer wieder freigegeben 434 // werden muss 435 String SbxBasicFormater::GetPosFormatString( const String& sFormatStrg, sal_Bool & bFound ) 436 { 437 bFound = sal_False; // default... 438 sal_uInt16 nPos = sFormatStrg.Search( FORMAT_SEPARATOR ); 439 440 if( nPos!=STRING_NOTFOUND ) 441 { 442 bFound = sal_True; 443 // der Format-String f"ur die positiven Zahlen ist alles 444 // vor dem ersten ';' 445 return sFormatStrg.Copy( 0,nPos ); 446 } 447 // kein ; gefunden, liefere Leerstring 448 String aRetStr; 449 aRetStr.AssignAscii( EMPTYFORMATSTRING ); 450 return aRetStr; 451 } 452 453 // siehe auch GetPosFormatString() 454 String SbxBasicFormater::GetNegFormatString( const String& sFormatStrg, sal_Bool & bFound ) 455 { 456 bFound = sal_False; // default... 457 sal_uInt16 nPos = sFormatStrg.Search( FORMAT_SEPARATOR ); 458 459 if( nPos!=STRING_NOTFOUND ) 460 { 461 // der Format-String f"ur die negative Zahlen ist alles 462 // zwischen dem ersten und dem zweiten ';'. 463 // Daher: hole erst mal alles nach dem ersten ';' 464 String sTempStrg = sFormatStrg.Copy( nPos+1 ); 465 // und suche darin ggf. ein weiteres ';' 466 nPos = sTempStrg.Search( FORMAT_SEPARATOR ); 467 bFound = sal_True; 468 if( nPos==STRING_NOTFOUND ) 469 // keins gefunden, liefere alles... 470 return sTempStrg; 471 else 472 // ansonsten den String zwischen den beiden ';' liefern 473 return sTempStrg.Copy( 0,nPos ); 474 } 475 String aRetStr; 476 aRetStr.AssignAscii( EMPTYFORMATSTRING ); 477 return aRetStr; 478 } 479 480 // siehe auch GetPosFormatString() 481 String SbxBasicFormater::Get0FormatString( const String& sFormatStrg, sal_Bool & bFound ) 482 { 483 bFound = sal_False; // default... 484 sal_uInt16 nPos = sFormatStrg.Search( FORMAT_SEPARATOR ); 485 486 if( nPos!=STRING_NOTFOUND ) 487 { 488 // der Format-String f"ur die Null ist alles 489 // was nach dem zweiten ';' kommt. 490 // Daher: hole erst mal alles nach dem ersten ';' 491 String sTempStrg = sFormatStrg.Copy( nPos+1 ); 492 // und suche darin ggf. ein weiteres ';' 493 nPos = sTempStrg.Search( FORMAT_SEPARATOR ); 494 if( nPos!=STRING_NOTFOUND ) 495 { 496 bFound = sal_True; 497 sTempStrg = sTempStrg.Copy( nPos+1 ); 498 nPos = sTempStrg.Search( FORMAT_SEPARATOR ); 499 if( nPos==STRING_NOTFOUND ) 500 // keins gefunden, liefere alles... 501 return sTempStrg; 502 else 503 return sTempStrg.Copy( 0,nPos ); 504 } 505 } 506 // kein ; gefunden, liefere Leerstring 507 String aRetStr; 508 aRetStr.AssignAscii( EMPTYFORMATSTRING ); 509 return aRetStr; 510 } 511 512 // siehe auch GetPosFormatString() 513 String SbxBasicFormater::GetNullFormatString( const String& sFormatStrg, sal_Bool & bFound ) 514 { 515 bFound = sal_False; // default... 516 sal_uInt16 nPos = sFormatStrg.Search( FORMAT_SEPARATOR ); 517 518 if( nPos!=STRING_NOTFOUND ) 519 { 520 // der Format-String f"ur die Null ist alles 521 // was nach dem dritten ';' kommt. 522 // Daher: hole erst mal alles nach dem ersten ';' 523 String sTempStrg = sFormatStrg.Copy( nPos+1 ); 524 // und suche darin ggf. ein weiteres ';' 525 nPos = sTempStrg.Search( FORMAT_SEPARATOR ); 526 if( nPos!=STRING_NOTFOUND ) 527 { 528 // und suche nun nach dem dritten ';' 529 sTempStrg = sTempStrg.Copy( nPos+1 ); 530 nPos = sTempStrg.Search( FORMAT_SEPARATOR ); 531 if( nPos!=STRING_NOTFOUND ) 532 { 533 bFound = sal_True; 534 return sTempStrg.Copy( nPos+1 ); 535 } 536 } 537 } 538 // kein ; gefunden, liefere Leerstring 539 String aRetStr; 540 aRetStr.AssignAscii( EMPTYFORMATSTRING ); 541 return aRetStr; 542 } 543 544 // analysiert den Format-String, liefert Wert <> 0 falls ein Fehler 545 // aufgetreten ist 546 short SbxBasicFormater::AnalyseFormatString( const String& sFormatStrg, 547 short& nNoOfDigitsLeft, short& nNoOfDigitsRight, 548 short& nNoOfOptionalDigitsLeft, 549 short& nNoOfExponentDigits, short& nNoOfOptionalExponentDigits, 550 sal_Bool& bPercent, sal_Bool& bCurrency, sal_Bool& bScientific, 551 sal_Bool& bGenerateThousandSeparator, 552 short& nMultipleThousandSeparators ) 553 { 554 sal_uInt16 nLen; 555 short nState = 0; 556 557 nLen = sFormatStrg.Len(); 558 // initialisiere alle Z"ahler und Flags 559 nNoOfDigitsLeft = 0; 560 nNoOfDigitsRight = 0; 561 nNoOfOptionalDigitsLeft = 0; 562 nNoOfExponentDigits = 0; 563 nNoOfOptionalExponentDigits = 0; 564 bPercent = sal_False; 565 bCurrency = sal_False; 566 bScientific = sal_False; 567 // ab 11.7.97: sobald ein Komma in dem Format String gefunden wird, 568 // werden alle 3 Zehnerpotenzen markiert (d.h. tausender, milionen, ...) 569 // bisher wurde nur an den gesetzten Position ein Tausender-Separator 570 // ausgegeben oder wenn ein @ im Format-String stand. 571 // Dies war ein Missverstaendnis der VB Kompatiblitaet. 572 bGenerateThousandSeparator = sFormatStrg.Search( ',' ) != STRING_NOTFOUND; 573 nMultipleThousandSeparators = 0; 574 // und untersuche den Format-String nach den gew"unschten Informationen 575 for( sal_uInt16 i=0; i<nLen; i++ ) 576 { 577 sal_Unicode c = sFormatStrg.GetChar( i ); 578 switch( c ) { 579 case '#': 580 case '0': 581 if( nState==0 ) 582 { 583 nNoOfDigitsLeft++; 584 // TODO hier ggf. bessere Fehler-"Uberpr"ufung der Mantisse auf g"ultige Syntax (siehe Grammatik) 585 // ACHTUNG: 'undefiniertes' Verhalten falls # und 0 586 // gemischt werden !!! 587 // BEMERKUNG: eigentlich sind #-Platzhalter bei Scientific 588 // Darstellung vor dem Dezimal-Punkt sinnlos ! 589 if( c=='#' ) 590 nNoOfOptionalDigitsLeft++; 591 } 592 else if( nState==1 ) 593 nNoOfDigitsRight++; 594 else if( nState==-1 ) // suche 0 im Exponent 595 { 596 if( c=='#' ) // # schaltet den Zustand weiter 597 { 598 nNoOfOptionalExponentDigits++; 599 nState = -2; 600 } 601 nNoOfExponentDigits++; 602 } 603 else if( nState==-2 ) // suche # im Exponent 604 { 605 if( c=='0' ) 606 // ERROR: 0 nach # im Exponent ist NICHT erlaubt !! 607 return -4; 608 nNoOfOptionalExponentDigits++; 609 nNoOfExponentDigits++; 610 } 611 break; 612 case '.': 613 nState++; 614 if( nState>1 ) 615 return -1; // ERROR: zu viele Dezimal-Punkte 616 break; 617 case '%': 618 bPercent = sal_True; 619 /* old: 620 bPercent++; 621 if( bPercent>1 ) 622 return -2; // ERROR: zu viele Prozent-Zeichen 623 */ 624 break; 625 case '(': 626 bCurrency = sal_True; 627 break; 628 case ',': 629 { 630 sal_Unicode ch = sFormatStrg.GetChar( i+1 ); 631 // vorl"aufig wird NUR auf zwei aufeinanderfolgede 632 // Zeichen gepr"uft 633 if( ch!=0 && (ch==',' || ch=='.') ) 634 nMultipleThousandSeparators++; 635 } break; 636 case 'e': 637 case 'E': 638 // #i13821 not when no digits before 639 if( nNoOfDigitsLeft > 0 || nNoOfDigitsRight > 0 ) 640 { 641 nState = -1; // breche jetzt das Z"ahlen der Stellen ab 642 bScientific = sal_True; 643 } 644 /* old: 645 bScientific++; 646 if( bScientific>1 ) 647 return -3; // ERROR: zu viele Exponent-Zeichen 648 */ 649 break; 650 // EIGENES Kommando-Zeichen, das die Erzeugung der 651 // Tausender-Trennzeichen einschaltet 652 case '\\': 653 // Ignore next char 654 i++; 655 break; 656 case CREATE_1000SEP_CHAR: 657 bGenerateThousandSeparator = sal_True; 658 break; 659 } 660 } 661 return 0; 662 } 663 664 // das Flag bCreateSign zeigt an, dass bei der Mantisse ein Vorzeichen 665 // erzeugt werden soll 666 void SbxBasicFormater::ScanFormatString( double dNumber, 667 const String& sFormatStrg, String& sReturnStrg, 668 sal_Bool bCreateSign ) 669 { 670 short /*nErr,*/nNoOfDigitsLeft,nNoOfDigitsRight,nNoOfOptionalDigitsLeft, 671 nNoOfExponentDigits,nNoOfOptionalExponentDigits, 672 nMultipleThousandSeparators; 673 sal_Bool bPercent,bCurrency,bScientific,bGenerateThousandSeparator; 674 675 // Initialisiere den Return-String 676 sReturnStrg = String(); 677 678 // analysiere den Format-String, d.h. bestimme folgende Werte: 679 /* 680 - Anzahl der Ziffern vor dem Komma 681 - Anzahl der Ziffern nach dem Komma 682 - optionale Ziffern vor dem Komma 683 - Anzahl der Ziffern im Exponent 684 - optionale Ziffern im Exponent 685 - Prozent-Zeichen gefunden ? 686 - () f"ur negatives Vorzeichen ? 687 - Exponetial-Schreibweise ? 688 - sollen Tausender-Separatoren erzeugt werden ? 689 - wird ein Prozent-Zeichen gefunden ? --> dNumber *= 100.0; 690 - gibt es aufeinanderfolgende Tausender-Trennzeichen ? 691 ,, oder ,. --> dNumber /= 1000.0; 692 - sonstige Fehler ? mehrfache Dezimalpunkte, E's, etc. 693 --> Fehler werden zur Zeit einfach ignoriert 694 */ 695 /*nErr =*/ AnalyseFormatString( sFormatStrg,nNoOfDigitsLeft,nNoOfDigitsRight, 696 nNoOfOptionalDigitsLeft,nNoOfExponentDigits, 697 nNoOfOptionalExponentDigits, 698 bPercent,bCurrency,bScientific,bGenerateThousandSeparator, 699 nMultipleThousandSeparators ); 700 /* es werden alle Fehler ignoriert, wie in Visual-Basic 701 if( nErr!=0 ) 702 { 703 char sBuffer[512]; 704 705 //sprintf( sBuffer,"bad format-string >%s< err=%i",sFormatStrg,nErr ); 706 strcpy( sBuffer,"bad format-string" ); 707 ShowError( sBuffer ); 708 } 709 else 710 */ 711 { 712 // Spezialbehandlung f"ur Spezialzeichen 713 if( bPercent ) 714 dNumber *= 100.0; 715 // TODO: diese Vorgabe (,, oder ,.) ist NICHT Visual-Basic kompatibel ! 716 // Frage: soll das hier stehen bleiben (Anforderungen) ? 717 if( nMultipleThousandSeparators ) 718 dNumber /= 1000.0; 719 720 // einige Arbeits-Variablen 721 double dExponent; 722 short i,nLen; 723 short nState,nDigitPos,nExponentPos,nMaxDigit,nMaxExponentDigit; 724 sal_Bool bFirstDigit,bFirstExponentDigit,bFoundFirstDigit, 725 bIsNegative,bZeroSpaceOn, bSignHappend,bDigitPosNegative; 726 727 // Initialisierung der Arbeits-Variablen 728 bSignHappend = sal_False; 729 bFoundFirstDigit = sal_False; 730 bIsNegative = dNumber<0.0; 731 nLen = sFormatStrg.Len(); 732 dExponent = get_number_of_digits( dNumber ); 733 nExponentPos = 0; 734 nMaxExponentDigit = 0; 735 nMaxDigit = (short)dExponent; 736 bDigitPosNegative = false; 737 if( bScientific ) 738 { 739 //if( nNoOfOptionalDigitsLeft>0 ) 740 // ShowError( "# in scientific-format in front of the decimal-point has no effect" ); 741 // beim Exponent ggf. "uberz"ahlige Stellen vor dem Komma abziehen 742 dExponent = dExponent - (double)(nNoOfDigitsLeft-1); 743 nDigitPos = nMaxDigit; 744 nMaxExponentDigit = (short)get_number_of_digits( dExponent ); 745 nExponentPos = nNoOfExponentDigits-1 - nNoOfOptionalExponentDigits; 746 } 747 else 748 { 749 nDigitPos = nNoOfDigitsLeft-1; // Z"ahlweise f"angt bei 0 an, 10^0 750 // hier ben"otigt man keine Exponent-Daten ! 751 bDigitPosNegative = (nDigitPos < 0); 752 } 753 bFirstDigit = sal_True; 754 bFirstExponentDigit = sal_True; 755 nState = 0; // 0 --> Mantisse; 1 --> Exponent 756 bZeroSpaceOn = 0; 757 758 759 #ifdef _with_sprintf 760 InitScan( dNumber ); 761 #endif 762 // scanne jetzt den Format-String: 763 sal_Unicode cForce = 0; 764 for( i=0; i<nLen; i++ ) 765 { 766 sal_Unicode c; 767 if( cForce ) 768 { 769 c = cForce; 770 cForce = 0; 771 } 772 else 773 { 774 c = sFormatStrg.GetChar( i ); 775 } 776 switch( c ) { 777 case '0': 778 case '#': 779 if( nState==0 ) 780 { 781 // Behandlung der Mantisse 782 if( bFirstDigit ) 783 { 784 //org:bFirstDigit = sal_False; 785 // ggf. Vorzeichen erzeugen 786 // Bem.: bei bCurrency soll das negative 787 // Vorzeichen durch () angezeigt werden 788 if( bIsNegative && !bCreateSign/*!bCurrency*/ && !bSignHappend ) 789 { 790 // nur einmal ein Vorzeichen ausgeben 791 bSignHappend = sal_True; 792 StrAppendChar( sReturnStrg,'-' ); 793 } 794 // hier jetzt "uberz"ahlige Stellen ausgeben, 795 // d.h. vom Format-String nicht erfasste Stellen 796 if( nMaxDigit>nDigitPos ) 797 { 798 for( short j=nMaxDigit; j>nDigitPos; j-- ) 799 { 800 short nTempDigit; 801 #ifdef _with_sprintf 802 AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPosScan( j,bFoundFirstDigit ) ); 803 #else 804 AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPos( dNumber,j,dNumber,bFoundFirstDigit ) ); 805 #endif 806 // wurde wirklich eine Ziffer eingefuegt ? 807 if( nTempDigit!=_NO_DIGIT ) 808 // jetzt wurde wirklich eine Ziffer ausgegeben, Flag setzen 809 bFirstDigit = sal_False; 810 // muss ggf. ein Tausender-Trennzeichen erzeugt werden? 811 if( bGenerateThousandSeparator && ( c=='0' || nMaxDigit>=nDigitPos ) && j>0 && (j % 3 == 0) ) 812 StrAppendChar( sReturnStrg,cThousandSep ); 813 } 814 } 815 } 816 // muss f"ur eine leere Stelle eventuell eine 0 ausgegeben werden ? 817 if( nMaxDigit<nDigitPos && ( c=='0' || bZeroSpaceOn ) ) 818 { 819 AppendDigit( sReturnStrg,0 ); // Ja 820 // jetzt wurde wirklich eine Ziffer ausgegeben, Flag setzen 821 bFirstDigit = sal_False; 822 bZeroSpaceOn = 1; 823 // BEM.: bei Visual-Basic schaltet die erste 0 f"ur alle 824 // nachfolgenden # (bis zum Dezimal-Punkt) die 0 ein, 825 // dieses Verhalten wird hier mit dem Flag simmuliert. 826 // muss ggf. ein Tausender-Trennzeichen erzeugt werden? 827 if( bGenerateThousandSeparator && ( c=='0' || nMaxDigit>=nDigitPos ) && nDigitPos>0 && (nDigitPos % 3 == 0) ) 828 StrAppendChar( sReturnStrg,cThousandSep ); 829 } 830 else 831 { 832 short nTempDigit; 833 #ifdef _with_sprintf 834 AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPosScan( nDigitPos,bFoundFirstDigit ) ); 835 #else 836 AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPos( dNumber,nDigitPos,dNumber,bFoundFirstDigit ) ); 837 #endif 838 // wurde wirklich eine Ziffer eingefuegt ? 839 if( nTempDigit!=_NO_DIGIT ) 840 // jetzt wurde wirklich eine Ziffer ausgegeben, Flag setzen 841 bFirstDigit = sal_False; 842 // muss ggf. ein Tausender-Trennzeichen erzeugt werden? 843 if( bGenerateThousandSeparator && ( c=='0' || nMaxDigit>=nDigitPos ) && nDigitPos>0 && (nDigitPos % 3 == 0) ) 844 StrAppendChar( sReturnStrg,cThousandSep ); 845 } 846 // und Position aktualisieren 847 nDigitPos--; 848 } 849 else 850 { 851 // Behandlung des Exponenten 852 if( bFirstExponentDigit ) 853 { 854 // Vorzeichen wurde schon bei e/E ausgegeben 855 bFirstExponentDigit = sal_False; 856 if( nMaxExponentDigit>nExponentPos ) 857 // hier jetzt "uberz"ahlige Stellen ausgeben, 858 // d.h. vom Format-String nicht erfasste Stellen 859 { 860 for( short j=nMaxExponentDigit; j>nExponentPos; j-- ) 861 { 862 #ifdef _with_sprintf 863 AppendDigit( sReturnStrg,GetDigitAtPosExpScan( dExponent,j,bFoundFirstDigit ) ); 864 #else 865 AppendDigit( sReturnStrg,GetDigitAtPos( dExponent,j,dExponent,bFoundFirstDigit ) ); 866 #endif 867 } 868 } 869 } 870 // muss f"ur eine leere Stelle eventuell eine 0 ausgegeben werden ? 871 if( nMaxExponentDigit<nExponentPos && c=='0' ) 872 AppendDigit( sReturnStrg,0 ); // Ja 873 else 874 #ifdef _with_sprintf 875 AppendDigit( sReturnStrg,GetDigitAtPosExpScan( dExponent,nExponentPos,bFoundFirstDigit ) ); 876 #else 877 AppendDigit( sReturnStrg,GetDigitAtPos( dExponent,nExponentPos,dExponent,bFoundFirstDigit ) ); 878 #endif 879 nExponentPos--; 880 } 881 break; 882 case '.': 883 if( bDigitPosNegative ) // #i13821: If no digits before . 884 { 885 bDigitPosNegative = false; 886 nDigitPos = 0; 887 cForce = '#'; 888 i-=2; 889 break; 890 } 891 // gebe Komma aus 892 StrAppendChar( sReturnStrg,cDecPoint ); 893 break; 894 case '%': 895 // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00 896 ParseBack( sReturnStrg,sFormatStrg,i-1 ); 897 // gebe Prozent-Zeichen aus 898 sReturnStrg.Insert('%'); 899 break; 900 case 'e': 901 case 'E': 902 // muss Mantisse noch gerundet werden, bevor der Exponent angezeigt wird ? 903 { 904 // gibt es ueberhaupt eine Mantisse ? 905 if( bFirstDigit ) 906 { 907 // anscheinend nicht, d.h. ungueltiger Format String, z.B. E000.00 908 // d.h. ignoriere diese e bzw. E Zeichen 909 // ggf. einen Fehler (wie Visual Basic) ausgeben ? 910 911 // #i13821: VB 6 behaviour 912 StrAppendChar( sReturnStrg,c ); 913 break; 914 } 915 916 sal_Bool bOverflow = sal_False; 917 #ifdef _with_sprintf 918 short nNextDigit = GetDigitAtPosScan( nDigitPos,bFoundFirstDigit ); 919 #else 920 short nNextDigit = GetDigitAtPos( dNumber,nDigitPos,dNumber,bFoundFirstDigit ); 921 #endif 922 if( nNextDigit>=5 ) 923 StrRoundDigit( sReturnStrg,sReturnStrg.Len()-1,bOverflow ); 924 if( bOverflow ) 925 { 926 // es wurde eine f"uhrende 9 gerundet, d.h. 927 // verschiebe den Dezimal-Punkt um eine Stelle nach links 928 LeftShiftDecimalPoint( sReturnStrg ); 929 // und l"osche die letzte Ziffer, diese wird 930 // duch die f"uhrende 1 ersetzt: 931 sReturnStrg.SetChar( sReturnStrg.Len()-1 , 0 ); 932 // der Exponent muss um 1 erh"oht werden, 933 // da der Dezimalpunkt verschoben wurde 934 dExponent += 1.0; 935 } 936 // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00 937 ParseBack( sReturnStrg,sFormatStrg,i-1 ); 938 } 939 // "andere Zustand des Scanners 940 nState++; 941 // gebe Exponent-Zeichen aus 942 StrAppendChar( sReturnStrg,c ); 943 // i++; // MANIPULATION der Schleifen-Variable ! 944 c = sFormatStrg.GetChar( ++i ); 945 // und gebe Vorzeichen / Exponent aus 946 if( c!=0 ) 947 { 948 if( c=='-' ) 949 { 950 // falls Exponent < 0 gebe - aus 951 if( dExponent<0.0 ) 952 StrAppendChar( sReturnStrg,'-' ); 953 } 954 else if( c=='+' ) 955 { 956 // gebe auf jeden Fall das Vorzeichen des Exponenten aus ! 957 if( dExponent<0.0 ) 958 StrAppendChar( sReturnStrg,'-' ); 959 else 960 StrAppendChar( sReturnStrg,'+' ); 961 } 962 //else 963 // ShowError( "operator e/E did not find + or -" ); 964 } 965 //else 966 // ShowError( "operator e/E ended with 0" ); 967 break; 968 case ',': 969 // ACHTUNG: nur falls Zahl bisher ausgegeben wurde 970 // das Zeichen ausgeben 971 ////--> Siehe Kommentar vom 11.7. in AnalyseFormatString() 972 ////if( !bFirstDigit ) 973 //// // gebe Tausender-Trennzeichen aus 974 //// StrAppendChar( sReturnStrg,cThousandSep ); 975 break; 976 case ';': 977 break; 978 case '(': 979 case ')': 980 // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00 981 ParseBack( sReturnStrg,sFormatStrg,i-1 ); 982 if( bIsNegative ) 983 StrAppendChar( sReturnStrg,c ); 984 break; 985 case '$': 986 // den String fuer die Waehrung dranhengen: 987 sReturnStrg += sCurrencyStrg; 988 break; 989 case ' ': 990 case '-': 991 case '+': 992 // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00 993 ParseBack( sReturnStrg,sFormatStrg,i-1 ); 994 // gebe das jeweilige Zeichen direkt aus 995 StrAppendChar( sReturnStrg,c ); 996 break; 997 case '\\': 998 // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00 999 // falls Sonderzeichen am Ende oder mitten in 1000 // Format-String vorkommen 1001 ParseBack( sReturnStrg,sFormatStrg,i-1 ); 1002 // Sonderzeichen gefunden, gebe N"ACHSTES 1003 // Zeichen direkt aus (falls es existiert) 1004 // i++; 1005 c = sFormatStrg.GetChar( ++i ); 1006 if( c!=0 ) 1007 StrAppendChar( sReturnStrg,c ); 1008 //else 1009 // ShowError( "operator \\ ended with 0" ); 1010 break; 1011 case CREATE_1000SEP_CHAR: 1012 // hier ignorieren, Aktion wurde schon in 1013 // AnalyseFormatString durchgef"uhrt 1014 break; 1015 default: 1016 // auch die Zeichen und Ziffern ausgeben (wie in Visual-Basic) 1017 if( ( c>='a' && c<='z' ) || 1018 ( c>='A' && c<='Z' ) || 1019 ( c>='1' && c<='9' ) ) 1020 StrAppendChar( sReturnStrg,c ); 1021 // else 1022 // ignorieren ! 1023 // ehemals: ShowError( "bad character in format-string" ); 1024 } 1025 } 1026 // Format-String wurde vollst"andig gescanned, 1027 // muss die letzte Stelle nun gerundet werden ? 1028 // Dies hier ist jedoch NUR notwendig, falls das 1029 // Zahlenformat NICHT Scientific-Format ist ! 1030 if( !bScientific ) 1031 { 1032 #ifdef _with_sprintf 1033 short nNextDigit = GetDigitAtPosScan( nDigitPos,bFoundFirstDigit ); 1034 #else 1035 short nNextDigit = GetDigitAtPos( dNumber,nDigitPos,dNumber,bFoundFirstDigit ); 1036 #endif 1037 if( nNextDigit>=5 ) 1038 StrRoundDigit( sReturnStrg,sReturnStrg.Len()-1 ); 1039 } 1040 // und ganz zum Schluss: 1041 // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00#, 1042 // ABER nur Stellen nach dem Dezimal-Punkt k"onnen gel"oscht werden 1043 if( nNoOfDigitsRight>0 ) 1044 ParseBack( sReturnStrg,sFormatStrg,sFormatStrg.Len()-1 ); 1045 } 1046 } 1047 1048 String SbxBasicFormater::BasicFormatNull( String sFormatStrg ) 1049 { 1050 sal_Bool bNullFormatFound; 1051 String sNullFormatStrg = GetNullFormatString( sFormatStrg,bNullFormatFound ); 1052 1053 if( bNullFormatFound ) 1054 return sNullFormatStrg; 1055 String aRetStr; 1056 aRetStr.AssignAscii( "null" ); 1057 return aRetStr; 1058 } 1059 1060 String SbxBasicFormater::BasicFormat( double dNumber, String sFormatStrg ) 1061 { 1062 sal_Bool bPosFormatFound,bNegFormatFound,b0FormatFound; 1063 1064 // analysiere Format-String auf vordefinierte Formate: 1065 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_GENERALNUMBER ) ) 1066 sFormatStrg.AssignAscii( GENERALNUMBER_FORMAT ); 1067 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_CURRENCY ) ) 1068 sFormatStrg = sCurrencyFormatStrg; // old: CURRENCY_FORMAT; 1069 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_FIXED ) ) 1070 sFormatStrg.AssignAscii( FIXED_FORMAT ); 1071 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_STANDARD ) ) 1072 sFormatStrg.AssignAscii( STANDARD_FORMAT ); 1073 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_PERCENT ) ) 1074 sFormatStrg.AssignAscii( PERCENT_FORMAT ); 1075 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_SCIENTIFIC ) ) 1076 sFormatStrg.AssignAscii( SCIENTIFIC_FORMAT ); 1077 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_YESNO ) ) 1078 return ( dNumber==0.0 ) ? sNoStrg : sYesStrg ; 1079 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_TRUEFALSE ) ) 1080 return ( dNumber==0.0 ) ? sFalseStrg : sTrueStrg ; 1081 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_ONOFF ) ) 1082 return ( dNumber==0.0 ) ? sOffStrg : sOnStrg ; 1083 1084 // analysiere Format-String auf ';', d.h. Format-Strings f"ur 1085 // positive-, negative- und 0-Werte 1086 String sPosFormatStrg = GetPosFormatString( sFormatStrg, bPosFormatFound ); 1087 String sNegFormatStrg = GetNegFormatString( sFormatStrg, bNegFormatFound ); 1088 String s0FormatStrg = Get0FormatString( sFormatStrg, b0FormatFound ); 1089 //String sNullFormatStrg = GetNullFormatString( sFormatStrg, bNullFormatFound ); 1090 1091 String sReturnStrg; 1092 String sTempStrg; 1093 1094 if( dNumber==0.0 ) 1095 { 1096 sTempStrg = sFormatStrg; 1097 if( b0FormatFound ) 1098 { 1099 // wurde ggf. Leer-String uebergeben ? 1100 if( s0FormatStrg.Len() == 0 && bPosFormatFound ) 1101 // --> Ja, dann verwende String fuer positive Werte 1102 sTempStrg = sPosFormatStrg; 1103 else 1104 sTempStrg = s0FormatStrg; 1105 } 1106 else if( bPosFormatFound ) 1107 { 1108 // verwende String fuer positive Werte 1109 sTempStrg = sPosFormatStrg; 1110 } 1111 ScanFormatString( dNumber, sTempStrg, sReturnStrg,/*bCreateSign=*/sal_False ); 1112 } 1113 else 1114 { 1115 if( dNumber<0.0 ) 1116 { 1117 if( bNegFormatFound ) 1118 { 1119 // wurde ggf. Leer-String uebergeben ? 1120 if( sNegFormatStrg.Len() == 0 && bPosFormatFound ) 1121 { 1122 // --> Ja, dann verwende String fuer positive Werte 1123 // und setzte Minus-Zeichen davor ! 1124 sTempStrg = String::CreateFromAscii("-"); 1125 sTempStrg += sPosFormatStrg; 1126 } 1127 else 1128 sTempStrg = sNegFormatStrg; 1129 } 1130 else 1131 sTempStrg = sFormatStrg; 1132 // falls KEIN Format-String speziell f"ur negative Werte angegeben 1133 // wurde, so soll das Vorzeichen ausgegeben werden 1134 ScanFormatString( dNumber, sTempStrg, sReturnStrg,/*bCreateSign=*/bNegFormatFound/*sNegFormatStrg!=EMPTYFORMATSTRING*/ ); 1135 } 1136 else // if( dNumber>0.0 ) 1137 { 1138 ScanFormatString( dNumber, 1139 (/*sPosFormatStrg!=EMPTYFORMATSTRING*/bPosFormatFound ? sPosFormatStrg : sFormatStrg), 1140 sReturnStrg,/*bCreateSign=*/sal_False ); 1141 } 1142 } 1143 return sReturnStrg; 1144 } 1145 1146 sal_Bool SbxBasicFormater::isBasicFormat( String sFormatStrg ) 1147 { 1148 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_GENERALNUMBER ) ) 1149 return sal_True; 1150 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_CURRENCY ) ) 1151 return sal_True; 1152 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_FIXED ) ) 1153 return sal_True; 1154 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_STANDARD ) ) 1155 return sal_True; 1156 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_PERCENT ) ) 1157 return sal_True; 1158 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_SCIENTIFIC ) ) 1159 return sal_True; 1160 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_YESNO ) ) 1161 return sal_True; 1162 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_TRUEFALSE ) ) 1163 return sal_True; 1164 if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_ONOFF ) ) 1165 return sal_True; 1166 return sal_False; 1167 } 1168 1169