欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Apache POI的使用(web网页Excel生成和下载)

程序员文章站 2022-03-15 13:49:30
...

POI简介

​ Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。

基本结构

  • HSSF - 提供读写[Microsoft Excel](https://baike.baidu.com/item/Microsoft Excel)格式档案的功能。
  • XSSF - 提供读写Microsoft Excel OOXML格式档案的功能。
  • HWPF - 提供读写[Microsoft Word](https://baike.baidu.com/item/Microsoft Word)格式档案的功能。
  • HSLF - 提供读写Microsoft PowerPoint格式档案的功能。
  • HDGF - 提供读写[Microsoft Visio](https://baike.baidu.com/item/Microsoft Visio)格式档案的功能。

Excel案例基本示例

  1. 创建Excel文档

    public class CreateXL {
    /** Excel 文件要存放的位置,假定在D盘下*/
    public static String outputFile = "D:\\test.xls";
        
    public static void main(String argv[]) {
    	try {
    		// 创建新的Excel 工作簿
    		HSSFWorkbook workbook = new HSSFWorkbook();
            
    		// 在Excel工作簿中建一工作表,其名为缺省值
    		// 如要新建一名为"效益指标"的工作表,其语句为:
    		// HSSFSheet sheet = workbook.createSheet("效益指标");
    		HSSFSheet sheet = workbook.createSheet();
            
    		// 创建行对象,索引0表示第一行,索引1表示第二行
    		HSSFRow row = sheet.createRow(0);
            
    		//在行对象的0索引位置创建单元格对象;一行中的单元格的索引从左到右依次为:0,1,2...
    		HSSFCell cell = row.createCell(0);
            
    		// 为单元格设置值
    		cell.setCellValue("增加值");
            
    		// 创建字节输出流
    		FileOutputStream fOut = new FileOutputStream(outputFile);
            
    		// 把相应的Excel 工作簿数据写入输出流中,输出存盘到电脑硬盘。
    		workbook.write(fOut);
    		//将流刷出到硬盘
             fOut.flush();
            
    		// 操作结束,关闭文件
    		fOut.close();
            
    		System.out.println("文件生成...");
    	} catch (Exception e) {
    		System.out.println("已运行 xlCreate() : " + e);
    	}
    }
    
  2. 读取Excel表

    public class ReadXL {
    //指定要读取的Excel表在硬盘中的位置
    public static String fileToBeRead = "D:\\test1.xls";
        
    public static void main(String argv[]) {
    	try {
    		// 读取Excel表,并创建工作簿对象
    		HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(fileToBeRead));
            
    		//从工作簿中获取指定的工作表对象
    		HSSFSheet sheet = workbook.getSheet("Sheet1");
    		// 也可用getSheetAt(int index)按索引引用,
    		// 在Excel文档中,第一张工作表的缺省索引是0,
    		// 其语句为:HSSFSheet sheet = workbook.getSheetAt(0);
            
            
    		// 获取行对象
    		HSSFRow row = sheet.getRow(0);
             //使用行对象,指定要读取索引处的单元格对象
    		HSSFCell cell = row.getCell(0);
            
    		// 输出单元内容,cell.getStringCellValue()就是取所在单元的值
    		System.out.println("左上端单元是: " + cell.getStringCellValue());
            
    	} catch (Exception e) {
    		System.out.println("已运行xlRead() : " + e);
    	}
    }
    

案例

​ 将数据库中的数据,生成为Excel表。

  • 题目实体类

    实体类中的属性就是对应的数据库中表的字段。

    /**
     * 题目实体类
     */
    public class Question {
        
        private String id;
        private String catalogId;
        private String catalogName;
        private String courseId;
        private String courseName;
        private String number;
        private String subject;
        private String type;
        private String difficulty;
        private String analysis;
        private String analysisVid;
        private String remark;
        private String isClassic;
        private String state;
        private String reviewStatus;
        private String createBy;
        private String createDept;
        private Date createTime;
        private String updateBy;
        private Date updateTime;
        private String companyId;
        private String companyName;
        private String picture;
        
        //get set 方法省略...
    }
    
  • 数据库就不展示了

  • POI——读取数据,封装到Excel表

    service业务层

    /**
     * 导出数据到Excel表
     */
    @Override
    public ByteArrayOutputStream exportExcel() {
    	//调用数据访问层,查询所有题目数据
    	List<Question> datas = questionDao.findAll();
    
    
    	//创建工作簿对象
    	XSSFWorkbook workbook = new XSSFWorkbook();
    	//创建工作表对象,test.xlsx指定的是工作表的名字
    	XSSFSheet sheet = workbook.createSheet("test.xlsx");
    
    	//设置Excel表头信息
    	String[] titles = {"ID标识", "所属目录ID", "所属目录名", "所属课程ID", "所属课程名", "题目编号", "subject",
    			"题目类型", "难度", "答案解析", "分析视频", "备注", "是否精选题目",
    			"题目状态", "审核状态", "创建人", "创建部门", "创建时间", "修改人",
    			"修改时间", "公司ID", "公司名", "图片路径"};
    
    	//获取行对象
    	XSSFRow row_0 = sheet.createRow(0);
    
    	//将数组中的值,设置为Excel的表头
    	for (int i = 0; i < titles.length; i++) {
    		//获取单元格对象
    		XSSFCell cell = row_0.createCell(i);
    		//设置单元格内容
    		cell.setCellValue(titles[i]);
    	}
    
    
    //        设置内容
    
    	//使用反射,获取question题目实体类的字段属性(0-22)
    	Field[] fields = Question.class.getDeclaredFields();
    
    	//遍历list集合
    	for (int j = 0; j < datas.size(); j++) {
    		//获取对象
    		Question question = datas.get(j);
    
    		//获取写入数据的行对象
    		XSSFRow row_temp = sheet.createRow(j + 1);
    
    		//循环将对象的数据写入单元格
    		for (int i = 0; i <= 22; i++) {
    			//使用行对象创建单元格对象,参数为行对象中的第几个单元格,从0开始
    			XSSFCell cell = row_temp.createCell(i);
    
    			//字段为private修饰,需要暴力**
    			fields[i].setAccessible(true);
    			//获取指定对象的指定字段的值
    			Object o = null;
    			try {
    				o = fields[i].get(question);
    			} catch (IllegalAccessException e) {
    				e.printStackTrace();
    			}
    
    			//判断o是否为空,不为空则调用toString方法,然后为单元格赋值
    			if (o != null) {
    				String value = o.toString();
    				//为单元格赋值
    				cell.setCellValue(value);
    			}
    
    
    		}
    	}
    
    	//将内存中的数据写入到字节数组输出流中,返回给servlet;
    	ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    
    	try {
    		workbook.write(byteArrayOutputStream);
    		//关闭流
    		workbook.close();
    	} catch (IOException e) {
    		e.printStackTrace();
    	}
    
    	return byteArrayOutputStream;
    }
    

    web层

    /**
     * 导出数据库数据到Excel表
     */
    private void toExport(HttpServletRequest request, HttpServletResponse response) throws IOException {
    	//设置响应的数据类型为XLSX格式
    	response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
    
    	//因为游览器不能直接使用中文,需要进行编码
    	String filename = new String("题目数据.xlsx".getBytes(), "iso8859-1");
    
    	//添加Content-disposition响应头,在用户请求下载文件的时候,设置文件的文件名
    	response.addHeader("content-disposition", "attachment;filename=" + filename);
    
    	//获取响应的流对象
    	ServletOutputStream os = response.getOutputStream();
    
    	//调用业务层
    	ByteArrayOutputStream outputStream = questionService.exportExcel();
    	//将原始数据流对象中的数据写入响应流中
    	outputStream.writeTo(os);
    
    	//将响应输出流中的数据刷新到游览器
    	os.flush();
        
    	//关流
    	outputStream.close();
    }
    

实现思想说明

​ 将数据库的某表的数据全部读取出来,每一行数据封装成一个实体类,将全部实体类用集合封装;然后使用反射,获取实体类的字段,并获取每个实体类的每个字段的值,写入到响应的单元格对象(前提是要创建好工作簿、工作表等)

​ 获取指定对象的指定字段的值-> field字段.get(实例对象);

​ 注意:一般来说实体类的字段都是私有化的private修饰,所以在获取字段的值之前,需要用反射暴力**->fields字段.setAccessible(true);