Begin by adding the required dependencies for Apache 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>
Below is the code, folllowed by an explanation.
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[] headerNames = { "id", "title", "name", "weight" ,"student"};
35 String[] fieldNames = { "id", "title", "name", "weight" ,"student.xx"};
36 List<Object> dataList = new ArrayList<>();
37 for (int i = 0; i < 100; i++) {
38 Person person = new Person();
39 person.setId(i + 1);
40 person.setName("name" + (i + 1));
41 person.setTitle("title" + (i + 1));
42 person.setWeight(new Random().nextInt(100000) + "g");
43 Student s = new Student();
44 s.setXx("222");
45 person.setStudent(s);
46 dataList.add(person);
47 }
48 Student student = new Student();
49 student.setXx("6666");
50 generateExcel(headerNames, fieldNames, dataList, FileType.XLSX);
51 processType(a);
52 }
53
54 /**
55 * @Title: generateExcel
56 * @Description: Create Excel using property groups with auto-generated numbering
57 * @param headerNames
58 * Column headers
59 * @param fieldNames
60 * Property names of the objects
61 * @param dataList
62 * Objects to be written into the Excel file
63 * @param fileType
64 * File type (xls or xlsx)
65 * @throws SecurityException
66 * @throws NoSuchFieldException
67 * @throws IllegalAccessException
68 * @throws IllegalArgumentException
69 * @throws IOException
70 */
71 public static void generateExcel(String[] headerNames, String[] fieldNames,
72 List<Object> dataList, FileType fileType) throws NoSuchFieldException,
73 SecurityException, IllegalArgumentException, IllegalAccessException {
74 if (fileType == null) {
75 throw new RuntimeException("Select a file extension");
76 }
77 Workbook workbook = null;
78 if (fileType == FileType.XLS) {
79 workbook = new HSSFWorkbook();
80 } else {
81 workbook = new XSSFWorkbook();
82 }
83 Sheet sheet = workbook.createSheet();
84 // Create the first row
85 Row firstRow = sheet.createRow(0);
86 // Set headers
87 for (int i = 0; i <= headerNames.length; i++) {
88 Cell cell = firstRow.createCell(i);
89 if (i == 0) {
90 cell.setCellValue("Number");
91 continue;
92 }
93 cell.setCellValue(headerNames[i - 1]);
94 }
95
96 // Fill data
97 for (int i = 0; i < dataList.size(); i++) {
98 Class<? extends Object> clazz = dataList.get(i).getClass();
99
100 Row row = sheet.createRow(i + 1);
101 for (int j = 0; j <= fieldNames.length; j++) {
102 // Create column j++
103 Cell cell = row.createCell(j);
104 if (j == 0) {
105 cell.setCellValue(i + 1);
106 continue;
107 }
108 // Check if the field name contains a dot
109 if(fieldNames[j - 1].indexOf(".") == -1){
110 // No dot
111 Field field = dataList.get(i).getClass()
112 .getDeclaredField(fieldNames[j - 1]);
113 // Allow access to private fields
114 field.setAccessible(true);
115 Object value = field.get(dataList.get(i));
116 cell.setCellValue(value + "");
117 }else{
118 // Contains a dot
119 Field field = dataList.get(i).getClass()
120 .getDeclaredField(fieldNames[j - 1].substring(0, fieldNames[j - 1].lastIndexOf(".")));
121 // Allow access to private fields
122 field.setAccessible(true);
123 Object value = field.get(dataList.get(i));
124 // Check if it's a basic type or contains a dot
125 if(!isBasicType(value) && fieldNames[j - 1].indexOf(".") != -1){
126 String fieldValue = getFieldInfo(value, fieldNames[j - 1]);
127 cell.setCellValue(fieldValue + "");
128 continue;
129 }
130 cell.setCellValue(value + "");
131 }
132 }
133 }
134 OutputStream outputStream = null;
135 try {
136 outputStream = new FileOutputStream("D:\\test."
137 + fileType.toString().toLowerCase());
138 workbook.write(outputStream);
139 } catch (Exception e) {
140 e.printStackTrace();
141 } finally {
142 if (outputStream != null) {
143 try {
144 workbook.close();
145 outputStream.close();
146 } catch (Exception e) {
147 e.printStackTrace();
148 }
149 }
150 if (workbook != null) {
151 try {
152 workbook.close();
153 } catch (Exception e) {
154 e.printStackTrace();
155 }
156 }
157 }
158 }
159
160 /**
161 *
162 * @Description: Retrieve field value
163 * @param obj
164 * Object
165 * @param fieldName
166 * Field name
167 * @return String
168 * @throws
169 */
170 public static String getFieldInfo(Object obj, String fieldName){
171 // Extract field name, supports only one level
172 try {
173 String fName = fieldName.substring(fieldName.lastIndexOf(".") + 1,fieldName.length());
174 // Create column
175 Field field = obj.getClass().getDeclaredField(fName);
176 // Allow access to private fields
177 field.setAccessible(true);
178 Object value = field.get(obj);
179 return value + "";
180 } catch (Exception e) {
181 e.printStackTrace();
182 }
183 return null;
184 }
185
186 public static boolean isBasicType(Object obj){
187 Class<?>[] types = {int.class,short.class,double.class,
188 float.class,byte.class,long.class,char.class,boolean.class,
189 String.class,Double.class,Float.class,Integer.class,Long.class,
190 Short.class,Boolean.class,Character.class,Byte.class,BigDecimal.class};
191
192 for (Class<?> c : types) {
193 if(obj.getClass().isAssignableFrom(c)){
194 return true;
195 }
196 }
197 return false;
198 }
199
200 }
201
202 enum FileType {
203 XLS, XLSX;
204 }
205
206 class Person {
207
208 private int id;
209 private String title;
210 private String name;
211 private String weight;
212 private Student student;
213
214 public int getId() {
215 return id;
216 }
217
218 public void setId(int id) {
219 this.id = id;
220 }
221
222 public String getTitle() {
223 return title;
224 }
225
226 public void setTitle(String title) {
227 this.title = title;
228 }
229
230 public String getName() {
231 return name;
232 }
233
234 public void setName(String name) {
235 this.name = name;
236 }
237
238 public String getWeight() {
239 return weight;
240 }
241
242 public void setWeight(String weight) {
243 this.weight = weight;
244 }
245
246 public Student getStudent() {
247 return student;
248 }
249
250 public void setStudent(Student student) {
251 this.student = student;
252 }
253
254 }
255
256 class Student {
257 private String xx;
258
259 public String getXx() {
260 return xx;
261 }
262
263 public void setXx(String xx) {
264 this.xx = xx;
265 }
266 }
Explanation:
The method automatically generates row numbers. The headerNames array represents the column titles, and the fieldNames array corresponds to the properties of the objects to be displayed. It supports only one level of nested objects. Since the value are retrieved direct by property names, any logic in getter methods may not be executed correctly. This will be improved in future updates.