第一次建立 a1.xlsx 寫入成功;第二次開啟同一檔案追加資料,執行無報錯但檔案內容未更新,仍只有首次寫入的資料。
FileMode.Append 僅將檔案指標移至末尾,無法直接在現有 XLSX 結構後追加資料。XLSX 是 ZIP 封裝的 XML 結構,必須完整讀取、修改記憶體模型、再整個覆寫回磁碟。
FileMode.Open, FileAccess.Read 讀取現有工作簿至記憶體。FileMode.Create, FileAccess.Write 建立新檔案覆寫原檔。private void AppendToExcel(string filePath, string[] rowData) {
// 1. 讀取現有工作簿
IWorkbook workbook;
using (FileStream fsRead = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
workbook = new XSSFWorkbook(fsRead); // .xlsx 用 XSSFWorkbook
}
// 2. 修改記憶體模型
ISheet sheet = workbook.GetSheetAt(0);
int newRowIndex = sheet.LastRowNum + 1; // 最後一行索引 + 1
IRow newRow = sheet.CreateRow(newRowIndex);
for (int i = 0; i < rowData.Length; i++) {
newRow.CreateCell(i).SetCellValue(rowData[i]);
}
// 3. 覆寫回磁碟(必須用新的 FileStream)
using (FileStream fsWrite = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None)) {
workbook.Write(fsWrite);
}
// 4. 釋放資源
workbook.Close();
}
FileStream(讀取時鎖定檔案,寫入時需截斷)。FileMode.Create 會截斷現有檔案,配合 workbook.Write() 完整序列化新結構。sheet.LastRowNum 回傳最後一行索引(0-based),新行索引為 LastRowNum + 1。File.Exists,不存在則 new XSSFWorkbook() 建立新工作簿並寫入表頭。頻繁追加(如每秒寫入)會造成大量 IO。建議:
List<string[]>,定時(如每 100 筆或 5 秒)一次性寫入。SXSSFWorkbook (Streaming API) 僅保留滾動視窗在記憶體。