参考
Springboot poi 导入、导出excel 简单步骤
https://www.jianshu.com/p/e12c69eea764POI复制Excel模板并填充数据
https://yq.aliyun.com/articles/680217Apache POI 之一:Excel文档的读取
https://www.jianshu.com/p/80a9c2c7ebe5SpringBoot静态资源的访问
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
-- ------------------------------ Table structure for t_fpts_tax_exemption-- ----------------------------DROP TABLE IF EXISTS `t_fpts_tax_exemption`;CREATE TABLE `t_fpts_tax_exemption` (`id` bigint(20) NOT NULL COMMENT '主键',`contract_party` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '合同方(合作方名称)',`contract_no` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '合同编号',`chinese_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '中文翻译名称',`product` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '产品\r\n',`signing_date` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '签订日期\r\n',`start_date` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '开始日期\r\n',`end_time` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '结束日期\r\n',`contract_type` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '合同类型\r\n',`remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '备注\r\n',`principal` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '负责商务\r\n',`records_date` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '税局备案日期\r\n',`tax_exemption_date` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '免增值税备案有效期\r\n',`supplier_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '供应商编码',`create_time` timestamp(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '创建时间',`create_by` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人',`update_time` timestamp(0) NULL DEFAULT NULL COMMENT '修改时间',`update_by` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人',`is_delete` tinyint(1) NULL DEFAULT NULL COMMENT '是否删除。1,-1',`biz_time` timestamp(0) NULL DEFAULT NULL COMMENT '系统时间戳',`create_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,`update_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;
测试数据
--导出Excel测试数据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)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');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)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');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)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
import com.baomidou.mybatisplus.annotation.FieldFill;import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.annotation.TableField;import com.baomidou.mybatisplus.annotation.TableId;import com.baomidou.mybatisplus.extension.activerecord.Model;import com.fasterxml.jackson.annotation.JsonFormat;import io.swagger.annotations.ApiModelProperty;import lombok.Data;import lombok.EqualsAndHashCode;import lombok.experimental.Accessors;import java.io.Serializable;import java.util.Date;/*** 基础实体类**/@EqualsAndHashCode(callSuper = true)@Data@Accessors(chain = true)public class SuperEntity<T extends Model> extends Model<T> {@TableId(type = IdType.ID_WORKER)@ApiModelProperty(value = "主键")private Long id;@ApiModelProperty(value = "创建时间", hidden = true)@TableField(value = "create_time", fill = FieldFill.INSERT)@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")private Date createTime;@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)@ApiModelProperty(value = "修改时间", hidden = true)@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")private Date updateTime;@ApiModelProperty(value = "创建人", hidden = true)@TableField(value = "create_by", fill = FieldFill.INSERT)private String createBy;@ApiModelProperty(value = "创建人名称", hidden = true)@TableField(value = "create_name", fill = FieldFill.INSERT)private String createName;@ApiModelProperty(value = "修改人", hidden = true)@TableField(value = "update_by", fill = FieldFill.INSERT_UPDATE)private String updateBy;@ApiModelProperty(value = "创建人名称", hidden = true)@TableField(value = "update_name", fill = FieldFill.INSERT)private String updateName;@ApiModelProperty(value = "是否删除(1、否,-1、是)", hidden = true)@TableField(value = "is_delete", fill = FieldFill.INSERT)private Integer isDelete;@ApiModelProperty(value = "系统时间戳", hidden = true)@TableField(value = "biz_time", fill = FieldFill.INSERT_UPDATE)@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")private Date bizTime;@Overrideprotected Serializable pkVal() {return this.id;}}
数据表映射类-TaxExemption
import com.baomidou.mybatisplus.annotation.TableName;import com.foreign.payment.model.base.SuperEntity;import lombok.Data;import lombok.EqualsAndHashCode;import lombok.experimental.Accessors;@Data@EqualsAndHashCode(callSuper = true)@Accessors(chain = true)@TableName("t_fpts_tax_exemption")public class TaxExemption extends SuperEntity {private static final long serialVersionUID=1L;/*** 合同方*/private String contractParty;/*** 合同编号*/private String contractNo;/*** 中文翻译名称*/private String chineseName;/*** 产品*/private String product;/*** 签订日期*/private String signingDate;/*** 开始日期*/private String startDate;/*** 结束日期*/private String endTime;/*** 合同类型*/private String contractType;/*** 备注*/private String remark;/*** 负责商务*/private String principal;/*** 税局备案日期*/private String recordsDate;/*** 免增值税备案有效期*/private String taxExemptionDate;/*** 供应商编码*/private String supplierCode;}
分页基础类-PageVO
import io.swagger.annotations.ApiModelProperty;import lombok.Getter;import lombok.Setter;import lombok.experimental.Accessors;/*** 分页基础类*/@Getter@Setter@Accessors(chain = true)public class PageVO {@ApiModelProperty("当前页数")private Integer current;@ApiModelProperty("每页显示条数")private Integer size;}
查询参数类-SupplierRequestData
import com.foreign.payment.vo.PageVO;import lombok.Data;/*** 供应商接口请求数据类(至少填写一个参数)*/@Datapublic class SupplierRequestData extends PageVO {/*** 供应商ID*/private String supplierId;/*** 供应商名称*/private String supplierName;}
Contract 接口
/*** 获取免税合同供应商** @param param 供应商信息* @return 免税合同供应商列表*/@PostMapping("/exemptTaxSupplier")ResponseVO<Page<TaxExemption>> exemptTaxSupplier(@RequestBody SupplierRequestData param);/*** 替换免税合同供应商(删除之前的所有数据)* @param param 免税合同供应商数据* @return 替换成功返回 true,失败返回 false*/@PostMapping("/replaceTaxExempt")ResponseVO replaceTaxExempt(@RequestBody List<TaxExemption> param);
Service 接口
Mapper 接口-TaxExemptionRepository
@Repositorypublic interface TaxExemptionRepository extends BaseMapper<TaxExemption> {/*** 删除所有免税合同供应商*/void delTaxExempt();}
Mapper 接口映射 XML-TaxExemptionMapper.xml
<select id="delTaxExempt">update t_fpts_tax_exemption set is_delete = -1</select>
数据库操作接口-TaxExemptionService
public interface TaxExemptionService extends IService<TaxExemption> {/*** 获取免税合同供应商* @param param 供应商信息* @return 免税合同供应商列表*/ResponseVO<Page<TaxExemption>> exemptTaxSupplier(SupplierRequestData param);/*** 删除免税合同供应商*/void delTaxExempt();/*** 添加免税合同供应商* @param param 免税合同供应商数据*/void addTaxExempt(List<TaxExemption> param);}
接口实现类-TaxExemptionServiceImpl
@Servicepublic class TaxExemptionServiceImpl extends ServiceImpl<TaxExemptionRepository, TaxExemption> implements TaxExemptionService {/*** 获取免税合同供应商* @param param 供应商信息* @return 免税合同供应商列表*/@Overridepublic ResponseVO<Page<TaxExemption>> exemptTaxSupplier(SupplierRequestData param){//分页条件Page<TaxExemption> page = new Page<>();page.setSize(param.getSize());page.setCurrent(param.getCurrent());//查询条件QueryWrapper<TaxExemption> wrapper = new QueryWrapper<>();wrapper.eq("is_delete",1);wrapper.like("supplier_code",param.getSupplierId());wrapper.like("contract_party",param.getSupplierName());IPage<TaxExemption> ipageData = baseMapper.selectPage(page,wrapper);Page<TaxExemption> pageData = CommonUtil.toPage(ipageData);ResponseVO<Page<TaxExemption>> responseVO = new ResponseVO<>(ResponseCode.OK);responseVO.setData(pageData);return responseVO;/*//类型转换ResponseVO<List<SupplierDataVO>> responseVO = new ResponseVO<>(ResponseCode.OK);if(pageData != null && pageData.getRecords() != null && pageData.getRecords().size() > 0){List<SupplierDataVO> data = new ArrayList<>();for(int i=0;i< pageData.getRecords().size();i++){TaxExemption item = pageData.getRecords().get(i);SupplierDataVO model = new SupplierDataVO();model.setId(item.getId());model.setSupplierCode(item.getSupplierCode());model.setSupplierName(item.getContractParty());model.setUpdateTime(item.getUpdateTime());data.add(model);}responseVO.setData(data);}*/}/*** 删除免税合同供应商*/@Overridepublic void delTaxExempt(){baseMapper.delTaxExempt();}/*** 添加免税合同供应商* @param param 免税合同供应商数据* @return 替换成功返回 true,失败返回 false*/@Overridepublic void addTaxExempt(List<TaxExemption> param){for(int i=0;i<param.size();i++){baseMapper.insert(param.get(i));}}}
Contrller-TaxPayerController
@Slf4j@RestController@Api("纳税人管理相关接口")public class TaxPayerController {/*** 免税合同供应商-服务接口*/@Autowiredprivate TaxExemptionService exemptionService;/*** 获取免税合同供应商* @param param 供应商信息* @return 免税合同供应商列表*/@PostMapping("/exemptTaxSupplier")public ResponseVO<Page<TaxExemption>> exemptTaxSupplier(@RequestBody SupplierRequestData param){return exemptionService.exemptTaxSupplier(param);}/*** 替换免税合同供应商(删除之前的所有数据)* @param param 免税合同供应商数据* @return 替换成功返回 true,失败返回 false*/@PostMapping("/replaceTaxExempt")public ResponseVO replaceTaxExempt(@RequestBody List<TaxExemption> param){exemptionService.delTaxExempt();exemptionService.addTaxExempt(param);ResponseVO<Boolean> responseVO = new ResponseVO<>(ResponseCode.OK);responseVO.setData(true);return responseVO;}}
Excel 模版
导入模版-ExemptTaxSupplierImport.xlsx

导出模版-ExemptTaxSupplierExport.xlsx

Web层
bootstrap.properties
#静态资源映射spring.mvc.static-path-pattern=/ExcelTemplate/*spring.resources.static-locations= classpath:ExcelTemplate/
Resource 放入 Excel 模版文件

yml 添加 Excel 相关配置
application.yml
server:port: 8081servlet:context-path: /paymentspring:profiles:active: dev
application-dev.yml
#文件导入导出相关配置file-config:excel-template: ExcelTemplate/ #Excel 模版文件夹名称tax-exempt-import: ExemptTaxSupplierImport.xlsx #免税供应商导入 Excel 模版名称tax-exempt-export: ExemptTaxSupplierExport.xlsx #免税供应商导出 Excel 模版名称tax-exempt-prefix: 免税合同供应商- #免税供应商导出 Excel 文件前缀
配置读取类-FileConfig
/*** 文件导入导出相关配置* @date: 2019-12-13 16:42*/@Component@ConfigurationProperties("file-config")@Getterpublic class FileConfig {/*** 获取 Excel 模版文件夹名称*/@Value("${file-config.excel-template}")private String excelTemplate;/*** 获取免税供应商导入 Excel 模版名称*/@Value("${file-config.tax-exempt-import}")private String taxExemptImport;/*** 获取免税供应商导出 Excel 模版名称*/@Value("${file-config.tax-exempt-export}")private String taxExemptExport;/*** 获取免税供应商导出 Excel 文件前缀*/@Value("${file-config.tax-exempt-prefix}")private String taxExemptPrefix;}
pom.xml 引入 POI 内容
<!-- 基本依赖,仅操作 xls 格式只需引入此依赖 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.14</version></dependency><!-- 使用 xlsx 格式需要额外引入此依赖 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.14</version></dependency>
Excel 操作公共类-ExcelUtils
/*** Excel 工具类* @date: 2019-12-13 16:14*/public class ExcelUtils {/*** 根据文件路径获取 Workbook 对象* @param readFilePath Excel 路径* @return POI Workbook 对象* @throws IOException*/public static Workbook getWorkbook(String readFilePath) throws IOException{//Excel 模版路径//String resourcePath = this.getClass().getResource("/").getPath();//String readFilePath = resourcePath + "ExcelTemplate/"+fileName;File file = new File(readFilePath);FileInputStream inputStream = new FileInputStream(file);//读取 Excel 模版Workbook workbook = null;if(isExcel2003(readFilePath)){workbook = new HSSFWorkbook(inputStream);}else if(isExcel2007(readFilePath)){workbook = new XSSFWorkbook(inputStream);}return workbook;}/*** 下载 Excle* @param response HttpServletResponse* @param workbook Workbook* @param prefixName 导出文件的前缀名称* @throws IOException*/public static void downLoadExcel(HttpServletResponse response, Workbook workbook, String saveFileName)throws IOException {//String saveFileName = prefixName + "-"+ DateUtils.format(new Date(),"yyyy-MM-dd-HHmmss")+".xlsx";if(isExcel2003(saveFileName)){response.setContentType("application/vnd.ms-excel");}else if(isExcel2007(saveFileName)){response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");}response.setCharacterEncoding("utf-8");response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(saveFileName, "UTF-8"));workbook.write(response.getOutputStream());//保存文件到本地//String saveFilePath = resourcePath +"ExcelExport/";//File dirSave = new File(saveFilePath);//if (!dirSave.exists()) {// dirSave.mkdirs();//}//FileOutputStream outputStream = new FileOutputStream(saveFilePath + saveFileName);//workbook.write(outputStream);//outputStream.close();}/*** 是否是 .xls 格式的 excel* @param filePath 文件路径* @return 是返回 true,否返回 false*/public static Boolean isExcel2003(String filePath) {return filePath.matches("^.+\\.(?i)(xls)$");}/*** 是否是 .xlsx 格式的 excel* @param filePath 文件路径* @return 是返回 true,否返回 false*/public static Boolean isExcel2007(String filePath) {return filePath.matches("^.+\\.(?i)(xlsx)$");}/*** 验证是否 EXCEL 文件* @param filePath 文件路径* @return 是返回 true,否返回 false*/public static Boolean validateExcel(String filePath){if (filePath == null || !(isExcel2003(filePath) || isExcel2007(filePath))){return false;}return true;}/*** 根据文件名称和 InputStream 获取对应类型的 Sheet* @param fileName 文件名称* @param inputStream InputStream* @return*/public static Sheet getSheet(String fileName, InputStream inputStream) throws IOException {//根据文件类型选择创建 Workbook 的方式Workbook workbook = null;Sheet sheet = null;//根据文件名称获取类型if(isExcel2007(fileName)){workbook = new XSSFWorkbook(inputStream);sheet = workbook.getSheetAt(0);}else if(isExcel2003(fileName)){workbook = new HSSFWorkbook(inputStream);sheet = workbook.getSheetAt(0);}return sheet;}/*** 获取 Cell 对应的字符串类型值* @param cell Cell* @return 字符串类型值*/public static String getStringValue(Cell cell){String value="";switch (cell.getCellType()) {case HSSFCell.CELL_TYPE_NUMERIC: // 数字//如果为时间格式的内容if (HSSFDateUtil.isCellDateFormatted(cell)) {//注:format格式 yyyy-MM-dd hh:mm:ss 中小时为12小时制,若要24小时制,则把小h变为H即可,yyyy-MM-dd HH:mm:ssSimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");value=sdf.format(HSSFDateUtil.getJavaDate(cell.getNumericCellValue())).toString();break;} else {value = new DecimalFormat("0").format(cell.getNumericCellValue());}break;case HSSFCell.CELL_TYPE_STRING: // 字符串value = cell.getStringCellValue();break;case HSSFCell.CELL_TYPE_BOOLEAN: // Booleanvalue = cell.getBooleanCellValue() + "";break;case HSSFCell.CELL_TYPE_FORMULA: // 公式value = cell.getCellFormula() + "";break;case HSSFCell.CELL_TYPE_BLANK: // 空值value = "";break;case HSSFCell.CELL_TYPE_ERROR: // 故障value = "非法字符";break;default:value = "未知类型";break;}return value;}}
Web 接口-TaxPayerController
公共部分
@Controller@RequestMapping(value = "/api")public class TaxPayerController extends BaseController {//====================================================================///*** 文件导入导出配置帮助类*/@Resourceprivate FileConfig config;/*** 获取根据日期名称的 Excel 文件名名称* @return Excel 文件名名称*/private String getExcelName(){return DateUtils.format(new Date(),"yyyy-MM-dd-HHmmss")+".xlsx";}/*** 获取 Resource 文件夹名称* @return*/private String getResourcePath(){String resourcePath = this.getClass().getResource("/").getPath();return resourcePath;}//........}
查询数据
/*** 获取免税合同供应商* @param param 供应商信息* @return 免税合同供应商列表*/@PostMapping("/exemptTaxSupplier")public ResponseVO<Page<TaxExemption>> exemptTaxSupplier(@RequestBody SupplierRequestData param){//TODO 判断权限return foreignPaymentConsumer.exemptTaxSupplier(param);}
测试结果

导出数据到 Excel
/*** 免税合同供应商-导出全部* @return*/@GetMapping("/exemptTaxSupplierExport")public void exemptTaxSupplierExport(HttpServletResponse response) throws IOException {//查询条件SupplierRequestData param = new SupplierRequestData();param.setSupplierId("");param.setSupplierName("");param.setCurrent(1);param.setSize(5000);//默认获取 5000 条数据//查询数据ResponseVO<Page<TaxExemption>> responseVO = foreignPaymentConsumer.exemptTaxSupplier(param);Page<TaxExemption> pageData = responseVO.getData();List<TaxExemption> listData = pageData.getRecords();//Excel 模版路径String readFilePath = getResourcePath() + config.getExcelTemplate() + config.getTaxExemptExport();Workbook workbook= ExcelUtils.getWorkbook(readFilePath);Sheet sheet = workbook.getSheetAt(0);if(listData != null && listData.size() > 0){for(Integer i=0;i<listData.size();i++){TaxExemption data = listData.get(i);Integer col= 0;//供应商名称 contract_partysheet.getRow(i+1).getCell(col++).setCellValue(data.getContractParty());//供应商编码 supplier_codesheet.getRow(i+1).getCell(col++).setCellValue(data.getSupplierCode());//合同编号 contract_nosheet.getRow(i+1).getCell(col++).setCellValue(data.getContractNo());//中文翻译名称 chinese_namesheet.getRow(i+1).getCell(col++).setCellValue(data.getChineseName());//产品 productsheet.getRow(i+1).getCell(col++).setCellValue(data.getProduct());//签订日期 signing_datesheet.getRow(i+1).getCell(col++).setCellValue(data.getSigningDate());//开始日期 start_datesheet.getRow(i+1).getCell(col++).setCellValue(data.getStartDate());//结束日期 end_timesheet.getRow(i+1).getCell(col++).setCellValue(data.getEndTime());//合同类型 contract_typesheet.getRow(i+1).getCell(col++).setCellValue(data.getContractType());//备注 remarksheet.getRow(i+1).getCell(col++).setCellValue(data.getRemark());//负责商务 principalsheet.getRow(i+1).getCell(col++).setCellValue(data.getPrincipal());//税局备案日期 records_datesheet.getRow(i+1).getCell(col++).setCellValue(data.getRecordsDate());//免增值税备案有效期 tax_exemption_datesheet.getRow(i+1).getCell(col++).setCellValue(data.getTaxExemptionDate());//创建时间 create_timeif(data.getCreateTime() != null){sheet.getRow(i+1).getCell(col++).setCellValue(DateUtils.format(data.getCreateTime(),"yyyy-MM-dd HH:mm:ss"));}//创建人 create_bysheet.getRow(i+1).getCell(col++).setCellValue(data.getCreateBy());//创建人名称 create_namesheet.getRow(i+1).getCell(col++).setCellValue(data.getCreateName());//修改时间 update_timeif(data.getUpdateTime() != null){sheet.getRow(i+1).getCell(col++).setCellValue(DateUtils.format(data.getUpdateTime(),"yyyy-MM-dd HH:mm:ss"));}//修改人 update_bysheet.getRow(i+1).getCell(col++).setCellValue(data.getUpdateBy());//修改人名称 update_namesheet.getRow(i+1).getCell(col++).setCellValue(data.getUpdateName());//is_delete//biz_time}}String saveFileName = config.getTaxExemptPrefix() + getExcelName();ExcelUtils.downLoadExcel(response,workbook,saveFileName);}
测试结果

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

导入 Excel
/*** 免税合同供应商-上传替换* @param file 上传文件* @return 上传成功返回 true,否则返回 false*/@PostMapping("/exemptTaxSupplierImport")public ResponseVO exemptTaxSupplierImport(@RequestParam(value="filename") MultipartFile file){ResponseVO<Boolean> responseVO = new ResponseVO<>(ResponseCode.SYSTEM_EXCEPTION);responseVO.setData(false);if(file.isEmpty()){responseVO.setCode(ResponseCode.PARAM_INVALID.value());responseVO.setMessage("文件为空!");return responseVO;}//获取文件名String fileName = file.getOriginalFilename();if(!ExcelUtils.validateExcel(fileName)){responseVO.setCode(ResponseCode.PARAM_INVALID.value());responseVO.setMessage("必须上传 Excel 文件!");return responseVO;}InputStream inputStream = null;try{inputStream = file.getInputStream();Sheet sheet = ExcelUtils.getSheet(fileName,inputStream);List<TaxExemption> listData = new ArrayList<>();Iterator<Row> rowItr=sheet.rowIterator();//遍历全部非空行//for(Row row : sheet){ //忽略表头 if(row.getRowNum() == 0) continue; //会获取所有行,包括空行//while(rowItr.hasNext()){ Row row=rowItr.next();//会获取所有行,包括空行int rowCount = sheet.getPhysicalNumberOfRows();for(int i = 1;i<rowCount;i++){Row row = sheet.getRow(i);//如果得到的行是空的一行,可以根据row.getFirstCellNum()是否大于等于0 来判断//该行为空那么:row.getFirstCellNum()=-1的,否则row.getFirstCellNum()=0if(null == row) break;if(row.getFirstCellNum() == -1) break;Integer col = 0;//列序号TaxExemption data = new TaxExemption();//供应商名称 contract_partydata.setContractParty(ExcelUtils.getStringValue(row.getCell(col++)));//供应商编码 supplier_codedata.setSupplierCode(ExcelUtils.getStringValue(row.getCell(col++)));//合同编号 contract_nodata.setContractNo(ExcelUtils.getStringValue(row.getCell(col++)));//中文翻译名称 chinese_namedata.setChineseName(ExcelUtils.getStringValue(row.getCell(col++)));//产品 productdata.setProduct(ExcelUtils.getStringValue(row.getCell(col++)));//签订日期 signing_datedata.setSigningDate(ExcelUtils.getStringValue(row.getCell(col++)));//开始日期 start_datedata.setStartDate(ExcelUtils.getStringValue(row.getCell(col++)));//结束日期 end_timedata.setEndTime(ExcelUtils.getStringValue(row.getCell(col++)));//合同类型 contract_typedata.setContractType(ExcelUtils.getStringValue(row.getCell(col++)));//备注 remarkdata.setRemark(ExcelUtils.getStringValue(row.getCell(col++)));//负责商务 principaldata.setPrincipal(ExcelUtils.getStringValue(row.getCell(col++)));//税局备案日期 records_datedata.setRecordsDate(ExcelUtils.getStringValue(row.getCell(col++)));//免增值税备案有效期 tax_exemption_datedata.setTaxExemptionDate(ExcelUtils.getStringValue(row.getCell(col++)));//创建时间 create_time//data.setCreateTime(row.getCell(col++).getDateCellValue());//创建人 create_by//data.setCreateBy(row.getCell(col++).getStringCellValue());//创建人名称 create_name//data.setCreateName(row.getCell(col++).getStringCellValue());//修改时间 update_time//data.setUpdateTime(row.getCell(col++).getDateCellValue());//修改人 update_by//data.setUpdateBy(row.getCell(col++).getStringCellValue());//修改人名称 update_name//data.setUpdateName(row.getCell(col++).getStringCellValue());//is_delete//biz_timeif(!StringUtil.isBlank(data.getContractParty())&& !StringUtil.isBlank((data.getSupplierCode()))&& !StringUtil.isBlank(data.getContractNo())){listData.add(data);}}if(listData.size() > 0){responseVO = foreignPaymentConsumer.replaceTaxExempt(listData);}}catch(IOException ex){responseVO.setMessage(ex.getMessage());}finally {if(inputStream != null){try {inputStream.close();} catch (IOException e) {e.printStackTrace();return responseVO;}}}return responseVO;}
测试结果
测试数据 免税合同供应商-导入测试数据-测试.xLsX



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


getRow getCell 空行返回 null 值问题
今天导出发现了一个问题,但导出的模板没有设置框线时,导出会报错

if (listData != null && listData.size() > 0) {for (Integer i = 0; i < listData.size(); i++) {TaxExemption data = listData.get(i);Integer col = 0;//合同方(合作方名称,供应商名称) contract_partysheet.getRow(i + 1).getCell(col++).setCellValue(data.getContractParty());
具体错误信息:java.lang.NullPointerException
设置了框线之后,才可以正常导出

过了一会之后,设置框线也报错了,也是服了,解决方案
sheet.createRow(i + 1).createCell(col++).setCellValue(data.getContractParty());