in poi/src/main/java/org/apache/poi/ss/formula/functions/Value.java [86:215]
public static Double convertTextToNumber(String strText) {
boolean foundCurrency = false;
boolean foundUnaryPlus = false;
boolean foundUnaryMinus = false;
boolean foundPercentage = false;
int len = strText.length();
int i;
for (i = 0; i < len; i++) {
char ch = strText.charAt(i);
if (Character.isDigit(ch) || ch == '.') {
break;
}
switch (ch) {
case ' ':
// intervening spaces between '$', '-', '+' are OK
continue;
case '$':
if (foundCurrency) {
// only one currency symbols is allowed
return null;
}
foundCurrency = true;
continue;
case '+':
if (foundUnaryMinus || foundUnaryPlus) {
return null;
}
foundUnaryPlus = true;
continue;
case '-':
if (foundUnaryMinus || foundUnaryPlus) {
return null;
}
foundUnaryMinus = true;
continue;
default:
// all other characters are illegal
return null;
}
}
if (i >= len) {
// didn't find digits or '.'
if (foundCurrency || foundUnaryMinus || foundUnaryPlus) {
return null;
}
return ZERO;
}
// remove thousands separators
boolean foundDecimalPoint = false;
int lastThousandsSeparatorIndex = Short.MIN_VALUE;
StringBuilder sb = new StringBuilder(len);
for (; i < len; i++) {
char ch = strText.charAt(i);
if (Character.isDigit(ch)) {
sb.append(ch);
continue;
}
switch (ch) {
case ' ':
String remainingTextTrimmed = strText.substring(i).trim();
// support for value[space]%
if (remainingTextTrimmed.equals("%")) {
foundPercentage = true;
break;
}
if (remainingTextTrimmed.length() > 0) {
// intervening spaces not allowed once the digits start
return null;
}
break;
case '.':
if (foundDecimalPoint) {
return null;
}
if (i - lastThousandsSeparatorIndex < MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR) {
return null;
}
foundDecimalPoint = true;
sb.append('.');
continue;
case ',':
if (foundDecimalPoint) {
// thousands separators not allowed after '.' or 'E'
return null;
}
int distanceBetweenThousandsSeparators = i - lastThousandsSeparatorIndex;
// as long as there are 3 or more digits between
if (distanceBetweenThousandsSeparators < MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR) {
return null;
}
lastThousandsSeparatorIndex = i;
// don't append ','
continue;
case 'E':
case 'e':
if (i - lastThousandsSeparatorIndex < MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR) {
return null;
}
// append rest of strText and skip to end of loop
sb.append(strText.substring(i));
i = len;
break;
case '%':
foundPercentage = true;
break;
default:
// all other characters are illegal
return null;
}
}
if (!foundDecimalPoint) {
if (i - lastThousandsSeparatorIndex < MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR) {
return null;
}
}
double d;
try {
d = Double.parseDouble(sb.toString());
} catch (NumberFormatException e) {
// still a problem parsing the number - probably out of range
return null;
}
double result = foundUnaryMinus ? -d : d;
return foundPercentage ? result / 100. : result;
}