最近公司项目需要把数据通过Excel形式展示给用户,由于第一次接触java 生成Excel,在网上找了很多资料,但是很多都不是很理想,自己设计了一个通过自定义注解把列名配置到实体类上,然后通过代码读取自定义注解作为列名,具体实现可以看一下代码(代码是实习时候写的,有点low,大家凑合着看吧,该功能已经上生产了,代码应该问题没什么问题了,就是不够优雅)
实体类
package com.ifp.business.common.utils; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern;
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.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.util.CellRangeAddress;
import com.ifp.common.common.utils.ColumnName;
@SuppressWarnings("all") public class CreateExcelTool { private static HSSFWorkbook workbook = null; private List listAll = new ArrayList(); private List listMap = null; private Map mapTitle = new HashMap(); private static String type[] = {"long","int","double","float","short","byte","boolean","char"}; /** * 判断文件是否存在. * @param fileDir 文件路径 * @return */ public static boolean fileExist(String fileDir){ boolean flag = false; File file = new File(fileDir); flag = file.exists(); return flag; } /** * 判断文件的sheet是否存在. * @param fileDir 文件路径 * @param sheetName 表格索引名 * @return */ public static boolean sheetExist(String fileDir,String sheetName) throws Exception{ boolean flag = false; File file = new File(fileDir); if(file.exists()){ //文件存在 //创建workbook try { workbook = new HSSFWorkbook(new FileInputStream(file)); //添加Worksheet(不添加sheet时生成的xls文件打开时会报错) HSSFSheet sheet = workbook.getSheet(sheetName); if(sheet!=null) flag = true; } catch (Exception e) { throw e; } }else{ //文件不存在 flag = false; } return flag; } /** * 创建新excel. * @param fileDir excel的路径 * @param sheetName 要创建的表格索引 * @param list excel的第一行即列名 */ public static void CreateExcelTitle(String fileDir,String sheetName,List list,String name) throws Exception{ //CreateExcelUtil.deleteExcel(fileDir); System.out.println("Excel路径:----------------------------------------"+fileDir); String path = fileDir.substring(0,fileDir.lastIndexOf("\\")+1); if (getCurrentOS().equals("linux")) { path = fileDir.substring(0,fileDir.lastIndexOf("/")+1); } File file=new File(path); if(!file.exists()){ file.mkdirs(); } HSSFSheet sheet1; Map sheetStyle = new HashMap(); //判断文件是否存在 if(CreateExcelUtil.fileExist(fileDir)){ workbook = new HSSFWorkbook(new FileInputStream(fileDir)); //判断sheet页是否存在 if(CreateExcelUtil.sheetExist(fileDir, sheetName)){ sheet1 = workbook.getSheet(sheetName); }else{ //添加Worksheet(不添加sheet时生成的xls文件打开时会报错) sheet1 = workbook.createSheet(sheetName); } }else{ workbook = new HSSFWorkbook(); //添加Worksheet(不添加sheet时生成的xls文件打开时会报错) sheet1 = workbook.createSheet(sheetName); } sheet1.autoSizeColumn(1); sheet1.autoSizeColumn(1, true); /**合并单元格 * 参数:起始行号,终止行号, 起始列号,终止列号 * 只有 该文件中不存在sheet页才会合并单元格 * */ sheet1.addMergedRegion(new CellRangeAddress(0, 0, 0, list.size() - 1)); sheet1.addMergedRegion(new CellRangeAddress(1, 1, 0, list.size() - 1)); SimpleDateFormat format = new SimpleDateFormat("yyyy年M月"); //新建文件 FileOutputStream out = null; try { HSSFFont fontName = workbook.createFont(); HSSFCellStyle cellStyleName = workbook.createCellStyle(); fontName.setFontHeightInPoints((short) 14); //字体高度 fontName.setFontName("宋体"); //字体 fontName.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); //加粗 cellStyleName.setAlignment(HSSFCellStyle.ALIGN_CENTER); cellStyleName.setFont(fontName); HSSFRow row1 = workbook.getSheet(sheetName).createRow(0); row1.setHeight((short)450); HSSFCell cell1 = row1.createCell(0); cell1.setCellValue(name); cell1.setCellStyle(cellStyleName); //设置单元格为文本格式 cell1.setCellType(HSSFCell.CELL_TYPE_STRING); HSSFRow row2 = workbook.getSheet(sheetName).createRow(1); HSSFCell cell2 = row2.createCell(0); cell2.setCellValue("制表日期:"+format.format(new Date())); //添加列名 HSSFRow row = workbook.getSheet(sheetName).createRow(2); //创建第一行 HSSFFont font = workbook.createFont(); HSSFCellStyle cellStyle = workbook.createCellStyle(); font.setFontHeightInPoints((short) 12); //字体高度 cellStyle.setFont(font); for(short i = 0;i < list.size();i++){ HSSFCell cell = row.createCell(i); //设置列宽 sheet1.setColumnWidth(i,list.get(i).toString().getBytes().length*256); cell.setCellValue("" + list.get(i)); cell.setCellStyle(cellStyle); } out = new FileOutputStream(fileDir); workbook.write(out); } catch (Exception e) { throw e; } finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 删除文件. * @param fileDir 文件路径 */ public static boolean deleteExcel(String fileDir) { boolean flag = false; File file = new File(fileDir); // 判断目录或文件是否存在 if (!file.exists()) { // 不存在返回 false return flag; } else { // 判断是否为文件 if (file.isFile()) { // 为文件时调用删除文件方法 file.delete(); flag = true; } } return flag; } /** * 往excel中写入 * @param fileDir 文件路径 * @param sheetName 表格索引 * @param object * @throws Exception */ public void writeToExcel(String fileDir,String sheetName,List mapList) throws Exception{ //创建workbook File file = new File(fileDir); try { workbook = new HSSFWorkbook(new FileInputStream(file)); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //流 FileOutputStream out = null; HSSFSheet sheet = workbook.getSheet(sheetName); HSSFFont font = workbook.createFont(); HSSFCellStyle cellStyle = workbook.createCellStyle(); font.setFontHeightInPoints((short) 12); //字体高度 cellStyle.setFont(font); /*sheet.setDefaultColumnWidth(14);//设置默认列宽 sheet.setDefaultRowHeight((short) (6 * 256)); //设置默认行高,表示2个字符的高度*/ // 获取表格的总行数 // int rowCount = sheet.getLastRowNum() + 1; // 需要加一 // 获取表头的列数 int columnCount = sheet.getRow(2).getLastCellNum(); try { // 获得表头行对象 HSSFRow titleRow = sheet.getRow(2); if(titleRow!=null){ int rowId = 3; int i = 0; int rowsIndex = 0; int row = 3; boolean flag = false; while(i Map map = mapList.get(i); HSSFRow newRow1=sheet.createRow(row); for (short columnIndex = 0; columnIndex < columnCount; columnIndex++) { //遍历表头 String titleName = titleRow.getCell(columnIndex).toString().trim().toString().trim(); String mapKey = (String) mapTitle.get(titleName); List list = new ArrayList(); if(map.get(mapKey)!=null&&map.get(mapKey).getClass().equals(list.getClass())){ flag = true; list = (List) map.get(mapKey); int j = 0; HSSFRow newRow; for(int listIndex = 0;listIndex if(sheet.getRow(rowId + j)!=null){ newRow = sheet.getRow(rowId+j); }else{ newRow=sheet.createRow(rowId+j); } newRow.setHeightInPoints(50); HSSFCell cell = newRow.createCell(columnIndex); //设置列宽 sheet.setColumnWidth(i,list.get(listIndex).toString().getBytes().length*256); cell.setCellValue(list.get(listIndex)==null ? null : list.get(listIndex).toString()); setStyle(cell,font); j++; rowsIndex = j; } }else{ try{ HSSFCell cell = newRow1.createCell(columnIndex); //判断字符串长度是否大于列宽,大于列宽,从新设置列宽 if(!"".equals(map.get(mapKey))&&map.get(mapKey)!=null){ //判断是否是中文 if(isContainChinese(map.get(mapKey).toString())&&sheet.getColumnWidth(columnIndex) sheet.setColumnWidth(columnIndex,map.get(mapKey).toString().getBytes().length*256); }else if(!isContainChinese(map.get(mapKey).toString())&&sheet.getColumnWidth(columnIndex) sheet.setColumnWidth(columnIndex,map.get(mapKey).toString().getBytes().length*512); } } cell.setCellValue(map.get(mapKey)==null ? null : map.get(mapKey).toString()); /*setStyle(cell,font);*/ cell.setCellStyle(cellStyle); }catch(Exception e){ System.out.println("------------------------------------空---------------------------"); e.printStackTrace(); } } } if(flag){ row = row+rowsIndex; }else{ row = row+rowsIndex + 1; } rowId = row; i++; } } out = new FileOutputStream(fileDir); workbook.write(out); } catch (Exception e) { e.printStackTrace(); } finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 将一个 JavaBean 对象转化为一个 Map * @param bean 要转化的JavaBean 对象 * @return 转化出来的 Map 对象 * @throws ClassNotFoundException * @throws InstantiationException * @throws IntrospectionException 如果分析类属性失败 * @throws IllegalAccessException 如果实例化 JavaBean 失败 * @throws InvocationTargetException 如果调用属性的 setter 方法失败 */ public static Map toMap(Object bean) throws ClassNotFoundException, InstantiationException { Map returnMap = new HashMap(); Class clazz = null; if(!bean.toString().contains("@")){ try { clazz = Class.forName(bean + ""); bean = clazz.newInstance(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }else{ clazz = bean.getClass(); } StringBuffer sb = new StringBuffer(); BeanInfo beanInfo = null; try { //得到的BeanInfo对象封装了把这个类当做JavaBean看的结果信息,即属性的信息 beanInfo = Introspector.getBeanInfo(clazz); //获取 clazz 类型中的 propertyName 的属性描述器 PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (int i = 0; i < propertyDescriptors.length; i++) { PropertyDescriptor descriptor = propertyDescriptors[i]; if("class".equals(descriptor.getName())){ continue; } String propertyType = descriptor.getPropertyType().toString(); boolean boo = com.ifp.common.common.utils.StringUtil.isInList(propertyType, com.ifp.common.common.utils.StringUtil.arrayToList(type)); if(propertyType.contains("java.util.List")){ try { Method readMethod = descriptor.getReadMethod(); List result = null; //调用 set 方法将传入的value值保存属性中去 result = (List) readMethod.invoke(bean, new Object[0]); for(Object o:result){ toMap(o); } } catch (SecurityException e) { e.printStackTrace(); } continue; }else if(propertyType.contains("lang") || boo){ String propertyName = descriptor.getName(); if (!propertyName.equals("class")) { Method readMethod = descriptor.getReadMethod(); Object result = null; //调用 set 方法将传入的value值保存属性中去 result = readMethod.invoke(bean, new Object[0]); if (null != result) { if(returnMap!=null&&returnMap.containsKey(propertyName)){ List list1 = new ArrayList(); List list2 = new ArrayList(); list1.add(result); if(!returnMap.get(propertyName).getClass().equals(list2.getClass())){ list2.add(returnMap.get(propertyName)); }else{ list2 = (List) returnMap.get(propertyName); } list1.addAll(list2); result = list1; }else{ result = result.toString(); } } returnMap.put(propertyName, result); } }else{ Object obj = propertyType.substring(propertyType.indexOf(" ") + 1); Method readMethod = descriptor.getReadMethod(); Object result = null; //调用 set 方法将传入的value值保存属性中去 result = readMethod.invoke(bean, new Object[0]); toMap(result); continue; } } } catch (IntrospectionException e) { System.out.println("分析类属性失败"); } catch (IllegalAccessException e) { System.out.println("实例化 JavaBean 失败"); } catch (IllegalArgumentException e) { System.out.println("映射错误"); } catch (InvocationTargetException e) { System.out.println("调用属性的 setter 方法失败"); } return returnMap; } /** * 获取父类和当前类所有属性(包括private) * @param object * @return */ public static List getAllFields(Object object){ Class clazz = object.getClass(); List fieldList = new ArrayList(); while (clazz != null){ for (Field field : clazz.getDeclaredFields()) { if (field.getGenericType().toString().contains("java.util.List")){ Object obj = (Object)field.toString().substring(field.toString().lastIndexOf(".")+1); Class clazzList = obj.getClass(); field.setAccessible(true); String fieldName = field.getName(); fieldList.add(fieldName); } } clazz = clazz.getSuperclass(); } return fieldList; } /** * 获得传入对象的所有属性名 * @param object * @return */ public List getFields(Object object){ Class cla = null; if(!object.toString().contains("@")){ try { cla = Class.forName(object + ""); } catch (ClassNotFoundException e) { e.printStackTrace(); } }else{ cla = object.getClass(); } for(Field field : cla.getDeclaredFields()){ boolean boo = com.ifp.common.common.utils.StringUtil.isInList(field.getGenericType().toString(), com.ifp.common.common.utils.StringUtil.arrayToList(type)); //判断该字段的声明类型 if(field.getGenericType().toString().contains("java.util.List")){ Object obj = (Object)(field.getGenericType().toString().substring(field.getGenericType().toString().indexOf("<")+1,field.getGenericType().toString().indexOf(">"))); getFields(obj); continue; }else if(field.getGenericType().toString().contains("lang") || boo){ field.setAccessible(true); //获取自定义注解 ColumnName anno = field.getAnnotation(ColumnName.class); String fieldName = field.getName(); String annoValue = null; if(anno == null){ /*annoValue = fieldName; mapTitle.put(fieldName, fieldName);*/ //如果该字段没有注解,直接跳过,表格中不会显示此字段 continue; }else{ annoValue = anno.value(); mapTitle.put(anno.value(),fieldName); } listAll.add(annoValue); }else{ Object obj = field.getGenericType().toString().substring(field.getGenericType().toString().indexOf(" ") + 1); getFields(obj); continue; } } return listAll; } /** * 判断字符串是否包含中文 * @param str * @return */ public static boolean isContainChinese(String str) { Pattern p = Pattern.compile("[\u4e00-\u9fa5]"); Matcher m = p.matcher(str); if (m.find()) { return true; } return false; } //设置字体样式 public static void setStyle(HSSFCell cell,HSSFFont font){ // 设置字体 font.setFontHeightInPoints((short) 12); //字体高度 //font.setColor(HSSFFont.COLOR_RED); //字体颜色 //font.setFontName("楷体"); //字体 //font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); //宽度 //font.setItalic(true); //是否使用斜体 //font.setStrikeout(true); //是否使用划线 // 设置单元格类型 HSSFCellStyle cellStyle = workbook.createCellStyle(); cellStyle.setFont(font); // cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); //水平布局:居中 //cellStyle.setWrapText(true); cell.setCellStyle(cellStyle); } public static String getCurrentOS() { String system = ""; int OS = System.getProperty("os.name").toUpperCase().indexOf("WINDOWS"); if (OS != -1) { system = "windows"; } else system = "linux"; return system; } /** * * @param fileDir * @param sheetName sheet页名字 * @param mapList * @throws Exception */ public void createExcel(String fileDir,String sheetName,List list, String name ) throws Exception{ listMap = new ArrayList(); List titleList = new ArrayList(); CreateExcelTool CreateExcelTool = new CreateExcelTool(); for(Object obj : list){ listMap.add(toMap(obj)); } //System.out.println(listMap); titleList = CreateExcelTool.getFields(list.get(0)); System.out.println("表头:"+titleList); CreateExcelTool.CreateExcelTitle(fileDir, sheetName, titleList,name); CreateExcelTool.writeToExcel(fileDir, sheetName,listMap); System.out.println("---------------------------------------生成表格成功-------------------------------------"); } public static void main(String[] args) throws Exception { List list=new ArrayList(); List list2=new ArrayList(); Map map=new HashMap(); /* for(int i = 0;i<3;i++){ Person p = new Person(); p.setName("2018-01-16 00:00:00.0"+i); p.setAge("2018-01-16 00:00:00.0"); p.setSex("2018-01-16 00:00:00.0"+i); list.add(p); } for(int i = 0;i<3;i++){ person2 p = new person2(); p.setName("list2少时诵诗书所所所所所所所所所所所所所所"+i); list2.add(p); }*/ CreateExcelTool CreateExcelTool = new CreateExcelTool(); String path ="E:/excel/123456778.xls"; CreateExcelTool.createExcel(path, "sheet1", list, "测试1"); CreateExcelTool.createExcel(path, "sheet2", list2, "测试2"); } } 自定义注解
package com.ifp.common.common.utils;
import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.ElementType; import java.lang.annotation.Target; /** * 自定义注解,程序可以读取注解values(该程序主要用于生成表格时,通过读取类属性中配置的注解,生产表格列名) * @author cdy * @Retention(RetentionPolicy.RUNTIME) 表示该注解在jvm运行时存在 *@Target(ElementType.FIELD) 只可以修饰属性 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ColumnName {
String value(); }