首先要注意一个问题:
2007版的,对应 .xlsx 格式,对应的那个某某类前面是 XSSF;
2003版的,对应 .xls 格式,对应的那个某某类前面是 HSSF;
最简单的POI导出:而且是不可以用在服务器上面的,通常用于测试(明显,这个只有输出流,没有输入流,输出流是自己生成的)
public static void main(String[] args) { //新建excel报表 HSSFWorkbook excel = new HSSFWorkbook(); //添加一个sheet,名字叫"我的POI之旅" HSSFSheet hssfSheet = excel.createSheet("我的POI之旅");//在workbook里面创建第一个sheet
HSSFSheet hssfSheet = excel.createSheet("哈哈我的POI之旅哈哈");//在workbook里面创建第二个sheet //往excel表格创建一行,excel的行号是从0开始的 HSSFRow hssfRow = hssfSheet.createRow(0); //第一行创建第一个单元格 HSSFCell hssfCell = hssfRow.createCell(0); //设置第一个单元格的值 hssfCell.setCellValue("poi"); FileOutputStream fout = null; try{ fout = new FileOutputStream("D:/students.xls");//生成输出流,一般都是通过这个方法的啦 excel.write(fout);//这个输出流是通过Excel的内置方法write()写出的(生成输出流之后一定要写出的啦) fout.close();//记得关闭 }catch (Exception e){ e.printStackTrace(); } }
从服务器取得模板,然后再对模板进行数据填写,在输出(这样的话他妈的就可以省去了对模板一大堆代码的编写)(不是标准代码,看到核心部分就是了)
@RequestMapping("downLoadExcelModel") @ResponseBody public Response downLoadExcelModel(HttpServletResponse response, HttpServletRequest request) { String modelName = request.getParameter("modelName"); try { String modelName1 = java.net.URLEncoder.encode(modelName, "UTF-8").replaceAll("%28", "\(").replaceAll("%29", "\)"); String pathName = "excel/" + modelName + ".xlsx"; String path = request.getSession().getServletContext().getRealPath(pathName); File file = new File(path); FileInputStream fileInputStream = new FileInputStream(file);// 得到了文件输入流 XSSFWorkbook wb = new XSSFWorkbook(fileInputStream);// 这个构造方法就可以得到了excel模板的对象了嘛 /* * 下面这段代码就是对取出来的模板进行赋值,没有没有这段代码的话,就是直接导出模板了 */ XSSFSheet sheet = wb.getSheetAt(0);// 取excel的第一个sheet(这个sheet的的标题已经搞定了吗,因为是从服务器取出来的,不用再编辑了) // 对sheet进行赋值(当然,值应该是从数据库取出来的) XSSFRow row1 = sheet.createRow(1); XSSFCell cell10 = row1.createCell(0); XSSFCell cell11 = row1.createCell(1); cell10.setCellValue("haha"); cell11.setCellValue("xixi"); String fileName = java.net.URLEncoder.encode("社保应缴报表", "UTF-8"); String filePath = fileName + ExcelUtil.getSytemTime("yyyy-MM-dd") + ".xlsx"; response.setContentType("application/vnd.ms-excel"); // 往response里面塞值,这里表明内容是excel表格的 response.setHeader("Content-disposition", "attachment;filename=" + filePath); // 说明里面是什么东东,比如这里里面是社保嘛,filePath里面已经写好了是什么标题 OutputStream ouputStream = response.getOutputStream(); // 然后通过response取得输出流 wb.write(ouputStream); // 写出输出流 ouputStream.flush(); // 缓冲,刷新 ouputStream.close(); // 关闭 } catch (UnsupportedEncodingException e) { logger.error("下载模版文件名转换异常", e); } catch (FileNotFoundException e) { logger.error("下载模版文件没有找到对应的模版名异常", e); } catch (IOException e) { logger.error("下载模版文件名IO异常", e); } return null; }
三种方法通用导出模板(反正我觉得第三种方法最可爱):
一、传入方法参数,根据方法得到值;
package poi; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.apache.poi.hssf.record.formula.functions.T; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class ExportTest { public static void main(String[] args) throws Exception{ List<InsurCombiMaintenDomain> list = ExportTest.getDO(); String fileName = java.net.URLEncoder.encode("险种组合导出表", "UTF-8"); String title="险种组合导出结果"; String [] headers={"缴纳城市","员工子组","户口类型"}; String [] methodNames={"getPayCity","getStaffGroup","getIdentityType"}; ExportTest.export(fileName, title, headers, list, methodNames); System.out.println("搞定"); } static <T> void export(String fileName, String title, String[] headers, List<T> list,String[] methodNames) throws IOException { FileOutputStream fout = null; XSSFWorkbook workbook=new XSSFWorkbook(); // 声明一个Excel 2007的版本 XSSFSheet sheet = workbook.createSheet(title); // 产生表格标题行 XSSFRow row = sheet.createRow(0); for (short i = 0; i < headers.length; i++) { XSSFCell cell = row.createCell(i); cell.setCellValue(headers[i]); } // 说白了就是往第几行第几列里面塞值嘛,根据这个东东就得到这个值:methods[i].invoke(obj) int rowNumber = 1; for (T obj : list) { row = sheet.createRow(rowNumber); // 创建这个值所在的行 // 得到传入对象的所有方法(InsurCombiMaintenDomain实体下面的get set 方法,以及Object的特定方法) Method[] methods = obj.getClass().getMethods(); String methodName = null; Object objValue = null; int cellNumber = 0; //循环与列头对应的列 for (String tempMethod : methodNames) { for (int i = 0; i < methods.length; i++) { methodName = methods[i].getName(); try { //匹配当前要那值的列 if (tempMethod.equals(methodName)) { objValue = methods[i].invoke(obj);// 例如:方法名,getPayCity()调用invoke方法就得到“东莞市一” XSSFCell cellTemp = row.createCell(cellNumber); // 创建这个值所在的列 if(null != objValue){//如果值为null就设置一个空字符 cellTemp.setCellValue(objValue.toString()); } else { cellTemp.setCellValue(""); } cellNumber++; } } catch (Exception e) { e.printStackTrace(); } } } rowNumber++; } try{ //用流将其写到D盘 fout = new FileOutputStream("D:/HAHA.xls"); workbook.write(fout); fout.close(); } catch (Exception e){ e.printStackTrace(); } } private static List<InsurCombiMaintenDomain> getDO() { List<InsurCombiMaintenDomain> listICMD = new ArrayList<>(); InsurCombiMaintenDomain iDomain = new InsurCombiMaintenDomain(); iDomain.setPayCity("东莞市一"); iDomain.setStaffGroup("员工子组一"); iDomain.setIdentityType("户口类型一"); InsurCombiMaintenDomain iDomain2 = new InsurCombiMaintenDomain(); iDomain2.setPayCity("东莞市二"); iDomain2.setStaffGroup("员工子组二"); iDomain2.setIdentityType("户口类型二"); InsurCombiMaintenDomain iDomain3 = new InsurCombiMaintenDomain(); iDomain3.setPayCity("东莞市三"); iDomain3.setStaffGroup("员工子组三"); iDomain3.setIdentityType("户口类型三"); listICMD.add(iDomain); listICMD.add(iDomain2); listICMD.add(iDomain3); return listICMD; } } class InsurCombiMaintenDomain { private String payCity;//缴交城市 private String staffGroup;//员工子组 private String identityType;//户口类型 public String getPayCity() { return payCity; } public void setPayCity(String payCity) { this.payCity = payCity; } public String getStaffGroup() { return staffGroup; } public void setStaffGroup(String staffGroup) { this.staffGroup = staffGroup; } public String getIdentityType() { return identityType; } public void setIdentityType(String identityType) { this.identityType = identityType; } }
二、传入实例变量参数,根据方法得到值:
package poi02; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class TestsMain { public static void main(String[] args) throws Exception{ List<InsurCombiMaintenDomain> list = ExportTest02.getDO(); String fileName = java.net.URLEncoder.encode("wocao", "UTF-8"); String sheetName="险种组合导出结果"; String [] headers={"缴纳城市","员工子组","户口类型"}; String [] columns={"payCity","staffGroup","identityType"}; ExportTest02.export(fileName, sheetName, headers, columns, list); System.out.println("搞定"); } } class ExportTest02 { /*** * * @param fileName 文件名称 * @param sheetName 所在的sheet名称 * @param headers 一般每个excel表都有表头的嘛 * @param listData 所要插入的输入 * @param methodNames * @throws IOException */ static <T> void export(String fileName, String sheetName, String[] headers, String [] columns, List<T> list) throws Exception { FileOutputStream out = null; XSSFWorkbook workbook = new XSSFWorkbook(); // 声明一个Excel 2007的版本 XSSFSheet sheet = workbook.createSheet(sheetName); // 产生表格标题行 XSSFRow row = sheet.createRow(0); for (short i = 0; i < headers.length; i++) { XSSFCell cell = row.createCell(i); cell.setCellValue(headers[i]); } // 说白了就是往第几行第几列里面塞值嘛,根据这个东东就得到这个值:methods[i].invoke(obj) int rowNumber = 1; for (T data : list) { // list里面的每一条数据代表excel的一行(遍历每一行) row = sheet.createRow(rowNumber); // 创建这个值所在的行 int columnNumber = 0; Class<? extends Object> clazz = data.getClass(); Field[] fieldArr = clazz.getDeclaredFields(); for (int i = 0; i < fieldArr.length; i++) { // 对这一行里面的每一个值进行遍历 String fieldName = fieldArr[i].getName(); for (int j = 0; j < columns.length; j++) { if (fieldName.equals(columns[j])) { String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); Method method = clazz.getMethod(getMethodName); Object value = method.invoke(data); XSSFCell cellTemp = row.createCell(columnNumber); // 创建这个值所在的列 if (value == null) { value = ""; } cellTemp.setCellValue(value.toString()); } } columnNumber++; } rowNumber++; } try { // 用流将其写到D盘 out = new FileOutputStream("D:/" + fileName + ".xls"); workbook.write(out); out.close(); } catch (Exception e) { e.printStackTrace(); } } static List<InsurCombiMaintenDomain> getDO() { // ...... 忽略 } } class InsurCombiMaintenDomain { // ......忽略 }
二、传入实例变量参数,根据参数得到值:
package poi03; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class TestsMain03 { public static void main(String[] args) throws Exception{ List<InsurCombiMaintenDomain> list = ExportTest02.getDO(); String fileName = java.net.URLEncoder.encode("wocao", "UTF-8"); String sheetName="险种组合导出结果"; String [] headers={"缴纳城市","员工子组","户口类型"}; String [] columns={"payCity","staffGroup","identityType"}; ExportTest02.export(fileName, sheetName, headers, columns, list); System.out.println("搞定"); } } class ExportTest02 { /*** * * @param fileName 文件名称 * @param sheetName 所在的sheet名称 * @param headers 一般每个excel表都有表头的嘛 * @param listData 所要插入的输入 * @param methodNames * @throws IOException */ static <T> void export(String fileName, String sheetName, String[] headers, String [] columns, List<T> list) throws Exception { FileOutputStream out = null; XSSFWorkbook workbook = new XSSFWorkbook(); // 声明一个Excel 2007的版本 XSSFSheet sheet = workbook.createSheet(sheetName); // 产生表格标题行 XSSFRow row = sheet.createRow(0); for (short i = 0; i < headers.length; i++) { XSSFCell cell = row.createCell(i); cell.setCellValue(headers[i]); } // 说白了就是往第几行第几列里面塞值嘛,根据这个东东就得到这个值:methods[i].invoke(obj) int rowNumber = 1; for (T data : list) { // list里面的每一条数据代表excel的一行(遍历每一行) row = sheet.createRow(rowNumber); // 创建这个值所在的行 int columnNumber = 0; Class<? extends Object> clazz = data.getClass(); Field[] fieldArr = clazz.getDeclaredFields(); // 得到该对象下面的所有属性(即该类的所有成员变量,或者叫实例变量) for (int i = 0; i < fieldArr.length; i++) { // 对这一行里面的每一个值进行遍历 String fieldName = fieldArr[i].getName(); for (int j = 0; j < columns.length; j++) { // columns 是我所需要的字段啊(因为有些字段可能不需要啊),所以这里是根据那边给过来的字段数组,筛选出我需要的字段,然后取值啊 if (fieldName.equals(columns[j])) { Field declaredField = clazz.getDeclaredField(fieldName); // 根据具体的字段值就可以得到相对应的对象了 declaredField.setAccessible(true); Object value = declaredField.get(data); // 然后利用反射就可以啦 XSSFCell cellTemp = row.createCell(columnNumber); // 创建这个值所在的列 if (value == null) { value = ""; } cellTemp.setCellValue(value.toString()); } } columnNumber++; } rowNumber++; } try { // 用流将其写到D盘 out = new FileOutputStream("D:/" + fileName + ".xls"); workbook.write(out); out.close(); } catch (Exception e) { e.printStackTrace(); } } static List<InsurCombiMaintenDomain> getDO() { // .....忽略 } } class InsurCombiMaintenDomain { // .....忽略 }
最简单的方法:
public static void main(String[] args) throws Exception { File file = new File("d:\user\80002795\桌面\haha导入\haha.xlsx"); InputStream in = new FileInputStream(file); Workbook xssfWorkbook = WorkbookFactory.create(in); Sheet sheet = xssfWorkbook.getSheetAt(0); System.out.println(sheet.getRow(0).getCell(0)); }
导入的基本方法:
/*** * 其实,根据个人的理解,导入的核心思想就是:首先要经过上传的步骤,把要导入的文件上传到服务器,然后再从服务器把文件取出来,再取出相关数据 * * @param commonsMultipartFile * @throws IOException * @throws InvalidFormatException */ @RequestMapping("excelUpload01") public void fileUpload02(@RequestParam("excel01") CommonsMultipartFile commonsMultipartFile) throws IOException, InvalidFormatException {try { // 获得文件名并且得到指定路径 // commonsMultipartFile.getOriginalFilename()这个方法是获取导入文件的文件名,说白了下面的代码就是得到文件名,用时间肯定要保持数据的独立性啊 String childFileName = new SimpleDateFormat("yyyyMMddHHmmss").format(Calendar.getInstance().getTime()) + commonsMultipartFile.getOriginalFilename(); System.out.println(childFileName); // 导入之后,要存进哪里的路径,如果没有这个路径,就创建一个呗 String parentPath = "E:\upload\upload22\upload33"; File filePart = new File(parentPath); if (!filePart.exists()) { filePart.mkdirs(); } File fileAll = new File(filePart, childFileName);// 记得,关于这个构造方法,第一个参数可以有两种形式,一种是File对象,一种是string类型的路径 commonsMultipartFile.transferTo(fileAll);// 1)要把导入的文件放进服务器;其实接下去的步骤就跟导出一模一样了 FileInputStream fis = new FileInputStream(fileAll);// 2)再从服务器取得相关的文件输入流 /* * 3)如果是2007版 的xlsx的话,就是用这个方法得到workbook以及sheet */ Workbook xssfWorkbook = WorkbookFactory.create(fis); Sheet sheet = xssfWorkbook.getSheetAt(0); /* * 3)如果是2003版的xls的话,就是用这个方法得到workbook以及sheet */ // HSSFWorkbook hssfWorkbook = new HSSFWorkbook(fis); // HSSFSheet sheet = hssfWorkbook.getSheetAt(0); Cell cell = sheet.getRow(0).getCell(0); System.out.println("***********************" + cell); } catch (FileNotFoundException e) { e.printStackTrace(); } }
最简单的利用反射方法导入
/*** * http://localhost:8080/testWeb/home.jsp * * @author 80002795 * */ @Controller @RequestMapping("excel") public class Excel { /*** * 其实,根据个人的理解,导入的核心思想就是:首先要经过上传的步骤,把要导入的文件上传到服务器,然后再从服务器把文件取出来,再取出相关数据 * * @param commonsMultipartFile * @throws IOException * @throws InvalidFormatException * @throws Exception * @throws NoSuchFieldException */ @RequestMapping("excelUpload01") public void fileUpload02(@RequestParam("excel01") CommonsMultipartFile commonsMultipartFile) throws Exception { String[] dataArr = {"city","empNum","wtype","ltype","createDate"}; int startRow = 1;// 从第几行开始 List<HaDO> list = Excel.excelUploadUtils(commonsMultipartFile, dataArr, startRow); for (HaDO haDO : list) { System.out.println(haDO); } } private static List<HaDO> excelUploadUtils(CommonsMultipartFile commonsMultipartFile, String[] dataArr, int startRow) throws Exception{ try { /* * 先导入 */ String childFileName = new SimpleDateFormat("yyyyMMddHHmmss").format(Calendar.getInstance().getTime()) + commonsMultipartFile.getOriginalFilename(); String parentPath = "E:\upload\upload22\upload33"; File filePart = new File(parentPath); if (!filePart.exists()) { filePart.mkdirs(); } File fileAll = new File(filePart, childFileName);// 记得,关于这个构造方法,第一个参数可以有两种形式,一种是File对象,一种是string类型的路径 commonsMultipartFile.transferTo(fileAll);// 1)要把导入的文件放进服务器;其实接下去的步骤就跟导出一模一样了 /* * 再从服务器得到sheet */ FileInputStream fis = new FileInputStream(fileAll);// 2)再从服务器取得相关的文件输入流 Workbook xssfWorkbook = WorkbookFactory.create(fis); Sheet sheet = xssfWorkbook.getSheetAt(0); int columnCount = sheet.getRow(0).getPhysicalNumberOfCells();// 得到一共有多少列 int rowCount = sheet.getLastRowNum();// 得到一共有多少行 List<HaDO> list = new ArrayList<>(); if (columnCount != dataArr.length) { throw new IllegalArgumentException("列数不正确,请重新检查再导入"); } for (int i = startRow; i < rowCount; i++) { // 首先对一行一行进行遍历 Row row = sheet.getRow(i); /* * 原始方法 */ // haDO.setCity(row.getCell(0).getStringCellValue()); // haDO.setEmpNum(row.getCell(1).getStringCellValue()); // haDO.setWtype(row.getCell(2).getStringCellValue()); // haDO.setLtype(row.getCell(3).getStringCellValue()); // haDO.setCreateDate(row.getCell(4).getStringCellValue()); /* * 用反射的方法 * 关键就是HaDO的成员变量要跟导入的值要对应得上,因为所导入的值是有顺序规律的,所以用反射的方法另set方法有顺序规律使其跟导入的值对应上就是了 */ Class<?> clazz = HaDO.class; HaDO haDO = (HaDO)clazz.newInstance(); for (int j = 0; j < dataArr.length; j++) { Field dataField = clazz.getDeclaredField(dataArr[j]);//这个字段跟下面的值对应 dataField.setAccessible(true); dataField.set(haDO, row.getCell(j).getStringCellValue());//这个值跟上面的字段对应 } list.add(haDO); } return list; } catch (FileNotFoundException e) { e.printStackTrace(); throw e; } } }
额外附注没有整理导出的用map:
/** * 中标结果列表 */ @RequestMapping("exportWonFlagList") @Action(description="中标结果列表") public void exportWonFlagList(HttpServletRequest request, HttpServletResponse response) throws Exception { response.setContentType("octets/stream"); String filedisplay = URLEncoder.encode("中标结果列表.xls", "UTF-8"); response.setHeader("Content-Disposition", "attachment;filename="+ filedisplay); try { List<Map> list = agntWonMarkResultService.exportWonFlagList(new QueryFilter(request,"agntWonMarkResultItem",false)); ExcelUtils.createExcel(getExportWonFlagListHead(),list, response.getOutputStream()); }catch(Exception e) { logger.error(e.getMessage(),e); } } static List<Map> getExportWonFlagListHead(){ List l=new ArrayList<Map>(); String[] nameColumnZh = { "招标批次", "区部代码", "雇员编号", "雇员姓名", "身份证", "标的编码", "得分", "是否中标", "是否已公示", "认证处理状态", "认证处理时间", "认证异常原因", "合同生成状态", "合同生成时间", "合同生成异常原因" }; String[] nameColumnEn = { "MARK_BATCH", "AREA_CODE", "EPIEMP_CODE", "EPIEMP_NAME", "CARD_NO", "MARK_CODE", "SCORE", "WON_FLAG", "PUBLISH_STATUS", "AUTH_STATUS", "AUTH_DATE", "AUTH_MSG", "AGR_STATUS", "AGR_DATE", "AGR_MSG" }; for(int i = 0;i<nameColumnZh.length;i++){ Map<String, Object> mapColumn = new HashMap<String, Object>(); mapColumn.put("COLUMN_NAME", nameColumnEn[i]); mapColumn.put("COLUMN_COMMENTS", nameColumnZh[i]); l.add(mapColumn); } return l; } public static void createExcel(List<Map> excelColList,List<Map> dataList,OutputStream fOut) { // 创建新的Excel 工作簿 Workbook workbook = new SXSSFWorkbook(100); // 在Excel工作簿中建一工作表,其名为缺省值 Sheet sheet = workbook.createSheet(); // 在索引0的位置创建行(最顶端的行) Row row = sheet.createRow(0); try { // =============================================================== for (int i=0;i<excelColList.size();i++){ Cell cell = row.createCell(i); // 定义单元格为字符串类型 cell.setCellType(HSSFCell.CELL_TYPE_STRING); cell.setCellValue(objToString(excelColList.get(i).get("COLUMN_COMMENTS"))); } for (int i=0;i<dataList.size();i++){ Row sheetRow = sheet.createRow(i+1); for (int j=0;j<excelColList.size();j++){ Map tm=dataList.get(i); Cell cell = sheetRow.createCell(j); // 定义单元格为字符串类型 cell.setCellType(HSSFCell.CELL_TYPE_STRING); cell.setCellValue(objToString(tm.get(excelColList.get(j).get("COLUMN_NAME")))); } } // 把相应的Excel 工作簿存盘 workbook.write(fOut); fOut.flush(); // 操作结束,关闭文件 fOut.close(); } catch (Exception e) { logger.error("生成excel失败!", e); } }
END!!