在项目中开发 Excel 表格导出功能,之前使用比较轻便实用的第三方组件 easypoi,现在由于数据对象某字段值的中英文转换问题(例如将
状态
这一列值MATERIAL_OCCUPIED
转换为存放产品
),决定使用 Apache 的 POI 组件来代替 easypoi。
使用 easypoi 效果:
期望效果:
尽管 easypoi 原生 API 中@Excel
注解中的replace
属性结合ExportCommonService
类中提供的replaceValue
方法可以对字符串类型的值进行替换,但由于使用_
下划线作为分割符,所以对于字段值本身包含_
符号(例如MATERIAL_OCCUPIED
)是无法进行处理的。
@Excel 注解类中的 replace 方法:
/**
* 值得替换 导出是{a_id,b_id} 导入反过来,所以只用写一个
*/
public String[] replace() default {
};
ExportCommonService 类中的 replaceValue 方法:
private Object replaceValue(String[] replace, String value) {
String[] temp;
for (String str : replace) {
temp = str.split("_");
if (value.equals(temp[1])) {
value = temp[0];
break;
}
}
return value;
}
使用 POI 组件需要在 pom 文件中添加依赖:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
如官网上这段话所说,上面的依赖适用于 2007 版本以下的 Excel 文档操作,而下面的依赖则适用于 2007 版本以上。
HSSF is the POI Project’s pure Java implementation of the Excel '97(-2007) file format. XSSF is the POI Project’s pure Java implementation of the Excel 2007 OOXML (.xlsx) file format.
Office OpenXML 格式是基于标准的 XML 文件格式,也是在微软 Office 2007 及以上版本中使用的新格式,包括xlsx,docx,pptx 等,代替了早期的二进制 Office 系统文件。
-
创建 Excel 文档。
HSSFWorkbook workbook = new HSSFWorkbook();
-
创建 Excel 表。
HSSFSheet sheet = workbook.createSheet(sheetName);
-
设置 Excel 表的列宽,0 表示第一列。
sheet.setColumnWidth(0, 15 * 256);
HSSFSheet 类中源码如下,15 * 256 表示列宽为 15 个字符长,约 8 个汉字。
* @param columnIndex - the column to set (0-based) * @param width - the width in units of 1/256th of a character width * @throws IllegalArgumentException if width > 255*256 (the maximum column width in Excel is 255 characters) */ @Override public void setColumnWidth(int columnIndex, int width) { _sheet.setColumnWidth(columnIndex, width); }
-
创建行,0 表示第一行。
HSSFRow firstRow = sheet.createRow(0);
-
设置行的高度,30 * 20 表示行高为 30 个像素高,高度大约如下:
firstRow.setHeight((short) (30 * 20));
行高不要设置太小,否则会导致 Excel 表格数据显示不出来。
-
创建单元格并写值,0 表示该行第一列,setCellValue() 方法写入值。
HSSFCell cell0 = headRow.createCell(0); cell0.setCellValue("编号");
-
创建和设置单元格样式。
//创建单元格样式 HSSFCellStyle style = workbook.createCellStyle(); //设置水平居中 style.setAlignment(HorizontalAlignment.CENTER); //设置垂直居中 style.setVerticalAlignment(VerticalAlignment.CENTER); //设置字体样式 HSSFFont font = workbook.createFont(); //设置加粗字体 font.setBold(true); style.setFont(font); //设置单元格样式 cell0.setCellStyle(style);
很奇怪为什么不将
createCell
方法、setCellStyle
方法和setCellValue
方法都设计成链式的。 -
更多 API 介绍请参考 官方文档 。
完整示例代码如下:
/**
* 导出用户信息
*/
public static ResponseEntity<byte[]> exportStorageLocation(List<User> data) throws ExcelExportException {
String fileName;
HttpHeaders httpHeaders = null;
try (
//1.创建Excel文档
HSSFWorkbook workbook = new HSSFWorkbook()
) {
//*********************************************2.创建Excel表*************************************************
HSSFSheet sheet = workbook.createSheet("用户表");
//设置Excel表列宽
sheet.setColumnWidth(0, 15 * 256);
sheet.setColumnWidth(1, 15 * 256);
//*********************************************3.创建表头*************************************************
HSSFRow headRow = sheet.createRow(0);
//设置行高
headRow.setHeight((short) (30 * 20));
//设置单元格样式
HSSFCellStyle headStyle = workbook.createCellStyle();
//设置水平居中
headStyle.setAlignment(HorizontalAlignment.CENTER);
//设置垂直居中
headStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//设置字体样式
HSSFFont headFont = workbook.createFont();
//设置加粗字体
headFont.setBold(true);
headStyle.setFont(headFont);
HSSFCell headCell0 = headRow.createCell(0);
headCell0.setCellValue("编号");
headCell0.setCellStyle(headStyle);
HSSFCell headCell1 = headRow.createCell(1);
headCell1.setCellValue("姓名");
headCell1.setCellStyle(headStyle);
//*********************************************4.填充数据*************************************************
HSSFCellStyle bodyStyle = workbook.createCellStyle();
bodyStyle.setAlignment(HorizontalAlignment.CENTER);
bodyStyle.setVerticalAlignment(VerticalAlignment.CENTER);
for (int i = 0; i < data.size(); i++) {
HSSFRow bodyRow = sheet.createRow(i + 1);
User user = data.get