先导入POI需要的依赖
<dependencies> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>4.1.2</version> </dependency> </dependencies>
上代码,后面再做解释
1 package top.hjie; 2 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 import java.io.OutputStream; 6 import java.lang.reflect.Field; 7 import java.math.BigDecimal; 8 import java.util.ArrayList; 9 import java.util.List; 10 import java.util.Random; 11 12 import org.apache.poi.hssf.usermodel.HSSFWorkbook; 13 import org.apache.poi.ss.usermodel.Cell; 14 import org.apache.poi.ss.usermodel.Row; 15 import org.apache.poi.ss.usermodel.Sheet; 16 import org.apache.poi.ss.usermodel.Workbook; 17 import org.apache.poi.xssf.usermodel.XSSFWorkbook; 18 19 import com.alibaba.fastjson.JSON; 20 import com.alibaba.fastjson.JSONArray; 21 import com.alibaba.fastjson.JSONObject; 22 23 /** 24 * @ClassName: PoiUtils 25 * @Description: TODO 26 * @author 何杰 27 * @date 2020年5月20日 28 */ 29 public class PoiUtil { 30 31 public static void main(String[] args) throws Exception { 32 String a = "student.xx"; 33 System.out.println(a.substring(0, a.lastIndexOf("."))); 34 String[] title = { "id", "标题", "名称", "重量" ,"学生"}; 35 String[] property = { "id", "title", "name", "weight" ,"student.xx"}; 36 List<Object> list = new ArrayList<Object>(); 37 for (int i = 0; i < 100; i++) { 38 Person person = new Person(); 39 person.setId(i + 1); 40 person.setName("名称" + (i + 1)); 41 person.setTitle("标题" + (i + 1)); 42 person.setWeight(new Random().nextInt(100000) + "g"); 43 Student s = new Student(); 44 s.setXx("222"); 45 person.setStudent(s); 46 list.add(person); 47 } 48 Student student = new Student(); 49 student.setXx("6666"); 50 createEcxelByGroups(title, property, list, PoiType.XLSX); 51 typeDict(a); 52 } 53 54 /** 55 * @Title: createEcxel 56 * @Description: 通过属性组创建Excel,序号自动生成 57 * @param title 58 * 标题 59 * @param property 60 * 对象的属性名 61 * @param coll 62 * 需要生成表格的对象 63 * @param suffix 64 * 后缀名 xls || xlsx 65 * @throws SecurityException 66 * @throws NoSuchFieldException 67 * @throws IllegalAccessException 68 * @throws IllegalArgumentException 69 * @throws IOException 70 */ 71 public static void createEcxelByGroups(String[] title, String[] property, 72 List<Object> coll, PoiType suffix) throws NoSuchFieldException, 73 SecurityException, IllegalArgumentException, IllegalAccessException { 74 if (suffix == null) { 75 throw new RuntimeException("请选择文件后缀名"); 76 } 77 Workbook wb = null; 78 if (suffix == PoiType.XLS) { 79 wb = new HSSFWorkbook(); 80 } else { 81 wb = new XSSFWorkbook(); 82 } 83 Sheet st = wb.createSheet(); 84 // 创建第一行 85 Row rowone = st.createRow(0); 86 // 设置标题 87 for (int i = 0; i <= title.length; i++) { 88 Cell cell = rowone.createCell(i); 89 if (i == 0) { 90 cell.setCellValue("序号"); 91 continue; 92 } 93 cell.setCellValue(title[i - 1]); 94 } 95 96 // 填充值 97 for (int i = 0; i < coll.size(); i++) { 98 Class<? extends Object> clazz = coll.get(i).getClass(); 99 100 Row row = st.createRow(i + 1); 101 for (int j = 0; j <= property.length; j++) { 102 // 创建j++列 103 Cell cell = row.createCell(j); 104 if (j == 0) { 105 cell.setCellValue(i + 1); 106 continue; 107 } 108 // 判断要获取的属性名是否包含. 109 if(property[j - 1].indexOf(".") == -1){ 110 // 不包含 111 Field field = coll.get(i).getClass() 112 .getDeclaredField(property[j - 1]); 113 // 设置对象的访问权限,保证对private的属性的访问 114 field.setAccessible(true); 115 Object o = field.get(coll.get(i)); 116 cell.setCellValue(o + ""); 117 }else{ 118 // 包含 119 Field field = coll.get(i).getClass() 120 .getDeclaredField(property[j - 1].substring(0, property[j - 1].lastIndexOf("."))); 121 // 设置对象的访问权限,保证对private的属性的访问 122 field.setAccessible(true); 123 Object o = field.get(coll.get(i)); 124 // 判断是否属于基本数据类型,或是否包含. 125 if(!typeDict(o) && property[j - 1].indexOf(".") != -1){ 126 String value = getFieldValue(o, property[j - 1]); 127 cell.setCellValue(value + ""); 128 continue; 129 } 130 cell.setCellValue(o + ""); 131 } 132 } 133 } 134 OutputStream fileOut = null; 135 try { 136 fileOut = new FileOutputStream("D:\测试." 137 + suffix.toString().toLowerCase()); 138 wb.write(fileOut); 139 } catch (Exception e) { 140 e.printStackTrace(); 141 } finally { 142 if (fileOut != null) { 143 try { 144 wb.close(); 145 fileOut.close(); 146 } catch (Exception e) { 147 e.printStackTrace(); 148 } 149 } 150 if (wb != null) { 151 try { 152 wb.close(); 153 } catch (Exception e) { 154 e.printStackTrace(); 155 } 156 } 157 } 158 } 159 160 /** 161 * 162 * @Description: 获取字段值 163 * @param @param obj 对象 164 * @param @param field 获取的字段名 165 * @param @return 166 * @return String 167 * @throws 168 */ 169 public static String getFieldValue(Object obj, String field){ 170 // 截取字段名,只支持一级,obj -> obj, 171 try { 172 String fname = field.substring(field.lastIndexOf(".") + 1,field.length()); 173 // 创建j++列 174 Field d = obj.getClass().getDeclaredField(fname); 175 // 设置对象的访问权限,保证对private的属性的访问 176 d.setAccessible(true); 177 Object o = d.get(obj); 178 return o + ""; 179 } catch (Exception e) { 180 e.printStackTrace(); 181 } 182 return null; 183 } 184 185 public static boolean typeDict(Object obj){ 186 Class<?>[] clazzs = {int.class,short.class,double.class, 187 float.class,byte.class,long.class,char.class,boolean.class, 188 String.class,Double.class,Float.class,Integer.class,Long.class, 189 Short.class,Boolean.class,Character.class,Byte.class,BigDecimal.class}; 190 191 for (Class<?> c : clazzs) { 192 if(obj.getClass().isAssignableFrom(c)){ 193 return true; 194 } 195 } 196 return false; 197 } 198 199 } 200 201 enum PoiType { 202 XLS, XLSX; 203 } 204 205 class Person { 206 207 private int id; 208 private String title; 209 private String name; 210 private String weight; 211 private Student student; 212 213 public int getId() { 214 return id; 215 } 216 217 public void setId(int id) { 218 this.id = id; 219 } 220 221 public String getTitle() { 222 return title; 223 } 224 225 public void setTitle(String title) { 226 this.title = title; 227 } 228 229 public String getName() { 230 return name; 231 } 232 233 public void setName(String name) { 234 this.name = name; 235 } 236 237 public String getWeight() { 238 return weight; 239 } 240 241 public void setWeight(String weight) { 242 this.weight = weight; 243 } 244 245 public Student getStudent() { 246 return student; 247 } 248 249 public void setStudent(Student student) { 250 this.student = student; 251 } 252 253 } 254 255 class Student { 256 private String xx; 257 258 public String getXx() { 259 return xx; 260 } 261 262 public void setXx(String xx) { 263 this.xx = xx; 264 } 265 }
解释:
自动生成序号,title为标题,property为改标题下需要显示的对象属性名与对象属性名一一对应,只支持嵌套一级对象,对象->对象,由于是直接根据属性名获取值所以存在在get里写逻辑无效的问题,后期更改!