首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C# NPOI 追加寫入現有 Excel (.xlsx) 失敗:雙流技巧完美解決

     編輯:程式設計疑難解答

問題現象

第一次建立 a1.xlsx 寫入成功;第二次開啟同一檔案追加資料,執行無報錯但檔案內容未更新,仍只有首次寫入的資料。

根本原因

FileMode.Append 僅將檔案指標移至末尾,無法直接在現有 XLSX 結構後追加資料。XLSX 是 ZIP 封裝的 XML 結構,必須完整讀取、修改記憶體模型、再整個覆寫回磁碟。

正確做法:雙流

  1. 讀取流:FileMode.Open, FileAccess.Read 讀取現有工作簿至記憶體。
  2. 操作記憶體模型:新增行、寫入儲存格。
  3. 寫入流: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();
}

關鍵細節

  • 讀取與寫入必須分兩個 using 區塊,不能共用同一 FileStream(讀取時鎖定檔案,寫入時需截斷)。
  • FileMode.Create 會截斷現有檔案,配合 workbook.Write() 完整序列化新結構。
  • sheet.LastRowNum 回傳最後一行索引(0-based),新行索引為 LastRowNum + 1。
  • 若檔案不存在,先判斷 File.Exists,不存在則 new XSSFWorkbook() 建立新工作簿並寫入表頭。

效能考量

頻繁追加(如每秒寫入)會造成大量 IO。建議:

  • 批次累積資料在記憶體 List<string[]>,定時(如每 100 筆或 5 秒)一次性寫入。
  • 大數據量改用 SXSSFWorkbook (Streaming API) 僅保留滾動視窗在記憶體。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved