①hutool工具(底层POI)
②模板引擎(thymeleaf或FreeMarker)
③POI
④其他对POI封装的插件
总的来说,POI好强大,不会用岂不可惜?继续往下看我使用POI批量导出Excel的实战日志吧!
Apache POI api的主要用途是用于文本提取应用程序,例如网络蜘蛛,索引构建器和内容管理系统。
官网如是说,其实就是用来读写Excel、Word文档、PPT等常见文档的工具而已。官网有详细说明,本贴重点在于拿来就用,省去大部分钻研时间(因为这次是因为开发批量导出Excel,所以只有批量导出Excel的内容,其他内容等我有业务需求再说,哈哈)
最近公司的一个老项目要添加批量导出功能,首先想到使用hutool,但是需要导出的Excel比较复杂,使用模板引擎(thymeleaf或FreeMarker)导出是比较省事的,但是公司的项目使用的是JSP。。。
所以只好使用POI啦。
思路:导出Excel文件,文件内包含多个sheet即多张表。
因为项目没有使用maven,所以直接导的jar包
使用maven的小伙伴或者需要导jar包的,可以去 https://mvnrepository.com/search?q=poi 下载
我需要导出Excel,所以下边三个就够了
如果你有操作其他文档的需求,但是不知道需要导什么jar包,我给你去官网截个图(链接http://poi.apache.org/components/index.html 浏览器打开 Ctrl+F搜索 Component Map)
看不懂没关系,我给你翻译一下
导出Excel首先要会用Excel不是?起码这几个单词啥意思需要懂
导出到本地磁盘或者浏览器呗,代码在下,毕竟得宠着。看完下边你就知道怎么导出创建的文件了,什么文件导出都是一样。
代码如下(示例):
/*创建Excel*/
String filePath="F:\\sample.xls";//文件路径
HSSFWorkbook workbook = new HSSFWorkbook();//创建Excel文件(Workbook)
HSSFSheet sheet = workbook.createSheet();//创建工作表(Sheet)
sheet = workbook.createSheet("Test");//创建工作表(Sheet)
FileOutputStream out = null;
try {
out = new FileOutputStream(filePath);
workbook.write(out);//保存Excel文件
out.close();//关闭文件流
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("OK!");
}
代码如下(示例):
/*创建Excel*/
HSSFWorkbook workbook = new HSSFWorkbook();//创建Excel文件(Workbook)
HSSFSheet sheet = workbook.createSheet();//创建工作表(Sheet)
sheet = workbook.createSheet("Test");//创建工作表(Sheet)
//将文件存到浏览器设置的下载位置
response.reset();
response.setContentType("application/msexcel;charset=UTF-8");
try {
SimpleDateFormat newsdf=new SimpleDateFormat("yyyyMMddHHmmss");
String date = newsdf.format(new Date());
response.addHeader("Content-Disposition", "attachment;filename=\""
+ new String(("数据表" + date + ".xls").getBytes("GBK"),
"ISO8859_1") + "\"");
OutputStream out = response.getOutputStream();
workbook.write(out);
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
js:
window.open("/contract/batchExport" ,'_self');
或者
window.location.href="/contract/batchExport";
嗯哼,数据量比较大的参数数据或者post携带的话?使用仿post提交!抱歉我没用上,所以没写,思路是
创建一次性表格,懂了吧
平时使用简单的get携带即可
window.location.href="/contract/batchExport?code=" + code;
@RequestMapping("/batchExport")
public void batchExport(HttpServletResponse response, String ids) {
String[] idList = ids.split(",");
/*创建Excel*/
HSSFWorkbook workbook = new HSSFWorkbook();//创建Excel文件(Workbook)
workbook.createInformationProperties();//创建文档信息
DocumentSummaryInformation dsi = workbook.getDocumentSummaryInformation();//摘要信息
dsi.setCategory("Excel文件");//类别
dsi.setManager("");//管理者
dsi.setCompany("");//公司
SummaryInformation si = workbook.getSummaryInformation();//摘要信息
// si.setSubject("");//主题
si.setTitle("");//标题
si.setAuthor("");//作者
// si.setComments("");//备注
try {
for (int i = 0, num = idList.length; i < num; i++) {
//获取数据
List<Product> list = contractService.listProduct(idList[i]);
Contract contract = contractService.getContract(idList[i]);
if (null!=contract) {
HSSFSheet sheet = workbook.createSheet(idList[i]);//创建工作表(Sheet)
HSSFRow row = sheet.createRow(0);// 创建行,从0开始
//合并列
HSSFCell cell = row.createCell(0);
cell.setCellValue("标题");
CellRangeAddress region1 = new CellRangeAddress(0, 2, 0, 7);
sheet.addMergedRegion(region1);
HSSFCellStyle style = workbook.createCellStyle();
style.setBorderBottom(BorderStyle.THIN);//下边框
style.setBorderLeft(BorderStyle.THIN);//左边框
style.setBorderRight(BorderStyle.THIN);//右边框
style.setBorderTop(BorderStyle.THIN); //上边框
HSSFFont font = workbook.createFont();
font.setFontHeightInPoints((short) 10);//设置字号
// font.setBold(true); //加粗
style.setFont(font);
style.setWrapText(true);//換行
Integer l = list.size();
for (int j = 0; j < l; j++) {
Product product = list.get(j);
HSSFRow rows = sheet.createRow(8 + j);
HSSFCell cellj1 = rows.createCell(0);
cellj1.setCellValue(product.getProduct_name());
HSSFCell cellj2 = rows.createCell(1);
cellj2.setCellValue(product.getProduct_model());
HSSFCell cellj3 = rows.createCell(2);
cellj3.setCellValue(product.getProduct_specification());
HSSFCell cellj4 = rows.createCell(3);
cellj4.setCellValue(product.getProduct_unit());
HSSFCell cellj5 = rows.createCell(4);
cellj5.setCellValue(product.getProduct_num());
HSSFCell cellj6 = rows.createCell(5);
cellj6.setCellValue(product.getProduct_unit_price() + "元");
HSSFCell cellj7 = rows.createCell(6);
cellj7.setCellValue(product.getMoney() + "元");
HSSFCell cellj8 = rows.createCell(7);
cellj8.setCellValue(product.getRemark());
cellj1.setCellStyle(style);
cellj2.setCellStyle(style);
cellj3.setCellStyle(style);
cellj4.setCellStyle(style);
cellj5.setCellStyle(style);
cellj6.setCellStyle(style);
cellj7.setCellStyle(style);
cellj8.setCellStyle(style);
}
//轮到8+l了
HSSFRow row8L = sheet.createRow(8 + l);
HSSFCell cell8L_1 = row8L.createCell(0);
cell8L_1.setCellValue("合同人民币大写金额:" + NumberToCN.number2CNMontrayUnit(new BigDecimal(contract.getContract_price())));
CellRangeAddress region2 = new CellRangeAddress(8 + l, 8 + l, 0, 5);
sheet.addMergedRegion(region2);
HSSFCell cell8L_2 = row8L.createCell(6);
cell8L_2.setCellValue(contract.getContract_price() + "元");
CellRangeAddress region3 = new CellRangeAddress(8 + l, 8 + l, 6, 7);
sheet.addMergedRegion(region3);
cell8L_1.setCellStyle(style);
cell8L_2.setCellStyle(style);
setRegionBorder(BorderStyle.THIN,region1,sheet);
setRegionBorder(BorderStyle.THIN,region2,sheet);
setRegionBorder(BorderStyle.THIN,region3,sheet);
sheet.setColumnWidth(0, 20 * 256);//设置第一列的宽度是20个字符宽度
sheet.setColumnWidth(1, 13 * 256);//设置第二列的宽度是13个字符宽度
sheet.setColumnWidth(2, 13 * 256);
sheet.setColumnWidth(3, 8 * 256);
sheet.setColumnWidth(4, 8 * 256);
sheet.setColumnWidth(5, 13 * 256);
sheet.setColumnWidth(6, 13 * 256);
sheet.setColumnWidth(7, 13 * 256);
row.setHeightInPoints(50);//设置行的高度是50个点
row8L.setHeightInPoints(20);//设置行的高度是20个点
HSSFPrintSetup ps = sheet.getPrintSetup();
ps.setLandscape(false); // 打印方向,true:横向,false:纵向
ps.setPaperSize(HSSFPrintSetup.A4_PAPERSIZE); //纸张
sheet.setMargin(HSSFSheet.BottomMargin, (double) 0.5);// 页边距(下)
sheet.setMargin(HSSFSheet.LeftMargin, (double) 0.1);// 页边距(左)
sheet.setMargin(HSSFSheet.RightMargin, (double) 0.1);// 页边距(右)
sheet.setMargin(HSSFSheet.TopMargin, (double) 0.5);// 页边距(上)
sheet.setHorizontallyCenter(true);//设置打印页面为水平居中
sheet.setVerticallyCenter(false);//设置打印页面为垂直居中使用POI输出Excel时打印页面的设置 - TOUGHGUYNEU - @EXPLORER使用POI输出Excel时打印页面的设置 - TOUGHGUYNEU - @EXPLORER
}
}
//将文件存到浏览器设置的下载位置
exportExcelByDownload(workbook, response, "批量导出Excel");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @Description: 解决合并单元格没有边框(边框被覆盖掉)
* @MethodName: setRegionBorder
* @Param: [border, region, sheet]
* @Return: void
* @Date: 2020-11-05
**/
private void setRegionBorder(BorderStyle border, CellRangeAddress region, Sheet sheet) {
RegionUtil.setBorderBottom(border, region, sheet);
RegionUtil.setBorderLeft(border, region, sheet);
RegionUtil.setBorderRight(border, region, sheet);
RegionUtil.setBorderTop(border, region, sheet);
}
/**
* excel表格直接下载
*/
public static void exportExcelByDownload(HSSFWorkbook wb, HttpServletResponse httpServletResponse, String fileName) throws Exception {
//响应类型为application/octet- stream情况下使用了这个头信息的话,那就意味着不想直接显示内容
httpServletResponse.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
//attachment为以附件方式下载
SimpleDateFormat newsdf = new SimpleDateFormat("yyyyMMddHHmmss");
String date = newsdf.format(new Date());
httpServletResponse.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(
fileName + date + ".xls",
"utf-8"));
/**
* 代码里面使用Content-Disposition来确保浏览器弹出下载对话框的时候。
* response.addHeader("Content-Disposition","attachment");一定要确保没有做过关于禁止浏览器缓存的操作
*/
httpServletResponse.setHeader("Cache-Control", "No-cache");
httpServletResponse.flushBuffer();
wb.write(httpServletResponse.getOutputStream());
wb.close();
}
/**
* @Description: 删除rowIndex行,并且上移其它行
* @MethodName: removeRow
* @Param: [sheet, rowIndex]
* @Return: void
* @Date: 2020-11-05
**/
private static void removeRow(HSSFSheet sheet, int rowIndex) {
int lastRowNum=sheet.getLastRowNum();
if(rowIndex>=0&&rowIndex<lastRowNum){
sheet.shiftRows(rowIndex+1,lastRowNum,-1);//将行号为rowIndex+1一直到行号为lastRowNum的单元格全部上移一行,以便删除rowIndex行
}
if(rowIndex==lastRowNum){
HSSFRow removingRow=sheet.getRow(rowIndex);
if(removingRow!=null)
sheet.removeRow(removingRow);
}
}
①JAVA POI的使用_林中静月下仙的博客-CSDN博客
②POI3切换为POI4修改内容
提示:写完后,我突然感觉为什么不封装个方法,循环数组即可,内容定义在数组里。虽然我也封装了不少,算了毕竟第一次使用POI,下回再说。
綜上:最好使用封装POI的工具(比如hutool等)去做导入导出,毕竟几行代码就能搞定,面对复杂的文件导出建议使用模板引擎。如果前者都不适用,那就选POI吧,POI功能强大,无所不能,无法无天,哈哈哈。
喜欢就关注我吧,我会努力更新的!
手机扫一扫
移动阅读更方便
你可能感兴趣的文章