AdSense

網頁

2025/3/13

Java HSSFWorkbook寫出xls檔範例

使用Apache POI的HSSFWorkbook搭配xls模板將資料寫出xls檔範例。


xls模板

範例的xls模板是一個只有3欗2列的xls檔內容如下,第1列為標頭,第2列開始為資料列。

+----+------+-----+
| id | name | age |
+----+------+-----+
|    |      |     |
+----+------+-----+


範例

package com.abc.demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 產生xls檔服務
 */
@Service
public class XlsService {
    private static Logger log = LoggerFactory.getLogger(XlsService.class);
    
    /**
     * 產生xls資料檔
     * @param list 資料清單
     */
    public void create(List<Map<String, Object>> list) {
        if (CollectionUtils.isEmpty(list)) {
            throw new IllegalArgumentException("list is empty");
        }

        try (
                FileInputStream fis = new FileInputStream(getTemplateFilePath()); // 讀取xls模板為輸入流
                HSSFWorkbook wb = new HSSFWorkbook(fis); // 將xls模板讀入工作簿
                FileOutputStream fos = new FileOutputStream(getOutputFilePath()); // 取得輸出檔案的輸出流
        ) { 
            setData(wb, list);
            wb.write(fos); // 將工作簿內容寫出至輸出檔案
        } catch (Exception e) {
            log.error("create xls file error", e);
        }

    }
    
    /**
     * 第一筆資料列索引
     */
    private static final int FIRST_DATA_ROW_INDEX = 1; // 從第2列開始
    
    /**
     * 填入資料
     * @param wb 工作簿
     * @param list 資料清單
     */
    private void setData(HSSFWorkbook wb, List<Map<String, Object>> list) {
        HSSFSheet sheet = wb.getSheetAt(0);
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> rowData = list.get(i); // 取得一列的資料
            
            int rowIndex = FIRST_DATA_ROW_INDEX + i;
            HSSFRow r = sheet.getRow(rowIndex);
            if (r == null) {
                r = createRow(sheet, rowIndex);
            }
            
            r.getCell(0).setCellValue(rowData.get("id"));
            r.getCell(1).setCellValue(rowData.get("name"));
            r.getCell(2).setCellValue(rowData.get("age"));

        }
        
    }
    
    /** 資料欄位數 */
    private static final int COL_NUM = 3;
    
    /**
     * 新增一列
     * @param sheet 工作表
     * @param rowIndex 新增一列的索引
     * @return 新增的一列
     */
    private HSSFRow createRow(HSSFSheet sheet, int rowIndex) {
        HSSFRow pr = sheet.getRow(rowIndex - 1); // 取得前一列
        HSSFRow r = sheet.createRow(rowIndex); // 建立新一列
        
        // 設定資料列每一欗的儲存格樣式
        for (int j = 0; j < COL_NUM; j++) {
            HSSFCell c = r.createCell(j);
            HSSFCell pc = pr.getCell(j);
            HSSFCellStyle pcs = pc.getCellStyle(); // 取得上一列的樣式
            c.setCellStyle(pcs); // 設定新一列的樣式為上一列的樣式
        }

        return r;
    }
   
}

沒有留言:

AdSense