SpringBoot POI 导入,导出 Excel

2019年12月13日 18:31 · 阅读(2159) ·

参考

Springboot poi 导入、导出excel 简单步骤
https://www.jianshu.com/p/e12c69eea764

POI复制Excel模板并填充数据
https://yq.aliyun.com/articles/680217

Apache POI 之一:Excel文档的读取
https://www.jianshu.com/p/80a9c2c7ebe5

SpringBoot静态资源的访问
https://www.jianshu.com/p/d40ee98b84b5

目标

SpringBoot 使用 POI 导入,导出 Excel 数据。

开发环境

名称 版本
操作系统 Windows 10 X64
JDK JDK1.8(jdk-8u151-windows-x64)
IntelliJ IDEA IntelliJ IDEA 2018.3
Maven Maven 3.6.0

说明

本文的代码结构基于 IntelliJ IDEA 2018.3 创建 Maven 多模块(Module)项目+负载均衡 项目上进行操作。

功能概述

数据表-t_fpts_tax_exemption

  1. -- ----------------------------
  2. -- Table structure for t_fpts_tax_exemption
  3. -- ----------------------------
  4. DROP TABLE IF EXISTS `t_fpts_tax_exemption`;
  5. CREATE TABLE `t_fpts_tax_exemption` (
  6. `id` bigint(20) NOT NULL COMMENT '主键',
  7. `contract_party` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '合同方(合作方名称)',
  8. `contract_no` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '合同编号',
  9. `chinese_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '中文翻译名称',
  10. `product` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '产品\r\n',
  11. `signing_date` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '签订日期\r\n',
  12. `start_date` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '开始日期\r\n',
  13. `end_time` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '结束日期\r\n',
  14. `contract_type` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '合同类型\r\n',
  15. `remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '备注\r\n',
  16. `principal` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '负责商务\r\n',
  17. `records_date` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '税局备案日期\r\n',
  18. `tax_exemption_date` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '免增值税备案有效期\r\n',
  19. `supplier_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '供应商编码',
  20. `create_time` timestamp(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '创建时间',
  21. `create_by` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人',
  22. `update_time` timestamp(0) NULL DEFAULT NULL COMMENT '修改时间',
  23. `update_by` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人',
  24. `is_delete` tinyint(1) NULL DEFAULT NULL COMMENT '是否删除。1,-1',
  25. `biz_time` timestamp(0) NULL DEFAULT NULL COMMENT '系统时间戳',
  26. `create_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,
  27. `update_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,
  28. PRIMARY KEY (`id`) USING BTREE
  29. ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;
  30. SET FOREIGN_KEY_CHECKS = 1;

测试数据

  1. --导出Excel测试数据
  2. insert into t_fpts_tax_exemption(id,contract_party,contract_no,chinese_name,product,signing_date,start_date,end_time,contract_type,remark,principal,records_date,tax_exemption_date,supplier_code,create_time,create_by,update_time,update_by,is_delete,biz_time,create_name,update_name
  3. )
  4. values(6,'测试供应商','contract_no-001','西安雅和印刷科技有限公司','产品-皮包','2019-01','2019-01','2019-12','企业','【测试】-v_hwhao-1','wuxingfeng','2018-01-01','2020-12-12','supplier_code-001',now(),'v_hwhao',now(),'v_hwhao',1,now(),'v_hwhao','v_hwhao');
  5. insert into t_fpts_tax_exemption(id,contract_party,contract_no,chinese_name,product,signing_date,start_date,end_time,contract_type,remark,principal,records_date,tax_exemption_date,supplier_code,create_time,create_by,update_time,update_by,is_delete,biz_time,create_name,update_name
  6. )
  7. values(7,'PIBAO-Company-2','contract_no-002','皮包公司','产品-皮包','2019-01','2019-01','2019-12','企业','【测试】-v_hwhao-1','wuxingfeng','2018-01-01','2020-12-12','supplier_code-003',now(),'v_hwhao',now(),'v_hwhao',1,now(),'v_hwhao','v_hwhao');
  8. insert into t_fpts_tax_exemption(id,contract_party,contract_no,chinese_name,product,signing_date,start_date,end_time,contract_type,remark,principal,records_date,tax_exemption_date,supplier_code,create_time,create_by,update_time,update_by,is_delete,biz_time,create_name,update_name
  9. )
  10. values(8,'TIAN-CHI-2','contract_no-003','天池茶叶公司','产品-大红袍','2019-01','2019-01','2019-12','企业','【测试】-v_hwhao-1','wuxingfeng','2018-01-01','2020-12-12','supplier_code-003',now(),'v_hwhao',now(),'v_hwhao',1,now(),'v_hwhao','v_hwhao');

公共类-增删查改操作类

Common-数据实体类

基础实体类-SuperEntity

  1. import com.baomidou.mybatisplus.annotation.FieldFill;
  2. import com.baomidou.mybatisplus.annotation.IdType;
  3. import com.baomidou.mybatisplus.annotation.TableField;
  4. import com.baomidou.mybatisplus.annotation.TableId;
  5. import com.baomidou.mybatisplus.extension.activerecord.Model;
  6. import com.fasterxml.jackson.annotation.JsonFormat;
  7. import io.swagger.annotations.ApiModelProperty;
  8. import lombok.Data;
  9. import lombok.EqualsAndHashCode;
  10. import lombok.experimental.Accessors;
  11. import java.io.Serializable;
  12. import java.util.Date;
  13. /**
  14. * 基础实体类
  15. *
  16. */
  17. @EqualsAndHashCode(callSuper = true)
  18. @Data
  19. @Accessors(chain = true)
  20. public class SuperEntity<T extends Model> extends Model<T> {
  21. @TableId(type = IdType.ID_WORKER)
  22. @ApiModelProperty(value = "主键")
  23. private Long id;
  24. @ApiModelProperty(value = "创建时间", hidden = true)
  25. @TableField(value = "create_time", fill = FieldFill.INSERT)
  26. @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
  27. private Date createTime;
  28. @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
  29. @ApiModelProperty(value = "修改时间", hidden = true)
  30. @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
  31. private Date updateTime;
  32. @ApiModelProperty(value = "创建人", hidden = true)
  33. @TableField(value = "create_by", fill = FieldFill.INSERT)
  34. private String createBy;
  35. @ApiModelProperty(value = "创建人名称", hidden = true)
  36. @TableField(value = "create_name", fill = FieldFill.INSERT)
  37. private String createName;
  38. @ApiModelProperty(value = "修改人", hidden = true)
  39. @TableField(value = "update_by", fill = FieldFill.INSERT_UPDATE)
  40. private String updateBy;
  41. @ApiModelProperty(value = "创建人名称", hidden = true)
  42. @TableField(value = "update_name", fill = FieldFill.INSERT)
  43. private String updateName;
  44. @ApiModelProperty(value = "是否删除(1、否,-1、是)", hidden = true)
  45. @TableField(value = "is_delete", fill = FieldFill.INSERT)
  46. private Integer isDelete;
  47. @ApiModelProperty(value = "系统时间戳", hidden = true)
  48. @TableField(value = "biz_time", fill = FieldFill.INSERT_UPDATE)
  49. @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
  50. private Date bizTime;
  51. @Override
  52. protected Serializable pkVal() {
  53. return this.id;
  54. }
  55. }

数据表映射类-TaxExemption

  1. import com.baomidou.mybatisplus.annotation.TableName;
  2. import com.foreign.payment.model.base.SuperEntity;
  3. import lombok.Data;
  4. import lombok.EqualsAndHashCode;
  5. import lombok.experimental.Accessors;
  6. @Data
  7. @EqualsAndHashCode(callSuper = true)
  8. @Accessors(chain = true)
  9. @TableName("t_fpts_tax_exemption")
  10. public class TaxExemption extends SuperEntity {
  11. private static final long serialVersionUID=1L;
  12. /**
  13. * 合同方
  14. */
  15. private String contractParty;
  16. /**
  17. * 合同编号
  18. */
  19. private String contractNo;
  20. /**
  21. * 中文翻译名称
  22. */
  23. private String chineseName;
  24. /**
  25. * 产品
  26. */
  27. private String product;
  28. /**
  29. * 签订日期
  30. */
  31. private String signingDate;
  32. /**
  33. * 开始日期
  34. */
  35. private String startDate;
  36. /**
  37. * 结束日期
  38. */
  39. private String endTime;
  40. /**
  41. * 合同类型
  42. */
  43. private String contractType;
  44. /**
  45. * 备注
  46. */
  47. private String remark;
  48. /**
  49. * 负责商务
  50. */
  51. private String principal;
  52. /**
  53. * 税局备案日期
  54. */
  55. private String recordsDate;
  56. /**
  57. * 免增值税备案有效期
  58. */
  59. private String taxExemptionDate;
  60. /**
  61. * 供应商编码
  62. */
  63. private String supplierCode;
  64. }

分页基础类-PageVO

  1. import io.swagger.annotations.ApiModelProperty;
  2. import lombok.Getter;
  3. import lombok.Setter;
  4. import lombok.experimental.Accessors;
  5. /**
  6. * 分页基础类
  7. */
  8. @Getter
  9. @Setter
  10. @Accessors(chain = true)
  11. public class PageVO {
  12. @ApiModelProperty("当前页数")
  13. private Integer current;
  14. @ApiModelProperty("每页显示条数")
  15. private Integer size;
  16. }

查询参数类-SupplierRequestData

  1. import com.foreign.payment.vo.PageVO;
  2. import lombok.Data;
  3. /**
  4. * 供应商接口请求数据类(至少填写一个参数)
  5. */
  6. @Data
  7. public class SupplierRequestData extends PageVO {
  8. /**
  9. * 供应商ID
  10. */
  11. private String supplierId;
  12. /**
  13. * 供应商名称
  14. */
  15. private String supplierName;
  16. }

Contract 接口

  1. /**
  2. * 获取免税合同供应商
  3. *
  4. * @param param 供应商信息
  5. * @return 免税合同供应商列表
  6. */
  7. @PostMapping("/exemptTaxSupplier")
  8. ResponseVO<Page<TaxExemption>> exemptTaxSupplier(@RequestBody SupplierRequestData param);
  9. /**
  10. * 替换免税合同供应商(删除之前的所有数据)
  11. * @param param 免税合同供应商数据
  12. * @return 替换成功返回 true,失败返回 false
  13. */
  14. @PostMapping("/replaceTaxExempt")
  15. ResponseVO replaceTaxExempt(@RequestBody List<TaxExemption> param);

Service 接口

Mapper 接口-TaxExemptionRepository

  1. @Repository
  2. public interface TaxExemptionRepository extends BaseMapper<TaxExemption> {
  3. /**
  4. * 删除所有免税合同供应商
  5. */
  6. void delTaxExempt();
  7. }

Mapper 接口映射 XML-TaxExemptionMapper.xml

  1. <select id="delTaxExempt">
  2. update t_fpts_tax_exemption set is_delete = -1
  3. </select>

数据库操作接口-TaxExemptionService

  1. public interface TaxExemptionService extends IService<TaxExemption> {
  2. /**
  3. * 获取免税合同供应商
  4. * @param param 供应商信息
  5. * @return 免税合同供应商列表
  6. */
  7. ResponseVO<Page<TaxExemption>> exemptTaxSupplier(SupplierRequestData param);
  8. /**
  9. * 删除免税合同供应商
  10. */
  11. void delTaxExempt();
  12. /**
  13. * 添加免税合同供应商
  14. * @param param 免税合同供应商数据
  15. */
  16. void addTaxExempt(List<TaxExemption> param);
  17. }

接口实现类-TaxExemptionServiceImpl

  1. @Service
  2. public class TaxExemptionServiceImpl extends ServiceImpl<TaxExemptionRepository, TaxExemption> implements TaxExemptionService {
  3. /**
  4. * 获取免税合同供应商
  5. * @param param 供应商信息
  6. * @return 免税合同供应商列表
  7. */
  8. @Override
  9. public ResponseVO<Page<TaxExemption>> exemptTaxSupplier(SupplierRequestData param){
  10. //分页条件
  11. Page<TaxExemption> page = new Page<>();
  12. page.setSize(param.getSize());
  13. page.setCurrent(param.getCurrent());
  14. //查询条件
  15. QueryWrapper<TaxExemption> wrapper = new QueryWrapper<>();
  16. wrapper.eq("is_delete",1);
  17. wrapper.like("supplier_code",param.getSupplierId());
  18. wrapper.like("contract_party",param.getSupplierName());
  19. IPage<TaxExemption> ipageData = baseMapper.selectPage(page,wrapper);
  20. Page<TaxExemption> pageData = CommonUtil.toPage(ipageData);
  21. ResponseVO<Page<TaxExemption>> responseVO = new ResponseVO<>(ResponseCode.OK);
  22. responseVO.setData(pageData);
  23. return responseVO;
  24. /*
  25. //类型转换
  26. ResponseVO<List<SupplierDataVO>> responseVO = new ResponseVO<>(ResponseCode.OK);
  27. if(pageData != null && pageData.getRecords() != null && pageData.getRecords().size() > 0){
  28. List<SupplierDataVO> data = new ArrayList<>();
  29. for(int i=0;i< pageData.getRecords().size();i++){
  30. TaxExemption item = pageData.getRecords().get(i);
  31. SupplierDataVO model = new SupplierDataVO();
  32. model.setId(item.getId());
  33. model.setSupplierCode(item.getSupplierCode());
  34. model.setSupplierName(item.getContractParty());
  35. model.setUpdateTime(item.getUpdateTime());
  36. data.add(model);
  37. }
  38. responseVO.setData(data);
  39. }*/
  40. }
  41. /**
  42. * 删除免税合同供应商
  43. */
  44. @Override
  45. public void delTaxExempt(){
  46. baseMapper.delTaxExempt();
  47. }
  48. /**
  49. * 添加免税合同供应商
  50. * @param param 免税合同供应商数据
  51. * @return 替换成功返回 true,失败返回 false
  52. */
  53. @Override
  54. public void addTaxExempt(List<TaxExemption> param){
  55. for(int i=0;i<param.size();i++){
  56. baseMapper.insert(param.get(i));
  57. }
  58. }
  59. }

Contrller-TaxPayerController

  1. @Slf4j
  2. @RestController
  3. @Api("纳税人管理相关接口")
  4. public class TaxPayerController {
  5. /**
  6. * 免税合同供应商-服务接口
  7. */
  8. @Autowired
  9. private TaxExemptionService exemptionService;
  10. /**
  11. * 获取免税合同供应商
  12. * @param param 供应商信息
  13. * @return 免税合同供应商列表
  14. */
  15. @PostMapping("/exemptTaxSupplier")
  16. public ResponseVO<Page<TaxExemption>> exemptTaxSupplier(@RequestBody SupplierRequestData param){
  17. return exemptionService.exemptTaxSupplier(param);
  18. }
  19. /**
  20. * 替换免税合同供应商(删除之前的所有数据)
  21. * @param param 免税合同供应商数据
  22. * @return 替换成功返回 true,失败返回 false
  23. */
  24. @PostMapping("/replaceTaxExempt")
  25. public ResponseVO replaceTaxExempt(@RequestBody List<TaxExemption> param){
  26. exemptionService.delTaxExempt();
  27. exemptionService.addTaxExempt(param);
  28. ResponseVO<Boolean> responseVO = new ResponseVO<>(ResponseCode.OK);
  29. responseVO.setData(true);
  30. return responseVO;
  31. }
  32. }

Excel 模版

导入模版-ExemptTaxSupplierImport.xlsx

导出模版-ExemptTaxSupplierExport.xlsx

Web层

bootstrap.properties

  1. #静态资源映射
  2. spring.mvc.static-path-pattern=/ExcelTemplate/*
  3. spring.resources.static-locations= classpath:ExcelTemplate/

Resource 放入 Excel 模版文件

yml 添加 Excel 相关配置

application.yml

  1. server:
  2. port: 8081
  3. servlet:
  4. context-path: /payment
  5. spring:
  6. profiles:
  7. active: dev

application-dev.yml

  1. #文件导入导出相关配置
  2. file-config:
  3. excel-template: ExcelTemplate/ #Excel 模版文件夹名称
  4. tax-exempt-import: ExemptTaxSupplierImport.xlsx #免税供应商导入 Excel 模版名称
  5. tax-exempt-export: ExemptTaxSupplierExport.xlsx #免税供应商导出 Excel 模版名称
  6. tax-exempt-prefix: 免税合同供应商- #免税供应商导出 Excel 文件前缀

配置读取类-FileConfig

  1. /**
  2. * 文件导入导出相关配置
  3. * @date: 2019-12-13 16:42
  4. */
  5. @Component
  6. @ConfigurationProperties("file-config")
  7. @Getter
  8. public class FileConfig {
  9. /**
  10. * 获取 Excel 模版文件夹名称
  11. */
  12. @Value("${file-config.excel-template}")
  13. private String excelTemplate;
  14. /**
  15. * 获取免税供应商导入 Excel 模版名称
  16. */
  17. @Value("${file-config.tax-exempt-import}")
  18. private String taxExemptImport;
  19. /**
  20. * 获取免税供应商导出 Excel 模版名称
  21. */
  22. @Value("${file-config.tax-exempt-export}")
  23. private String taxExemptExport;
  24. /**
  25. * 获取免税供应商导出 Excel 文件前缀
  26. */
  27. @Value("${file-config.tax-exempt-prefix}")
  28. private String taxExemptPrefix;
  29. }

pom.xml 引入 POI 内容

  1. <!-- 基本依赖,仅操作 xls 格式只需引入此依赖 -->
  2. <dependency>
  3. <groupId>org.apache.poi</groupId>
  4. <artifactId>poi</artifactId>
  5. <version>3.14</version>
  6. </dependency>
  7. <!-- 使用 xlsx 格式需要额外引入此依赖 -->
  8. <dependency>
  9. <groupId>org.apache.poi</groupId>
  10. <artifactId>poi-ooxml</artifactId>
  11. <version>3.14</version>
  12. </dependency>

Excel 操作公共类-ExcelUtils

  1. /**
  2. * Excel 工具类
  3. * @date: 2019-12-13 16:14
  4. */
  5. public class ExcelUtils {
  6. /**
  7. * 根据文件路径获取 Workbook 对象
  8. * @param readFilePath Excel 路径
  9. * @return POI Workbook 对象
  10. * @throws IOException
  11. */
  12. public static Workbook getWorkbook(String readFilePath) throws IOException{
  13. //Excel 模版路径
  14. //String resourcePath = this.getClass().getResource("/").getPath();
  15. //String readFilePath = resourcePath + "ExcelTemplate/"+fileName;
  16. File file = new File(readFilePath);
  17. FileInputStream inputStream = new FileInputStream(file);
  18. //读取 Excel 模版
  19. Workbook workbook = null;
  20. if(isExcel2003(readFilePath)){
  21. workbook = new HSSFWorkbook(inputStream);
  22. }else if(isExcel2007(readFilePath)){
  23. workbook = new XSSFWorkbook(inputStream);
  24. }
  25. return workbook;
  26. }
  27. /**
  28. * 下载 Excle
  29. * @param response HttpServletResponse
  30. * @param workbook Workbook
  31. * @param prefixName 导出文件的前缀名称
  32. * @throws IOException
  33. */
  34. public static void downLoadExcel(HttpServletResponse response, Workbook workbook, String saveFileName)throws IOException {
  35. //String saveFileName = prefixName + "-"+ DateUtils.format(new Date(),"yyyy-MM-dd-HHmmss")+".xlsx";
  36. if(isExcel2003(saveFileName)){
  37. response.setContentType("application/vnd.ms-excel");
  38. }else if(isExcel2007(saveFileName)){
  39. response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
  40. }
  41. response.setCharacterEncoding("utf-8");
  42. response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(saveFileName, "UTF-8"));
  43. workbook.write(response.getOutputStream());
  44. //保存文件到本地
  45. //String saveFilePath = resourcePath +"ExcelExport/";
  46. //File dirSave = new File(saveFilePath);
  47. //if (!dirSave.exists()) {
  48. // dirSave.mkdirs();
  49. //}
  50. //FileOutputStream outputStream = new FileOutputStream(saveFilePath + saveFileName);
  51. //workbook.write(outputStream);
  52. //outputStream.close();
  53. }
  54. /**
  55. * 是否是 .xls 格式的 excel
  56. * @param filePath 文件路径
  57. * @return 是返回 true,否返回 false
  58. */
  59. public static Boolean isExcel2003(String filePath) {
  60. return filePath.matches("^.+\\.(?i)(xls)$");
  61. }
  62. /**
  63. * 是否是 .xlsx 格式的 excel
  64. * @param filePath 文件路径
  65. * @return 是返回 true,否返回 false
  66. */
  67. public static Boolean isExcel2007(String filePath) {
  68. return filePath.matches("^.+\\.(?i)(xlsx)$");
  69. }
  70. /**
  71. * 验证是否 EXCEL 文件
  72. * @param filePath 文件路径
  73. * @return 是返回 true,否返回 false
  74. */
  75. public static Boolean validateExcel(String filePath){
  76. if (filePath == null || !(isExcel2003(filePath) || isExcel2007(filePath))){
  77. return false;
  78. }
  79. return true;
  80. }
  81. /**
  82. * 根据文件名称和 InputStream 获取对应类型的 Sheet
  83. * @param fileName 文件名称
  84. * @param inputStream InputStream
  85. * @return
  86. */
  87. public static Sheet getSheet(String fileName, InputStream inputStream) throws IOException {
  88. //根据文件类型选择创建 Workbook 的方式
  89. Workbook workbook = null;
  90. Sheet sheet = null;
  91. //根据文件名称获取类型
  92. if(isExcel2007(fileName)){
  93. workbook = new XSSFWorkbook(inputStream);
  94. sheet = workbook.getSheetAt(0);
  95. }else if(isExcel2003(fileName)){
  96. workbook = new HSSFWorkbook(inputStream);
  97. sheet = workbook.getSheetAt(0);
  98. }
  99. return sheet;
  100. }
  101. /**
  102. * 获取 Cell 对应的字符串类型值
  103. * @param cell Cell
  104. * @return 字符串类型值
  105. */
  106. public static String getStringValue(Cell cell){
  107. String value="";
  108. switch (cell.getCellType()) {
  109. case HSSFCell.CELL_TYPE_NUMERIC: // 数字
  110. //如果为时间格式的内容
  111. if (HSSFDateUtil.isCellDateFormatted(cell)) {
  112. //注:format格式 yyyy-MM-dd hh:mm:ss 中小时为12小时制,若要24小时制,则把小h变为H即可,yyyy-MM-dd HH:mm:ss
  113. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  114. value=sdf.format(HSSFDateUtil.getJavaDate(cell.
  115. getNumericCellValue())).toString();
  116. break;
  117. } else {
  118. value = new DecimalFormat("0").format(cell.getNumericCellValue());
  119. }
  120. break;
  121. case HSSFCell.CELL_TYPE_STRING: // 字符串
  122. value = cell.getStringCellValue();
  123. break;
  124. case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean
  125. value = cell.getBooleanCellValue() + "";
  126. break;
  127. case HSSFCell.CELL_TYPE_FORMULA: // 公式
  128. value = cell.getCellFormula() + "";
  129. break;
  130. case HSSFCell.CELL_TYPE_BLANK: // 空值
  131. value = "";
  132. break;
  133. case HSSFCell.CELL_TYPE_ERROR: // 故障
  134. value = "非法字符";
  135. break;
  136. default:
  137. value = "未知类型";
  138. break;
  139. }
  140. return value;
  141. }
  142. }

Web 接口-TaxPayerController

公共部分

  1. @Controller
  2. @RequestMapping(value = "/api")
  3. public class TaxPayerController extends BaseController {
  4. //====================================================================//
  5. /**
  6. * 文件导入导出配置帮助类
  7. */
  8. @Resource
  9. private FileConfig config;
  10. /**
  11. * 获取根据日期名称的 Excel 文件名名称
  12. * @return Excel 文件名名称
  13. */
  14. private String getExcelName(){
  15. return DateUtils.format(new Date(),"yyyy-MM-dd-HHmmss")+".xlsx";
  16. }
  17. /**
  18. * 获取 Resource 文件夹名称
  19. * @return
  20. */
  21. private String getResourcePath(){
  22. String resourcePath = this.getClass().getResource("/").getPath();
  23. return resourcePath;
  24. }
  25. //........
  26. }

查询数据

  1. /**
  2. * 获取免税合同供应商
  3. * @param param 供应商信息
  4. * @return 免税合同供应商列表
  5. */
  6. @PostMapping("/exemptTaxSupplier")
  7. public ResponseVO<Page<TaxExemption>> exemptTaxSupplier(@RequestBody SupplierRequestData param){
  8. //TODO 判断权限
  9. return foreignPaymentConsumer.exemptTaxSupplier(param);
  10. }
测试结果

导出数据到 Excel

  1. /**
  2. * 免税合同供应商-导出全部
  3. * @return
  4. */
  5. @GetMapping("/exemptTaxSupplierExport")
  6. public void exemptTaxSupplierExport(HttpServletResponse response) throws IOException {
  7. //查询条件
  8. SupplierRequestData param = new SupplierRequestData();
  9. param.setSupplierId("");
  10. param.setSupplierName("");
  11. param.setCurrent(1);
  12. param.setSize(5000);//默认获取 5000 条数据
  13. //查询数据
  14. ResponseVO<Page<TaxExemption>> responseVO = foreignPaymentConsumer.exemptTaxSupplier(param);
  15. Page<TaxExemption> pageData = responseVO.getData();
  16. List<TaxExemption> listData = pageData.getRecords();
  17. //Excel 模版路径
  18. String readFilePath = getResourcePath() + config.getExcelTemplate() + config.getTaxExemptExport();
  19. Workbook workbook= ExcelUtils.getWorkbook(readFilePath);
  20. Sheet sheet = workbook.getSheetAt(0);
  21. if(listData != null && listData.size() > 0){
  22. for(Integer i=0;i<listData.size();i++){
  23. TaxExemption data = listData.get(i);
  24. Integer col= 0;
  25. //供应商名称 contract_party
  26. sheet.getRow(i+1).getCell(col++).setCellValue(data.getContractParty());
  27. //供应商编码 supplier_code
  28. sheet.getRow(i+1).getCell(col++).setCellValue(data.getSupplierCode());
  29. //合同编号 contract_no
  30. sheet.getRow(i+1).getCell(col++).setCellValue(data.getContractNo());
  31. //中文翻译名称 chinese_name
  32. sheet.getRow(i+1).getCell(col++).setCellValue(data.getChineseName());
  33. //产品 product
  34. sheet.getRow(i+1).getCell(col++).setCellValue(data.getProduct());
  35. //签订日期 signing_date
  36. sheet.getRow(i+1).getCell(col++).setCellValue(data.getSigningDate());
  37. //开始日期 start_date
  38. sheet.getRow(i+1).getCell(col++).setCellValue(data.getStartDate());
  39. //结束日期 end_time
  40. sheet.getRow(i+1).getCell(col++).setCellValue(data.getEndTime());
  41. //合同类型 contract_type
  42. sheet.getRow(i+1).getCell(col++).setCellValue(data.getContractType());
  43. //备注 remark
  44. sheet.getRow(i+1).getCell(col++).setCellValue(data.getRemark());
  45. //负责商务 principal
  46. sheet.getRow(i+1).getCell(col++).setCellValue(data.getPrincipal());
  47. //税局备案日期 records_date
  48. sheet.getRow(i+1).getCell(col++).setCellValue(data.getRecordsDate());
  49. //免增值税备案有效期 tax_exemption_date
  50. sheet.getRow(i+1).getCell(col++).setCellValue(data.getTaxExemptionDate());
  51. //创建时间 create_time
  52. if(data.getCreateTime() != null){
  53. sheet.getRow(i+1).getCell(col++).setCellValue(DateUtils.format(data.getCreateTime(),"yyyy-MM-dd HH:mm:ss"));
  54. }
  55. //创建人 create_by
  56. sheet.getRow(i+1).getCell(col++).setCellValue(data.getCreateBy());
  57. //创建人名称 create_name
  58. sheet.getRow(i+1).getCell(col++).setCellValue(data.getCreateName());
  59. //修改时间 update_time
  60. if(data.getUpdateTime() != null){
  61. sheet.getRow(i+1).getCell(col++).setCellValue(DateUtils.format(data.getUpdateTime(),"yyyy-MM-dd HH:mm:ss"));
  62. }
  63. //修改人 update_by
  64. sheet.getRow(i+1).getCell(col++).setCellValue(data.getUpdateBy());
  65. //修改人名称 update_name
  66. sheet.getRow(i+1).getCell(col++).setCellValue(data.getUpdateName());
  67. //is_delete
  68. //biz_time
  69. }
  70. }
  71. String saveFileName = config.getTaxExemptPrefix() + getExcelName();
  72. ExcelUtils.downLoadExcel(response,workbook,saveFileName);
  73. }
测试结果

免税合同供应商-2019-12-12-143548.xlsx

导入 Excel

  1. /**
  2. * 免税合同供应商-上传替换
  3. * @param file 上传文件
  4. * @return 上传成功返回 true,否则返回 false
  5. */
  6. @PostMapping("/exemptTaxSupplierImport")
  7. public ResponseVO exemptTaxSupplierImport(@RequestParam(value="filename") MultipartFile file){
  8. ResponseVO<Boolean> responseVO = new ResponseVO<>(ResponseCode.SYSTEM_EXCEPTION);
  9. responseVO.setData(false);
  10. if(file.isEmpty()){
  11. responseVO.setCode(ResponseCode.PARAM_INVALID.value());
  12. responseVO.setMessage("文件为空!");
  13. return responseVO;
  14. }
  15. //获取文件名
  16. String fileName = file.getOriginalFilename();
  17. if(!ExcelUtils.validateExcel(fileName)){
  18. responseVO.setCode(ResponseCode.PARAM_INVALID.value());
  19. responseVO.setMessage("必须上传 Excel 文件!");
  20. return responseVO;
  21. }
  22. InputStream inputStream = null;
  23. try{
  24. inputStream = file.getInputStream();
  25. Sheet sheet = ExcelUtils.getSheet(fileName,inputStream);
  26. List<TaxExemption> listData = new ArrayList<>();
  27. Iterator<Row> rowItr=sheet.rowIterator();//遍历全部非空行
  28. //for(Row row : sheet){ //忽略表头 if(row.getRowNum() == 0) continue; //会获取所有行,包括空行
  29. //while(rowItr.hasNext()){ Row row=rowItr.next();//会获取所有行,包括空行
  30. int rowCount = sheet.getPhysicalNumberOfRows();
  31. for(int i = 1;i<rowCount;i++){
  32. Row row = sheet.getRow(i);
  33. //如果得到的行是空的一行,可以根据row.getFirstCellNum()是否大于等于0 来判断
  34. //该行为空那么:row.getFirstCellNum()=-1的,否则row.getFirstCellNum()=0
  35. if(null == row) break;
  36. if(row.getFirstCellNum() == -1) break;
  37. Integer col = 0;//列序号
  38. TaxExemption data = new TaxExemption();
  39. //供应商名称 contract_party
  40. data.setContractParty(ExcelUtils.getStringValue(row.getCell(col++)));
  41. //供应商编码 supplier_code
  42. data.setSupplierCode(ExcelUtils.getStringValue(row.getCell(col++)));
  43. //合同编号 contract_no
  44. data.setContractNo(ExcelUtils.getStringValue(row.getCell(col++)));
  45. //中文翻译名称 chinese_name
  46. data.setChineseName(ExcelUtils.getStringValue(row.getCell(col++)));
  47. //产品 product
  48. data.setProduct(ExcelUtils.getStringValue(row.getCell(col++)));
  49. //签订日期 signing_date
  50. data.setSigningDate(ExcelUtils.getStringValue(row.getCell(col++)));
  51. //开始日期 start_date
  52. data.setStartDate(ExcelUtils.getStringValue(row.getCell(col++)));
  53. //结束日期 end_time
  54. data.setEndTime(ExcelUtils.getStringValue(row.getCell(col++)));
  55. //合同类型 contract_type
  56. data.setContractType(ExcelUtils.getStringValue(row.getCell(col++)));
  57. //备注 remark
  58. data.setRemark(ExcelUtils.getStringValue(row.getCell(col++)));
  59. //负责商务 principal
  60. data.setPrincipal(ExcelUtils.getStringValue(row.getCell(col++)));
  61. //税局备案日期 records_date
  62. data.setRecordsDate(ExcelUtils.getStringValue(row.getCell(col++)));
  63. //免增值税备案有效期 tax_exemption_date
  64. data.setTaxExemptionDate(ExcelUtils.getStringValue(row.getCell(col++)));
  65. //创建时间 create_time
  66. //data.setCreateTime(row.getCell(col++).getDateCellValue());
  67. //创建人 create_by
  68. //data.setCreateBy(row.getCell(col++).getStringCellValue());
  69. //创建人名称 create_name
  70. //data.setCreateName(row.getCell(col++).getStringCellValue());
  71. //修改时间 update_time
  72. //data.setUpdateTime(row.getCell(col++).getDateCellValue());
  73. //修改人 update_by
  74. //data.setUpdateBy(row.getCell(col++).getStringCellValue());
  75. //修改人名称 update_name
  76. //data.setUpdateName(row.getCell(col++).getStringCellValue());
  77. //is_delete
  78. //biz_time
  79. if(!StringUtil.isBlank(data.getContractParty())
  80. && !StringUtil.isBlank((data.getSupplierCode()))
  81. && !StringUtil.isBlank(data.getContractNo())){
  82. listData.add(data);
  83. }
  84. }
  85. if(listData.size() > 0){
  86. responseVO = foreignPaymentConsumer.replaceTaxExempt(listData);
  87. }
  88. }catch(IOException ex){
  89. responseVO.setMessage(ex.getMessage());
  90. }finally {
  91. if(inputStream != null){
  92. try {
  93. inputStream.close();
  94. } catch (IOException e) {
  95. e.printStackTrace();
  96. return responseVO;
  97. }
  98. }
  99. }
  100. return responseVO;
  101. }
测试结果

测试数据 免税合同供应商-导入测试数据-测试.xLsX

下载 Excel 导入模版

  1. /**
  2. * 免税合同供应商-下载导入模版
  3. * @return 导入模版 Url
  4. */
  5. @PostMapping("/downExemptTaxTemplate")
  6. public ResponseVO downExemptTaxTemplate(){
  7. //http://localhost:8081/payment/ExcelTemplate/ExemptTaxSupplierImport.xlsx
  8. ResponseVO<String> responseVO = new ResponseVO<>(ResponseCode.OK);
  9. //responseVO.setData("/ExcelTemplate/ExemptTaxSupplierImport.xlsx");
  10. responseVO.setData("/"+config.getExcelTemplate()+config.getTaxExemptImport());
  11. return responseVO;
  12. }
静态资源映射配置-bootstrap.properties
  1. #静态资源映射
  2. spring.mvc.static-path-pattern=/ExcelTemplate/*
  3. spring.resources.static-locations= classpath:ExcelTemplate/
测试结果

getRow getCell 空行返回 null 值问题

今天导出发现了一个问题,但导出的模板没有设置框线时,导出会报错

  1. if (listData != null && listData.size() > 0) {
  2. for (Integer i = 0; i < listData.size(); i++) {
  3. TaxExemption data = listData.get(i);
  4. Integer col = 0;
  5. //合同方(合作方名称,供应商名称) contract_party
  6. sheet.getRow(i + 1).getCell(col++).setCellValue(data.getContractParty());
  1. 具体错误信息:java.lang.NullPointerException

设置了框线之后,才可以正常导出

过了一会之后,设置框线也报错了,也是服了,解决方案

  1. sheet.createRow(i + 1).createCell(col++).setCellValue(data.getContractParty());

相关附件 SpringBoot POI 导入,导出 Excel | 大小:0.03M | 下载