Apache POI มีโมดูลแยกกันสำหรับจัดการไฟล์ Excel แต่ละเวอร์ชัน:
- XLS (Excel 97-2003):
- ฟอร์แมต: เป็นไฟล์แบบ Binary ที่เรียกว่า HSSF (Horrible Spreadsheet Format)
- คลาสหลักที่ใช้:
HSSFWorkbookHSSFSheetHSSFRowHSSFCell
- XLSX (Excel 2007 และใหม่กว่า):
- ฟอร์แมต: เป็นไฟล์แบบ XML-based ที่เรียกว่า XSSF (XML Spreadsheet Format) ซึ่งเป็นส่วนหนึ่งของมาตรฐาน Office Open XML
- คลาสหลักที่ใช้:
XSSFWorkbookXSSFSheetXSSFRowXSSFCell
ทีนี้ถ้าเราต้องการ support ไฟล์ทั้ง 2 ชนิด เพราะ เราไม่รู้ว่า user จะได้ไฟล์แบบไหนมา แต่ถ้าต้องมานั่งเขียนรองรับทั้ง 2 แบบก็กระไรอยู่ ซึ่ง Apache POI ก็มี Class WorkbookFactory มาให้แล้ว – เพิ่งจะรู้
หลักการทำงาน:
WorkbookFactoryเป็นคลาสอรรถประโยชน์ที่จะตรวจสอบเนื้อหาของไฟล์ (ไม่ใช่แค่นามสกุล) แล้วสร้างอ็อบเจกต์ของคลาสที่เหมาะสม (HSSFWorkbookหรือXSSFWorkbook) ให้เราโดยอัตโนมัติ- ผลลัพธ์ที่ได้จาก
WorkbookFactory.create()จะเป็นอ็อบเจกต์ชนิดWorkbookซึ่งเป็น Interface กลาง - หลังจากนั้น เราสามารถเขียนโค้ดเพื่อวนลูปอ่านข้อมูลโดยใช้ Interface
Sheet,Row,Cellได้เลย ซึ่งโค้ดส่วนนี้จะทำงานได้กับไฟล์ทั้งสองชนิดโดยไม่ต้องเปลี่ยนแปลงอะไร
import org.apache.poi.ss.usermodel.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class UniversalExcelReader {
public void readExcelFile(String filePath) {
try (FileInputStream fis = new FileInputStream(new File(filePath));
// 1. ใช้ WorkbookFactory สร้าง Workbook จากไฟล์
// ไม่ต้องสนใจว่าเป็น XLS หรือ XLSX, Factory จัดการให้
Workbook workbook = WorkbookFactory.create(fis)) {
// 2. ดึง Sheet แรกออกมา (เราได้อ็อบเจกต์เป็น Interface 'Sheet')
Sheet sheet = workbook.getSheetAt(0);
// 3. วนลูปอ่านข้อมูลโดยใช้ Interface 'Row' และ 'Cell'
// โค้ดส่วนนี้เหมือนกันทั้งหมด ไม่ว่าต้นทางจะเป็นไฟล์ชนิดใด
for (Row row : sheet) {
for (Cell cell : row) {
// พิมพ์ค่าใน Cell ออกมา โดยจัดการตามประเภทของข้อมูล
printCellValue(cell);
}
System.out.println(); // ขึ้นบรรทัดใหม่เมื่อจบแถว
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void printCellValue(Cell cell) {
switch (cell.getCellType()) {
case STRING:
System.out.print(cell.getStringCellValue() + "\t");
break;
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
System.out.print(cell.getDateCellValue() + "\t");
} else {
System.out.print(cell.getNumericCellValue() + "\t");
}
break;
case BOOLEAN:
System.out.print(cell.getBooleanCellValue() + "\t");
break;
case FORMULA:
System.out.print(cell.getCellFormula() + "\t");
break;
case BLANK:
System.out.print("[BLANK]\t");
break;
default:
System.out.print("[UNKNOWN]\t");
}
}
}
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version> </dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version> </dependency>
</dependencies>
เพิ่มเติมสำหรับการ แปลง ค่า column name (A, B, C, …) ให้เป็น index (1, 2, 3, …)
import org.apache.poi.ss.util.CellReference;
public class ExcelColumnConverter {
public static void main(String[] args) {
String columnLetter1 = "A";
String columnLetter2 = "Z";
String columnLetter3 = "AA";
String columnLetter4 = "AZ";
// แปลง "AA" (คอลัมน์ที่ 27)
int zeroBasedIndex = CellReference.convertColStringToIndex(columnLetter3); // จะได้ 26
int oneBasedIndex = zeroBasedIndex + 1; // บวก 1 เพื่อให้ได้ 27
System.out.println("'" + columnLetter1 + "' คือคอลัมน์ที่ " + (CellReference.convertColStringToIndex(columnLetter1) + 1));
System.out.println("'" + columnLetter2 + "' คือคอลัมน์ที่ " + (CellReference.convertColStringToIndex(columnLetter2) + 1));
System.out.println("'" + columnLetter3 + "' คือคอลัมน์ที่ " + oneBasedIndex);
System.out.println("'" + columnLetter4 + "' คือคอลัมน์ที่ " + (CellReference.convertColStringToIndex(columnLetter4) + 1));
}
}

