java 利用poi根据excel模板导出数据(一) 您所在的位置:网站首页 poi导出xlsx打不开 java 利用poi根据excel模板导出数据(一)

java 利用poi根据excel模板导出数据(一)

2023-04-10 21:34| 来源: 网络整理| 查看: 265

前言

作为B端开发,导出数据是不可以避免的,但是有时候需求很变态,表头复杂的一笔,各种合并单元格,如下图:

 这些虽说用代码可以实现,但是很繁琐,而且代码并不能通用,遇到更复杂的更难受。为了追求更简单,高效率,我们需要换个方法——-利用模板导出数据!

?????能用模板?????

sure!

本文所用的excel样式,如果列更多、更复杂,直接套用就行  (下方图片中的数字是列名),行序号为1的是表格标题名称,行序号为2的是适应导出时把条件也导出来的情况,别怀疑,就是有这种需求!!

正文开始

1.需要用到的包

 poi

org.apache.poi poi 4.0.0 org.apache.poi poi-ooxml 4.0.0 org.apache.poi poi-ooxml-schemas 4.0.0 org.apache.poi ooxml-schemas 1.3

nutz(工具包,非必须,公司框架,本文与之相关的就只有一个NutMap==Map,不用这个请手动替换)

org.nutz nutz 1.r.68.v20200427

2.直接上代码

  入口

public static void doExportLongArrearsData() { // 要导出的数据 NutMap nutMap = NutMap.NEW(); nutMap.addv("comm","1111"); nutMap.addv("a","1111"); nutMap.addv("b","2222"); nutMap.addv("c","11333311"); nutMap.addv("d","1114441"); nutMap.addv("e","555"); nutMap.addv("f","6666"); nutMap.addv("g","7777"); nutMap.addv("h","88888"); List list = Lists.newArrayList(); list.add(nutMap); // 导出列 列数 int colNum = 9; int[] colWidth = new int[colNum]; for (int i = 0; i < colNum; i++) { colWidth[i] = 23; } // 从XX行开始为数据内容 excel 第一行为0 int startRow = 5; //  2003版本的Excel (xls) ---- HSSFWorkbook // 2007版本以及更高版本 (xlsx)---- XSSFWorkbook XSSFWorkbook workbook = null; try { // 此处linux和windows通用 /files/cq.xlsx 在resource目录下 视情况而定 /** * 特殊说明: this.getClass().getResourceAsStream * 如果fileUrl路径前不加 / 那么会读取类文件夹下的文件。加了才会读取resource下面的文件 * exp: this.getClass().getResourceAsStream("/files/cq.xlsx") ==>读取resource下面的文件 * this.getClass().getResourceAsStream("files/cq.xlsx") ==>读取当前类下的文件 * 源码: * private String resolveName(String name) { * if (name == null) { * return name; * } * if (!name.startsWith("/")) { * Class c = this; * while (c.isArray()) { * c = c.getComponentType(); * } * String baseName = c.getName(); * int index = baseName.lastIndexOf('.'); * if (index != -1) { * name = baseName.substring(0, index).replace('.', '/') * +"/"+name; * } * } else { * name = name.substring(1); * } * return name; * } */ // InputStream inputStream = this.getClass().getResourceAsStream("/files/cq.xlsx"); FileInputStream inputStream = new FileInputStream( new File("C:\\Users\\usaer\\Desktop\\buss.xlsx")); workbook = new XSSFWorkbook(inputStream); // 获取sheet XSSFSheet sheetAt = workbook.getSheetAt(0); // 动态列 修改表头名 、修改模板数据等操作 // 自定义参数 int k = 1; updateCellLoad(workbook,sheetAt,k); // 填充数据 fillBodyData( sheetAt,startRow,list,colWidth); // 设置单元格宽度 (不设置的话,就是模板的宽度) if (null != colWidth) { for (int i = 0; i < colWidth.length; i++) { sheetAt.setColumnWidth(i, colWidth[i] * 256 + 184); } } // 输出流 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // excel工作空间写入流 workbook.write(byteArrayOutputStream); InputStream wrap = Streams.wrap(byteArrayOutputStream.toByteArray()); // 写到本地 writeToLocal("C:\\Users\\usaer\\Desktop\\buss_"+k+".xlsx",wrap); } catch (Exception e) { System.out.println(e.getMessage()); } finally { // 关闭流 if (null != workbook) try { workbook.close(); } catch (IOException e) { } } }

修改列的方法 (填充数据之前之后都可以修改内容,包括但不限于修改列、修改行、样式等)

public static void updateCellLoad( XSSFWorkbook workbook,Sheet sheet,int k) { try { //设置行 指定行 Row titlerow=sheet.getRow(2); //根据索引获取对应的列 如果合并单元格 有可能第一列就找不到 根据需求修改参数值 Cell cell=titlerow.getCell(0, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); //设置列的类型是字符串 cell.setCellType(CellType.STRING); cell.setCellValue(k==1?"1":"0"); String titleValue=cell.getStringCellValue(); System.out.println(titleValue); // 设置行 指定行修改数据和样式 有可能第一行就找不到 根据需求修改参数值 CellStyle style1 = workbook.createCellStyle(); // 自动换行 style1.setWrapText(true); Row row1 = sheet.createRow(1); // 行高度 row1.setHeight(Short.parseShort("1000")); Cell row1Cell = row1.createCell(0, CellType.STRING); row1Cell.setCellStyle(style1); StringBuilder sb = new StringBuilder(); sb.append("条件1:").append("ABC").append("\r\n"); sb.append("条件2:").append("DEF").append("\r\n"); sb.append("条件3:").append("GHI").append("\r\n"); row1Cell.setCellValue(sb.toString()); } catch (EncryptedDocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } }

填充数据的方法

private static void fillBodyData(Sheet sheet, int startRow, List bodyList, int[] colWidth) { // 碰到 时间、金额等需要转换的 在setCellValue 里面操作 for (int rowNum = 0; rowNum < bodyList.size(); rowNum++) { NutMap map = bodyList.get(rowNum); Row row = sheet.createRow(rowNum + startRow); int colNum = 0; // comm Cell accountNumberCell = row.createCell(colNum++, CellType.STRING); String accountNumber = map.getString("comm"); colWidth[colNum - 1] = Math.max(colWidth[colNum - 1], Strings.charLength(accountNumber)); accountNumberCell.setCellValue(accountNumber); // a Cell accountNameCell = row.createCell(colNum++, CellType.STRING); String accountName = map.getString("a"); colWidth[colNum - 1] = Math.max(colWidth[colNum - 1], Strings.charLength(accountName)); accountNameCell.setCellValue(accountName); // b Cell mobileCell = row.createCell(colNum++, CellType.STRING); String mobile = map.getString("b"); colWidth[colNum - 1] = Math.max(colWidth[colNum - 1], Strings.charLength(mobile)); mobileCell.setCellValue(mobile); // c Cell addressCell = row.createCell(colNum++, CellType.STRING); String address = map.getString("c"); colWidth[colNum - 1] = Math.max(colWidth[colNum - 1], Strings.charLength(address)); addressCell.setCellValue(address); // d Cell meterNoCell = row.createCell(colNum++, CellType.STRING); String meterNo = map.getString("d"); meterNoCell.setCellValue(meterNo); colWidth[colNum - 1] = Math.max(colWidth[colNum - 1], Strings.charLength(meterNo)); // e Cell uncollectedNumberCell = row.createCell(colNum++, CellType.STRING); String uncollectedNumber = map.getString("e"); uncollectedNumberCell.setCellValue(uncollectedNumber); colWidth[colNum - 1] = Math.max(colWidth[colNum - 1], Strings.charLength(uncollectedNumber)); // f Cell uncollectedDosageCell = row.createCell(colNum++, CellType.STRING); String uncollectedDosage = map.getString("f"); uncollectedDosageCell.setCellValue(uncollectedDosage); colWidth[colNum - 1] = Math.max(colWidth[colNum - 1], Strings.charLength(uncollectedDosage)); // g Cell uncollectedDosageCell1 = row.createCell(colNum++, CellType.STRING); String uncollectedDosage1 = map.getString("g"); uncollectedDosageCell1.setCellValue(uncollectedDosage1); colWidth[colNum - 1] = Math.max(colWidth[colNum - 1], Strings.charLength(uncollectedDosage1)); // h Cell uncollectedDosageCell2 = row.createCell(colNum++, CellType.STRING); String uncollectedDosage2 = map.getString("h"); uncollectedDosageCell2.setCellValue(uncollectedDosage2); colWidth[colNum - 1] = Math.max(colWidth[colNum - 1], Strings.charLength(uncollectedDosage2)); } }

写到本地

private static void writeToLocal(String destination, InputStream input) throws IOException { int index = 0; byte[] bytes = new byte[1024]; FileOutputStream downloadFile = new FileOutputStream(destination); while ((index = input.read(bytes)) > 0) { downloadFile.write(bytes, 0, index); } downloadFile.close(); input.close(); }

代码就这些,纯测试,有些命名很随意,到时候用的时候自己改

效果图

注意: 

本文读取文件是从本地读取的,部署后,需要把模板文件放在resource下,利用代码中

// 此处linux和windows通用 /files/cq.xlsx 在resource目录下 视情况而定 // InputStream inputStream = this.getClass().getResourceAsStream("/files/cq.xlsx");

 来读取(本人框架非spring,spring自行解决),总之,获取到模板文件就是成功!!

如果想要设置单元格的样式比如字体垂直、水平居中等可以在  fillBodyData 中添加如下代码

// 单元格样式 XSSFCellStyle cellStyle = workbook.createCellStyle(); // 设置单元格的水平对齐类型 cellStyle.setAlignment(HorizontalAlignment.CENTER); // 设置单元格的垂直对齐类型 cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

然后再循环体内每个cell设置style ,例如:

Cell accountNumberCell = row.createCell(colNum++, CellType.STRING); String accountNumber = map.getString("comm"); colWidth[colNum - 1] = Math.max(colWidth[colNum - 1], Strings.charLength(accountNumber)); accountNumberCell.setCellValue(accountNumber); // 设置style accountNumberCell.setCellStyle(cellStyle);

后续有更好的我会更新此贴,大家将就一下

续篇来了 ,基本上没区别就是poi导出excel的三种形式的简单说明和解释

java 利用poi根据excel模板导出数据(二)

来源:Stuild Stuil

您可能感兴趣的内容: Python–openpyxl详解 YOLOV5源码的详细解读 python实现——处理Excel表格(超详细) 基于Python+MySQL的图书管理系统 Python正则表达式一文详解+实例代码展示


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有