最近協助朋友開發 Excel 導出功能,面對複雜的表格樣式與儲存格合併需求,確實令人頭疼。回想初入職場時處理 Word 轉 HTML 的經驗,複雜文件轉換總是充滿挑戰。雖然從未實作過 Excel 導出,但憑藉查閱官方文檔與網路資源,從晚間八點開始摸索,歷經三小時與無數實驗,終於攻克關鍵技術難點。本文將詳細記錄實作過程、踩坑經驗與核心代碼,幫助開發者快速掌握 POI 複雜 Excel 導出技術。
網路上搜尋 "hssfrow 合併儲存格" 可找到兩篇關鍵參考資料:
初期嘗試直接運行參考一的代碼卻持續報錯,核心問題在於 Region 類別已過時。經查閱官方文檔並結合參考二修正,採用 CellRangeAddress 類別替代,成功解決合併儲存格功能。
package com.mouse.moon.frepoi;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
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.hssf.util.HSSFColor;
import org.apache.poi.ss.util.CellRangeAddress;
/**
* 複雜儲存格合併測試類
* 演示多行多列合併、樣式設定、動態表頭生成
*/
public class TestFreMergedCells {
public static void main(String[] args) throws IOException {
// 1. 建立工作簿與工作表
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("new sheet");
// 2. 基礎儲存格建立與合併示範
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell(0);
cell.setCellValue("第一行第二行合併,第一列");
// 合併第一列的第1-2行 (0-based: 行0-1, 列0)
sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 0));
// 合併第二列的第1-2行 (0-based: 行0-1, 列1)
sheet.addMergedRegion(new CellRangeAddress(0, 1, 1, 1));
// 3. 字體與樣式設定
HSSFFont font = wb.createFont();
font.setFontHeightInPoints((short) 10);
font.setFontName("新宋體");
font.setColor(HSSFColor.BLUE.index);
font.setBoldweight((short) 0.8);
HSSFCellStyle style = wb.createCellStyle();
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
style.setFont(font);
style.setWrapText(true);
// 邊框樣式設定
style.setBorderTop(HSSFCellStyle.BORDER_DOUBLE);
style.setBorderLeft(HSSFCellStyle.BORDER_DOUBLE);
style.setTopBorderColor(HSSFColor.GOLD.index);
style.setLeftBorderColor(HSSFColor.PLUM.index);
cell.setCellStyle(style);
// 4. 多行多列合併核心邏輯
HSSFRow rowOther = sheet.createRow(0);
HSSFCell cellOther = rowOther.createCell(4);
cellOther.setCellValue("多行多列合併");
// 合併第1-3行、第5-10列 (0-based: 行0-2, 列4-9)
sheet.addMergedRegion(new CellRangeAddress(0, 2, 4, 9));
// 5. 一般資料寫入
HSSFRow row2 = sheet.createRow(3);
HSSFCell cell2 = row2.createCell(3);
cell2.setCellValue("只是一個資料而已");
// 6. 檔案輸出
FileOutputStream fileOut = new FileOutputStream("/Mouse/poi/test.xls");
wb.write(fileOut);
fileOut.close();
}
}
經實測發現關鍵規則:合併區域的數據必須寫入左上角起始儲存格。以此代碼為例:
HSSFRow rowOther = sheet.createRow(0);
HSSFCell cellOther = rowOther.createCell(4);
cellOther.setCellValue("多行多列合併");
sheet.addMergedRegion(new CellRangeAddress(0, 2, 4, 9));
此處建立第1行(索引0)、第5列(索引4)的儲存格並寫入數據,合併範圍涵蓋第1-3行、第5-10列。若嘗試在合併區域內其他位置寫入(如第2行第5列),導出的 Excel 將顯示空白。
實際專案中表頭與行數均為動態生成,最終導出效果如下:

解決技術難題的關鍵在於:找準切入點、保持冷靜試錯、善用官方文檔。許多看似棘手的問題,實際操作後往往沒有想像中困難。這次經驗也提醒自己:持續學習、多閱源碼、計劃執行,技術成長自會水到渠成。