POI導入導出Excel(HSSF格式,User Model方式)


1.POI說明

Apache POI是Apache軟件基金會的開源代碼庫,
POI提供對Microsoft Office格式檔案讀和寫的功能。

POI支持的格式:
HSSF - 提供讀寫Microsoft Excel格式檔案的功能。
XSSF - 提供讀寫Microsoft Excel OOXML格式檔案的功能。
HWPF - 提供讀寫Microsoft Word格式檔案的功能。
HSLF - 提供讀寫Microsoft PowerPoint格式檔案的功能。
HDGF - 提供讀寫Microsoft Visio格式檔案的功能。

其中Excel支持HSSF和XSSF兩種格式:
HSSF對應Excel 2003及以前版本生成的文件格式(.xls),
XSSF對應Excel 2007及之后版本生成的文件格式(.xlsx)。
本文僅介紹Excel文件的讀寫,
並且使用HSSF讀寫.xls格式的Excel文件。

2.HSSF說明

HSSF是Horrible Spread Sheet Format的縮寫,
即糟糕的表格格式。
HSSF為讀取操作提供了兩類API:
User Model,Event ModelEvent User Model
即"用戶模型", "事件模型"和"事件-用戶-模型"。

User Model是類似於Dom方式的解析,
API使用起來很簡單,
但是占用內存,處理效率低。
Event Model是類似於Sax方式的解析,
比User Model更節約內存,效率更高,
但是抽象程度相比User Model更低,
相比User Model功能更少,
API使用門檻也要高一些。
Event User Model是結合了上面的兩個優點,
基於Event Model的流解析方式進一步封裝,
提供了類似User Model更友好的操作方式。

學過Xml的都知道,
Dom解析就是將文件全部讀入內存,
對文件內部的結構進行建模成一顆Dom樹的過程。
下面是POI對Excel的建模的Dom樹結構:

本文下面僅介紹使用User Model方式,
操作HSSF(.xls)格式的文件,
其他方式請參考后續文章。

3.Jar包依賴

在pom.xml中添加如下依賴:

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.2</version>
</dependency>

4.Excel文件

現在有需要導入的city_date.xls,
內容如下:


5.Area對象

根據上面的Excel文件內容,
抽象出來Area對象,
其中屬性一一對應文件中列名。

package org.apache.poi;

import java.util.Date;

public class Area {

    /** 省份 */
    private String province;
    /** 城市 */
    private String city;
    /** 城市排名 */
    private Integer order;
    /** 城市紀念日 */
    private Date cityDay;
    /** 是否一線大城市 */
    private Boolean isBigCity;
    /** 城市描述 */
    private String description;

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public Integer getOrder() {
        return order;
    }

    public void setOrder(Integer order) {
        this.order = order;
    }

    public Date getCityDay() {
        return cityDay;
    }

    public void setCityDay(Date cityDay) {
        this.cityDay = cityDay;
    }

    public Boolean getIsBigCity() {
        return isBigCity;
    }

    public void setIsBigCity(Boolean isBigCity) {
        this.isBigCity = isBigCity;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public String toString() {
        return "Area [province=" + province + ", city=" + city + ", order=" + order + ", cityDay=" + cityDay
                + ", isBigCity=" + isBigCity + ", description=" + description + "]";
    }

}

6.導入Excel

解析.xls格式文件,
轉換為內存中的Java對象。

public static List<Area> importExcel() throws Exception {
    InputStream fileIn = null;
    HSSFWorkbook workbook = null;
    try {
        // 1.創建文件輸入流
        fileIn = new FileInputStream("city_date.xls");
        // 2.創建Excel工作簿對象
        workbook = new HSSFWorkbook(fileIn);
        // 校驗excel中的工作表是否存在
        int numberOfSheets = workbook.getNumberOfSheets();
        if (numberOfSheets <= 0) {
            return null;
        }
        // 3.獲取Excel工作表對象
        HSSFSheet sheetAt = workbook.getSheetAt(0);
        ArrayList<Area> citys = new ArrayList<>();
        // 工作表中至少要有一行數據
        if (sheetAt.getLastRowNum() < 0) {
            return null;
        }

        // 4.循環讀取表格數據
        for (Row row : sheetAt) {
            // 首行(即表頭)不讀取,后面可以校驗表頭
            if (row.getRowNum() == 0) {
                continue;
            }
            // 一行至少有6列信息,無法解析需要跳過
            if (row.getLastCellNum() < 5) {
                continue;
            }
            // 讀取當前行中單元格數據,索引從0開始
            String province = row.getCell(0).getStringCellValue();
            String cityName = row.getCell(1).getStringCellValue();
            Integer order = (int) row.getCell(2).getNumericCellValue();
            Date cityDay = row.getCell(3).getDateCellValue();
            Boolean isBigCity = row.getCell(4).getBooleanCellValue();
            String description = row.getCell(5).getStringCellValue();

            Area city = new Area();
            city.setProvince(province);
            city.setCity(cityName);
            city.setOrder(order);
            city.setCityDay(cityDay);
            city.setIsBigCity(isBigCity);
            city.setDescription(description);
            citys.add(city);

            return citys;
        }
    } finally {
        // 5.關閉流
        if (fileIn != null) {
            fileIn.close();
        }
        if (workbook != null) {
            workbook.close();
        }
    }
    return null;
}

7.導出Excel

將內存中的Java對象,
寫入到.xls格式文件。
導出后的文件即為上面第4步的city_date.xls。

public static void exportExcel() throws Exception {
    HSSFWorkbook workbook = null;
    FileOutputStream fileOut = null;
    try {
        // 1.需要導出的數據
        List<Area> citys = new ArrayList<>();
        Area changzhou = new Area();
        changzhou.setProvince("江蘇省");
        changzhou.setCity("常州市");
        changzhou.setOrder(88);
        changzhou.setCityDay(new Date());
        changzhou.setIsBigCity(false);
        changzhou.setDescription("常州是個美麗的旅游和實業城市~");
        citys.add(changzhou);

        // 2.在內存中創建一個excel文件
        workbook = new HSSFWorkbook();
        // 3.創建工作簿
        HSSFSheet sheet = workbook.createSheet("city sheet");
        // 4.創建標題行
        HSSFRow titlerRow = sheet.createRow(0);
        titlerRow.createCell(0).setCellValue("省份");
        titlerRow.createCell(1).setCellValue("城市");
        titlerRow.createCell(2).setCellValue("排名");
        titlerRow.createCell(3).setCellValue("紀念日");
        titlerRow.createCell(4).setCellValue("大城市");
        titlerRow.createCell(5).setCellValue("描述");

        // 獲取最后一行的行號
        int lastRowNum = sheet.getLastRowNum();
        // 5.遍歷數據,創建數據行
        for (Area city : citys) {
            // 在最后一行后面添加新的一行
            lastRowNum++;
            HSSFRow dataRow = sheet.createRow(lastRowNum);
            dataRow.createCell(0).setCellValue(city.getProvince());
            dataRow.createCell(1).setCellValue(city.getCity());
            dataRow.createCell(2).setCellValue(city.getOrder());

            HSSFCell dateCell = dataRow.createCell(3);
            setDateStyle(dateCell, workbook);
            dateCell.setCellValue(city.getCityDay());

            dataRow.createCell(4).setCellValue(city.getIsBigCity());
            dataRow.createCell(5).setCellValue(city.getDescription());
        }
        for (int i = 0; i <= 5; i++) {
            // 設置自適應列寬,必須數據全部插入后才調用
            sheet.autoSizeColumn(i);
        }
        // 6.指定輸出的文件名
        String fileName = "city_date.xls";
        fileOut = new FileOutputStream(fileName);
        // 7.寫文件
        workbook.write(fileOut);
    } finally {
        // 8.關閉流
        if (workbook != null) {
            workbook.close();
        }
        if (fileOut != null) {
            fileOut.close();
        }
    }
}

private static void setDateStyle(HSSFCell cell, HSSFWorkbook wb) {
    HSSFDataFormat format = wb.createDataFormat();
    HSSFCellStyle style = wb.createCellStyle();
    style.setDataFormat(format.getFormat("yyyy年MM月dd日"));
    cell.setCellStyle(style);
}

8.頭文件說明

上面的代碼使用到的類如下:

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;

9.參考文章

Busy Developers' Guide to HSSF and XSSF Features
POI操作Excel
Java POI操作Excel(User Model)
Java使用POI操作Excel


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM