in poi/src/main/java/org/apache/poi/ss/format/CellNumberFormatter.java [427:560]
public void formatValue(StringBuffer toAppendTo, Object valueObject) {
BigDecimal bd = BigDecimal.valueOf(((Number) valueObject).doubleValue()).multiply(BigDecimal.valueOf(scale));
double value = bd.doubleValue();
// For negative numbers:
// - If the cell format has a negative number format, this method
// is called with a positive value and the number format has
// the negative formatting required, e.g. minus sign or brackets.
// - If the cell format does not have a negative number format,
// this method is called with a negative value and the number is
// formatted with a minus sign at the start.
boolean negative = value < 0;
if (negative)
value = -value;
// Split out the fractional part if we need to print a fraction
double fractional = 0;
if (slash != null) {
if (improperFraction) {
fractional = value;
value = 0;
} else {
fractional = value % 1.0;
//noinspection SillyAssignment
value = (long) value;
}
}
Set<CellNumberStringMod> mods = new TreeSet<>();
StringBuffer output = new StringBuffer(localiseFormat(desc));
if (exponent != null) {
writeScientific(value, output, mods);
} else if (improperFraction) {
writeFraction(value, null, fractional, output, mods);
} else {
StringBuffer result = new StringBuffer();
try (Formatter f = new Formatter(result, locale)) {
f.format(locale, printfFmt, value);
} catch (IllegalFormatException e) {
throw new IllegalArgumentException("Format: " + printfFmt, e);
}
if (numerator == null) {
writeFractional(result, output);
writeInteger(result, output, integerSpecials, mods, showGroupingSeparator);
} else {
writeFraction(value, result, fractional, output, mods);
}
}
DecimalFormatSymbols dfs = getDecimalFormatSymbols();
String groupingSeparator = Character.toString(dfs.getGroupingSeparator());
// Now strip out any remaining '#'s and add any pending text ...
Iterator<CellNumberStringMod> changes = mods.iterator();
CellNumberStringMod nextChange = (changes.hasNext() ? changes.next() : null);
// records chars already deleted
SparseBitSet deletedChars = new SparseBitSet();
int adjust = 0;
for (Special s : specials) {
int adjustedPos = s.pos + adjust;
if (!deletedChars.get(s.pos) && output.charAt(adjustedPos) == '#') {
output.deleteCharAt(adjustedPos);
adjust--;
deletedChars.set(s.pos);
}
while (nextChange != null && s == nextChange.getSpecial()) {
int lenBefore = output.length();
int modPos = s.pos + adjust;
switch (nextChange.getOp()) {
case CellNumberStringMod.AFTER:
// ignore adding a comma after a deleted char (which was a '#')
if (nextChange.getToAdd().equals(groupingSeparator) && deletedChars.get(s.pos)) {
break;
}
output.insert(modPos + 1, nextChange.getToAdd());
break;
case CellNumberStringMod.BEFORE:
output.insert(modPos, nextChange.getToAdd());
break;
case CellNumberStringMod.REPLACE:
// delete starting pos in original coordinates
int delPos = s.pos;
if (!nextChange.isStartInclusive()) {
delPos++;
modPos++;
}
// Skip over anything already deleted
while (deletedChars.get(delPos)) {
delPos++;
modPos++;
}
// delete end point in original
int delEndPos = nextChange.getEnd().pos;
if (nextChange.isEndInclusive()) {
delEndPos++;
}
// delete end point in current
int modEndPos = delEndPos + adjust;
if (modPos < modEndPos) {
if (nextChange.getToAdd() != null && nextChange.getToAdd().length() == 0) {
output.delete(modPos, modEndPos);
}
else {
char fillCh = nextChange.getToAdd().charAt(0);
for (int i = modPos; i < modEndPos; i++) {
output.setCharAt(i, fillCh);
}
}
deletedChars.set(delPos, delEndPos);
}
break;
default:
throw new IllegalStateException("Unknown op: " + nextChange.getOp());
}
adjust += output.length() - lenBefore;
nextChange = (changes.hasNext()) ? changes.next() : null;
}
}
// Finally, add it to the string
if (negative) {
toAppendTo.append('-');
}
toAppendTo.append(output);
}