如果你已經會用 C# 操作 Excel,下一步就是學習如何進行格式設定。本篇 C# NPOI 教學,將介紹如何使用 NPOI 套件來調整 Excel 樣式,例如字體、顏色、欄寬與儲存格格式,讓你的報表不只是能用,還能更專業。
在C# 操作 Excel 教學|自動產生報表完整實作(.NET)(NPOI)|C# Excel 系列 我們收到生產部同事們自動產生Excel檔案的需求

ChatGpt的範例檔產出的格式如下

現在我們就開始從範例檔深入了解程式的運作。
開始程式進階調整修改
1 . 開啟前一篇文章建立的程式
找到button1的進入點
private void button1_Click(object sender, EventArgs e)
如專案開啟時沒有自動幫你開啟頁面,只需要再方案總管對著Form1.cs右鍵,選擇檢視程式碼,就會跳出Form1.cs的程式碼頁面

2 . 程式碼研究
private void button1_Click(object sender, EventArgs e)
{
IWorkbook workbook = new XSSFWorkbook();
ISheet sheet = workbook.CreateSheet("Sheet1");
IRow headerRow = sheet.CreateRow(0);
headerRow.CreateCell(0).SetCellValue("ID");
headerRow.CreateCell(1).SetCellValue("Name");
headerRow.CreateCell(2).SetCellValue("Age");
IRow row1 = sheet.CreateRow(1);
row1.CreateCell(0).SetCellValue(1);
row1.CreateCell(1).SetCellValue("John Doe");
row1.CreateCell(2).SetCellValue(30);
IRow row2 = sheet.CreateRow(2);
row2.CreateCell(0).SetCellValue(2);
row2.CreateCell(1).SetCellValue("Jane Smith");
row2.CreateCell(2).SetCellValue(25);
using (FileStream fs = new FileStream("exportedData.xlsx", FileMode.Create, FileAccess.Write))
{
workbook.Write(fs);
}
MessageBox.Show("Excel 文件已成功生成!");
}
程式碼 第 4 行:
IWorkbook workbook = new XSSFWorkbook();
IWorkbook 先跟程式宣告我們要一個Excel的工作簿,名稱就叫做workbook,屬於 XSSFWorkbook()這個型別。
IWorkbook XSSFWorkbook()這兩個沒什麼特別意思,就只是我們用NPOI要建Excel時,第一步就是要建立一個工作簿。NPOI套件規定建立工作簿要下
IWorkbook workbook = new XSSFWorkbook();這個指令,就會出現一個工作簿。
程式碼 第 5 行:
ISheet sheet = workbook.CreateSheet("Sheet1");
有了工作簿以後我們要在上面建立一個Sheet工作表,這整段程式碼也只是固定的格式,唯一需要注意的是"Sheet1",這個我們可以自己取想要的名稱,當這行指令下完就會產生Excel的工作表,如下圖紅框處,就會出現一個Sheet1的工作表,如果命名為Sheet2到時候紅框處就會顯示Sheet2。到這一步你就會發現程式其實是很直覺並且視覺化的。

程式碼 第 8 行:
IRow headerRow = sheet.CreateRow(0);
有了工作表後,我們要在工作表裡面開始把每列(Row)的資料建立起來,透過第5行建立出來的sheet這個工作表,我們用sheet.CreateRow(0)建立出第一列並且命名為headerRow。
程式碼 第 9-11行:
headerRow.CreateCell(0).SetCellValue("ID");
headerRow.CreateCell(1).SetCellValue("Name");
headerRow.CreateCell(2).SetCellValue("Age");
建立出第一列headerRow後,我們要對列裡面的每一欄(Cell)設定值,這三行程式碼就是分別對第一列的A欄、B欄、C欄設定,先透過CreateCell建立Cell,在用SetCellValue設定裡面的值,這三行設定好後我們就有表頭了,分別是ID、Name、Age。
程式碼 第 14-22行:
IRow row1 = sheet.CreateRow(1);
row1.CreateCell(0).SetCellValue(1);
row1.CreateCell(1).SetCellValue("John Doe");
row1.CreateCell(2).SetCellValue(30);
IRow row2 = sheet.CreateRow(2);
row2.CreateCell(0).SetCellValue(2);
row2.CreateCell(1).SetCellValue("Jane Smith");
row2.CreateCell(2).SetCellValue(25);
這裡就很簡單,依據程式碼 第 8-11 行 舉一反三就會知道這些程式碼是在建立第二、三列,然後設定裡面的資料。
程式碼 第 25-29行:
using (FileStream fs = new FileStream("exportedData.xlsx", FileMode.Create, FileAccess.Write))
{
workbook.Write(fs);
}
這個也是固定的用法,把我們的工作簿workbook的內容輸出成xlsx檔案,檔名為exportedData。
程式碼 第 30行:
MessageBox.Show("Excel 文件已成功生成!");
這個只是跳一個訊息告訴我們檔案產生好了。
3 . 依據需求調整範例程式碼
在研究完範例程式碼後你就會發現,原來程式很多都是既定的格式只要直接複製貼上。真正需要我們自己去調整的其實只有要產出來的內容,或者是一些計算的邏輯等等。目前我們只要調整範例程式碼的 8 - 22行,調整成符合使用者想要的Excel內容就完成開發工作了。
表頭調整:
(範例版)
IRow headerRow = sheet.CreateRow(0);
headerRow.CreateCell(0).SetCellValue("ID");
headerRow.CreateCell(1).SetCellValue("Name");
headerRow.CreateCell(2).SetCellValue("Age");
(新版)
IRow headerRow = sheet.CreateRow(0);
headerRow.CreateCell(0).SetCellValue("生產日期");
headerRow.CreateCell(1).SetCellValue("出貨日期");
headerRow.CreateCell(2).SetCellValue("貨品名稱");
headerRow.CreateCell(3).SetCellValue("出貨數量");
headerRow.CreateCell(4).SetCellValue("貨品價格");
headerRow.CreateCell(5).SetCellValue("生產人員");
我們前面三個Cell只需要把SetCellValue裡面的名稱改成正確的即可。因為範例程式碼只有三欄,使用者需要的表頭是六個,所以我們自己再增加三個Cell 3、4、5,SetCellValue填入正確的表頭名稱。
表身調整:
(範例版)
IRow row1 = sheet.CreateRow(1);
row1.CreateCell(0).SetCellValue(1);
row1.CreateCell(1).SetCellValue("John Doe");
row1.CreateCell(2).SetCellValue(30);
IRow row2 = sheet.CreateRow(2);
row2.CreateCell(0).SetCellValue(2);
row2.CreateCell(1).SetCellValue("Jane Smith");
row2.CreateCell(2).SetCellValue(25);
(新版)
IRow row1 = sheet.CreateRow(1);
row1.CreateCell(0).SetCellValue("20250901");
row1.CreateCell(1).SetCellValue("20250901");
row1.CreateCell(2).SetCellValue("測試貨1");
row1.CreateCell(3).SetCellValue(1);
row1.CreateCell(4).SetCellValue(1);
row1.CreateCell(5).SetCellValue("John");
IRow row2 = sheet.CreateRow(2);
row2.CreateCell(0).SetCellValue("20250902");
row2.CreateCell(1).SetCellValue("20250902");
row2.CreateCell(2).SetCellValue("測試貨2");
row2.CreateCell(3).SetCellValue(2);
row2.CreateCell(4).SetCellValue(2);
row2.CreateCell(5).SetCellValue("John");
IRow row3 = sheet.CreateRow(3);
row3.CreateCell(0).SetCellValue("20250903");
row3.CreateCell(1).SetCellValue("20250903");
row3.CreateCell(2).SetCellValue("測試貨3");
row3.CreateCell(3).SetCellValue(3);
row3.CreateCell(4).SetCellValue(3);
row3.CreateCell(5).SetCellValue("John");
IRow row4 = sheet.CreateRow(4);
row4.CreateCell(0).SetCellValue("20250904");
row4.CreateCell(1).SetCellValue("20250904");
row4.CreateCell(2).SetCellValue("測試貨4");
row4.CreateCell(3).SetCellValue(4);
row4.CreateCell(4).SetCellValue(4);
row4.CreateCell(5).SetCellValue("John");
IRow row5 = sheet.CreateRow(5);
row5.CreateCell(0).SetCellValue("20250905");
row5.CreateCell(1).SetCellValue("20250905");
row5.CreateCell(2).SetCellValue("測試貨5");
row5.CreateCell(3).SetCellValue(5);
row5.CreateCell(4).SetCellValue(5);
row5.CreateCell(5).SetCellValue("John");
IRow row6 = sheet.CreateRow(6);
row6.CreateCell(0).SetCellValue("20250906");
row6.CreateCell(1).SetCellValue("20250906");
row6.CreateCell(2).SetCellValue("測試貨6");
row6.CreateCell(3).SetCellValue(6);
row6.CreateCell(4).SetCellValue(6);
row6.CreateCell(5).SetCellValue("John");
IRow row7 = sheet.CreateRow(7);
row7.CreateCell(0).SetCellValue("20250907");
row7.CreateCell(1).SetCellValue("20250907");
row7.CreateCell(2).SetCellValue("測試貨7");
row7.CreateCell(3).SetCellValue(7);
row7.CreateCell(4).SetCellValue(7);
row7.CreateCell(5).SetCellValue("John");
IRow row8 = sheet.CreateRow(8);
row8.CreateCell(0).SetCellValue("20250908");
row8.CreateCell(1).SetCellValue("20250908");
row8.CreateCell(2).SetCellValue("測試貨8");
row8.CreateCell(3).SetCellValue(8);
row8.CreateCell(4).SetCellValue(8);
row8.CreateCell(5).SetCellValue("John");
IRow row9 = sheet.CreateRow(9);
row9.CreateCell(0).SetCellValue("20250909");
row9.CreateCell(1).SetCellValue("20250909");
row9.CreateCell(2).SetCellValue("測試貨9");
row9.CreateCell(3).SetCellValue(9);
row9.CreateCell(4).SetCellValue(9);
row9.CreateCell(5).SetCellValue("John");
範例程式碼只有兩列的資料,我們先把這兩列前三欄改成正確的資料,因為使用者需要的是每一列有六欄資料,所以我們再把後面三欄補正確資料上去,做法也相當簡單,多增加Cell 3、4 、5然後一樣使用SetCellValue設定裡面的資料即可。
最後,再把剩下的七列資料也寫上去,因為格式都是固定的所以我們可以快速地把格式複製下來,然後貼上七次,再去改裡面的資料,整個功能就大功告成了!
4 . 開發完成,測試專案
完成上述所有步驟後,現在的private void button1_Click(object sender, EventArgs e)大括號裡面的程式碼會如下:
private void button1_Click(object sender, EventArgs e)
{
IWorkbook workbook = new XSSFWorkbook();
ISheet sheet = workbook.CreateSheet("Sheet1");
IRow headerRow = sheet.CreateRow(0);
headerRow.CreateCell(0).SetCellValue("生產日期");
headerRow.CreateCell(1).SetCellValue("出貨日期");
headerRow.CreateCell(2).SetCellValue("貨品名稱");
headerRow.CreateCell(3).SetCellValue("出貨數量");
headerRow.CreateCell(4).SetCellValue("貨品價格");
headerRow.CreateCell(5).SetCellValue("生產人員");
IRow row1 = sheet.CreateRow(1);
row1.CreateCell(0).SetCellValue("20250901");
row1.CreateCell(1).SetCellValue("20250901");
row1.CreateCell(2).SetCellValue("測試貨1");
row1.CreateCell(3).SetCellValue(1);
row1.CreateCell(4).SetCellValue(1);
row1.CreateCell(5).SetCellValue("John");
IRow row2 = sheet.CreateRow(2);
row2.CreateCell(0).SetCellValue("20250902");
row2.CreateCell(1).SetCellValue("20250902");
row2.CreateCell(2).SetCellValue("測試貨2");
row2.CreateCell(3).SetCellValue(2);
row2.CreateCell(4).SetCellValue(2);
row2.CreateCell(5).SetCellValue("John");
IRow row3 = sheet.CreateRow(3);
row3.CreateCell(0).SetCellValue("20250903");
row3.CreateCell(1).SetCellValue("20250903");
row3.CreateCell(2).SetCellValue("測試貨3");
row3.CreateCell(3).SetCellValue(3);
row3.CreateCell(4).SetCellValue(3);
row3.CreateCell(5).SetCellValue("John");
IRow row4 = sheet.CreateRow(4);
row4.CreateCell(0).SetCellValue("20250904");
row4.CreateCell(1).SetCellValue("20250904");
row4.CreateCell(2).SetCellValue("測試貨4");
row4.CreateCell(3).SetCellValue(4);
row4.CreateCell(4).SetCellValue(4);
row4.CreateCell(5).SetCellValue("John");
IRow row5 = sheet.CreateRow(5);
row5.CreateCell(0).SetCellValue("20250905");
row5.CreateCell(1).SetCellValue("20250905");
row5.CreateCell(2).SetCellValue("測試貨5");
row5.CreateCell(3).SetCellValue(5);
row5.CreateCell(4).SetCellValue(5);
row5.CreateCell(5).SetCellValue("John");
IRow row6 = sheet.CreateRow(6);
row6.CreateCell(0).SetCellValue("20250906");
row6.CreateCell(1).SetCellValue("20250906");
row6.CreateCell(2).SetCellValue("測試貨6");
row6.CreateCell(3).SetCellValue(6);
row6.CreateCell(4).SetCellValue(6);
row6.CreateCell(5).SetCellValue("John");
IRow row7 = sheet.CreateRow(7);
row7.CreateCell(0).SetCellValue("20250907");
row7.CreateCell(1).SetCellValue("20250907");
row7.CreateCell(2).SetCellValue("測試貨7");
row7.CreateCell(3).SetCellValue(7);
row7.CreateCell(4).SetCellValue(7);
row7.CreateCell(5).SetCellValue("John");
IRow row8 = sheet.CreateRow(8);
row8.CreateCell(0).SetCellValue("20250908");
row8.CreateCell(1).SetCellValue("20250908");
row8.CreateCell(2).SetCellValue("測試貨8");
row8.CreateCell(3).SetCellValue(8);
row8.CreateCell(4).SetCellValue(8);
row8.CreateCell(5).SetCellValue("John");
IRow row9 = sheet.CreateRow(9);
row9.CreateCell(0).SetCellValue("20250909");
row9.CreateCell(1).SetCellValue("20250909");
row9.CreateCell(2).SetCellValue("測試貨9");
row9.CreateCell(3).SetCellValue(9);
row9.CreateCell(4).SetCellValue(9);
row9.CreateCell(5).SetCellValue("John");
using (FileStream fs = new FileStream("exportedData.xlsx", FileMode.Create, FileAccess.Write))
{
workbook.Write(fs);
}
MessageBox.Show("Excel 文件已成功生成!");
}
結論
接下來只要把程式跑起來,按下button1看一下產出的Excel格式有沒有正確,這樣我們就成功完成Excel自動產生的功能了!















