Apache POI สำหรับ อ่านเขียนไฟล์ XLS, XLSX

Apache POI สำหรับ อ่านเขียนไฟล์ XLS, XLSX

Apache POI มีโมดูลแยกกันสำหรับจัดการไฟล์ Excel แต่ละเวอร์ชัน:

  1. XLS (Excel 97-2003):
    • ฟอร์แมต: เป็นไฟล์แบบ Binary ที่เรียกว่า HSSF (Horrible Spreadsheet Format)
    • คลาสหลักที่ใช้:
      • HSSFWorkbook
      • HSSFSheet
      • HSSFRow
      • HSSFCell
  2. XLSX (Excel 2007 และใหม่กว่า):
    • ฟอร์แมต: เป็นไฟล์แบบ XML-based ที่เรียกว่า XSSF (XML Spreadsheet Format) ซึ่งเป็นส่วนหนึ่งของมาตรฐาน Office Open XML
    • คลาสหลักที่ใช้:
      • XSSFWorkbook
      • XSSFSheet
      • XSSFRow
      • XSSFCell

ทีนี้ถ้าเราต้องการ 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));
    }
}

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *