ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring Boot下的一种Excel文件导出的代码框架

2021-06-19 20:04:32  阅读:89  来源: 互联网

标签:Excel String Spring 导出 item Boot new import


1、前言

​ 在Spring Boot项目中,将数据导出成Excel格式文件是常见的功能。与Excel文件导入类似,此处也用代码框架式的方式实现Excel文件导出,使得代码具有可重用性,并保持导出数据转换的灵活性。

​ 相对于导入Excel文件的处理,导出Excel文件要简单一些。这里的Excel文件支持xlsx格式。

2、基本框架

​ 包括一个接口类ExcelExportable和一个Excel导出处理类ExcelExportHandler,以及支持ExcelExportable接口类的实体类。与基类相比,使用接口类的好处是可以实现多个接口类,而不会有多重继承的麻烦。这样实体类可以同时支持Excel和CSV格式文件的导出。

2.1、Excel导出处理类ExcelExportHandler

​ ExcelExportHandler类的代码如下:

package com.abc.questInvest.excel;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;

import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.abc.questInvest.excel.ExcelExportable;

/**
 * @className	: ExcelExportHandler
 * @description	: Excel导出处理类
 *
 */
public class ExcelExportHandler<T extends ExcelExportable> {
	
	/**
	 * 
	 * @methodName		: exportExcelFile
	 * @description		: 导出Excel文件供下载
	 * @param rowDataList	: 导出的数据列表
	 * @param excelFilePath	: Excel文件临时文件路径
	 * @param sheetName: sheet页名称
	 * @throws Exception	: 发生异常时,抛出
	 *
	 */
	public void exportExcelFile(List<T> rowDataList,String excelFilePath,String sheetName) 
			throws Exception {
		if (rowDataList.size() == 0) {
			//必须要有导出数据,否则创建标题列失败
			throw new Exception("无导出数据.");
		}
		
		XSSFWorkbook wb = null;
		wb = new XSSFWorkbook();

		//创建sheet页
		XSSFSheet sheet = wb.createSheet(sheetName);
		
		//创建标题行
		createTitle(wb,sheet,rowDataList.get(0));
		
		//添加数据
		addSheetContent(sheet,wb,rowDataList);
		
		//输出文件数据供下载
		outputExcelFile(excelFilePath,wb);
		
	}	
	
	/**
	 * 
	 * @methodName		: createTitle
	 * @description		: 设置标题行
	 * @param workbook	: workbook对象
	 * @param sheet		: sheet对象
	 * @throws Exception	: 发生异常时,抛出
	 *
	 */
	private void createTitle(XSSFWorkbook workbook, XSSFSheet sheet,T rowData) throws Exception{
	    XSSFRow row = sheet.createRow(0);
		//取得标题行
		String[] arrTitles = rowData.outputTitleList();

	    //设置列宽
	    for (int i = 0; i < arrTitles.length; i++){
	    	//设置固定宽度,setColumnWidth的第二个参数的单位是1/256个字节宽度
	        sheet.setColumnWidth(i,arrTitles[i].getBytes("UTF-8").length * 256);
	    	
	    	//设置自适应宽度,性能不高,故不用了
	    	//sheet.autoSizeColumn(i);
		}
	    
	    //设置为居中加粗
	    XSSFCellStyle style = workbook.createCellStyle();
	    XSSFFont font = workbook.createFont();
	    font.setBold(true);
	    style.setAlignment(HorizontalAlignment.CENTER);
	    style.setFont(font);

	    XSSFCell cell;
		for (int i = 0; i < arrTitles.length; i++){
			cell = row.createCell(i);
			cell.setCellValue(arrTitles[i]);
			cell.setCellStyle(style);
		}
				
	}
	
	/**
	 * 
	 * @methodName		: addSheetContent
	 * @description		: 为sheet对象添加数据行内容
	 * @param sheet		: sheet对象
	 * @param workbook	: workbook对象
	 * @param rowDataList	: 数据行列表
	 * @throws Exception	: 发生异常时,抛出
	 *
	 */
	private void addSheetContent(XSSFSheet sheet, XSSFWorkbook workbook, List<T> rowDataList)
			 throws Exception
	{
		//单元格居中
	    XSSFCellStyle style = workbook.createCellStyle();
	    style.setAlignment(HorizontalAlignment.CENTER);
	    
	    //数据行下标从1开始
	    int rowNum=1;
	    //遍历导出数据行
	    for(int i=0;i<rowDataList.size();i++){
	        XSSFRow row = sheet.createRow(rowNum);
	        XSSFCell cell;
			T rowData = rowDataList.get(i);
			String[] arrRow = rowData.outputList();
			for (int j = 0; j < arrRow.length; j++) {
				cell = row.createCell(j);
				cell.setCellValue(arrRow[j]);
				cell.setCellStyle(style);
			}
	        rowNum++;
	    }
	}	
	
	/**
	 * 
	 * @methodName		: outputExcelFile
	 * @description		: 输出Excel文件
	 * @param filePath	: 输出的文件路径
	 * @param workbook	: workbook对象
	 * @throws Exception	: 发生异常时,抛出
	 *
	 */
	private void outputExcelFile(String filePath,XSSFWorkbook workbook) throws Exception{
	    OutputStream outputStream = new FileOutputStream(new File(filePath));
	    workbook.write(outputStream);
	    outputStream.flush();
	    outputStream.close();
	}
}

​ ExcelExportHandler支持泛型T,T限定必需支持ExcelExportable接口类。只要实体类实现ExcelExportable类的接口方法,就可以利用ExcelExportHandler的方法实现Excel文件导出。

2.2、可Excel导出的接口类ExcelExportable

​ ExcelExportable类的代码如下:

package com.abc.questInvest.excel;

/**
 * @className	: ExcelExportable
 * @description	: 可Excel导出的接口类,由POJO类实现
 *
 */
public interface ExcelExportable {

	/**
	 * 
	 * @methodName		: outputTitleList
	 * @description		: 输出标题列表,用于标题行 
	 * @return			: 字符串数组
	 *
	 */
	public String[] outputTitleList();
	
	/**
	 * 
	 * @methodName		: outputList
	 * @description		: 输出数据列表,用于数据行
	 * @return			: 字符串数组
	 *
	 */
	public String[] outputList();		
}

​ ExcelExportable类定义了2个接口方法:

  • outputTitleList方法,输出标题列表,用于标题行。
  • outputList方法,输出数据列表,用于数据行。

2.3、实体类例子

​ 对需要导出Excel文件的现有的实体类进行改造,使之支持ExcelExportable接口类。

​ 实体类为AnswerInfo,代码如下:

package com.abc.questInvest.entity;

import java.util.Date;

import javax.persistence.Column;

import com.abc.questInvest.excel.ExcelExportable;

import lombok.Data;

/**
 * @className	: AnswerInfo
 * @description	: 答卷信息类,支持Excel数据导出
 *
 */
@Data
public class AnswerInfo implements ExcelExportable {
    // 记录id
    @Column(name = "rec_id")
    private Integer recId;	
    
    // 发布任务id
    @Column(name = "task_id")
    private Integer taskId;
    
    // 问卷id
    @Column(name = "questionnaire_id")
    private Integer questionnaireId;

    // 问题编号
    @Column(name = "question_no")
    private Integer questionNo;

    // 答案
    @Column(name = "answer")
    private String answer;
    
	//========记录操作信息================
    // 操作人姓名
    @Column(name = "login_name")
    private String loginName;   
    
    // 记录删除标记,保留
    @Column(name = "delete_flag")
    private Byte deleteFlag;    

    // 创建时间
    @Column(name = "create_time")
    private Date createTime;

    // 更新时间
    @Column(name = "update_time")
    private Date updateTime;  
    

	//========实现ExcelExportable接口================
    
    //导出的Excel数据的列数
    private static final int COLUMN_COUNT = 5;
    
	/**
	 * 
	 * @methodName		: outputTitleList
	 * @description		: 输出标题列表,用于标题行 
	 * @return			: 字符串数组
	 *
	 */
    @Override
	public String[] outputTitleList() {
    	String[] arrTitle = new String[COLUMN_COUNT];
    	arrTitle[0] = "问卷ID";
    	arrTitle[1] = "发布任务ID";
    	arrTitle[2] = "记录ID";
    	arrTitle[3] = "题号";
    	arrTitle[4] = "答案";
    	return arrTitle;
    }
	
	/**
	 * 
	 * @methodName		: outputList
	 * @description		: 输出数据列表,用于数据行
	 * @return			: 字符串数组
	 *
	 */
    @Override
	public String[] outputList() {
    	String[] arrRowData = new String[COLUMN_COUNT];
    	
    	//各属性字段,从数据库中取出,都为非null值
    	//此处实现导出字段的物理含义转换和计算
    	arrRowData[0] = questionnaireId.toString();
    	arrRowData[1] = taskId.toString();
    	arrRowData[2] = recId.toString();
    	arrRowData[3] = questionNo.toString();
    	arrRowData[4] = answer; 
    	
    	return arrRowData;
    }
}

2.4、单元测试

​ 下面进行Excel文件导出的单元测试。测试代码如下:

package com.abc.questInvest.excel;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.abc.questInvest.entity.AnswerInfo;

/**
 * @className	: ExcelExportHandlerTest
 * @description	: Excel文件导出测试 
 *
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class ExcelExportHandlerTest {

	@Test
	public void exportExcelFileTest() {
		ExcelExportHandler<AnswerInfo> excelExp = new ExcelExportHandler<AnswerInfo>();
		
		AnswerInfo item = new AnswerInfo();
		item.setQuestionnaireId(1);
		item.setTaskId(1);
		item.setRecId(1);
		item.setQuestionNo(1);
		item.setAnswer("A");
		dataList.add(item);
		
		item = new AnswerInfo();
		item.setQuestionnaireId(1);
		item.setTaskId(1);
		item.setRecId(1);
		item.setQuestionNo(2);
		item.setAnswer("B");
		dataList.add(item);
		
		item = new AnswerInfo();
		item.setQuestionnaireId(1);
		item.setTaskId(1);
		item.setRecId(1);
		item.setQuestionNo(3);
		item.setAnswer("A");
		dataList.add(item);
		
		item = new AnswerInfo();
		item.setQuestionnaireId(1);
		item.setTaskId(1);
		item.setRecId(2);
		item.setQuestionNo(1);
		item.setAnswer("B");
		dataList.add(item);
		
		item = new AnswerInfo();
		item.setQuestionnaireId(1);
		item.setTaskId(1);
		item.setRecId(2);
		item.setQuestionNo(2);
		item.setAnswer("B");
		dataList.add(item);
		
		item = new AnswerInfo();
		item.setQuestionnaireId(1);
		item.setTaskId(1);
		item.setRecId(2);
		item.setQuestionNo(3);
		item.setAnswer("C");
		dataList.add(item);
		
		String property = System.getProperty("user.dir");
		String filePath = property + "\\answer_data_Q1_T1.xlsx";
		String sheetName = "Q1_T1";

		List<AnswerInfo> dataList = new ArrayList<AnswerInfo>();
		
		try {
			excelExp.exportExcelFile(dataList,filePath, sheetName);			
		}catch(Exception e) {
			e.printStackTrace();
		}
		
	}
}

执行测试代码,可以看到导出的Excel文件,文件内容如下:

3、Excel文件导出并下载

​ 在导出生成了Excel文件后,只需与文件下载代码结合起来,就可以实现Excel文件下载了。

​ 文件下载,可作为静态的公共方法,放入工具类中。代码如下:

	/**
	 * 
	 * @methodName		: download
	 * @description		: 下载指定路径的文件
	 * @param response	: reponse对象
	 * @param filePath	: 需要下载的文件路径
	 * @param contentType	: response header中的ContentType,常用取值如下:
	 * 		普通二进制文件	: application/octet-stream
	 * 		Excel文件		: application/vnd.ms-excel
	 * 		文本文件		: text/plain; charset=utf-8
	 * 		html文件		: text/html; charset=utf-8
	 * 		xml文件			: text/xml; charset=utf-8
	 * 		jpeg文件		: image/jpeg
	 * @throws Exception	: 异常发生时,抛出。没有异常,说明下载成功。
	 *
	 */
	public static void download(HttpServletResponse response,String filePath,
			 String contentType) throws Exception{
    	
    	File file = new File(filePath);
    	if (file.exists()) {
            //设置读取流的缓存为1K
            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;    
            //设置ContentType
			response.setContentType(contentType);
			// 下载文件能正常显示中文
			String filename = filePath.substring(filePath.lastIndexOf("/")+1);
			response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
			//获取输入流
			fis = new FileInputStream(file);
			bis = new BufferedInputStream(fis);
			//输出流
			OutputStream os = response.getOutputStream();
			int len = bis.read(buffer);
			while (len != -1) {
				os.write(buffer, 0, len);
				len = bis.read(buffer);
			}             
			
			//关闭流
			if (bis != null) {
				bis.close();
			}
			if (fis != null) {
				fis.close();
			}        		
    	} 
    }	

​ 调用download方法,contentType参数取值为“application/vnd.ms-excel”即可。

标签:Excel,String,Spring,导出,item,Boot,new,import
来源: https://www.cnblogs.com/alabo1999/p/14904684.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有