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