前情提要
参与的项目有一个导出excel的功能,是之前已经完成的功能,现在要添加新的序号列;发现导出的excel中的数值单元格是文本型数字,并非数字,换句话说,excel将这些数据识别为文本而非数字,单元格右上角会出现绿三角。
下方的平均值和求和也不生效。
我发现的原因:代码将数据写入workbook对象时,这些数据是String类型。
测试
public class Test04 {
public static void main(String[] args) throws IOException {
// List<List<String>> dataList = new ArrayList<>();
// dataList.add(List.of("10000", "1.12345", "0.1234567"));
// dataList.add(List.of("10000", "1.12345", "0.1234567"));
// dataList.add(List.of("10000", "1.12345", "0.1234567"));
List<List<Double>> dataList = new ArrayList<>();
List<Double> list = new ArrayList<>();
list.add(10000D);
list.add(-12345.12345D);
list.add(0.1234567D);
dataList.add(list);
dataList.add(list);
dataList.add(list);
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("sheet1");
CellStyle style = workbook.createCellStyle();
CreationHelper creationHelper = workbook.getCreationHelper();
// 格式分类设为常规 (避免出现小数部分显示不全)
style.setDataFormat(creationHelper.createDataFormat().getFormat("General"));
for (int j = 0; j < dataList.size(); j++) {
Row row = sheet.createRow(j);
for (int k = 0; k < dataList.get(j).size(); k++) {
Cell first = row.createCell(k);
first.setCellValue(dataList.get(j).get(k));
first.setCellStyle(style);
}
}
FileOutputStream outputStream = new FileOutputStream("D:\\test1.xlsx");
workbook.write(outputStream);
workbook.close();
outputStream.close();
}
}
用Double类型写入后,就是正常的数字了(整型和浮点都可以,对应的包装类也可以)
如果用String的话,就会出现不是数字的情况
小数显示问题
上边测试代码有一行设置了格式分类为常规是为了显示全部小数,也可设置其他的来控制
style.setDataFormat(creationHelper.createDataFormat().getFormat("General"));
当设置为“0”,即
style.setDataFormat(creationHelper.createDataFormat().getFormat("0"));
设置为“0.0”,即
等等
具体设置什么要看需求决定
实际应用
可以直接在写入workbook对象时将需要的数据处理为Double,要考虑精度问题;
也可以在写入workbook对象之后再取出来转换为Double,例如
public static void dealCellType(Workbook workbook, ExportHeadType exportHeadType, Boolean exportType){
List<String> exportHead = getExportHead(exportHeadType); // 获得表头对应的list
Sheet sheet = workbook.getSheetAt(0);
CellStyle style = workbook.createCellStyle();
CreationHelper helper = workbook.getCreationHelper();
style.setDataFormat(helper.createDataFormat().getFormat("General")); // 格式分类设为常规 (避免出现小数部分显示不全)
int lastRowNum = sheet.getLastRowNum();
for (int i = 3; i < lastRowNum + 1; i++) { // 除去表头,数据从第三行开始
Row row = sheet.getRow(i);
for (int j = 0; j < exportHead.size(); j++) {
if (Objects.equals(exportHead.get(j), "合计金额")){
Cell cell = row.getCell(j);
String s = cell.getStringCellValue().replace(",", ""); //可能会出现分级号
if (StringUtils.hasText(s)) {
double value = Double.parseDouble(s); // 转为double 即可转为数值型
cell.setCellValue(value);
cell.setCellStyle(style);
}
}
}
}
}
这只是一个示例,具体还想看项目情况决定条件,整体思路为拿到需要转换的单元格内的数据,转换为Double,再写回去
PS:只是我个人发现的一个处理方法,欢迎大家指正补充