做网站有陪标现象吗,网站开发协议百度,网络营销专业就业公司,线上广告推广平台目录 前言一、情景介绍二、文档介绍2.1 读取模板2.2 填充模板 三、代码示例3.1 案例一#xff1a;工资表3.2 案例二#xff1a;报价单 四、我所遇到的问题 前言
Java-easyExcel入门教程#xff1a;https://blog.csdn.net/xhmico/article/details/134714025
之前有介绍过如… 目录 前言一、情景介绍二、文档介绍2.1 读取模板2.2 填充模板 三、代码示例3.1 案例一工资表3.2 案例二报价单 四、我所遇到的问题 前言
Java-easyExcel入门教程https://blog.csdn.net/xhmico/article/details/134714025
之前有介绍过如何使用 easyExcel以及写了两个入门的 demo 这两个 demo 能应付在开发中大多数的导入和导出需求不过有时候面对一些复杂的表格就会有点不够用该篇是如何使用模板实现导出功能 一、情景介绍
在实际的开发过程中可能会遇到需要导出一些带有复杂表头的表格比如工资表和考勤表 或者是类似于发票、报价单这种具有模板性质的表格 如果仅仅通过代码去实现是比较困难的通常情况下会写一个模板 excel模板中的需要变动的数据用占位符替代导出的文件按照该模板填充数据 二、文档介绍
easyexcel 也提供了根据模板写入的功能可以用较为简单的方式实现上述功能其基本步骤为
① 读取模板文件② 填充模板中的占位符 2.1 读取模板
官方文档根据模板写入 在官方文档中给出了如何使用 easyexcel 读取模板的代码示例
官网代码示例 /*** 根据模板写入* p1. 创建excel对应的实体对象 参照{link IndexData}* p2. 使用{link ExcelProperty}注解指定写入的列* p3. 使用withTemplate 写取模板* p4. 直接写即可*/Testpublic void templateWrite() {String templateFileName TestFileUtil.getPath() demo File.separator demo.xlsx;String fileName TestFileUtil.getPath() templateWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭// 这里要注意 withTemplate 的模板文件会全量存储在内存里面所以尽量不要用于追加文件如果文件模板文件过大会OOM// 如果要再文件中追加无法在一个线程里面处理可以在一个线程的建议参照多次写入的demo 建议临时存储到数据库 或者 磁盘缓存(ehcache) 然后再一次性写入EasyExcel.write(fileName, DemoData.class).withTemplate(templateFileName).sheet().doWrite(data());}从上述示例代码中可以看到读取模板文件的方法为withTemplate() public ExcelWriterBuilder withTemplate(InputStream templateInputStream) {this.writeWorkbook.setTemplateInputStream(templateInputStream);return this;}public ExcelWriterBuilder withTemplate(File templateFile) {this.writeWorkbook.setTemplateFile(templateFile);return this;}public ExcelWriterBuilder withTemplate(String pathName) {return this.withTemplate(new File(pathName));}2.2 填充模板
官方文档填充Excel
注意这里建议先去看下官方文档中给的示例会比较好理解 在模板中占位符用 {变量} 表示比如 {name}、{age} 如果占位符为列表则使用 {.变量} 表示比如{.name}、{.age}
进行填充的方法为fill() public ExcelWriter fill(Object data, WriteSheet writeSheet) {return this.fill((Object)data, (FillConfig)null, writeSheet);}public ExcelWriter fill(Object data, FillConfig fillConfig, WriteSheet writeSheet) {this.excelBuilder.fill(data, fillConfig, writeSheet);return this;}public ExcelWriter fill(SupplierObject supplier, WriteSheet writeSheet) {return this.fill((Object)supplier.get(), (FillConfig)null, writeSheet);}public ExcelWriter fill(SupplierObject supplier, FillConfig fillConfig, WriteSheet writeSheet) {this.excelBuilder.fill(supplier.get(), fillConfig, writeSheet);return this;}在 EasyExcel 中FillConfig 类用于配置单元格填充相关的设置。
以下是一些 FillConfig 类中常用的配置项
forceNewRow是否强制写入到新行。当设置为 true 时每次写入都会创建新的行而不是在现有行上进行覆盖direction填充方向可以指定是水平填充还是垂直填充 属性 WriteDirectionEnum.VERTICAL垂直填充WriteDirectionEnum.HORIZONTAL水平填充
如果有多列组合填充的情况通过 {前缀.变量} 的形式区分不同的列表例如 使用 FillWrapper 构建 Excel 写入时的填充模板 ...excelWriter.fill(new FillWrapper(data1, data()), writeSheet);excelWriter.fill(new FillWrapper(data2, data()), writeSheet);excelWriter.fill(new FillWrapper(data3, data()), writeSheet);...三、代码示例
简单介绍了 easyexcel 如何使用模板进行导出接下来就通过几个简单的案例进行演示
以下案例使用的模板文件均可在文章顶部下载 3.1 案例一工资表
编写 excel 模板 实体类
StaffSalaryEntity.java
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;Data
Builder
NoArgsConstructor
AllArgsConstructor
public class StaffSalaryEntity {ApiModelProperty(value 姓名)private String name;ApiModelProperty(value 职称)private String post;ApiModelProperty(value 月薪)private BigDecimal mouthSalary;ApiModelProperty(value 时薪)private BigDecimal hourSalary;ApiModelProperty(value 应出勤天数)private Double shouldAttend;ApiModelProperty(value 出勤天数)private Double actualAttend;ApiModelProperty(value 平时加班时数)private Double overtime;ApiModelProperty(value 周末加班时数)private Double weekOvertime;ApiModelProperty(value 国假天数)private Double holiday;ApiModelProperty(value 正班薪资)private BigDecimal normalSalary;ApiModelProperty(value 平时加班薪资)private BigDecimal overtimeSalary;ApiModelProperty(value 周末加班薪资)private BigDecimal weekOvertimeSalary;ApiModelProperty(value 国假薪资)private BigDecimal holidaySalary;ApiModelProperty(value 岗位津贴)private BigDecimal postSubsidy;ApiModelProperty(value 全勤补贴)private BigDecimal fullAttendSubsidy;ApiModelProperty(value 全勤奖)private BigDecimal award;ApiModelProperty(value 事假缺勤扣款)private BigDecimal deduction;ApiModelProperty(value 社保费用)private BigDecimal social;ApiModelProperty(value 应得薪资)private BigDecimal shouldSalary;ApiModelProperty(value 个人扣税)private BigDecimal selfTax;ApiModelProperty(value 实发薪资)private BigDecimal actualSalary;ApiModelProperty(value 员工签名)private BigDecimal sign;
}实体类中的字段要跟模板中占位符中的变量对应
代码示例
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.mike.server.system.domain.excel.ProductOfferExcelEntity;
import com.mike.server.system.entity.StaffSalaryEntity;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;public class TestDemo {/*** 案例一工资表*/Testpublic void salaryList() {// 模板文件路径String templateFilePath D:\\excel-files\\gzb-template.xlsx;// 输出文件路径String outFilePath D:\\excel-files\\gzb.xlsx;// 创建 ExcelWriter 实例ExcelWriter writer EasyExcel// 写入到.write(outFilePath)// 指定模板.withTemplate(templateFilePath).build();WriteSheet sheet EasyExcel.writerSheet().build();// 获取员工工资数据ListStaffSalaryEntity staffSalaryEntities getStaffSalaryEntities();FillConfig fillConfig FillConfig.builder()// 开启填充换行.forceNewRow(true).build();// 执行填充操作writer.fill(staffSalaryEntities, fillConfig, sheet);// 结束writer.finish();}public ListStaffSalaryEntity getStaffSalaryEntities() {ListStaffSalaryEntity list new ArrayList();list.add(StaffSalaryEntity.builder().name(米大傻).post(开发).mouthSalary(new BigDecimal(1320)).hourSalary(new BigDecimal(7.59)).shouldAttend(21.0).actualAttend(21.0).overtime(21.0).weekOvertime(8.0).holiday(0.0).normalSalary(new BigDecimal(1320)).overtimeSalary(new BigDecimal(238.97)).weekOvertimeSalary(new BigDecimal(242.76)).holidaySalary(new BigDecimal(0)).postSubsidy(new BigDecimal(0)).award(new BigDecimal(20)).deduction(new BigDecimal(0)).social(new BigDecimal(113.6)).shouldSalary(new BigDecimal(1688.12)).selfTax(new BigDecimal(0)).actualSalary(new BigDecimal(1688.1)).build());list.add(StaffSalaryEntity.builder().name(曹大力).post(店长).mouthSalary(new BigDecimal(13200)).hourSalary(new BigDecimal(7.59)).shouldAttend(21.0).actualAttend(21.0).overtime(21.0).weekOvertime(8.0).holiday(0.0).normalSalary(new BigDecimal(1320)).overtimeSalary(new BigDecimal(238.97)).weekOvertimeSalary(new BigDecimal(242.76)).holidaySalary(new BigDecimal(0)).postSubsidy(new BigDecimal(0)).award(new BigDecimal(20)).deduction(new BigDecimal(0)).social(new BigDecimal(113.6)).shouldSalary(new BigDecimal(13200.12)).selfTax(new BigDecimal(0)).actualSalary(new BigDecimal(13200.1)).build());list.add(StaffSalaryEntity.builder().name(张大仙).post(经理).mouthSalary(new BigDecimal(13200)).hourSalary(new BigDecimal(7.59)).shouldAttend(21.0).actualAttend(21.0).overtime(21.0).weekOvertime(8.0).holiday(0.0).normalSalary(new BigDecimal(1320)).overtimeSalary(new BigDecimal(238.97)).weekOvertimeSalary(new BigDecimal(242.76)).holidaySalary(new BigDecimal(0)).postSubsidy(new BigDecimal(0)).deduction(new BigDecimal(0)).social(new BigDecimal(113.6)).shouldSalary(new BigDecimal(13200.12)).selfTax(new BigDecimal(0)).actualSalary(new BigDecimal(13200.1)).build());return list;}
}展示 3.2 案例二报价单
编写模板 模板文件放在项目的 resources 目录下的 templates/excel 文件夹下 实体类
OfferDetailEntity.java
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;Data
Builder
NoArgsConstructor
AllArgsConstructor
public class OfferDetailEntity {ApiModelProperty(value 公司名称)private String companyName;ApiModelProperty(value 报价日期)private String offerDate;ApiModelProperty(value 报价有效期)private String offerValidDate;ApiModelProperty(value 客户名称)private String customerName;ApiModelProperty(value 客户地址)private String customerAddress;ApiModelProperty(value 联系方式)private String contact;ApiModelProperty(value 合计数量)private Integer totalQty;ApiModelProperty(value 合计金额)private BigDecimal totalAmount;
}ProductOfferEntity.java
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.math.BigDecimal;Data
Builder
NoArgsConstructor
AllArgsConstructor
public class ProductOfferEntity {ApiModelProperty(value 产品名称)private String productName;ApiModelProperty(value 型号及规格)private String typeSpec;ApiModelProperty(value 数量)private Integer quantity;ApiModelProperty(value 单价)private BigDecimal price;ApiModelProperty(value 金额)private BigDecimal amount;ApiModelProperty(value 备注)private String remark;}代码示例
TestController.java GetMapping(/export/by-template)ApiOperation(value 导出-按模板格式, produces application/octet-stream)public ResponseBeanString exportByTemplate(HttpServletResponse response) {testService.exportByTemplate(response);return ResponseBean.success();}TestService.java /*** 导出-按模板格式*/void exportByTemplate(HttpServletResponse response);TestServiceImpl.java SneakyThrowsOverridepublic void exportByTemplate(HttpServletResponse response) {ServletOutputStream out response.getOutputStream();EasyExcelUtil.initResponse(response, 报价单);// 文件模板输入流将 excel 模板放到 resources 目录下InputStream templateFile new ClassPathResource(templates/excel/bjd.xlsx).getInputStream();ExcelWriter writer EasyExcel.write(out).withTemplate(templateFile).build();WriteSheet sheet EasyExcel.writerSheet().build();/*HashMapString, Object offerDetail new HashMap();offerDetail.put(companyName, 多加辣科技);offerDetail.put(offerDate, 2024-04-07);offerDetail.put(offerValidDate, 2024-04-11);offerDetail.put(customerName, 米大傻);offerDetail.put(customerAddress, 广东省广州市);offerDetail.put(contact, 078-182****4568);offerDetail.put(totalQty, 5);offerDetail.put(totalAmount, new BigDecimal(10300));*/OfferDetailEntity offerDetail OfferDetailEntity.builder().companyName(多加辣科技).offerDate(2024-04-07).offerValidDate(2024-04-11).customerName(米大傻).customerAddress(广东省广州市).contact(078-182****4568).totalQty(5).totalAmount(new BigDecimal(10300)).build();// 填充普通占位符// 这里 data 使用对象或者 Map 都可以writer.fill(offerDetail, sheet);ListProductOfferEntity list new ArrayList();list.add(ProductOfferEntity.builder().productName(电脑).typeSpec(联想).price(new BigDecimal(5000)).quantity(2).amount(new BigDecimal(10000)).build());list.add(ProductOfferEntity.builder().productName(鼠标).typeSpec(联想).price(new BigDecimal(100)).quantity(3).amount(new BigDecimal(300)).build());// 填充配置开启组合填充换行FillConfig fillConfig FillConfig.builder().forceNewRow(true).build();// 填充列表占位符writer.fill(list, fillConfig, sheet);//填充完成writer.finish();}相关工具类
EasyExcelUtil.java
package com.mike.common.core.utils.excel;import com.mike.common.core.constant.DateFormatConstant;
import com.mike.common.core.utils.StringUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;public class EasyExcelUtil {/*** 初始化响应体* param response 请求头* param fileName 导出名称*/public static void initResponse(HttpServletResponse response, String fileName) {// 最终文件名文件名_(截止yyyy-MM-dd) -- 这块地方得根据你们自己项目做更改了String finalFileName fileName _(截止 StringUtils.getNowTimeStr(DateFormatConstant.Y0M0D));// 设置content—type 响应类型response.setContentType(application/vnd.ms-excel);response.setCharacterEncoding(utf-8);try {// 这里URLEncoder.encode可以防止中文乱码finalFileName URLEncoder.encode(finalFileName, UTF-8);} catch (UnsupportedEncodingException e) {e.printStackTrace();}response.setHeader(Content-disposition, attachment;filename finalFileName .xlsx);}
}测试 四、我所遇到的问题 1驼峰命名导致填充数据失败
我在编写工资条案例时最开始的模板如下 导出效果 数据都有但是导出的表格中有些字段填充失败
这个我也不知道具体原因是为什么不过测了几组数据之后得出以下结论
如果占位符中的变量采用的是驼峰命名的方式且组成变量的 “单词” 存在过于简单的时就会出现该状况比如说
月薪的占位符 {.mSalary} 中的 mSalary 是由 m 和 salary 组成m 只有一个字母 {.mSalary} 填充不上但是如果单独使用 {.m} 或者 {.salary} 却可以填充上去或者把每个组成的单词写复杂一点比如写成 {.mouthSalary} 也是可以填充上的
解决方案要么就不要用驼峰命名要么驼峰命名就写规范点不要简写
3模板单元格样式消失
如果你使用模板导出发现有些单元格的样式消失了比如 这是因为在 write() 方法中添加了表格头的 class 对象 通过模板导出的方式不需要设置这个类对象去掉即可 ExcelWriter writer EasyExcel.write(out).withTemplate(templateFile).build();参考文章
easyexcel导出excel表格https://blog.csdn.net/qq_57732418/article/details/136944211
SpringBoot集成阿里EasyExcel导出excel高级实战https://blog.csdn.net/Blueeyedboy521/article/details/128257388
springboot 使用 EasyExcel 通过模板导出EXCEL 带多个动态列表https://www.cnblogs.com/guanxiaohe/p/17719954.html