Có thể bạn quan tâm: Quản Lý Khách Hàng Excel: Bí Quyết Tối Ưu Hóa Dữ Liệu Và Nâng Cao Hiệu Suất Kinh Doanh
1. Giới thiệu chung
Trong nhiều ứng dụng doanh nghiệp, dữ liệu thường được lưu trữ và chia sẻ dưới dạng bảng tính Excel. Khi xây dựng các hệ thống quản lý, báo cáo, hoặc tích hợp dữ liệu, nhà phát triển Java thường cần truy cập và xử lý nội dung của các file Excel (.xls, .xlsx). Việc đọc file Excel trong Java không những giúp tự động hóa quy trình nhập dữ liệu mà còn giảm thiểu sai sót khi người dùng nhập tay.
Trong bài viết này, chúng ta sẽ đi sâu vào:
- Các định dạng file Excel phổ biến và những đặc trưng của chúng.
- Các thư viện Java phổ biến hỗ trợ đọc file Excel.
- Cách cài đặt và cấu hình môi trường phát triển.
- Các ví dụ chi tiết: từ cách đọc dữ liệu đơn giản, xử lý dữ liệu phức tạp, tới các trường hợp đặc biệt như định dạng thời gian, số tiền, công thức.
- Mẹo tối ưu hiệu năng và xử lý lỗi.
- Các nguồn tài nguyên và lưu ý khi triển khai production.
Có thể bạn quan tâm: Quality Management For Organizational Excellence: Chiến Lược, Thực Tiễn Và Lợi Ích Đột Phá
2. Hiểu rõ định dạng file Excel
2.1. XLS vs XLSX
| Đặc tính | XLS (BIFF) | XLSX (Office Open XML) |
|---|---|---|
| Định dạng file | Binary Interchange File Format (BIFF) | Zip archive chứa XML |
| Kích thước tối đa | 65,535 dòng, 256 cột (để ý 2007 trở lên vẫn hỗ trợ) | 1,048,576 dòng, 16,384 cột |
| Tính năng | Giới hạn, không hỗ trợ công thức phức tạp | Hỗ trợ đầy đủ, công thức, định dạng, macro |
| Tốc độ đọc | Nhanh hơn, nhưng hạn chế hơn | Đòi hỏi giải nén, có thể chậm hơn |
| Độ tương thích | Cần trình duyệt hỗ trợ legacy | Hỗ trợ rộng rãi, chuẩn mở |
| Thư viện hỗ trợ | Apache POI HSSF, JExcelApi | Apache POI XSSF, SXSSF, JExcelApi không hỗ trợ |
Khi quyết định thư viện, bạn cần xem xét kích thước file, tính năng cần dùng và môi trường triển khai.
2.2. Các thành phần trong file Excel
- Workbook: Tập hợp các Sheet.
- Sheet: Mỗi bảng tính có tên, có thể lưu trữ dữ liệu dạng 2 chiều.
- Row: Chứa các Cell.
- Cell: Có thể chứa dữ liệu kiểu
String,Numeric,Boolean,Formula,Error. - Style: Định dạng (font, màu, alignment).
- Comment: Ghi chú trong ô.
Việc hiểu rõ cấu trúc giúp viết code linh hoạt hơn.
Có thể bạn quan tâm: Cách Đọc File Excel (.xlsx) Trong Python: Hướng Dẫn Chi Tiết Và Toàn Diện
3. Các thư viện Java hỗ trợ đọc Excel
| Thư viện | Định dạng hỗ trợ | Đặc trưng | Thư viện chính | Cách cài đặt |
|---|---|---|---|---|
| Apache POI | XLS, XLSX | Thư viện chuẩn, mạnh mẽ | HSSF (xls), XSSF (xlsx), SXSSF (stream) | Maven/Gradle |
| JExcelApi | XLS | Nhỏ gọn, nhanh nhưng hạn chế | JExcelApi | Maven/Gradle |
| Excel4J | XLSX | Dựa trên POI nhưng API dễ dùng | Excel4J | Maven |
| EasyExcel | XLSX | Đọc/ghi nhanh, hỗ trợ streaming | EasyExcel | Maven |
| SheetJS (Java port) | XLSX | Dựa trên JavaScript, dễ mở rộng | SheetJS | JAR |
Tối ưu lựa chọn: Nếu dự án chỉ cần đọc file Excel đơn giản, EasyExcel hoặc Apache POI XSSF là lựa chọn hàng đầu. Nếu cần xử lý file lớn (> 100k dòng) thì SXSSF (streaming) hay EasyExcel giúp giảm bộ nhớ.
4. Cài đặt môi trường
4.1. Sử dụng Maven
<dependencies> <!-- Apache POI --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.5</version> </dependency> <!-- EasyExcel --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.2.5</version> </dependency>
</dependencies>
4.2. Sử dụng Gradle
dependencies { implementation 'org.apache.poi:poi-ooxml:5.2.5' implementation 'com.alibaba:easyexcel:3.2.5'
}
4.3. Thư viện JExcelApi (đối với XLS)
<dependency> <groupId>net.sourceforge.jexcelapi</groupId> <artifactId>jxl</artifactId> <version>2.6.12</version>
</dependency>
5. Cách đọc file Excel với Apache POI
5.1. Đọc file XLSX (XSSF)
import org.apache.poi.ss.usermodel.;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.FileInputStream;
import java.io.IOException;
import java.util.; public class ExcelReaderXSSF { public static void main(String args) throws IOException { String filePath = "data.xlsx"; try (FileInputStream fis = new FileInputStream(filePath); Workbook workbook = new XSSFWorkbook(fis)) { Sheet sheet = workbook.getSheetAt(0); // Sheet đầu tiên Iterator<Row> rowIterator = sheet.iterator(); while (rowIterator.hasNext()) { Row row = rowIterator.next(); Iterator<Cell> cellIterator = row.cellIterator(); List<String> cellValues = new ArrayList<>(); while (cellIterator.hasNext()) { Cell cell = cellIterator.next(); cellValues.add(getCellValueAsString(cell)); } System.out.println(cellValues); } } } private static String getCellValueAsString(Cell cell) { DataFormatter formatter = new DataFormatter(); return formatter.formatCellValue(cell); }
}
Giải thích:
DataFormattertự động chuyển đổi dữ liệu theo định dạng hiển thị trong Excel (định dạng số, ngày tháng).sheet.iterator()duyệt từng hàng,cellIterator()duyệt từng ô.
5.2. Đọc file XLS (HSSF)
import org.apache.poi.hssf.usermodel.HSSFWorkbook; public static void readXLS(String filePath) throws IOException { try (FileInputStream fis = new FileInputStream(filePath); Workbook workbook = new HSSFWorkbook(fis)) { // Tương tự như XSSF }
}
5.3. Đọc file lớn với SXSSF (streaming)
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.ss.usermodel.; public static void readLargeFile(String filePath) throws IOException { try (InputStream is = new FileInputStream(filePath); Workbook workbook = new SXSSFWorkbook(new XSSFWorkbook(is))) { Sheet sheet = workbook.getSheetAt(0); // Xử lý như bình thường, SXSSF tự động flush rows ra disk khi đạt giới hạn }
}
Lưu ý: SXSSF chỉ hỗ trợ viết file, đọc vẫn phải dùng XSSF. Tuy nhiên, bạn có thể đọc bằng
XSSFReaderđể tránh tải toàn bộ workbook vào bộ nhớ.
6. Đọc file Excel với EasyExcel
6.1. Định nghĩa POJO

Có thể bạn quan tâm: Cách Chuyển Đổi Bảng Html Trong React Sang Tệp Excel: Hướng Dẫn Toàn Diện Và Chi Tiết
import com.alibaba.excel.annotation.ExcelProperty; public class User { @ExcelProperty("Tên") private String name; @ExcelProperty("Tuổi") private Integer age; @ExcelProperty("Email") private String email; // getters & setters
}
6.2. Đọc dữ liệu
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener; import java.util.List; public class EasyExcelDemo { public static void main(String args) { String filePath = "users.xlsx"; EasyExcel.read(filePath, User.class, new PageReadListener<User>(list -> { // list: danh sách User trong một trang list.forEach(user -> System.out.println(user)); })).sheet().doRead(); }
}
Ưu điểm:
- Không cần xử lý từng ô, chỉ cần ánh xạ tới POJO.
- Hỗ trợ đọc file lớn với streaming (PageReadListener).
- Hỗ trợ ghi file nhanh.
6.3. Đọc dữ liệu tùy chỉnh (row/column index)
EasyExcel.read(filePath, new AnalysisEventListener<Map<Integer, Object>>() { @Override public void invoke(Map<Integer, Object> data, AnalysisContext context) { // data: key là columnIndex, value là giá trị System.out.println(data); } @Override public void doAfterAllAnalysed(AnalysisContext context) {}
}).sheet().doRead();
7. Xử lý dữ liệu phức tạp trong Excel
7.1. Định dạng ngày tháng
POI:
java if (DateUtil.isCellDateFormatted(cell)) { Date date = cell.getDateCellValue(); } else { Date date = DataFormatter.formatCellValue(cell, formatter); // chuyển thành string rồi parse }EasyExcel: Định nghĩa
@ExcelPropertyvớiconverter = DateConverter.class(tự viết converter).
7.2. Định dạng số tiền
- Sử dụng
DataFormattervới pattern"#,##0.00".
7.3. Đọc công thức
if (cell.getCellType() == CellType.FORMULA) { FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator(); CellValue cellValue = evaluator.evaluate(cell); // xử lý cellValue
}
7.4. Đọc dữ liệu có merge cells
CellRangeAddress mergedRegion = sheet.getMergedRegion(0);
int firstRow = mergedRegion.getFirstRow();
int lastRow = mergedRegion.getLastRow();
int firstCol = mergedRegion.getFirstColumn();
int lastCol = mergedRegion.getLastColumn();
8. Tối ưu hiệu năng và bộ nhớ
| Khía cạnh | Mẹo |
|---|---|
| Đọc file lớn | Sử dụng SXSSF (streaming) hoặc EasyExcel với PageReadListener. |
| Định dạng ngày | Cách DateUtil.isCellDateFormatted nhanh hơn DataFormatter. |
| Đọc nhiều sheet | Nếu chỉ cần một sheet, tránh gọi workbook.getSheetAt(0) nhiều lần. |
| Đóng tài nguyên | Luôn đóng FileInputStream và Workbook trong try-with-resources. |
| Đếm dòng nhanh | sheet.getLastRowNum() + sheet.getPhysicalNumberOfRows() (có thể trùng). |
| Giảm số lượng đối tượng POJO | Chỉ tạo POJO khi cần, tránh lưu trữ toàn bộ dữ liệu trong bộ nhớ. |
9. Xử lý lỗi và ngoại lệ
| Lỗi | Nguyên nhân | Giải pháp |
|---|---|---|
FileNotFoundException | Đường dẫn file sai hoặc không tồn tại | Kiểm tra đường dẫn, quyền đọc. |
EncryptedDocumentException | File được bảo vệ bằng mật khẩu | Sử dụng WorkbookFactory.create(is, password) |
IOException | Lỗi IO khi mở/đọc file | Đảm bảo file không bị khóa, có thể thực hiện retry. |
IllegalStateException: sheet is not found | Sheet không tồn tại | Kiểm tra tên sheet, số thứ tự. |
IndexOutOfBoundsException | Truy cập cell ngoài phạm vi | Kiểm tra row.getLastCellNum(). |
10. Ví dụ thực tế: Tải dữ liệu từ Excel vào cơ sở dữ liệu
Giả sử chúng ta có file employees.xlsx với cột: ID, Name, Position, Salary.
public class ImportEmployees { public static void main(String args) { String filePath = "employees.xlsx"; try (FileInputStream fis = new FileInputStream(filePath); Workbook workbook = new XSSFWorkbook(fis)) { Sheet sheet = workbook.getSheet("Sheet1"); for (Row row : sheet) { if (row.getRowNum() == 0) continue; // skip header Employee emp = new Employee(); emp.setId((int) row.getCell(0).getNumericCellValue()); emp.setName(row.getCell(1).getStringCellValue()); emp.setPosition(row.getCell(2).getStringCellValue()); emp.setSalary(row.getCell(3).getNumericCellValue()); // Ghi vào DB saveToDB(emp); } } catch (IOException e) { e.printStackTrace(); } } private static void saveToDB(Employee emp) { // JDBC hoặc JPA }
}
Tip: Đối với file lớn, nên batch insert với JDBC
addBatch().
11. Thêm tính năng: Ghi file Excel
11.1. Sử dụng POI
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("Report");
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("ID");
header.createCell(1).setCellValue("Name"); for (int i = 0; i < data.size(); i++) { Row row = sheet.createRow(i + 1); row.createCell(0).setCellValue(data.get(i).getId()); row.createCell(1).setCellValue(data.get(i).getName());
}
try (FileOutputStream fos = new FileOutputStream("report.xlsx")) { workbook.write(fos);
}
11.2. Sử dụng EasyExcel
EasyExcel.write("report.xlsx", User.class).sheet("Users").doWrite(userList);
12. Mẹo và best practice
- Sử dụng
DataFormatterkhi cần hiển thị dữ liệu gốc. Nếu bạn chỉ cần giá trị, dùngcell.getNumericCellValue(),cell.getStringCellValue()để tránh xử lý chuỗi. - Đọc file một lần, xử lý ngay. Tránh lưu trữ toàn bộ dữ liệu trong bộ nhớ nếu không cần.
- Sử dụng
try-with-resourcesđể tự động đóngInputStreamvàWorkbook. - Xử lý
MergedRegionkhi cần dữ liệu gạt ngang hoặc dọc. - Kiểm tra
CellTypetrước khi lấy giá trị. Không nên gọigetStringCellValue()trên cell kiểu số. - Đặt
sheet.getFirstRowNum()vàsheet.getLastRowNum()để biết phạm vi dữ liệu thực tế. - Định nghĩa POJO với
@ExcelPropertyđể tránh lỗi mapping khi tên cột thay đổi. - Sử dụng
ThreadPoolExecutorkhi đọc nhiều file đồng thời, tránh chặn thread chính.
13. Tổng kết
- Apache POI là thư viện chuẩn, hỗ trợ cả định dạng XLS và XLSX, nhưng có thể tốn bộ nhớ khi đọc file lớn.
- EasyExcel tối ưu cho thao tác đọc/ghi nhanh, đặc biệt khi làm việc với file lớn, nhờ streaming và API đơn giản.
- JExcelApi phù hợp khi chỉ cần xử lý các file XLS cũ và muốn thư viện nhẹ.
- Đối với file lớn, hãy sử dụng SXSSF hoặc EasyExcel với streaming.
- Luôn kiểm tra kiểu cell, xử lý ngày tháng, công thức, merge region đúng cách.
- Tối ưu bộ nhớ, đóng tài nguyên và xử lý lỗi cẩn thận.
Với những kiến thức và ví dụ trên, bạn đã có thể tự tin triển khai chức năng đọc file Excel trong dự án Java của mình, từ ứng dụng nhỏ đến hệ thống enterprise lớn. Happy coding!

Tiến sĩ Lê Thống Nhất sinh năm 1955 tại Nghệ An, là nhà giáo, nhà báo và doanh nhân trong lĩnh vực giáo dục. Ông từng giảng dạy Toán học tại Trường THPT Chuyên Phan Bội Châu và đảm nhiệm nhiều vai trò trong ngành giáo dục, từ viết sách, biên soạn tài liệu đến sáng lập các dự án hỗ trợ học tập trực tuyến.
Ông là người sáng lập BigSchool – nền tảng giáo dục trực tuyến kết nối giáo viên và học sinh cả nước. Ngoài ra, ông còn nổi tiếng với vai trò tác giả, diễn giả truyền cảm hứng và khách mời trên nhiều chương trình truyền hình, trong đó có “Ai là triệu phú” trên truyền hình VTV.
Trong suốt sự nghiệp, Tiến sĩ Lê Thống Nhất đã nhận nhiều giải thưởng giáo dục và được biết đến như một người luôn đổi mới, ứng dụng công nghệ vào dạy và học, góp phần lan tỏa tri thức và niềm say mê học tập cho thế hệ trẻ.
