Of course! "Java ExcelUtils" typically refers to a utility class or a set of helper methods designed to simplify reading from and writing to Excel files using Java. Instead of writing the same boilerplate Apache POI code over and over, you wrap it in a clean, reusable utility class.

Here’s a comprehensive guide covering:
- Why use a Utility Class?
- Choosing a Library (Apache POI vs. EasyExcel)
- A Complete
ExcelUtilsExample using Apache POI - A Complete
ExcelUtilsExample using EasyExcel (Recommended) - Best Practices
Why Use a Utility Class?
When working with Excel files directly in Java, the code can become verbose and repetitive. A ExcelUtils class provides:
- Abstraction: Hides the complexity of the underlying library.
- Reusability: Write the logic once and use it everywhere in your project.
- Consistency: Ensures all Excel operations in your project are handled in the same way.
- Readability: Your business logic code becomes cleaner and easier to understand. For example,
ExcelUtils.readToList("data.xlsx", "Sheet1", Person.class)is much cleaner than a 20-line POI block.
Choosing a Library
For Java and Excel, you have two main popular choices:
| Feature | Apache POI | EasyExcel (by Alibaba) |
|---|---|---|
| Maturity | The industry standard, very mature. | Newer, but widely adopted and battle-tested in large companies. |
| Performance | Can be memory-intensive, especially for large files (XLSX). | Excellent. Uses a streaming API to read large files with very low memory footprint. |
| Ease of Use | Can be verbose and complex. | Much simpler. Provides annotations to map Excel columns to Java objects. |
| Dependency Size | Relatively large. | Smaller. |
| Recommendation | Good for general use, especially if you need to support legacy .xls files. |
Highly recommended for most modern applications, especially those dealing with large data volumes. |
For this guide, we'll provide examples for both, but we'll start with EasyExcel as it's more developer-friendly.

ExcelUtils Example using EasyExcel (Recommended)
This is the modern, simpler, and more efficient approach.
Step 1: Add Dependency
Add the EasyExcel dependency to your pom.xml:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.2</version> <!-- Check for the latest version -->
</dependency>
Step 2: Create a Data Model
Create a simple Java class (POJO) that represents a row in your Excel file. Use @ExcelProperty to map columns.
import com.alibaba.excel.annotation.ExcelProperty;
// The index of the column (0-based) or the header name
public class Person {
@ExcelProperty("姓名") // Maps to the column with header "姓名"
private String name;
@ExcelProperty("年龄")
private Integer age;
@ExcelProperty("邮箱")
private String email;
// Constructors, Getters, and Setters are required
public Person() {
}
public Person(String name, Integer age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", email='" + email + '\'' +
'}';
}
}
Step 3: Create the ExcelUtils Class
This utility class will provide static methods for reading and writing.

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import org.apache.poi.ss.usermodel.Row;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
public class ExcelUtils {
/**
* Reads an Excel file and maps its content to a list of objects.
*
* @param inputStream The input stream of the Excel file.
* @param sheetNo The sheet number to read (0-based).
* @param clazz The class of the objects to map to.
* @return A list of objects.
*/
public static <T> List<T> read(InputStream inputStream, int sheetNo, Class<T> clazz) {
return EasyExcel.read(inputStream)
.sheet(sheetNo)
.head(clazz)
.doReadSync();
}
/**
* Writes a list of objects to an Excel file.
*
* @param outputStream The output stream to write to.
* @param data The list of objects to write.
* @param sheetName The name of the sheet.
* @param clazz The class of the objects.
*/
public static <T> void write(OutputStream outputStream, List<T> data, String sheetName, Class<T> clazz) {
EasyExcel.write(outputStream, clazz)
.sheet(sheetName)
.doWrite(data);
}
}
Step 4: Use the Utility Class
Here's how you would use the ExcelUtils in your application.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MainApplication {
public static void main(String[] args) {
String filePath = "people.xlsx";
// 1. Prepare data for writing
List<Person> peopleToWrite = new ArrayList<>();
peopleToWrite.add(new Person("张三", 30, "zhangsan@example.com"));
peopleToWrite.add(new Person("李四", 25, "lisi@example.com"));
peopleToWrite.add(new Person("王五", 28, "wangwu@example.com"));
// 2. Write data to Excel
try (FileOutputStream fos = new FileOutputStream(filePath)) {
ExcelUtils.write(fos, peopleToWrite, "用户信息", Person.class);
System.out.println("Excel file written successfully to: " + filePath);
} catch (IOException e) {
e.printStackTrace();
}
// 3. Read data from Excel
File file = new File(filePath);
try (FileInputStream fis = new FileInputStream(file)) {
List<Person> peopleRead = ExcelUtils.read(fis, 0, Person.class);
System.out.println("\n--- Data Read from Excel ---");
for (Person person : peopleRead) {
System.out.println(person);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
ExcelUtils Example using Apache POI
This is the traditional approach. It's more verbose but good to know.
Step 1: Add Dependencies
You need multiple dependencies for POI as it handles different formats (.xls and .xlsx).
<dependencies>
<!-- For XLSX (OOXML) format -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version> <!-- Check for the latest version -->
</dependency>
<!-- For XLS (BIFF) format -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version>
</dependency>
</dependencies>
Step 2: Create the ExcelUtils Class
This utility class will handle both reading and writing. Notice how much more code is required.
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
public class ApachePoiExcelUtils {
/**
* Reads an Excel file and maps its content to a list of objects.
* NOTE: This is a simplified example and doesn't handle all edge cases.
* A robust solution would use a library like EasyExcel or a more complex mapping logic.
*
* @param inputStream The input stream of the Excel file.
* @param sheetNo The sheet number to read (0-based).
* @param clazz The class of the objects to map to.
* @return A list of objects.
*/
public static <T> List<T> read(InputStream inputStream, int sheetNo, Class<T> clazz) {
List<T> resultList = new ArrayList<>();
try (Workbook workbook = WorkbookFactory.create(inputStream)) {
Sheet sheet = workbook.getSheetAt(sheetNo);
DataFormatter dataFormatter = new DataFormatter();
// Assumes the first row contains headers
Row headerRow = sheet.getRow(0);
Field[] fields = clazz.getDeclaredFields();
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row currentRow = sheet.getRow(i);
if (currentRow == null) continue;
try {
T instance = clazz.getDeclaredConstructor().newInstance();
for (Cell cell : currentRow) {
String headerValue = dataFormatter.formatCellValue(headerRow.getCell(cell.getColumnIndex()));
for (Field field : fields) {
if (field.getName().equalsIgnoreCase(headerValue)) {
field.setAccessible(true);
Object value = getCellValueAsType(cell, field.getType());
field.set(instance, value);
break;
}
}
}
resultList.add(instance);
} catch (Exception e) {
System.err.println("Error processing row " + i + ": " + e.getMessage());
}
}
} catch (IOException e) {
e.printStackTrace();
}
return resultList;
}
/**
* Writes a list of objects to an Excel file.
*
* @param outputStream The output stream to write to.
* @param data The list of objects to write.
* @param sheetName The name of the sheet.
* @param clazz The class of the objects.
*/
public static <T> void write(OutputStream outputStream, List<T> data, String sheetName, Class<T> clazz) {
try (Workbook workbook = new XSSFWorkbook()) {
Sheet sheet = workbook.createSheet(sheetName);
CreationHelper createHelper = workbook.getCreationHelper();
// Create header row
Row headerRow = sheet.createRow(0);
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
headerRow.createCell(i).setCellValue(fields[i].getName());
}
// Create data rows
int rowNum = 1;
for (T item : data) {
Row row = sheet.createRow(rowNum++);
for (int i = 0; i < fields.length; i++) {
fields[i].setAccessible(true);
Object value = fields[i].get(item);
Cell cell = row.createCell(i);
if (value instanceof String) {
cell.setCellValue((String) value);
} else if (value instanceof Integer) {
cell.setCellValue((Integer) value);
} else if (value instanceof Double) {
cell.setCellValue((Double) value);
}
// Add more type handling as needed
}
}
// Auto-size columns for better display
for (int i = 0; i < fields.length; i++) {
sheet.autoSizeColumn(i);
}
workbook.write(outputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
private static Object getCellValueAsType(Cell cell, Class<?> targetType) {
if (cell == null) return null;
// Simplified type conversion. A real implementation would be more robust.
if (targetType == String.class) {
return cell.getStringCellValue();
} else if (targetType == Integer.class || targetType == int.class) {
return (int) cell.getNumericCellValue();
} else if (targetType == Double.class || targetType == double.class) {
return cell.getNumericCellValue();
}
return null;
}
}
Best Practices
-
Use Try-with-Resources: Always wrap
InputStreamandOutputStreamin atry-with-resourcesblock to ensure they are closed automatically, preventing resource leaks.try (FileInputStream fis = new FileInputStream("file.xlsx")) { // ... use fis ... } // fis is automatically closed here -
Choose the Right Library: For new projects, EasyExcel is almost always the better choice due to its performance and simplicity. Use Apache POI if you have a specific need for it (e.g., legacy
.xlssupport, or if you're already deeply integrated into the POI ecosystem). -
Handle Exceptions Gracefully: Excel operations can fail for many reasons (file not found, corrupt file, invalid format). Wrap your calls in
try-catchblocks and handleIOExceptionand other relevant exceptions. -
Data Validation: When reading, be prepared for missing or malformed data. The POI example shows a basic
try-catchinside the loop to handle bad rows. EasyExcel is more robust but you should still validate your data after reading. -
Configuration: Both libraries offer extensive configuration. For example, in EasyExcel, you can set the head row number, specify date formats, and define custom converters. In POI, you can set cell styles, fonts, and borders. The
ExcelUtilsclass is a great place to centralize these common configurations.
