1.什么是Apache POI?

Apache POI是一种流行的API,它允许程序员使用Java程序创建,修改和显示MS Office文件。这由Apache软件基金会开发使用Java分布式设计或修改Microsoft Office文件的开源库。它包含类和方法对用户输入数据或文件到MS Office文档进行解码。在我们实际的开发中,表现层的解决方案虽然有多样,但是IE浏览器已成为最多人使用的浏览器,因为大家都用Windows。在企业办公系统中,常常有客户这样子要求:你要把我们的报表直接用Excel打开(电信系统、银行系统)。或者是:我们已经习惯用Excel打印。Apache的Jakata项目的POI子项目,目前比较成熟的是HSSF接口,处理MSExcel对象。它不象我们仅仅是用csv生成的没有格式的可以由Excel转换的东西,而是真正的Excel对象,你可以控制一些属性如sheet,cell等等。ApachePOI

2.Servlet3.0上传文件

2.1在index.jsp中:

<body>
	<form action="FileServlet" enctype="multipart/form-data"
		method="post">
		用户文件:<input type="file" name="file"><br>
		<input type="submit"><br>
	</form>
</body>

2.2FileServlet中:

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

@MultipartConfig
// 标识Servlet支持文件上传
public class FileServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");
		// 存储路径
		String savePath = request.getServletContext().getRealPath("/upload");
		// 获取上传的文件集合
		Collection<Part> parts = request.getParts();
		// 上传单个文件
		if (parts.size() == 1) {
			// Servlet3.0将multipart/form-data的POST请求封装成Part,通过Part对上传的文件进行操作。
			// Part part = parts[0];//从上传的文件集合中获取Part对象
			Part part = request.getPart("file");
			// 通过表单file控件(<input type="file"
			// name="file">)的名字直接获取Part对象
			// Servlet3没有提供直接获取文件名的方法,需要从请求头中解析出来
			// 获取请求头,请求头的格式:form-data; name="file"; filename="snmp4j--api.zip"
			String header = part.getHeader("content-disposition");
			// 获取文件名
			String fileName = getFileName(header);
			// 把文件写到指定路径
			part.write(savePath + File.separator + fileName);
			
			
			
		} else {
			// 一次性上传多个文件
			for (Part part : parts) {// 循环处理上传的文件
				// 获取请求头,请求头的格式:form-data; name="file";
				// filename="snmp4j--api.zip"
				String header = part.getHeader("content-disposition");
				// 获取文件名
				String fileName = getFileName(header);
				// 把文件写到指定路径
				part.write(savePath + File.separator + fileName);
			}
		}
	}

	/**
	 * 根据请求头解析出文件名 请求头的格式:火狐和google浏览器下:form-data; name="file";
	 * filename="snmp4j--api.zip" IE浏览器下:form-data; name="file";
	 * filename="E:\snmp4j--api.zip"
	 * 
	 * @param header
	 *            请求头
	 * @return 文件名
	 */
	public String getFileName(String header) {
		/**
		 * String[] tempArr1 =
		 * header.split(";");代码执行完之后,在不同的浏览器下,tempArr1数组里面的内容稍有区别
		 * 火狐或者google浏览器下:
		 * tempArr1={form-data,name="file",filename="snmp4j--api.zip"}
		 * IE浏览器下:tempArr1={form-data,name="file",filename="E:\snmp4j--api.zip"}
		 */
		String[] tempArr1 = header.split(";");
		/**
		 * 火狐或者google浏览器下:tempArr2={filename,"snmp4j--api.zip"}
		 * IE浏览器下:tempArr2={filename,"E:\snmp4j--api.zip"}
		 */
		String[] tempArr2 = tempArr1[2].split("=");
		// 获取文件名,兼容各种浏览器的写法
		String fileName = tempArr2[1].substring(
				tempArr2[1].lastIndexOf("\\") + 1).replaceAll("\"", "");
		//替换文件名
		String result = "";
		if(fileName.lastIndexOf(".")!= -1){
			 // 获取文件的后缀 
			String fileType = fileName.substring(fileName.lastIndexOf("."), fileName.length());
			result = UUID.randomUUID().toString()+fileType;
		}
		return result;
	}

}

2.3测试结果:

java poi操作word文档 javaweb poi_poi

3.poi批量导入

3.1poi架包

java poi操作word文档 javaweb poi_java poi操作word文档_02

java poi操作word文档 javaweb poi_java poi操作word文档_03

java poi操作word文档 javaweb poi_java poi操作word文档_04

上图中所需jar包都需要导入。若不导入完全中途可能会出现错误。

3.2ImportExcel文件转换成List集合工具类

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

import cn.edu.abtc.model.User;

public class ImportExcel {
	public static List<User> analyExcelUserBlock(HttpServletRequest request,String fileName){
		List<User> list = new ArrayList<User>();
		String targetDirectory = request.getServletContext().getRealPath("/upload");
		File target = new File(targetDirectory,fileName);
		try {
			FileInputStream fi = new FileInputStream(target);
			Workbook workbook = WorkbookFactory.create(fi);
			//获取第一张sheet表
			Sheet sheet = workbook.getSheetAt(0);
			//获取总行数
			int rowCount = sheet.getPhysicalNumberOfRows();
			//遍历每一行  
			for(int r = 1 ; r < rowCount ; r++){
				User user = new User();
				Row row = sheet.getRow(r);
				
				//用户id
				Cell id = row.getCell(0);
				if(id != null){
					//id.setCellType(Cell.CELL_TYPE_STRING);//deprecated
					id.setCellType(CellType.NUMERIC);
					user.setId((int)id.getNumericCellValue());
				}else{
					throw new Exception("excel表格数据类型不一致");
				}
				//用户姓名
				Cell name = row.getCell(1);
				if(name != null){
					//id.setCellType(Cell.CELL_TYPE_STRING);//deprecated
					id.setCellType(CellType.STRING);
					user.setName(id.getStringCellValue());
				}else{
					user.setName("");
				}
				//用户年龄
				Cell age = row.getCell(2);
				if(age != null){
					age.setCellType(CellType.STRING);
					user.setAge(age.getStringCellValue());
				}else{
					user.setAge("");
				}
				//用户性别
				Cell sex = row.getCell(3);
				if(sex != null){
					sex.setCellType(CellType.STRING);
					user.setSex(sex.getStringCellValue());
				}else{
					user.setSex("");
				}
				list.add(user);
				user = null;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
		return list;
	}
}

3.3在servlet中加入以下代码:

//通过ImportExcel将上传的文件转为List
			
			List<User> list = ImportExcel.analyExcelUserBlock(request, fileName);
			for(User u:list){
				System.out.println(u);
			}


java poi操作word文档 javaweb poi_javaweb_05


3.4测试结果:

java poi操作word文档 javaweb poi_jsp_06

3.5上传文件的模板:

java poi操作word文档 javaweb poi_javaweb_07

3.6注意事项:

以上项目中新建了一个User.java但是本博客中没有表现出来。很多具体问题可以私聊我。

3.7POI导出excel文件

3.7.1新建一个servlet

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;

import cn.edu.abtc.model.User;

public class ExportServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		OutputStream out = null; 
		try {
			//response.setContentType("application/msexcel;charset=UTF-8");
			out = response.getOutputStream();
			String excelName = "测试案例";
			response.setHeader("Content-Disposition", "attachment;filename="+new String( excelName.getBytes("gb2312"), "ISO8859-1" )+".xls");
			response.setContentType("application/msexcel;charset=UTF-8");
			String[] headers = new String[]{"name","age","性别"}; 
            exportExcel(excelName, headers, createUserList(), out, "yyyy-MM-dd");
            
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	public void exportExcel(String title,String[] headers,List infos,OutputStream out,String pattern){  
        //声明一个工作簿  
        HSSFWorkbook workbook = new HSSFWorkbook();  
        //生成一个表格  
        HSSFSheet sheet = workbook.createSheet(title);  
        //设置表格默认列宽度为15个字符  
        sheet.setDefaultColumnWidth(20);  
        //生成一个样式,用来设置标题样式  
        HSSFCellStyle style = workbook.createCellStyle();  
        //设置这些样式  
        style.setFillForegroundColor(IndexedColors.GREEN.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);  
        style.setBorderTop(BorderStyle.THIN);  
        style.setAlignment(HorizontalAlignment.CENTER);
        //生成一个字体  
        HSSFFont font = workbook.createFont(); 
        font.setColor(IndexedColors.WHITE.getIndex());
        font.setBold(true);
        //font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);  
        //把字体应用到当前的样式  
        style.setFont(font);  
        // 生成并设置另一个样式,用于设置内容样式  
        HSSFCellStyle style2 = workbook.createCellStyle();  
        style2.setFillForegroundColor(IndexedColors.YELLOW.getIndex()); 
        style2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style2.setBorderBottom(BorderStyle.THIN);  
        style2.setBorderLeft(BorderStyle.THIN);  
        style2.setBorderRight(BorderStyle.THIN);  
        style2.setBorderTop(BorderStyle.THIN);  
        style2.setAlignment(HorizontalAlignment.CENTER);  
        style2.setVerticalAlignment(VerticalAlignment.CENTER);  
        // 生成另一个字体  
        HSSFFont font2 = workbook.createFont();  
        font2.setBold(true);  
        // 把字体应用到当前的样式  
        style2.setFont(font2);  
        //产生表格标题行  
        HSSFRow row = sheet.createRow(0);  
        for(int i = 0; i<headers.length;i++){  
            HSSFCell cell = row.createCell(i);  
            cell.setCellStyle(style);  
            HSSFRichTextString text = new HSSFRichTextString(headers[i]);  
            cell.setCellValue(text);  
        }
        for(int i=0; i<infos.size(); i++){
        	User u = (User) infos.get(i);
        	row = sheet.createRow(i+1);  
            int j = 0;
            
            if(u.getName() != null){
            	row.createCell(j++).setCellValue(u.getName());
            }else{
            	row.createCell(j++).setCellValue("");
            }
            if(u.getAge() != null){
            	row.createCell(j++).setCellValue(u.getAge());
            }else{
            	row.createCell(j++).setCellValue("");
            }
            if(u.getSex() != null){
            	row.createCell(j++).setCellValue(u.getSex());
            }else{
            	row.createCell(j++).setCellValue("");
            }
        }
        try {  
            workbook.write(out);  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }
	public List<User> createUserList(){
		List<User> list = new ArrayList<User>();
		for(int i = 1 ; i < 30 ; i++){
			User u = new User();
			u.setName(""+i);
			u.setAge(""+i*2);
			if(i%2==1){
				u.setSex("男");
			}else{
				u.setSex("女");
			}
			list.add(u);
			u = null;
		}
		return list;
	}
}

3.7.2测试结果

java poi操作word文档 javaweb poi_java_08

结束语:经过多次摸索测试,在查阅相关资料的情况下,终于完成了POI的批量导入和批量导出功能的实现。

在完成的过程有几个地方需要注意:

1.批量导入的过程中思路是:先将excel文件上传到服务器,本例中使用的是servlet3.0特性。然后再读取文件,将文件转换成一个List集合对象,再逐条插入数据库中。

2.再处理文件转换成List对象的时候没有考虑数据量非常大的情况,需要放在线程池中进行处理。

3.POI不同的版本有不一样的用法,需要查看所下载的POI包的文档。