利用POI导出Excel表格

一、Apache POI

        Apache POI是免费开源的、具有能对Microsoft Office格式文件进行读和写功能的Java API。它支持对Microsoft Office各种格式文件的读写,但在实际应用中,我们最常使用的是利用POI来导入导出Excel表格。

        所以这篇文章就主要讲,如何使用POI导出Excel表格,以及动态数据的导出。

二、导入必须的jar包

        若我们只需要导入导出Excel表格,则只需要导入以下三个jar包:poi.jar; poi-ooxml.jar; poi-ooxml-schemas.jar。

        poi-3.9_Excel表格所需jar包下载

三、简单的导出Excel表格示例

public void exportExcel(HttpServletRequest request, HttpServletResponse response) throws IOException{
	/**  创建excel表格  */
	// 1.创建HSSFWorkbook对象(excel的文档对象)
	HSSFWorkbook wb = new HSSFWorkbook();
	// 2.建立新的sheet对象(excel的表单)
	HSSFSheet sheet = wb.createSheet("测试导出表格");
   
	sheet.setDefaultColumnWidth(20);         //设置缺省列宽
	sheet.setDefaultRowHeight((short)22);    // 设置缺省行高
	sheet.setDefaultRowHeightInPoints(22);
	
	/** 添加样式 */
	HSSFCellStyle cellDefStyle = wb.createCellStyle();   // 创建单元格样式
	cellDefStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);   // 设置左右居中
	cellDefStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);    // 设置水平居中
	// 设置单元格边框(四周都有边框线)
	cellDefStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);    // HSSFCellStyle.BORDER_NONE:无边框线
	cellDefStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
	cellDefStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
	cellDefStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
	cellDefStyle.setWrapText(true);  // 自动换行
	// 设置文字样式
	HSSFFont fontDef = wb.createFont();
	fontDef.setFontName("宋体");    // 设置字体类型
	fontDef.setFontHeightInPoints((short)12);    // 设置字体大小
	fontDef.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);   // 设置字体加粗(fontDef.setBold(true)同样有用)
	fontDef.setUnderline(HSSFFont.U_SINGLE);    // 设置下划线
	cellDefStyle.setFont(fontDef);
  
	
	/** 设置标题  */
	// 1.在sheet里创建第一行,参数为行索引(excel的行),可以是0~65535之间的任何一个
	int rowIndex = 0;    // 记录行号
	HSSFRow titleRow = sheet.createRow(rowIndex);
	titleRow.setHeightInPoints(30);    // 设置此行的行高
	// 2.创建单元格(excel的单元格,参数为列索引,可以是0~255之间的任何一个
	HSSFCell cell = titleRow.createCell(0);
	cell.setCellValue("测试导出Excel表格");    // 设置单元格内容
	// 3.设置单元格样式
	cell.setCellStyle(cellDefStyle);
	// 4.合并单元格CellRangeAddress构造参数依次表示起始行,截至行,起始列, 截至列
	sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 0, 5));
	++ rowIndex;
	
	/** 设置表格内容  */
	// 1.获取要填入表格的数据(根据自己实际情况获取数据)
	List<T> datas = 。。。
	for (T obj : datas) {
		HSSFRow contentRow = sheet.createRow(rowIndex);
		cell = contentRow.createCell(0);
		cell.setCellValue(obj.getName());
		cell.setCellStyle(cellDefStyle);
		cell = contentRow.createCell(1);
		cell.setCellValue(obj.getSex());
		cell.setCellStyle(cellDefStyle);
		sheet.setColumnWidth(colIndex -1,  256 * 20);    // 设置列宽(第一个参数是列号, 第二个参数是宽度)(setColumnWidth这个方法宽度的单位是字符数的256分之一)
		cell = contentRow.createCell(2);
		cell.setCellValue(obj.getAge());
		cell.setCellStyle(cellcontentStyle);
		sheet.setColumnWidth(colIndex - 1,  256 * 80);
		sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 2, 5));    // 合并单元格CellRangeAddress构造参数依次表示起始行,截至行,起始列,截止列
		++ rowIndex;
	}
	
	
	/** 设置行高(前面设置了默认行高,这里只需设置非默认部分,) */
	for (int i = 2; i < rowIndex - 1; i++) {
		HSSFRow row = sheet.getRow(i);
		row.setHeightInPoints(22);
	}
	
	/** 画表格对角线(表格中常有需要画对角线) */
	HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
	HSSFClientAnchor anchor = new HSSFClientAnchor();   // 建立锚点(startRow, startCol, startX, startY, endRow, endCol, endX, endY)
	anchor.setAnchor((short) 1, 5, 0, 0, (short) 3, 6, 0, 0);
	HSSFSimpleShape line = patriarch.createSimpleShape(anchor);    // 建立一个简单的图形
	line.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);    // 线
	line.setLineStyle(HSSFShape.LINESTYLE_SOLID);    // 实线
	line.setLineWidth(HSSFShape.LINEWIDTH_ONE_PT);   // 设置线条粗细(HSSFShape.LINEWIDTH_ONE_PT表示1pt)
	
	//输出Excel文件
	OutputStream output = response.getOutputStream();
	response.reset();
	response.setCharacterEncoding("UTF-8");        
	String fileName = "导出Excel表格测试文件.xls";
	response.setContentType("application/vnd.ms-excel");
	response.setHeader("Content-disposition", "attachment; filename=" + dealFileName(request, fileName) );
	wb.write(output);
	output.close();
}

/** 处理导出文件名乱码的问题 */ 
public String dealFileName(HttpServletRequest request, String fileName) {
	String returnFileName = "";
	try {
		String userAgent = request.getHeader("USER-AGENT");
		if (userAgent != null && (userAgent.indexOf("MSIE") != -1 || userAgent.indexOf("Trident") != -1) {    // IE浏览器
			returnFileName = java.net.URLEncoder.encode(fileName, "UTF8");
		} else if (userAgent != null && userAgent.indexOf("Mozilla") != -1) {    // 火狐,chrome浏览器等
			returnFileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
	return returnFileName;
}

四、动态数据的导出简单示例

        当我们要导出的数据格式是一致时,我们可以以对象的形式创建每一行的数据,通过对象数据列表,从而动态导出所有数据表格。

public String exportExcel() {
    try {
        // arg0:数据的集合
        List<?> data = getUserList();
        // arg1:集合中的数据的类型
        Class<?> clazz = User.class;
			
        // 创建工作本
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 创建工作表
        HSSFSheet sheet = workbook.createSheet("Sheet1");
        // 创建第1行
        HSSFRow row = sheet.createRow(0);
			
        // 获取数据的字段列表
        Field[] fields = clazz.getDeclaredFields();
			
        // 创建?个单元格
        for (int i = 0; i < fields.length; i++) {
            // 设置当前字段可见
            fields[i].setAccessible(true);
            // 创建单元格
            HSSFCell cell = row.createCell((short) i);
            // 设计各单元格的数据类型(非必要)
            if ("java.lang.Integer".equals(fields[i].getType().getName())) {
                cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
            } else {
                cell.setCellType(HSSFCell.CELL_TYPE_STRING);
            }
            // 添加数据
            cell.setCellValue(fields[i].getName());
        }
	
        // 循环添加数据
        for (int i = 0; i < data.size(); i++) {
            // 创建第?行
            row = sheet.createRow(i + 1);
            // 循环创建?个单元格
            for (int c = 0; c < fields.length; c++) {
                // 创建单元格
                HSSFCell cell = row.createCell((short) c);
                // 设计各单元格的数据类型(非必要)
                if ("java.lang.Integer".equals(fields[c].getType().getName())) {
                    cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
                } else {
                    cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                }
                // 添加数据
                cell.setCellValue(fields[c].get(data.get(i)).toString());
            }
        }
	
        // 将数据写到输出流对象中
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        workbook.write(out);
        // 通过输出流得到数据的byte[]
        byte[] bytes = out.toByteArray();
        // 关闭流
        out.close(); // 连接型资源都需要close()
        // 基于byte[]创建输入流对象,以返回给客户端
        setExcelStream(new ByteArrayInputStream(bytes));
        // 返回
        return "success";
    } catch (Exception e) {
        e.printStackTrace();
    }
    return "error";
}

注:我们还可以通过自定义注解,获得每一个字段的中文列名,以及该字段是否需要导出。

发布了47 篇原创文章 · 获赞 16 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/zorro_jin/article/details/84701757