Efficient Excel Generation Using Apache POI

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.

Tags: ApachePOI java ExcelGeneration reflection FileHandling

Posted on Thu, 01 Oct 2026 17:02:28 +0000 by martinacevedo