引用依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
写一个 ExcelUtils 工具类
import org.apache.poi.hssf.usermodel.*;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ExcelUtils {
public static class ExcelDataFormat {
public static final String CURRENCY = "¥#,##0.0000;¥-#,##0.0000"; // 货币
public static final String DATETIME = "yyyy/m/d h:mm"; // 日期
public static final String DECIMAL = "0.00"; // 小数
public static final String INTEGER = "0"; // 整数
}
public static void createExcel(List<Map<String, Object>> datas, String fileName) {
if (datas.size() > 0) {
final Map<String, Object> map = datas.get(0);
final String[] keys = map.keySet().toArray(new String[0]);
createExcel(keys, datas, fileName);
}
}
public static void createExcel(String[] keys, List<Map<String, Object>> datas, String fileName) {
createExcel(keys, datas, fileName, new HashMap<>(), new HashMap<>());
}
public static void createExcel(
List<Map<String, Object>> datas,
String fileName,
Map<String, String> cellStyleFormatMap,
Map<String, Integer> columnWidthMap
) {
if (datas.size() > 0) {
final Map<String, Object> map = datas.get(0);
final String[] keys = map.keySet().toArray(new String[0]);
createExcel(keys, datas, fileName, cellStyleFormatMap, columnWidthMap);
}
}
/**
* 单元格带有不同格式的 Excel
*
* @param keys 要输出的key的值,输出的数据列将按照这个顺序
* @param datas Map数据列表
* @param fileName 文件名
* @param cellStyleFormatMap 键值对应 keys 中的列的单元格数据格式,见 ExcelDataFormat 个别示例,或者查看Excel软件的单元格里的自定义格式列表
* @param columnWidthMap 键值对应 keys 中的列的单元格宽度
*/
public static void createExcel(
String[] keys,
List<Map<String, Object>> datas,
String fileName,
Map<String, String> cellStyleFormatMap,
Map<String, Integer> columnWidthMap
) {
FileOutputStream os;
final int MAX_LEN = 60000;
try {
os = new FileOutputStream(fileName);
// 创建Excel的工作书册 Workbook,对应到一个excel文档
HSSFWorkbook wb = new HSSFWorkbook();
// 生成样式
Map<String, HSSFCellStyle> styleMap = new HashMap<>();
for (int i = 0; i < keys.length; i++) {
final String formatString = cellStyleFormatMap.get(keys[i]);
if (formatString != null) {
final HSSFCellStyle style = wb.createCellStyle();
final HSSFDataFormat dataFormat = wb.createDataFormat();
style.setDataFormat(dataFormat.getFormat(formatString));
styleMap.put(keys[i], style);
}
}
int size = datas.size() / MAX_LEN;
for (int i = 0; i < size; i++) {
// 创建Excel的工作sheet,对应到一个excel文档的 tab
HSSFSheet sheet = wb.createSheet("sheet" + (i + 1));
for (int j = 0; j < MAX_LEN; j++) {
Map<String, Object> model = datas.get(i * MAX_LEN + j);
setCell(keys, model, sheet, j, cellStyleFormatMap, styleMap);
}
for (int i1 = 0; i1 < keys.length; i1++) {
if (columnWidthMap.containsKey(keys[i1])) {
sheet.setColumnWidth(i1, columnWidthMap.get(keys[i1]));
}
}
}
int tempSize = datas.size() % MAX_LEN;
if (tempSize > 0) {
HSSFSheet sheet = wb.createSheet("sheet" + (size + 1));
// 设置 Sheet 数据
for (int z = 0; z < tempSize; z++) {
Map<String, Object> model = datas.get(size * MAX_LEN + z);
setCell(keys, model, sheet, z, cellStyleFormatMap, styleMap);
}
for (int i1 = 0; i1 < keys.length; i1++) {
if (columnWidthMap.containsKey(keys[i1])) {
sheet.setColumnWidth(i1, columnWidthMap.get(keys[i1]));
}
}
}
wb.write(os);
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 具有数据格式的单元格
*/
public static void setCell(
String[] keys, Map<String, Object> model, HSSFSheet sheet, int index,
Map<String, String> cellStyleFormatMap, Map<String, HSSFCellStyle> styleMap
) {
// 创建Excel的sheet的一行
HSSFRow row = sheet.createRow(index);
// 创建一个Excel的单元格
for (int i = 0; i < keys.length; i++) {
HSSFCell cell = row.createCell(i);
Object v = model.get(keys[i]);
if (index > 0) {
try {
// 设置样式
if (styleMap.containsKey(keys[i])) {
final HSSFCellStyle style = styleMap.get(keys[i]);
cell.setCellStyle(style);
}
// 判断数据类型,转为对应的类型。如果不转为对应类型,默认打开显示的效果是文本的效果
final String formatString = cellStyleFormatMap.get(keys[i]);
if (ExcelDataFormat.CURRENCY.equals(formatString)) {
if (v != null) {
cell.setCellValue((new BigDecimal(v.toString())).doubleValue());
}
} else if (ExcelDataFormat.DECIMAL.equals(formatString)) {
if (v != null) {
cell.setCellValue(Double.parseDouble(v.toString()));
}
} else if (ExcelDataFormat.INTEGER.equals(formatString)) {
if (v != null) {
// 直接用 Long.parseLong 转换会报错,先转为 double 类型再转为整型
cell.setCellValue((long) Double.parseDouble(v.toString()));
}
} else {
cell.setCellValue(v != null ? v.toString() : "");
}
} catch (Exception e) {
System.out.println();
System.out.println(String.format("转换数据类型时出现错误:key=%s, value=%s ", keys[i], v));
System.out.println(String.format("错误信息:%", e.toString()));
}
} else {
cell.setCellValue(v != null ? v.toString() : "");
}
}
}
/**
* 读取 Excel
*
* @param pathname 文件路径名
*/
public static Object[][] readExcel(String pathname) {
File file = new File(pathname);
HSSFWorkbook workbook = null;
try {
workbook = new HSSFWorkbook(new FileInputStream(file));
} catch (IOException e) {
System.out.printf("错误信息:%s%n", e.toString());
return null;
}
//获得表格中的第0个Sheet
final HSSFSheet sheet = workbook.getSheetAt(0);
//得到有多少行
int numberRows = sheet.getPhysicalNumberOfRows();
//获得第一行有多少列
int numberCells = sheet.getRow(0).getPhysicalNumberOfCells();
//获得第一行第一列所在的位置
int numberFirst = sheet.getRow(0).getFirstCellNum();
//创建一个Object二维数组,用来作为参数返回。
//因为第一行是说明,则跳过第一行,所以行数减一
Object[][] data = new Object[numberRows][];
//创建一个保存列的对象
HSSFRow row = null;
for (int i = sheet.getFirstRowNum(); i < numberRows; i++) {
//得到第i+1行,即第二行的实际数据
row = sheet.getRow(i);
// 创建一个字符数组,用来保存一行中,每一列的数据
String[] strings = new String[numberCells];
//row.getFirstCellNum() 获得一行中实际数据所在列,不一为第一列,如图第4行
for (int j = numberFirst; j < numberCells; j++) {
// 数据是通过key-value方式保存,遍历是会出现空指针异常(图中红色部分)。
//出现的多余没有输入的单元格会出现异常,并对没有数据输入的单元格(红色部分)是进行空字符处理
try {
//设置为字符类型,这里主要是因为在获取Excel数据时,
//数字出现小数点,主要用于不加小数点,可以简单这么理解。大家可以看一下源码就知道什么原因了
row.getCell(j).setCellType(CellType.STRING);
} catch (NullPointerException e) {
//出现空指针异常,说明数据没有输入,即空数据,做空字符串处理
strings[j] = "";
//跳过当前循环
continue;
}
// 保存数据
strings[j] = row.getCell(j).getStringCellValue();
}
//把获得数据添加到data
data[i] = strings;
}
return data;
}
}
如果有数据的话,写个类进行测试一下
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Main {
public static List<Map<String, Object>> getDatas() {
List<Map<String, Object>> datas = new ArrayList<>();
String[] name = {
"aaa",
"bbb",
"ccc",
"ddd",
"eee"
};
int[] sum = {1, 2, 3, 4, 5};
BigDecimal[] price = {
new BigDecimal(10.245),
new BigDecimal(54.234),
new BigDecimal(9.12948),
new BigDecimal(0.342),
new BigDecimal(101)
};
for (int i = 0; i < name.length; i++) {
final HashMap<String, Object> item = new HashMap<>();
item.put("name", name[i]);
item.put("sum", sum[i]);
item.put("price", price[i]);
datas.add(item);
}
return datas;
}
public static void main(String[] args) {
// 获取数据
final List<Map<String, Object>> datas = getDatas();
// 设置字段头列表的名称
final HashMap<String, Object> map = new HashMap<>();
map.put("name", "药品名称");
map.put("sum", "数量");
map.put("price", "单价(元)");
datas.add(0, map);
System.out.println(datas);
// 输出的列字段与顺序
String[] keys = {"name", "sum", "price"};
// 单元格数据格式
Map<String, String> cellStyleFormatMap = new HashMap<>();
cellStyleFormatMap.put("sum", ExcelUtils.ExcelDataFormat.INTEGER);
cellStyleFormatMap.put("price", ExcelUtils.ExcelDataFormat.CURRENCY);
// 单元格宽度
Map<String, Integer> cellWidthMap = new HashMap<>();
cellWidthMap.put("price", 6000);
// 创建excel文件
String fileName = "C:\\Users\\Administrator\\Desktop\\test.xls";
ExcelUtils.createExcel(keys, datas, fileName, cellStyleFormatMap, cellWidthMap);
}
}
相关参考链接:
设置单元格格式时遇到问题
POI Excel HSSFCell 设置单元格数字格式
在报表系统中遇到一个问题,需要设置数字格式,因为默认文本格式,需要手动刷数值格式,解决代码如下:
// HeCG95
// (1)设置 HSSFCell 为数值类型,如果传入字符串,后面一步设置格式也失效的
HSSFCell.setCellValue(Float.parseFloat(value));
// (2)设置样式
HSSFCellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00"));
对Excel的各个单元格的格式进行判断并转换
/**
* 对Excel的各个单元格的格式进行判断并转换
*/
public static String getCellValue(Cell cell) {
String cellValue = "";
if (cell == null) {
return cellValue;
}
// 判断数据的类型
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC: // 数字
//short s = cell.getCellStyle().getDataFormat();
if (HSSFDateUtil.isCellDateFormatted(cell)) {// 处理日期格式、时间格式
SimpleDateFormat sdf = null;
// 验证short值
if (cell.getCellStyle().getDataFormat() == 14) {
sdf = new SimpleDateFormat("yyyy/MM/dd");
} else if (cell.getCellStyle().getDataFormat() == 21) {
sdf = new SimpleDateFormat("HH:mm:ss");
} else if (cell.getCellStyle().getDataFormat() == 22) {
sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
} else {
throw new RuntimeException("日期格式错误!!!");
}
Date date = cell.getDateCellValue();
cellValue = sdf.format(date);
} else {//处理数值格式
cell.setCellType(Cell.CELL_TYPE_STRING);
cellValue = String.valueOf(cell.getRichStringCellValue().getString()).trim();
}
break;
case Cell.CELL_TYPE_STRING: // 字符串
cellValue = String.valueOf(cell.getStringCellValue()).trim();
break;
case Cell.CELL_TYPE_BOOLEAN: // Boolean
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_FORMULA: // 公式
cellValue = String.valueOf(cell.getCellFormula());
break;
case Cell.CELL_TYPE_BLANK: // 空值
cellValue = "";
break;
case Cell.CELL_TYPE_ERROR: // 故障
cellValue = "非法字符";
break;
default:
cellValue = "未知类型";
break;
}
return cellValue;
}
推荐链接:
springboot 如何通过HSSFWorkbook和XSSFWorkbook读取写入excel文件
https://blog.csdn.net/d303577562/article/details/114331158