- Sản phẩm & Dịch vụSản phẩm & Dịch vụ
- Giải phápGiải pháp
- Bảng giáBảng giá
- Công tyCông ty
- Tài liệuTài liệu
vi
vi
Chuyên mục với các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.
Web Developer
I’m passionate about web development and sharing my insights through articles, with over 8 years of experience. I hope these sharings inspire you and help build a strong web development community. @#@ Tôi đam mê phát triển web và chia sẻ những hiểu biết của mình thông qua các bài viết, với hơn 8 năm kinh nghiệm. Tôi hy vọng những chia sẻ này sẽ truyền cảm hứng cho các bạn và giúp xây dựng một cộng đồng phát triển web mạnh mẽ.
Thảo luận (0)
Đăng nhập để thảo luận
Đôi khi chúng ta cần đọc dữ liệu hoặc tạo báo cáo ở định dạng Excel, chủ yếu cho mục đích kinh doanh hoặc tài chính. Vì Java không có công cụ tích hợp sẵn để làm việc với các file Excel nên chúng ta sẽ cần dùng các API mã nguồn mở cho mục đích này.

Cụ thể, JExcel và Apache POI là hai lựa chọn được cộng đồng Java đề xuất nhiều nhất. Sau khi tìm hiểu kỹ hơn, chúng tôi nhận thấy Apache POI là lựa chọn tối hơn ưu vì một vài lý do:
Apache POI hỗ trợ các tài liệu Microsoft Excel một cách tuyệt vời với khả năng xử lý cả hai định dạng bảng tính là xls và xlsx. Dưới đây là một số điểm quan trọng về API này:
Nếu bạn đang sử dụng Maven, hãy thêm các dependency dưới đây cho Apache POI:
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.10-FINAL</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.10-FINAL</version> </dependency>
Phiên bản Apache POI tại thời điểm viết bài là 3.10-FINAL. Nếu bạn có ứng dụng Java chạy riêng, thêm các file JAR trong hình dưới đây.

Giả sử chúng ta có một file Excel tên là “Sample.xlsx” gồm hai sheet và chứa dữ liệu như hình minh họa bên dưới. Chúng ta muốn đọc file Excel này và tạo ra một danh sách các đối tượng Country. Sheet1 có một số dữ liệu không liên quan. Chúng ta sẽ bỏ qua phần dữ liệu này khi đọc nó.


Code cho Java bean Country.java của chúng ta như sau:
package com.journaldev.excel.read;public class Country {
private String name; private String shortCode; public Country(String n, String c){ this.name=n; this.shortCode=c; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getShortCode() { return shortCode; } public void setShortCode(String shortCode) { this.shortCode = shortCode; } @Override public String toString(){ return name + "::" + shortCode; }}
Chương trình ví dụ sử dụng Apache POI để đọc file Excel và lưu dữ liệu vào danh sách các đối tượng Country có code như dưới:
package com.journaldev.excel.read;import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ReadExcelFileToList {
public static List<Country> readExcelData(String fileName) { List<Country> countriesList = new ArrayList<Country>(); try { //Create the input stream from the xlsx/xls file FileInputStream fis = new FileInputStream(fileName); //Create Workbook instance for xlsx/xls file input stream Workbook workbook = null; if(fileName.toLowerCase().endsWith("xlsx")){ workbook = new XSSFWorkbook(fis); }else if(fileName.toLowerCase().endsWith("xls")){ workbook = new HSSFWorkbook(fis); } //Get the number of sheets in the xlsx file int numberOfSheets = workbook.getNumberOfSheets(); //loop through each of the sheets for(int i=0; i < numberOfSheets; i++){ //Get the nth sheet from the workbook Sheet sheet = workbook.getSheetAt(i); //every sheet has rows, iterate over them Iterator<Row> rowIterator = sheet.iterator(); while (rowIterator.hasNext()) { String name = ""; String shortCode = ""; //Get the row object Row row = rowIterator.next(); //Every row has columns, get the column iterator and iterate over them Iterator<Cell> cellIterator = row.cellIterator(); while (cellIterator.hasNext()) { //Get the Cell object Cell cell = cellIterator.next(); //check the cell type and process accordingly switch(cell.getCellType()){ case Cell.CELL_TYPE_STRING: if(shortCode.equalsIgnoreCase("")){ shortCode = cell.getStringCellValue().trim(); }else if(name.equalsIgnoreCase("")){ //2nd column name = cell.getStringCellValue().trim(); }else{ //random data, leave it System.out.println("Random data::"+cell.getStringCellValue()); } break; case Cell.CELL_TYPE_NUMERIC: System.out.println("Random data::"+cell.getNumericCellValue()); } } //end of cell iterator Country c = new Country(name, shortCode); countriesList.add(c); } //end of rows iterator } //end of sheets for loop //close file input stream fis.close(); } catch (IOException e) { e.printStackTrace(); } return countriesList; } public static void main(String args[]){ List<Country> list = readExcelData("Sample.xlsx"); System.out.println("Country List\\n"+list); }}
Chương trình này gồm các bước chính sau:
Workbook phù hợp với loại file: XSSFWorkbook cho định dạng .xlsx và HSSFWorkbook cho định dạng .xls. Lưu ý rằng chúng ta có thể tạo một lớp wrapper sử dụng Factory pattern để lấy instance Workbook dựa trên tên file.getNumberOfSheets() của Workbook để lấy tổng số sheet, sau đó dùng vòng lặp for để duyệt qua từng sheet. Lấy instance Sheet bằng phương thức getSheetAt(int i).Row rồi từ đó lấy iterator cho Cell để truy cập đối tượng Cell. Ở đây Apache POI sử dụng Iterator pattern.switch-case để xác định kiểu dữ liệu của Cell và xử lý sao cho phù hợp.Khi chạy chương trình ví dụ Apache POI ở trên, output trên console sẽ như sau:
Random data::1.0 Random data::2.0 Random data::3.0 Random data::4.0 Country List [India::IND, Afghanistan::AFG, United States of America::USA, Anguilla::AIA, Denmark ::DNK, Dominican Republic ::DOM, Algeria ::DZA, Ecuador ::ECU]
Việc ghi file Excel bằng Apache POI cũng tương tự như việc đọc, chỉ khác là ở đây chúng ta cần tạo Workbook trước. Sau đó, ta tạo các sheet, row, cell và gán giá trị cho chúng, rồi dùng FileOutputStream để ghi Workbook ra file.
Chúng ta hãy xem một ví dụ Apache POI đơn giản, trong đó ta sẽ sử dụng danh sách các đối tượng Country từ ví dụ đọc ở trên để lưu vào một sheet của một file Excel khác.
package com.journaldev.excel.read;import java.io.FileOutputStream; import java.util.Iterator; import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class WriteListToExcelFile {
public static void writeCountryListToFile(String fileName, List<Country> countryList) throws Exception{ Workbook workbook = null; if(fileName.endsWith("xlsx")){ workbook = new XSSFWorkbook(); }else if(fileName.endsWith("xls")){ workbook = new HSSFWorkbook(); }else{ throw new Exception("invalid file name, should be xls or xlsx"); } Sheet sheet = workbook.createSheet("Countries"); Iterator<Country> iterator = countryList.iterator(); int rowIndex = 0; while(iterator.hasNext()){ Country country = iterator.next(); Row row = sheet.createRow(rowIndex++); Cell cell0 = row.createCell(0); cell0.setCellValue(country.getName()); Cell cell1 = row.createCell(1); cell1.setCellValue(country.getShortCode()); } //lets write the excel data to file now FileOutputStream fos = new FileOutputStream(fileName); workbook.write(fos); fos.close(); System.out.println(fileName + " written successfully"); } public static void main(String args[]) throws Exception{ List<Country> list = ReadExcelFileToList.readExcelData("Sample.xlsx"); WriteListToExcelFile.writeCountryListToFile("Countries.xls", list); }}
Khi chạy ví dụ ở trên, file Excel được tạo ra sẽ có dạng như hình minh họa bên dưới.

Đôi khi chúng ta cần xử lý các file Excel phức tạp chứa nhiều công thức. Hãy cùng xem một ví dụ Apache POI đơn giản để đọc nội dung công thức của một cell cũng như giá trị được tính toán từ công thức đó.

package com.journaldev.excel.read;import java.io.FileInputStream; import java.io.IOException; import java.util.Iterator;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ReadExcelFormula {
public static void readExcelFormula(String fileName) throws IOException{ FileInputStream fis = new FileInputStream(fileName); //assuming xlsx file Workbook workbook = new XSSFWorkbook(fis); Sheet sheet = workbook.getSheetAt(0); Iterator<Row> rowIterator = sheet.iterator(); while (rowIterator.hasNext()) { Row row = rowIterator.next(); Iterator<Cell> cellIterator = row.cellIterator(); while (cellIterator.hasNext()) { Cell cell = cellIterator.next(); switch(cell.getCellType()){ case Cell.CELL_TYPE_NUMERIC: System.out.println(cell.getNumericCellValue()); break; case Cell.CELL_TYPE_FORMULA: System.out.println("Cell Formula="+cell.getCellFormula()); System.out.println("Cell Formula Result Type="+cell.getCachedFormulaResultType()); if(cell.getCachedFormulaResultType() == Cell.CELL_TYPE_NUMERIC){ System.out.println("Formula Value="+cell.getNumericCellValue()); } } } } } public static void main(String args[]) throws IOException { readExcelFormula("FormulaMultiply.xlsx"); }}
Khi chạy ví dụ ở trên, chúng ta sẽ nhận được output như sau:
1.0 2.0 3.0 4.0 Cell Formula=A1*A2*A3*A4 Cell Formula Result Type=0 Formula Value=24.0
Đôi khi, chúng ta cần thực hiện một số phép tính rồi mới ghi giá trị vào cell. Ta có thể sử dụng công thức của Excel để thực hiện việc tính toán này. Cách này sẽ giúp đảm bảo tính chính xác cao hơn, vì giá trị của cell chứa công thức sẽ tự động cập nhật nếu các cell tham chiếu trong công thức bị thay đổi.
Hãy xem một ví dụ đơn giản về cách ghi công thức vào file Excel bằng Apache POI API.
package com.journaldev.excel.read;import java.io.FileOutputStream; import java.io.IOException;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class WriteExcelWithFormula {
public static void writeExcelWithFormula(String fileName) throws IOException{ Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Numbers"); Row row = sheet.createRow(0); row.createCell(0).setCellValue(10); row.createCell(1).setCellValue(20); row.createCell(2).setCellValue(30); //set formula cell row.createCell(3).setCellFormula("A1*B1*C1"); //lets write to file FileOutputStream fos = new FileOutputStream(fileName); workbook.write(fos); fos.close(); System.out.println(fileName + " written successfully"); } public static void main(String[] args) throws IOException { writeExcelWithFormula("Formulas.xlsx"); }}
File Excel được tạo ra từ chương trình trên sẽ có dạng như hình bên dưới.

Trên đây là toàn bộ nội dung hướng dẫn về Apache POI để làm việc với file Excel. Bạn có thể tìm hiểu thêm các tính năng khác của Apache POI bằng cách xem qua tài liệu chính thức về các class và method của thư viện này. Chúc bạn nhanh chóng làm chủ Apache POI và các khả năng mà nó mang lại.