fun*_*her 6 java excel apache-poi
我想在 Apache-POI(XSSF 和 SAX 事件 API)的帮助下导入 XLSX 文件。
由于 Excel 将数字存储为浮点数,因此需要在 java 中将它们格式化回它们在 Excel 中的原始外观。这可以通过读取单元格格式来实现:
String cellStyle = sheetReader.getAttributeValue(null, "s");
if (cellStyle != null) {
// save the format of the cell for later use.
int styleIndex = Integer.parseInt(cellStyle);
XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);
formatIndex = style.getDataFormat();
formatString = style.getDataFormatString();
if (formatString == null) {
// formatString could not be found, so it must be a builtin format.
formatString = BuiltinFormats.getBuiltinFormat(formatIndex);
}
}
...
// format the floating-point value
String xlsxValue = formatter.formatRawCellContents(
Double.parseDouble(value),
formatIndex,
formatString);
Run Code Online (Sandbox Code Playgroud)
上面的代码对我来说效果很好...但它给我的数字就像它们在德国语言环境中运行 Excel 时最初在 Excel 中的格式一样。此类数字的示例:
10,30
100.00.00,43
Run Code Online (Sandbox Code Playgroud)
现在我如何重新格式化这些数字,以便将它们提供给 Java Double 和 Java BigDecimal?
Apache-POI 似乎没有为这种情况提供实用程序类,但是如何在 java 中处理这些数字呢?
我已经侵入poi来实现这样的效果,但是没有其他办法吗?
// hack apache-poi classes that are private, so we can retrieve the 'format'
// which helps us to transform the formated value to the expected java-format
CellStyle style = new CellStyleHack(formatIndex, formatString);
Cell cell = new CellHack(Double.parseDouble(xlsxValue), style);
java.text.Format format = formatter.createFormat(cell);
if (format instanceof DecimalFormat) {
DecimalFormat decimalFormat = ((DecimalFormat) format);
char dSep = decimalFormat.getDecimalFormatSymbols().getDecimalSeparator();
char gSep = decimalFormat.getDecimalFormatSymbols().getGroupingSeparator();
String cSymbol = decimalFormat.getDecimalFormatSymbols().getCurrencySymbol();
// java always expects '.' as decimal seperator for BigDecimal and Double.
xlsxValue = xlsxValue.replace("" + gSep, "");
xlsxValue = xlsxValue.replace(dSep, '.');
if (cSymbol != null) {
xlsxValue = xlsxValue.replace(cSymbol, "").trim();
}
}
Run Code Online (Sandbox Code Playgroud)
在 @AxelRichter 的帮助下,以下解决方案现在解决了我的问题:
// we must use Locale.US, because we want to make sure that the DataFormatter will
// always product "." as decimal-separator and "," as thousands-separator.
this.formatter = new DataFormatter(Locale.US);
// format the floating-point value
String xlsxValue = formatter.formatRawCellContents(
Double.parseDouble(value),
formatIndex,
formatString);
// xlsxValue may contain format-symbols, which we need to remove...
xlsxValue = xlsxValue.replaceAll("[^\\d.]", "");
Run Code Online (Sandbox Code Playgroud)