2015年7月13日 星期一

[NPOI]將套版從xls改寫成xlsx

安裝方法可google, 或參考此處:[NuGet]NPOI

原本是XLS, 為了將來就先測試怎麼用XLSX
需求是「讀取已設定過格式的舊檔、經過處理後另存新檔、不在伺服器中留檔」

總之, 下面是融合兩個官方範例後產生的東西... 大概?(失憶)
主要分成兩步驟

  1. 將HSSF全部替換成XSSF
  2. 修改Response的設定


先來看用於XLS的原始碼(※EmptyWorkbook為事先產生, 作為樣板的excel檔)
  using System.IO;
  using NPOI.HSSF.UserModel;
  using NPOI.HSSF.Util;
  using NPOI.SS.UserModel;

  string strFilePath = string.Format(Server.MapPath(".") + "\\EmptyWorkbook.xlsx");
  HSSFWorkbook workbook;
  using (FileStream fs = new FileStream(strFilePath, FileMode.Open, FileAccess.ReadWrite)) {
      workbook = new HSSFWorkbook(fs);
  }

  /*
   *--自由發揮--
   */

  MemoryStream ms = new MemoryStream();
  workbook.Write(ms);
  Response.AddHeader("Content-Disposition", string.Format("attchment; filename=editedWorkbook.xls"));
  Response.BinaryWrite(ms.ToArray());
  workbook = null;
  ms.Close();
  ms.Dispose();

第一步:將HSSF全部替換成XSSF
  using System.IO;
  using NPOI.XSSF.UserModel;
  using NPOI.XSSF.Util;
  using NPOI.SS.UserModel;

  string strFilePath = string.Format(Server.MapPath(".") + "\\EmptyWorkbook.xls");
  XSSFWorkbook workbook;
  using (FileStream fs = new FileStream(strFilePath, FileMode.Open, FileAccess.ReadWrite)) {
      workbook = new XSSFWorkbook(fs);
  }

  /*
   *--自由發揮--
   */

  MemoryStream ms = new MemoryStream();
  workbook.Write(ms);
  Response.AddHeader("Content-Disposition", string.Format("attchment; filename=editedWorkbook.xls"));
  Response.BinaryWrite(ms.ToArray());
  workbook = null;
  ms.Close();
  ms.Dispose();

第二步:修改Response的設定
  using System.IO;
  using NPOI.XSSF.UserModel;
  using NPOI.XSSF.Util;
  using NPOI.SS.UserModel;

  string strFilePath = string.Format(Server.MapPath(".") + "\\EmptyWorkbook.xlsx");
  XSSFWorkbook workbook;
  using (FileStream fs = new FileStream(strFilePath, FileMode.Open, FileAccess.ReadWrite)) {
      workbook = new XSSFWorkbook(fs);
  }

  /*
   *--自由發揮--
   */

  MemoryStream ms = new MemoryStream();
  workbook.Write(ms);
  Response.AddHeader("Content-Disposition", string.Format("attchment; filename=editedWorkbook.xlsx"));
  Response.BinaryWrite(ms.ToArray());
  workbook = null;
  ms.Close();
  ms.Dispose();
  Response.Clear();
  Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
  Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", "editedWorkbook.xlsx"));
  Response.BinaryWrite(ms.ToArray());
  Response.Flush();
  Response.End();

這樣就大功告成了

====2015/7/23 補充====
Response.ContentType對應的檔案類型可參考:https://filext.com/faq/office_mime_types.php
如果是用XSSFWokbook類別,在調用上需強制轉型(XSSFWorkbook),用IWorkbook就可以省略

Response.Write不建議使用在有巨集或複雜的excel
由於會產生溢位,xlsm的編輯待解決
目前解法:在server端複製一份→用NPOI改好→下載下來
下載檔案的寫法:[ASP.NET] 檔案下載寫法
失敗:只要透過stearm, 就可能出現溢位, 真要做還是只能參考老方法

http://www.dotblogs.com.tw/yc421206/archive/2009/07/08/9255.aspx
[ADO.NET] 如何 使用 OLE DB 讀寫 Excel / 建立 Excel 檔案 (一)