Java导出Excel
简介
我们知道最简单的导出excel的方式其实是导出csv, 例如dbv的导出功能就是导出csv, 非常的傻瓜方便, 也不需要引入依赖, 但是当导出的文件内容中含有 "," (逗号)时, 文件的格式就乱了. 效果不好.
Java 导出 Excel的轮子还是挺多的, 有些也非常简单易用, 下面就简单叙述下
Apache poi
官方文档 https://poi.apache.org/components/spreadsheet/quick-guide.html
生成Excel的方式是通过Java代码, 例子如
Workbook wb = new XSSFWorkbook();
//Workbook wb = new XSSFWorkbook();
CreationHelper createHelper = wb.getCreationHelper();
Sheet sheet = wb.createSheet("new sheet");
// Create a row and put some cells in it. Rows are 0 based.
Row row = sheet.createRow(0);
row.createCell(0).setCellValue(" \uD83D\uDE0E \uD83D\uDE00 ☺ \uD83D\uDC7D");
row.createCell(1).setCellValue(1.2);
// 创建一个富文本 ,设定一下颜色
RichTextString rx = createHelper.createRichTextString("特殊表情来了");
XSSFFont font = (XSSFFont) wb.createFont();
font.setColor(new XSSFColor(new java.awt.Color(0, 255, 0)));
//
rx.applyFont(font);
row.createCell(2).setCellValue(rx);
row.createCell(3).setCellValue(true);
// Write the output to a file
try (OutputStream fileOut = new FileOutputStream("workbook.xlsx")) {
wb.write(fileOut);
}
可以看到, 基本上是通过手撸代码的方式 , 颗粒度比较细, 但还是非常的繁琐, 每一行的创建都需要手撸, 样式什么的统统得用代码来控制, 量还是比较大的
测试的时候, 发现使用xlsx 格式导出的时候 ,如果使用emoji, 生成的excel中emoji会变成??, 而使用xls格式的时候就不会, 看了下源码, 应该是 HSSFRichTextString 这个类在转化的时候正确处理的emoji, 而生成xlsx的 XSSFRichTextString 没有正确处理
JXL (Java Excel API)
这个文档已经比较老了 , https://www.teamdev.com/downloads/jexcel/docs/JExcel-PGuide.html
乍一看, 最近一次的更新也是2011年的时候了, 用法其实和上面的类似, 也是通过手撸代码, 并且不支持xlsx类型, 所以不推荐使用了, (既然要手撸代码, 为啥不选择poi呢?)
@Test
public void javaExcelTest() throws Exception {
// 类似, 构建一个xls文件
WritableWorkbook wworkbook = jxl.Workbook.createWorkbook(new File("output.xls"));
WritableSheet wsheet = wworkbook.createSheet("First Sheet", 0);
// 在某个单元格创建, 下标从0开始
Label label = new Label(0, 2, "A label record"); // 即 单元格 A3
wsheet.addCell(label);
Number number = new Number(3, 4, 3.1459); //单元格 D5
wsheet.addCell(number);
wworkbook.write();
wworkbook.close();
jxl.Workbook workbook = jxl.Workbook.getWorkbook(new File("output.xls"));
jxl.Sheet sheet = workbook.getSheet(0);
Cell cell1 = sheet.getCell(0, 2);
System.out.println(cell1.getContents());
Cell cell2 = sheet.getCell(3, 4);
System.out.println(cell2.getContents());
workbook.close();
}
JXLS2
官网上JXLS的文档例子比较详细, 有时间的话可以读一下
如果不想看英文的, 可以看这个中文文档, 比较新
乍一看这个和上面那个很像, 但是可以说是非常不一样了, 同时JXLS2 和 JXLS1 使用方式还是有很大的区别, 这里就只讲述JXLS2的使用方式
JXLS2和上面的编码方式最大的不同就是可以使用模板, 废话少说, 直接步入正题
步骤
1.引入依赖
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls-poi</artifactId>
<version>1.0.15</version>
</dependency>
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls-reader</artifactId>
<version>2.0.3</version>
</dependency>
2.导入excel模板
这是一个样例模板
下载下来会发现, 里面有一些黄色的标记就是JXLS用来生成数据指令, 下面这段话比较关键
jx:area(lastCell="D4")
作用是从打上批注的这行单元格开始, 到 lastCell 所在的单元格区域, 是需要转化的矩形区域, 即我们的模板数据, 就必须写在这个区域内
下面这行数据使用了 jxls的 each指令
jx:each(items="employees" var="employee" lastCell="D4")
3. 编写代码
按照上面定义好模板后 ,生成的代码就非常简单, 可以看到
@Test
public void t() throws Exception {
//构造需要填充的数据
List<Employee> employees = new ArrayList<>();
employees.add(new Employee().setName("jack").setBirthDate(new Date()).setPayment(BigDecimal.valueOf(System.currentTimeMillis())));
employees.add(new Employee().setName("wuli").setBirthDate(new Date()).setPayment(BigDecimal.valueOf(System.currentTimeMillis())));
employees.add(new Employee().setName("fiefei").setBirthDate(new Date().setPayment(BigDecimal.valueOf(System.currentTimeMillis())));
employees.add(new Employee().setName("keai").setBirthDate(new Date()).setPayment(BigDecimal.valueOf(System.currentTimeMillis())));
try (InputStream is = ExportExcelTest.class.getResourceAsStream("/object_collection_template.xls")) {
try (OutputStream os = new FileOutputStream("target/object_collection_output.xls")) {
Context context = new Context();
// 放入上下文
context.putVar("employees", employees);
JxlsHelper.getInstance().processTemplate(is, os, context);
}
}
}
其他的方式也有, 例如不需要写批注, 可以使用xml来编写,但是试了一下,发现有点繁琐,, 不如这种简便,
无一例外, 都需要事先准备好一个excel模板, 如果有复杂的生成要求, 可以下载对照官网例子来实现
https://bitbucket.org/leonate/jxls-demo/downloads/?tab=downloads