2005-04-13 08:25:31 +00:00
|
|
|
|
/*************************************************************************
|
|
|
|
|
*
|
2008-04-11 11:19:34 +00:00
|
|
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
2005-04-13 08:25:31 +00:00
|
|
|
|
*
|
2008-04-11 11:19:34 +00:00
|
|
|
|
* Copyright 2008 by Sun Microsystems, Inc.
|
2005-04-13 08:25:31 +00:00
|
|
|
|
*
|
2008-04-11 11:19:34 +00:00
|
|
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
2005-04-13 08:25:31 +00:00
|
|
|
|
*
|
2008-04-11 11:19:34 +00:00
|
|
|
|
* $RCSfile: sbxscan.cxx,v $
|
2008-07-02 09:04:30 +00:00
|
|
|
|
* $Revision: 1.14 $
|
2005-04-13 08:25:31 +00:00
|
|
|
|
*
|
2008-04-11 11:19:34 +00:00
|
|
|
|
* This file is part of OpenOffice.org.
|
2005-04-13 08:25:31 +00:00
|
|
|
|
*
|
2008-04-11 11:19:34 +00:00
|
|
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
|
|
|
* only, as published by the Free Software Foundation.
|
2005-04-13 08:25:31 +00:00
|
|
|
|
*
|
2008-04-11 11:19:34 +00:00
|
|
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU Lesser General Public License version 3 for more details
|
|
|
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
2005-04-13 08:25:31 +00:00
|
|
|
|
*
|
2008-04-11 11:19:34 +00:00
|
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
|
|
|
* <http://www.openoffice.org/license.html>
|
|
|
|
|
* for a copy of the LGPLv3 License.
|
2005-04-13 08:25:31 +00:00
|
|
|
|
*
|
|
|
|
|
************************************************************************/
|
|
|
|
|
|
2006-09-17 09:11:30 +00:00
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
|
|
|
#include "precompiled_basic.hxx"
|
2005-04-13 08:25:31 +00:00
|
|
|
|
#include <tools/errcode.hxx>
|
2007-06-27 13:31:47 +00:00
|
|
|
|
#include <basic/sbx.hxx>
|
2005-04-13 08:25:31 +00:00
|
|
|
|
#include "sbxconv.hxx"
|
|
|
|
|
|
|
|
|
|
#include "svtools/syslocale.hxx"
|
|
|
|
|
|
2006-06-19 16:51:12 +00:00
|
|
|
|
#if defined ( UNX )
|
2005-04-13 08:25:31 +00:00
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef _APP_HXX //autogen
|
|
|
|
|
#include <vcl/svapp.hxx>
|
|
|
|
|
#endif
|
|
|
|
|
#include <math.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
|
|
#include "sbxres.hxx"
|
2007-06-27 13:31:47 +00:00
|
|
|
|
#include <basic/sbxbase.hxx>
|
|
|
|
|
#include <basic/sbxform.hxx>
|
2005-04-13 08:25:31 +00:00
|
|
|
|
#include <svtools/svtools.hrc>
|
|
|
|
|
|
|
|
|
|
#include "basrid.hxx"
|
2008-10-28 08:22:18 +00:00
|
|
|
|
#include "runtime.hxx"
|
2005-04-13 08:25:31 +00:00
|
|
|
|
|
2008-01-28 13:01:14 +00:00
|
|
|
|
#include <svtools/zforlist.hxx>
|
|
|
|
|
#include <comphelper/processfactory.hxx>
|
|
|
|
|
|
|
|
|
|
|
2005-04-13 08:25:31 +00:00
|
|
|
|
void ImpGetIntntlSep( sal_Unicode& rcDecimalSep, sal_Unicode& rcThousandSep )
|
|
|
|
|
{
|
|
|
|
|
SvtSysLocale aSysLocale;
|
|
|
|
|
const LocaleDataWrapper& rData = aSysLocale.GetLocaleData();
|
|
|
|
|
rcDecimalSep = rData.getNumDecimalSep().GetBuffer()[0];
|
|
|
|
|
rcThousandSep = rData.getNumThousandSep().GetBuffer()[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Scannen eines Strings nach BASIC-Konventionen
|
|
|
|
|
// Dies entspricht den ueblichen Konventionen, nur dass der Exponent
|
|
|
|
|
// auch ein D sein darf, was den Datentyp auf SbxDOUBLE festlegt.
|
|
|
|
|
// Die Routine versucht, den Datentyp so klein wie moeglich zu gestalten.
|
|
|
|
|
// Das ganze gibt auch noch einen Konversionsfehler, wenn der Datentyp
|
|
|
|
|
// Fixed ist und das ganze nicht hineinpasst!
|
|
|
|
|
|
|
|
|
|
SbxError ImpScan( const XubString& rWSrc, double& nVal, SbxDataType& rType,
|
|
|
|
|
USHORT* pLen, BOOL bAllowIntntl, BOOL bOnlyIntntl )
|
|
|
|
|
{
|
|
|
|
|
ByteString aBStr( rWSrc, RTL_TEXTENCODING_ASCII_US );
|
|
|
|
|
|
|
|
|
|
// Bei International Komma besorgen
|
|
|
|
|
char cIntntlComma, cIntntl1000;
|
|
|
|
|
char cNonIntntlComma = '.';
|
|
|
|
|
|
2006-10-12 13:33:35 +00:00
|
|
|
|
sal_Unicode cDecimalSep, cThousandSep = 0;
|
2005-04-13 08:25:31 +00:00
|
|
|
|
if( bAllowIntntl || bOnlyIntntl )
|
|
|
|
|
{
|
|
|
|
|
ImpGetIntntlSep( cDecimalSep, cThousandSep );
|
|
|
|
|
cIntntlComma = (char)cDecimalSep;
|
|
|
|
|
cIntntl1000 = (char)cThousandSep;
|
|
|
|
|
}
|
|
|
|
|
// Sonst einfach auch auf . setzen
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cIntntlComma = cNonIntntlComma;
|
|
|
|
|
cIntntl1000 = cNonIntntlComma; // Unschaedlich machen
|
|
|
|
|
}
|
|
|
|
|
// Nur International -> IntnlComma uebernehmen
|
|
|
|
|
if( bOnlyIntntl )
|
|
|
|
|
{
|
|
|
|
|
cNonIntntlComma = cIntntlComma;
|
|
|
|
|
cIntntl1000 = (char)cThousandSep;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char* pStart = aBStr.GetBuffer();
|
|
|
|
|
const char* p = pStart;
|
|
|
|
|
char buf[ 80 ], *q = buf;
|
|
|
|
|
BOOL bRes = TRUE;
|
|
|
|
|
BOOL bMinus = FALSE;
|
|
|
|
|
nVal = 0;
|
|
|
|
|
SbxDataType eScanType = SbxSINGLE;
|
|
|
|
|
// Whitespace wech
|
|
|
|
|
while( *p &&( *p == ' ' || *p == '\t' ) ) p++;
|
|
|
|
|
// Zahl? Dann einlesen und konvertieren.
|
|
|
|
|
if( *p == '-' )
|
|
|
|
|
p++, bMinus = TRUE;
|
|
|
|
|
if( isdigit( *p ) ||( (*p == cNonIntntlComma || *p == cIntntlComma ||
|
|
|
|
|
*p == cIntntl1000) && isdigit( *(p+1 ) ) ) )
|
|
|
|
|
{
|
|
|
|
|
short exp = 0; // >0: Exponentteil
|
|
|
|
|
short comma = 0; // >0: Nachkomma
|
|
|
|
|
short ndig = 0; // Anzahl Ziffern
|
|
|
|
|
short ncdig = 0; // Anzahl Ziffern nach Komma
|
|
|
|
|
ByteString aSearchStr( "0123456789DEde" );
|
|
|
|
|
// Kommas ergaenzen
|
|
|
|
|
aSearchStr += cNonIntntlComma;
|
|
|
|
|
if( cIntntlComma != cNonIntntlComma )
|
|
|
|
|
aSearchStr += cIntntlComma;
|
|
|
|
|
if( bOnlyIntntl )
|
|
|
|
|
aSearchStr += cIntntl1000;
|
|
|
|
|
const char* pSearchStr = aSearchStr.GetBuffer();
|
|
|
|
|
while( strchr( pSearchStr, *p ) && *p )
|
|
|
|
|
{
|
|
|
|
|
// 1000er-Trenner ueberlesen
|
|
|
|
|
if( bOnlyIntntl && *p == cIntntl1000 )
|
|
|
|
|
{
|
|
|
|
|
p++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Komma oder Exponent?
|
|
|
|
|
if( *p == cNonIntntlComma || *p == cIntntlComma )
|
|
|
|
|
{
|
|
|
|
|
// Immer '.' einfuegen, damit atof funktioniert
|
|
|
|
|
p++;
|
|
|
|
|
if( ++comma > 1 )
|
|
|
|
|
continue;
|
|
|
|
|
else
|
|
|
|
|
*q++ = '.';
|
|
|
|
|
}
|
|
|
|
|
else if( strchr( "DdEe", *p ) )
|
|
|
|
|
{
|
|
|
|
|
if( ++exp > 1 )
|
|
|
|
|
{
|
|
|
|
|
p++; continue;
|
|
|
|
|
}
|
|
|
|
|
if( toupper( *p ) == 'D' )
|
|
|
|
|
eScanType = SbxDOUBLE;
|
|
|
|
|
*q++ = 'E'; p++;
|
|
|
|
|
// Vorzeichen hinter Exponent?
|
|
|
|
|
if( *p == '+' )
|
|
|
|
|
p++;
|
|
|
|
|
else
|
|
|
|
|
if( *p == '-' )
|
|
|
|
|
*q++ = *p++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*q++ = *p++;
|
|
|
|
|
if( comma && !exp ) ncdig++;
|
|
|
|
|
}
|
|
|
|
|
if( !exp ) ndig++;
|
|
|
|
|
}
|
|
|
|
|
*q = 0;
|
|
|
|
|
// Komma, Exponent mehrfach vorhanden?
|
|
|
|
|
if( comma > 1 || exp > 1 )
|
|
|
|
|
bRes = FALSE;
|
|
|
|
|
// Kann auf Integer gefaltet werden?
|
|
|
|
|
if( !comma && !exp )
|
|
|
|
|
{
|
|
|
|
|
if( nVal >= SbxMININT && nVal <= SbxMAXINT )
|
|
|
|
|
eScanType = SbxINTEGER;
|
|
|
|
|
else if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
|
|
|
|
|
eScanType = SbxLONG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nVal = atof( buf );
|
2006-10-12 13:33:35 +00:00
|
|
|
|
ndig = ndig - comma;
|
2005-04-13 08:25:31 +00:00
|
|
|
|
// zu viele Zahlen fuer SINGLE?
|
|
|
|
|
if( ndig > 15 || ncdig > 6 )
|
|
|
|
|
eScanType = SbxDOUBLE;
|
|
|
|
|
|
|
|
|
|
// Typkennung?
|
|
|
|
|
if( strchr( "%!&#", *p ) && *p ) p++;
|
|
|
|
|
}
|
|
|
|
|
// Hex/Oktalzahl? Einlesen und konvertieren:
|
|
|
|
|
else if( *p == '&' )
|
|
|
|
|
{
|
|
|
|
|
p++;
|
|
|
|
|
eScanType = SbxLONG;
|
|
|
|
|
const char *cmp = "0123456789ABCDEF";
|
|
|
|
|
char base = 16;
|
|
|
|
|
char ndig = 8;
|
|
|
|
|
char xch = *p++;
|
|
|
|
|
switch( toupper( xch ) )
|
|
|
|
|
{
|
|
|
|
|
case 'O': cmp = "01234567"; base = 8; ndig = 11; break;
|
|
|
|
|
case 'H': break;
|
|
|
|
|
default : bRes = FALSE;
|
|
|
|
|
}
|
|
|
|
|
long l = 0;
|
|
|
|
|
int i;
|
|
|
|
|
while( isalnum( *p ) )
|
|
|
|
|
{
|
2006-10-12 13:33:35 +00:00
|
|
|
|
char ch = sal::static_int_cast< char >( toupper( *p ) );
|
2005-04-13 08:25:31 +00:00
|
|
|
|
p++;
|
|
|
|
|
if( strchr( cmp, ch ) ) *q++ = ch;
|
|
|
|
|
else bRes = FALSE;
|
|
|
|
|
}
|
|
|
|
|
*q = 0;
|
|
|
|
|
for( q = buf; *q; q++ )
|
|
|
|
|
{
|
|
|
|
|
i =( *q & 0xFF ) - '0';
|
|
|
|
|
if( i > 9 ) i -= 7;
|
|
|
|
|
l =( l * base ) + i;
|
|
|
|
|
if( !ndig-- )
|
|
|
|
|
bRes = FALSE;
|
|
|
|
|
}
|
|
|
|
|
if( *p == '&' ) p++;
|
|
|
|
|
nVal = (double) l;
|
|
|
|
|
if( l >= SbxMININT && l <= SbxMAXINT )
|
|
|
|
|
eScanType = SbxINTEGER;
|
|
|
|
|
}
|
2008-10-28 08:22:18 +00:00
|
|
|
|
else if ( SbiRuntime::isVBAEnabled() )
|
|
|
|
|
{
|
|
|
|
|
OSL_TRACE("Reporting error converting");
|
|
|
|
|
return SbxERR_CONVERSION;
|
|
|
|
|
}
|
2005-04-13 08:25:31 +00:00
|
|
|
|
if( pLen )
|
|
|
|
|
*pLen = (USHORT) ( p - pStart );
|
|
|
|
|
if( !bRes )
|
|
|
|
|
return SbxERR_CONVERSION;
|
|
|
|
|
if( bMinus )
|
|
|
|
|
nVal = -nVal;
|
|
|
|
|
rType = eScanType;
|
|
|
|
|
return SbxERR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Schnittstelle fuer CDbl im Basic
|
|
|
|
|
SbxError SbxValue::ScanNumIntnl( const String& rSrc, double& nVal, BOOL bSingle )
|
|
|
|
|
{
|
|
|
|
|
SbxDataType t;
|
|
|
|
|
USHORT nLen = 0;
|
|
|
|
|
SbxError nRetError = ImpScan( rSrc, nVal, t, &nLen,
|
|
|
|
|
/*bAllowIntntl*/FALSE, /*bOnlyIntntl*/TRUE );
|
|
|
|
|
// Komplett gelesen?
|
|
|
|
|
if( nRetError == SbxERR_OK && nLen != rSrc.Len() )
|
|
|
|
|
nRetError = SbxERR_CONVERSION;
|
|
|
|
|
|
|
|
|
|
if( bSingle )
|
|
|
|
|
{
|
|
|
|
|
SbxValues aValues( nVal );
|
|
|
|
|
nVal = (double)ImpGetSingle( &aValues ); // Hier Error bei Overflow
|
|
|
|
|
}
|
|
|
|
|
return nRetError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
static double roundArray[] = {
|
|
|
|
|
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,
|
|
|
|
|
0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14,0.5e-15 };
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
|
|*
|
|
|
|
|
|* void myftoa( double, char *, short, short, BOOL, BOOL )
|
|
|
|
|
|*
|
|
|
|
|
|* Beschreibung: Konversion double --> ASCII
|
|
|
|
|
|* Parameter: double die Zahl.
|
|
|
|
|
|* char * der Zielpuffer
|
|
|
|
|
|* short Anzahl Nachkommastellen
|
|
|
|
|
|* short Weite des Exponenten( 0=kein E )
|
|
|
|
|
|* BOOL TRUE: mit 1000er Punkten
|
|
|
|
|
|* BOOL TRUE: formatfreie Ausgabe
|
|
|
|
|
|*
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void myftoa( double nNum, char * pBuf, short nPrec, short nExpWidth,
|
|
|
|
|
BOOL bPt, BOOL bFix, sal_Unicode cForceThousandSep = 0 )
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
short nExp = 0; // Exponent
|
|
|
|
|
short nDig = nPrec + 1; // Anzahl Digits in Zahl
|
|
|
|
|
short nDec; // Anzahl Vorkommastellen
|
|
|
|
|
register int i, digit;
|
|
|
|
|
|
|
|
|
|
// Komma besorgen
|
|
|
|
|
sal_Unicode cDecimalSep, cThousandSep;
|
|
|
|
|
ImpGetIntntlSep( cDecimalSep, cThousandSep );
|
|
|
|
|
if( cForceThousandSep )
|
|
|
|
|
cThousandSep = cForceThousandSep;
|
|
|
|
|
|
|
|
|
|
// Exponentberechnung:
|
|
|
|
|
nExp = 0;
|
|
|
|
|
if( nNum > 0.0 )
|
|
|
|
|
{
|
|
|
|
|
while( nNum < 1.0 ) nNum *= 10.0, nExp--;
|
|
|
|
|
while( nNum >= 10.0 ) nNum /= 10.0, nExp++;
|
|
|
|
|
}
|
|
|
|
|
if( !bFix && !nExpWidth )
|
2006-10-12 13:33:35 +00:00
|
|
|
|
nDig = nDig + nExp;
|
2005-04-13 08:25:31 +00:00
|
|
|
|
else if( bFix && !nPrec )
|
|
|
|
|
nDig = nExp + 1;
|
|
|
|
|
|
|
|
|
|
// Zahl runden:
|
|
|
|
|
if( (nNum += roundArray [( nDig > 16 ) ? 16 : nDig] ) >= 10.0 )
|
|
|
|
|
{
|
|
|
|
|
nNum = 1.0;
|
|
|
|
|
++nExp;
|
|
|
|
|
if( !nExpWidth ) ++nDig;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Bestimmung der Vorkommastellen:
|
|
|
|
|
if( !nExpWidth )
|
|
|
|
|
{
|
|
|
|
|
if( nExp < 0 )
|
|
|
|
|
{
|
|
|
|
|
// #41691: Auch bei bFix eine 0 spendieren
|
|
|
|
|
*pBuf++ = '0';
|
|
|
|
|
if( nPrec ) *pBuf++ = (char)cDecimalSep;
|
|
|
|
|
i = -nExp - 1;
|
|
|
|
|
if( nDig <= 0 ) i = nPrec;
|
|
|
|
|
while( i-- ) *pBuf++ = '0';
|
|
|
|
|
nDec = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
nDec = nExp+1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
nDec = 1;
|
|
|
|
|
|
|
|
|
|
// Zahl ausgeben:
|
|
|
|
|
if( nDig > 0 )
|
|
|
|
|
{
|
|
|
|
|
for( i = 0 ; ; ++i )
|
|
|
|
|
{
|
|
|
|
|
if( i < 16 )
|
|
|
|
|
{
|
|
|
|
|
digit = (int) nNum;
|
2006-10-12 13:33:35 +00:00
|
|
|
|
*pBuf++ = sal::static_int_cast< char >(digit + '0');
|
2005-04-13 08:25:31 +00:00
|
|
|
|
nNum =( nNum - digit ) * 10.0;
|
|
|
|
|
} else
|
|
|
|
|
*pBuf++ = '0';
|
|
|
|
|
if( --nDig == 0 ) break;
|
|
|
|
|
if( nDec )
|
|
|
|
|
{
|
|
|
|
|
nDec--;
|
|
|
|
|
if( !nDec )
|
|
|
|
|
*pBuf++ = (char)cDecimalSep;
|
|
|
|
|
else if( !(nDec % 3 ) && bPt )
|
|
|
|
|
*pBuf++ = (char)cThousandSep;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Exponent ausgeben:
|
|
|
|
|
if( nExpWidth )
|
|
|
|
|
{
|
|
|
|
|
if( nExpWidth < 3 ) nExpWidth = 3;
|
|
|
|
|
nExpWidth -= 2;
|
|
|
|
|
*pBuf++ = 'E';
|
|
|
|
|
*pBuf++ =( nExp < 0 ) ?( (nExp = -nExp ), '-' ) : '+';
|
|
|
|
|
while( nExpWidth > 3 ) *pBuf++ = '0', nExpWidth--;
|
|
|
|
|
if( nExp >= 100 || nExpWidth == 3 )
|
|
|
|
|
{
|
2006-10-12 13:33:35 +00:00
|
|
|
|
*pBuf++ = sal::static_int_cast< char >(nExp/100 + '0');
|
2005-04-13 08:25:31 +00:00
|
|
|
|
nExp %= 100;
|
|
|
|
|
}
|
|
|
|
|
if( nExp/10 || nExpWidth >= 2 )
|
2006-10-12 13:33:35 +00:00
|
|
|
|
*pBuf++ = sal::static_int_cast< char >(nExp/10 + '0');
|
|
|
|
|
*pBuf++ = sal::static_int_cast< char >(nExp%10 + '0');
|
2005-04-13 08:25:31 +00:00
|
|
|
|
}
|
|
|
|
|
*pBuf = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Die Zahl wird unformatiert mit der angegebenen Anzahl NK-Stellen
|
|
|
|
|
// aufbereitet. Evtl. wird ein Minus vorangestellt.
|
|
|
|
|
// Diese Routine ist public, weil sie auch von den Put-Funktionen
|
|
|
|
|
// der Klasse SbxImpSTRING verwendet wird.
|
|
|
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
#pragma optimize( "", off )
|
2007-11-13 14:23:45 +00:00
|
|
|
|
#pragma warning(disable: 4748) // "... because optimizations are disabled ..."
|
2005-04-13 08:25:31 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void ImpCvtNum( double nNum, short nPrec, XubString& rRes, BOOL bCoreString )
|
|
|
|
|
{
|
|
|
|
|
char *q;
|
|
|
|
|
char cBuf[ 40 ], *p = cBuf;
|
|
|
|
|
|
|
|
|
|
sal_Unicode cDecimalSep, cThousandSep;
|
|
|
|
|
ImpGetIntntlSep( cDecimalSep, cThousandSep );
|
|
|
|
|
if( bCoreString )
|
|
|
|
|
cDecimalSep = '.';
|
|
|
|
|
|
|
|
|
|
if( nNum < 0.0 ) {
|
|
|
|
|
nNum = -nNum;
|
|
|
|
|
*p++ = '-';
|
|
|
|
|
}
|
|
|
|
|
double dMaxNumWithoutExp = (nPrec == 6) ? 1E6 : 1E14;
|
|
|
|
|
myftoa( nNum, p, nPrec,( nNum &&( nNum < 1E-1 || nNum > dMaxNumWithoutExp ) ) ? 4:0,
|
|
|
|
|
FALSE, TRUE, cDecimalSep );
|
|
|
|
|
// Trailing Zeroes weg:
|
|
|
|
|
for( p = cBuf; *p &&( *p != 'E' ); p++ ) {}
|
|
|
|
|
q = p; p--;
|
|
|
|
|
while( nPrec && *p == '0' ) nPrec--, p--;
|
|
|
|
|
if( *p == cDecimalSep ) p--;
|
|
|
|
|
while( *q ) *++p = *q++;
|
|
|
|
|
*++p = 0;
|
|
|
|
|
rRes = String::CreateFromAscii( cBuf );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
#pragma optimize( "", on )
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
BOOL ImpConvStringExt( XubString& rSrc, SbxDataType eTargetType )
|
|
|
|
|
{
|
|
|
|
|
// Merken, ob ueberhaupt was geaendert wurde
|
|
|
|
|
BOOL bChanged = FALSE;
|
|
|
|
|
String aNewString;
|
|
|
|
|
|
|
|
|
|
// Nur Spezial-F<>lle behandeln, als Default tun wir nichts
|
|
|
|
|
switch( eTargetType )
|
|
|
|
|
{
|
|
|
|
|
// Bei Fliesskomma International beruecksichtigen
|
|
|
|
|
case SbxSINGLE:
|
|
|
|
|
case SbxDOUBLE:
|
|
|
|
|
case SbxCURRENCY:
|
|
|
|
|
{
|
|
|
|
|
ByteString aBStr( rSrc, RTL_TEXTENCODING_ASCII_US );
|
|
|
|
|
|
|
|
|
|
// Komma besorgen
|
|
|
|
|
sal_Unicode cDecimalSep, cThousandSep;
|
|
|
|
|
ImpGetIntntlSep( cDecimalSep, cThousandSep );
|
|
|
|
|
aNewString = rSrc;
|
|
|
|
|
|
|
|
|
|
// Ersetzen, wenn DecimalSep kein '.' (nur den ersten)
|
|
|
|
|
if( cDecimalSep != (sal_Unicode)'.' )
|
|
|
|
|
{
|
|
|
|
|
USHORT nPos = aNewString.Search( cDecimalSep );
|
|
|
|
|
if( nPos != STRING_NOTFOUND )
|
|
|
|
|
{
|
|
|
|
|
aNewString.SetChar( nPos, '.' );
|
|
|
|
|
bChanged = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Bei BOOL TRUE und FALSE als String pruefen
|
|
|
|
|
case SbxBOOL:
|
|
|
|
|
{
|
|
|
|
|
if( rSrc.EqualsIgnoreCaseAscii( "true" ) )
|
|
|
|
|
{
|
|
|
|
|
aNewString = String::CreateFromInt32(SbxTRUE);
|
|
|
|
|
bChanged = TRUE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if( rSrc.EqualsIgnoreCaseAscii( "false" ) )
|
|
|
|
|
{
|
|
|
|
|
aNewString = String::CreateFromInt32(SbxFALSE);
|
|
|
|
|
bChanged = TRUE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2006-06-19 16:51:12 +00:00
|
|
|
|
default: break;
|
2005-04-13 08:25:31 +00:00
|
|
|
|
}
|
|
|
|
|
// String bei Aenderung uebernehmen
|
|
|
|
|
if( bChanged )
|
|
|
|
|
rSrc = aNewString;
|
|
|
|
|
return bChanged;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Formatierte Zahlenausgabe
|
|
|
|
|
// Der Returnwert ist die Anzahl Zeichen, die aus dem
|
|
|
|
|
// Format verwendt wurden.
|
|
|
|
|
|
|
|
|
|
#ifdef _old_format_code_
|
|
|
|
|
// lasse diesen Code vorl"aufig drin, zum 'abgucken'
|
|
|
|
|
// der bisherigen Implementation
|
|
|
|
|
|
|
|
|
|
static USHORT printfmtnum( double nNum, XubString& rRes, const XubString& rWFmt )
|
|
|
|
|
{
|
|
|
|
|
const String& rFmt = rWFmt;
|
|
|
|
|
char cFill = ' '; // Fuellzeichen
|
|
|
|
|
char cPre = 0; // Startzeichen( evtl. "$" )
|
|
|
|
|
short nExpDig= 0; // Anzahl Exponentstellen
|
|
|
|
|
short nPrec = 0; // Anzahl Nachkommastellen
|
|
|
|
|
short nWidth = 0; // Zahlenweite gesamnt
|
|
|
|
|
short nLen; // Laenge konvertierte Zahl
|
|
|
|
|
BOOL bPoint = FALSE; // TRUE: mit 1000er Kommas
|
|
|
|
|
BOOL bTrail = FALSE; // TRUE, wenn folgendes Minus
|
|
|
|
|
BOOL bSign = FALSE; // TRUE: immer mit Vorzeichen
|
|
|
|
|
BOOL bNeg = FALSE; // TRUE: Zahl ist negativ
|
|
|
|
|
char cBuf [1024]; // Zahlenpuffer
|
|
|
|
|
char * p;
|
|
|
|
|
const char* pFmt = rFmt;
|
|
|
|
|
rRes.Erase();
|
|
|
|
|
// $$ und ** abfangen. Einfach wird als Zeichen ausgegeben.
|
|
|
|
|
if( *pFmt == '$' )
|
|
|
|
|
if( *++pFmt != '$' ) rRes += '$';
|
|
|
|
|
if( *pFmt == '*' )
|
|
|
|
|
if( *++pFmt != '*' ) rRes += '*';
|
|
|
|
|
|
|
|
|
|
switch( *pFmt++ )
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
break;
|
|
|
|
|
case '+':
|
|
|
|
|
bSign = TRUE; nWidth++; break;
|
|
|
|
|
case '*':
|
|
|
|
|
nWidth++; cFill = '*';
|
|
|
|
|
if( *pFmt == '$' ) nWidth++, pFmt++, cPre = '$';
|
|
|
|
|
break;
|
|
|
|
|
case '$':
|
|
|
|
|
nWidth++; cPre = '$'; break;
|
|
|
|
|
case '#':
|
|
|
|
|
case '.':
|
|
|
|
|
case ',':
|
|
|
|
|
pFmt--; break;
|
|
|
|
|
}
|
|
|
|
|
// Vorkomma:
|
|
|
|
|
for( ;; )
|
|
|
|
|
{
|
|
|
|
|
while( *pFmt == '#' ) pFmt++, nWidth++;
|
|
|
|
|
// 1000er Kommas?
|
|
|
|
|
if( *pFmt == ',' )
|
|
|
|
|
{
|
|
|
|
|
nWidth++; pFmt++; bPoint = TRUE;
|
|
|
|
|
} else break;
|
|
|
|
|
}
|
|
|
|
|
// Nachkomma:
|
|
|
|
|
if( *pFmt == '.' )
|
|
|
|
|
{
|
|
|
|
|
while( *++pFmt == '#' ) nPrec++;
|
|
|
|
|
nWidth += nPrec + 1;
|
|
|
|
|
}
|
|
|
|
|
// Exponent:
|
|
|
|
|
while( *pFmt == '^' )
|
|
|
|
|
pFmt++, nExpDig++, nWidth++;
|
|
|
|
|
// Folgendes Minus:
|
|
|
|
|
if( !bSign && *pFmt == '-' )
|
|
|
|
|
pFmt++, bTrail = TRUE;
|
|
|
|
|
|
|
|
|
|
// Zahl konvertieren:
|
|
|
|
|
if( nPrec > 15 ) nPrec = 15;
|
|
|
|
|
if( nNum < 0.0 ) nNum = -nNum, bNeg = TRUE;
|
|
|
|
|
p = cBuf;
|
|
|
|
|
if( bSign ) *p++ = bNeg ? '-' : '+';
|
|
|
|
|
myftoa( nNum, p, nPrec, nExpDig, bPoint, FALSE );
|
|
|
|
|
nLen = strlen( cBuf );
|
|
|
|
|
|
|
|
|
|
// Ueberlauf?
|
|
|
|
|
if( cPre ) nLen++;
|
|
|
|
|
if( nLen > nWidth ) rRes += '%';
|
|
|
|
|
else {
|
|
|
|
|
nWidth -= nLen;
|
|
|
|
|
while( nWidth-- ) rRes += (xub_Unicode)cFill;
|
|
|
|
|
if( cPre ) rRes += (xub_Unicode)cPre;
|
|
|
|
|
}
|
|
|
|
|
rRes += (xub_Unicode*)&(cBuf[0]);
|
|
|
|
|
if( bTrail )
|
|
|
|
|
rRes += bNeg ? '-' : ' ';
|
|
|
|
|
|
|
|
|
|
return (USHORT) ( pFmt - (const char*) rFmt );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif //_old_format_code_
|
|
|
|
|
|
|
|
|
|
static USHORT printfmtstr( const XubString& rStr, XubString& rRes, const XubString& rFmt )
|
|
|
|
|
{
|
|
|
|
|
const xub_Unicode* pStr = rStr.GetBuffer();
|
|
|
|
|
const xub_Unicode* pFmtStart = rFmt.GetBuffer();
|
|
|
|
|
const xub_Unicode* pFmt = pFmtStart;
|
|
|
|
|
rRes.Erase();
|
|
|
|
|
switch( *pFmt )
|
|
|
|
|
{
|
|
|
|
|
case '!':
|
|
|
|
|
rRes += *pStr++; pFmt++; break;
|
|
|
|
|
case '\\':
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
rRes += *pStr ? *pStr++ : static_cast< xub_Unicode >(' ');
|
|
|
|
|
pFmt++;
|
|
|
|
|
} while( *pFmt != '\\' );
|
|
|
|
|
rRes += *pStr ? *pStr++ : static_cast< xub_Unicode >(' ');
|
|
|
|
|
pFmt++; break;
|
|
|
|
|
case '&':
|
|
|
|
|
rRes = rStr;
|
|
|
|
|
pFmt++; break;
|
|
|
|
|
default:
|
|
|
|
|
rRes = rStr;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return (USHORT) ( pFmt - pFmtStart );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
BOOL SbxValue::Scan( const XubString& rSrc, USHORT* pLen )
|
|
|
|
|
{
|
|
|
|
|
SbxError eRes = SbxERR_OK;
|
|
|
|
|
if( !CanWrite() )
|
|
|
|
|
eRes = SbxERR_PROP_READONLY;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
double n;
|
|
|
|
|
SbxDataType t;
|
|
|
|
|
eRes = ImpScan( rSrc, n, t, pLen );
|
|
|
|
|
if( eRes == SbxERR_OK )
|
|
|
|
|
{
|
|
|
|
|
if( !IsFixed() )
|
|
|
|
|
SetType( t );
|
|
|
|
|
PutDouble( n );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if( eRes )
|
|
|
|
|
{
|
|
|
|
|
SetError( eRes ); return FALSE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2005-09-29 17:42:37 +00:00
|
|
|
|
|
|
|
|
|
ResMgr* implGetResMgr( void )
|
|
|
|
|
{
|
|
|
|
|
static ResMgr* pResMgr = NULL;
|
|
|
|
|
if( !pResMgr )
|
|
|
|
|
{
|
|
|
|
|
::com::sun::star::lang::Locale aLocale = Application::GetSettings().GetUILocale();
|
2008-01-28 13:01:14 +00:00
|
|
|
|
pResMgr = ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(sb), aLocale );
|
2005-09-29 17:42:37 +00:00
|
|
|
|
}
|
|
|
|
|
return pResMgr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SbxValueFormatResId : public ResId
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
SbxValueFormatResId( USHORT nId )
|
2007-04-26 07:33:49 +00:00
|
|
|
|
: ResId( nId, *implGetResMgr() )
|
2005-09-29 17:42:37 +00:00
|
|
|
|
{}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2008-07-02 09:04:30 +00:00
|
|
|
|
enum VbaFormatType
|
|
|
|
|
{
|
|
|
|
|
VBA_FORMAT_TYPE_OFFSET, // standard number format
|
|
|
|
|
VBA_FORMAT_TYPE_USERDEFINED, // user defined number format
|
|
|
|
|
VBA_FORMAT_TYPE_NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct VbaFormatInfo
|
|
|
|
|
{
|
|
|
|
|
VbaFormatType meType;
|
|
|
|
|
const char* mpVbaFormat; // Format string in vba
|
|
|
|
|
NfIndexTableOffset meOffset; // SvNumberFormatter format index, if meType = VBA_FORMAT_TYPE_OFFSET
|
|
|
|
|
const char* mpOOoFormat; // if meType = VBA_FORMAT_TYPE_USERDEFINED
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define VBA_FORMAT_OFFSET( pcUtf8, eOffset ) \
|
|
|
|
|
{ VBA_FORMAT_TYPE_OFFSET, pcUtf8, eOffset, 0 }
|
|
|
|
|
|
|
|
|
|
#define VBA_FORMAT_USERDEFINED( pcUtf8, pcDefinedUtf8 ) \
|
|
|
|
|
{ VBA_FORMAT_TYPE_USERDEFINED, pcUtf8, NF_NUMBER_STANDARD, pcDefinedUtf8 }
|
|
|
|
|
|
|
|
|
|
static VbaFormatInfo pFormatInfoTable[] =
|
|
|
|
|
{
|
|
|
|
|
VBA_FORMAT_OFFSET( "Long Date", NF_DATE_SYSTEM_LONG ),
|
|
|
|
|
VBA_FORMAT_USERDEFINED( "Medium Date", "DD-MMM-YY" ),
|
|
|
|
|
VBA_FORMAT_OFFSET( "Short Date", NF_DATE_SYSTEM_SHORT ),
|
|
|
|
|
VBA_FORMAT_USERDEFINED( "Long Time", "H:MM:SS AM/PM" ),
|
|
|
|
|
VBA_FORMAT_OFFSET( "Medium Time", NF_TIME_HHMMAMPM ),
|
|
|
|
|
VBA_FORMAT_OFFSET( "Short Time", NF_TIME_HHMM ),
|
|
|
|
|
VBA_FORMAT_OFFSET( "ddddd", NF_DATE_SYSTEM_SHORT ),
|
|
|
|
|
VBA_FORMAT_OFFSET( "dddddd", NF_DATE_SYSTEM_LONG ),
|
|
|
|
|
VBA_FORMAT_USERDEFINED( "ttttt", "H:MM:SS AM/PM" ),
|
|
|
|
|
VBA_FORMAT_OFFSET( "ww", NF_DATE_WW ),
|
|
|
|
|
{ VBA_FORMAT_TYPE_NULL, 0, NF_INDEX_TABLE_ENTRIES, 0 }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VbaFormatInfo* getFormatInfo( const String& rFmt )
|
|
|
|
|
{
|
|
|
|
|
VbaFormatInfo* pInfo = NULL;
|
|
|
|
|
INT16 i = 0;
|
|
|
|
|
while( (pInfo = pFormatInfoTable + i )->mpVbaFormat != NULL )
|
|
|
|
|
{
|
|
|
|
|
if( rFmt.EqualsIgnoreCaseAscii( pInfo->mpVbaFormat ) )
|
|
|
|
|
break;
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
return pInfo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define VBAFORMAT_GENERALDATE "General Date"
|
|
|
|
|
#define VBAFORMAT_C "c"
|
|
|
|
|
#define VBAFORMAT_N "n"
|
|
|
|
|
#define VBAFORMAT_NN "nn"
|
|
|
|
|
#define VBAFORMAT_W "w"
|
|
|
|
|
#define VBAFORMAT_Y "y"
|
|
|
|
|
#define VBAFORMAT_LOWERCASE "<"
|
|
|
|
|
#define VBAFORMAT_UPPERCASE ">"
|
|
|
|
|
|
|
|
|
|
// From methods1.cxx
|
|
|
|
|
INT16 implGetWeekDay( double aDate, bool bFirstDayParam = false, INT16 nFirstDay = 0 );
|
|
|
|
|
// from methods.cxx
|
|
|
|
|
INT16 implGetMinute( double dDate );
|
|
|
|
|
INT16 implGetDateYear( double aDate );
|
|
|
|
|
BOOL implDateSerial( INT16 nYear, INT16 nMonth, INT16 nDay, double& rdRet );
|
|
|
|
|
|
2005-04-13 08:25:31 +00:00
|
|
|
|
void SbxValue::Format( XubString& rRes, const XubString* pFmt ) const
|
|
|
|
|
{
|
2006-06-19 16:51:12 +00:00
|
|
|
|
short nComma = 0;
|
2006-10-12 13:33:35 +00:00
|
|
|
|
double d = 0;
|
2008-01-28 13:01:14 +00:00
|
|
|
|
|
2008-07-02 09:04:30 +00:00
|
|
|
|
// pflin, It is better to use SvNumberFormatter to handle the date/time/number format.
|
|
|
|
|
// the SvNumberFormatter output is mostly compatible with
|
|
|
|
|
// VBA output besides the OOo-basic output
|
2008-01-28 13:01:14 +00:00
|
|
|
|
if( pFmt && !SbxBasicFormater::isBasicFormat( *pFmt ) )
|
|
|
|
|
{
|
2008-07-02 09:04:30 +00:00
|
|
|
|
String aStr = GetString();
|
|
|
|
|
|
|
|
|
|
if( pFmt->EqualsIgnoreCaseAscii( VBAFORMAT_LOWERCASE ) )
|
|
|
|
|
{
|
|
|
|
|
rRes = aStr.ToLowerAscii();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if( pFmt->EqualsIgnoreCaseAscii( VBAFORMAT_UPPERCASE ) )
|
|
|
|
|
{
|
|
|
|
|
rRes = aStr.ToUpperAscii();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-28 13:01:14 +00:00
|
|
|
|
LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
|
|
|
|
|
com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >
|
|
|
|
|
xFactory = comphelper::getProcessServiceFactory();
|
|
|
|
|
SvNumberFormatter aFormatter( xFactory, eLangType );
|
|
|
|
|
|
|
|
|
|
sal_uInt32 nIndex;
|
|
|
|
|
xub_StrLen nCheckPos = 0;
|
|
|
|
|
short nType;
|
2008-07-02 09:04:30 +00:00
|
|
|
|
double nNumber;
|
|
|
|
|
Color* pCol;
|
|
|
|
|
|
|
|
|
|
BOOL bSuccess = aFormatter.IsNumberFormat( aStr, nIndex, nNumber );
|
2008-01-28 13:01:14 +00:00
|
|
|
|
|
2008-07-02 09:04:30 +00:00
|
|
|
|
// number format, use SvNumberFormatter to handle it.
|
|
|
|
|
if( bSuccess )
|
2008-01-28 13:01:14 +00:00
|
|
|
|
{
|
2008-07-02 09:04:30 +00:00
|
|
|
|
String aFmtStr = *pFmt;
|
|
|
|
|
VbaFormatInfo* pInfo = getFormatInfo( aFmtStr );
|
|
|
|
|
if( pInfo && pInfo->meType != VBA_FORMAT_TYPE_NULL )
|
|
|
|
|
{
|
|
|
|
|
if( pInfo->meType == VBA_FORMAT_TYPE_OFFSET )
|
|
|
|
|
{
|
|
|
|
|
nIndex = aFormatter.GetFormatIndex( pInfo->meOffset, eLangType );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
aFmtStr.AssignAscii( pInfo->mpOOoFormat );
|
|
|
|
|
aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType );
|
|
|
|
|
}
|
|
|
|
|
aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol );
|
|
|
|
|
}
|
|
|
|
|
else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_GENERALDATE )
|
|
|
|
|
|| aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_C ))
|
|
|
|
|
{
|
|
|
|
|
if( nNumber <=-1.0 || nNumber >= 1.0 )
|
|
|
|
|
{
|
|
|
|
|
// short date
|
|
|
|
|
nIndex = aFormatter.GetFormatIndex( NF_DATE_SYSTEM_SHORT, eLangType );
|
|
|
|
|
aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol );
|
|
|
|
|
|
|
|
|
|
// long time
|
|
|
|
|
if( floor( nNumber ) != nNumber )
|
|
|
|
|
{
|
|
|
|
|
aFmtStr.AssignAscii( "H:MM:SS AM/PM" );
|
|
|
|
|
aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType );
|
|
|
|
|
String aTime;
|
|
|
|
|
aFormatter.GetOutputString( nNumber, nIndex, aTime, &pCol );
|
|
|
|
|
rRes.AppendAscii(" ");
|
|
|
|
|
rRes += aTime;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// long time only
|
|
|
|
|
aFmtStr.AssignAscii( "H:MM:SS AM/PM" );
|
|
|
|
|
aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType );
|
|
|
|
|
aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_N )
|
|
|
|
|
|| aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_NN ))
|
|
|
|
|
{
|
|
|
|
|
INT32 nMin = implGetMinute( nNumber );
|
|
|
|
|
if( nMin < 10 && aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_NN ) )
|
|
|
|
|
{
|
|
|
|
|
// Minute in two digits
|
|
|
|
|
sal_Unicode* p = rRes.AllocBuffer( 2 );
|
|
|
|
|
*p++ = '0';
|
|
|
|
|
*p = sal_Unicode( '0' + nMin );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rRes = String::CreateFromInt32( nMin );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_W ))
|
|
|
|
|
{
|
|
|
|
|
INT32 nWeekDay = implGetWeekDay( nNumber );
|
|
|
|
|
rRes = String::CreateFromInt32( nWeekDay );
|
|
|
|
|
}
|
|
|
|
|
else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_Y ))
|
|
|
|
|
{
|
|
|
|
|
INT16 nYear = implGetDateYear( nNumber );
|
|
|
|
|
double dBaseDate;
|
|
|
|
|
implDateSerial( nYear, 1, 1, dBaseDate );
|
|
|
|
|
INT32 nYear32 = 1 + INT32( nNumber - dBaseDate );
|
|
|
|
|
rRes = String::CreateFromInt32( nYear32 );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType );
|
|
|
|
|
aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol );
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-28 13:01:14 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-13 08:25:31 +00:00
|
|
|
|
SbxDataType eType = GetType();
|
|
|
|
|
switch( eType )
|
|
|
|
|
{
|
|
|
|
|
case SbxCHAR:
|
|
|
|
|
case SbxBYTE:
|
|
|
|
|
case SbxINTEGER:
|
|
|
|
|
case SbxUSHORT:
|
|
|
|
|
case SbxLONG:
|
|
|
|
|
case SbxULONG:
|
|
|
|
|
case SbxINT:
|
|
|
|
|
case SbxUINT:
|
|
|
|
|
case SbxNULL: // #45929 NULL mit durchschummeln
|
|
|
|
|
nComma = 0; goto cvt;
|
|
|
|
|
case SbxSINGLE:
|
|
|
|
|
nComma = 6; goto cvt;
|
|
|
|
|
case SbxDOUBLE:
|
|
|
|
|
nComma = 14;
|
|
|
|
|
|
|
|
|
|
cvt:
|
|
|
|
|
if( eType != SbxNULL )
|
|
|
|
|
d = GetDouble();
|
|
|
|
|
|
|
|
|
|
// #45355 weiterer Einsprungpunkt fuer isnumeric-String
|
|
|
|
|
cvt2:
|
|
|
|
|
if( pFmt )
|
|
|
|
|
{
|
|
|
|
|
// hole die 'statischen' Daten f"ur Sbx
|
|
|
|
|
SbxAppData* pData = GetSbxData_Impl();
|
|
|
|
|
|
|
|
|
|
LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
|
|
|
|
|
if( pData->pBasicFormater )
|
|
|
|
|
{
|
|
|
|
|
if( pData->eBasicFormaterLangType != eLangType )
|
|
|
|
|
{
|
|
|
|
|
delete pData->pBasicFormater;
|
|
|
|
|
pData->pBasicFormater = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pData->eBasicFormaterLangType = eLangType;
|
|
|
|
|
|
|
|
|
|
// falls bisher noch kein BasicFormater-Objekt
|
|
|
|
|
// existiert, so erzeuge dieses
|
|
|
|
|
if( !pData->pBasicFormater )
|
|
|
|
|
{
|
|
|
|
|
SvtSysLocale aSysLocale;
|
|
|
|
|
const LocaleDataWrapper& rData = aSysLocale.GetLocaleData();
|
|
|
|
|
sal_Unicode cComma = rData.getNumDecimalSep().GetBuffer()[0];
|
|
|
|
|
sal_Unicode c1000 = rData.getNumThousandSep().GetBuffer()[0];
|
|
|
|
|
String aCurrencyStrg = rData.getCurrSymbol();
|
|
|
|
|
|
|
|
|
|
// Initialisierung des Basic-Formater-Hilfsobjekts:
|
|
|
|
|
// hole die Resourcen f"ur die vordefinierten Ausgaben
|
|
|
|
|
// des Format()-Befehls, z.B. f"ur "On/Off".
|
2005-09-29 17:42:37 +00:00
|
|
|
|
String aOnStrg = String( SbxValueFormatResId(
|
2005-04-13 08:25:31 +00:00
|
|
|
|
STR_BASICKEY_FORMAT_ON ) );
|
2005-09-29 17:42:37 +00:00
|
|
|
|
String aOffStrg = String( SbxValueFormatResId(
|
2005-04-13 08:25:31 +00:00
|
|
|
|
STR_BASICKEY_FORMAT_OFF) );
|
2005-09-29 17:42:37 +00:00
|
|
|
|
String aYesStrg = String( SbxValueFormatResId(
|
2005-04-13 08:25:31 +00:00
|
|
|
|
STR_BASICKEY_FORMAT_YES) );
|
2005-09-29 17:42:37 +00:00
|
|
|
|
String aNoStrg = String( SbxValueFormatResId(
|
2005-04-13 08:25:31 +00:00
|
|
|
|
STR_BASICKEY_FORMAT_NO) );
|
2005-09-29 17:42:37 +00:00
|
|
|
|
String aTrueStrg = String( SbxValueFormatResId(
|
2005-04-13 08:25:31 +00:00
|
|
|
|
STR_BASICKEY_FORMAT_TRUE) );
|
2005-09-29 17:42:37 +00:00
|
|
|
|
String aFalseStrg = String( SbxValueFormatResId(
|
2005-04-13 08:25:31 +00:00
|
|
|
|
STR_BASICKEY_FORMAT_FALSE) );
|
2005-09-29 17:42:37 +00:00
|
|
|
|
String aCurrencyFormatStrg = String( SbxValueFormatResId(
|
2005-04-13 08:25:31 +00:00
|
|
|
|
STR_BASICKEY_FORMAT_CURRENCY) );
|
|
|
|
|
// erzeuge das Basic-Formater-Objekt
|
|
|
|
|
pData->pBasicFormater
|
|
|
|
|
= new SbxBasicFormater( cComma,c1000,aOnStrg,aOffStrg,
|
|
|
|
|
aYesStrg,aNoStrg,aTrueStrg,aFalseStrg,
|
|
|
|
|
aCurrencyStrg,aCurrencyFormatStrg );
|
|
|
|
|
}
|
|
|
|
|
// Bem.: Aus Performance-Gr"unden wird nur EIN BasicFormater-
|
|
|
|
|
// Objekt erzeugt und 'gespeichert', dadurch erspart man
|
|
|
|
|
// sich das teure Resourcen-Laden (f"ur landesspezifische
|
|
|
|
|
// vordefinierte Ausgaben, z.B. "On/Off") und die st"andige
|
|
|
|
|
// String-Erzeugungs Operationen.
|
|
|
|
|
// ABER: dadurch ist dieser Code NICHT multithreading f"ahig !
|
|
|
|
|
|
|
|
|
|
// hier gibt es Probleme mit ;;;Null, da diese Methode nur aufgerufen
|
|
|
|
|
// wird, wenn der SbxValue eine Zahl ist !!!
|
|
|
|
|
// dazu koennte: pData->pBasicFormater->BasicFormatNull( *pFmt ); aufgerufen werden !
|
|
|
|
|
if( eType != SbxNULL )
|
|
|
|
|
{
|
|
|
|
|
rRes = pData->pBasicFormater->BasicFormat( d ,*pFmt );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rRes = pData->pBasicFormater->BasicFormatNull( *pFmt );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Die alte Implementierung:
|
|
|
|
|
//old: printfmtnum( GetDouble(), rRes, *pFmt );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
ImpCvtNum( GetDouble(), nComma, rRes );
|
|
|
|
|
break;
|
|
|
|
|
case SbxSTRING:
|
|
|
|
|
if( pFmt )
|
|
|
|
|
{
|
|
|
|
|
// #45355 wenn es numerisch ist, muss gewandelt werden
|
|
|
|
|
if( IsNumericRTL() )
|
|
|
|
|
{
|
|
|
|
|
ScanNumIntnl( GetString(), d, /*bSingle*/FALSE );
|
|
|
|
|
goto cvt2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Sonst String-Formatierung
|
|
|
|
|
printfmtstr( GetString(), rRes, *pFmt );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
rRes = GetString();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
rRes = GetString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|