2014年7月28日 星期一

[ASP.NET]讀取 Excel 的方式 - 使用 NPOI 方式

繼上一次的 Excel 讀取方式
[ASP.NET]讀取 Excel 的方式 - 使用 Excel模組 方式

這次要說明的是另一個讀取 Excel 方式 就是使用 NPOI 的方式
NPOI (POI for .NET) 是從 POI  移植過來的 .NET版

POI 是 Apache 的開放原始碼的 Java 函式庫
專門用來讀取大部分 Microsoft Office的檔案格式

因為目前只有學習ASP.NET的東西,所以只有講解 NPOI 的部分
  • NPOI 是個額外的套件,取得的方式可透過 網站下載 或使用 Microsoft Visual Studio 內的 NuGet 套件進行安裝
  • 引用的函式分別是 
    • HSSF 使用於 Excel 2003 
    • XSSF 使用於 Excel 2007
    • XWPF 使用於 Word 2007
  • 引用的方式為 
    using NPOI.HSSF.UserModel;
  • 似乎只能讀取 2007 版本以下的 Excel 檔
  • 在Excel內編輯過的資料,就算刪除了也會讀進 ( 就變成了空白欄位 )
因為範例很多,所以只提供檔案下載



參考資料

NPOI教學

NPOI.FillPattern 使用方法

Memory Stream 使用方法
[VB.NET][C#.NET] MemoryStream / BufferedStream 類別



2014年7月26日 星期六

[ASP.NET]讀取 Excel 的方式 - 使用 Excel模組 方式

在寫入資料庫的網站上 (尤其是後台)
匯入與匯出 Excel 檔是一個很重要的功能
尤其是 再輸入大量資料的時候。

目前所知的匯入Excel 檔的方式有兩個:
這次先介紹直接使用 Excel模組的方式
  • 最正統的方式,也是很麻煩的方式
  • 這個方法主要是從我們的電腦上找出 Excel的執行程式來執行
  • 使用加入參考的方式來匯入 Excel 模組
  • 也就是說如果需要自己架設伺服器的話,那台伺服器上就必須安裝 Excel
  • 此方法會有資源占用的問題,處理完之後記得釋放資源
以下是參考 所寫出的程式
[ASP.net WebForm] 把Excel資料匯入資料庫的懶人Code分享 - Microsoft.office.Interop.Excel篇

HTML 碼

   1:  <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="Excel_匯入_正統_.WebForm1" %>
   2:   
   3:  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   4:   
   5:  <html xmlns="http://www.w3.org/1999/xhtml">
   6:  <head runat="server">
   7:      <title></title>
   8:  </head>
   9:  <body>
  10:      <form id="form1" runat="server">
  11:      <div>
  12:      
  13:          <asp:FileUpload ID="FuFile" runat="server" />
  14:          <br />
  15:          <asp:GridView ID="GridView1" runat="server">
  16:          </asp:GridView>
  17:          <br />
  18:          <asp:Button ID="btnOK" runat="server" onclick="btnOK_Click" Text="匯入Excel" />
  19:      
  20:      </div>
  21:      </form>
  22:  </body>
  23:  </html>

CS 檔


   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Web;
   5:  using System.Web.UI;
   6:  using System.Web.UI.WebControls;
   7:  using System.Data;
   8:   
   9:  // 引用 Microsoft Excel 參考
  10:  using Microsoft.Office.Interop;
  11:  using Microsoft.Office.Interop.Excel;
  12:   
  13:  namespace Excel_匯入_正統_
  14:  {
  15:      public partial class WebForm1 : System.Web.UI.Page
  16:      {
  17:          // 使用 Excel 的應用程式
  18:          Microsoft.Office.Interop.Excel.Application xlApp = null;
  19:          // WorkBook
  20:          Workbook wb = null;
  21:          // 工作表
  22:          Worksheet ws = null;
  23:          // 加入範圍
  24:          Range aRange = null;
  25:   
  26:          protected void Page_Load(object sender, EventArgs e)
  27:          {
  28:   
  29:          }
  30:   
  31:          protected void btnOK_Click(object sender, EventArgs e)
  32:          {
  33:              // 紀錄上傳路徑方便使用
  34:              string Path = "";
  35:              try
  36:              {
  37:                  // 確認 上傳檔案控制項是否有檔案
  38:                  if (FuFile.HasFile)
  39:                  {
  40:                      // 檔名使用亂碼來命名 (可用可不用)
  41:                      string filename = Guid.NewGuid().ToString();
  42:                      // 紀錄路徑
  43:                      Path = Server.MapPath(@"Upload/" + filename);
  44:                      // 把上傳的檔案儲存在伺服器內
  45:                      FuFile.SaveAs(Path);
  46:   
  47:                      if (this.xlApp == null)
  48:                      {
  49:                          this.xlApp = new Microsoft.Office.Interop.Excel.Application();
  50:                      }
  51:   
  52:                      // 打開上傳到伺服器的檔案
  53:                      this.xlApp.Workbooks.Open(Path, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
  54:                      this.wb = xlApp.Workbooks[1]; // 第一個Workbook
  55:                      this.wb.Save();
  56:   
  57:                      // 從第一個工作表讀資料
  58:                      SaveOrInsertSheet(Path, (Worksheet)xlApp.Worksheets[1]);
  59:   
  60:                      // 顯示訊息
  61:                      ClientScript.RegisterClientScriptBlock(this.GetType(), "匯入完成", "<script>alert('匯入完成');</script>");
  62:                  }
  63:              }
  64:              catch (Exception ex)
  65:              {
  66:                  throw ex; // 拋出錯誤
  67:              }
  68:              finally // 最後一定執行
  69:              {
  70:                  // 關閉 Excel 程式
  71:                  xlApp.Workbooks.Close();
  72:                  xlApp.Quit();
  73:                  try
  74:                  {
  75:                      // 刪除 Windows 工作管理員中的 Excel.exe 處理緒
  76:                      System.Runtime.InteropServices.Marshal.ReleaseComObject(this.xlApp);
  77:                      System.Runtime.InteropServices.Marshal.ReleaseComObject(this.ws);
  78:                      System.Runtime.InteropServices.Marshal.ReleaseComObject(this.aRange);
  79:                  }
  80:                  catch { }
  81:                  this.xlApp = null;
  82:                  this.wb = null;
  83:                  this.ws = null;
  84:                  this.aRange = null;
  85:   
  86:                  // 刪除 伺服器上的 Excel 檔
  87:                  System.IO.File.Delete(Path);
  88:   
  89:                  // 回收記憶體
  90:                  GC.Collect();
  91:              }
  92:          }
  93:   
  94:          private void SaveOrInsertSheet(string excel_filename, Worksheet ws)
  95:          {
  96:              // 要開始讀取的起始列(微軟工作列是從1開始算)
  97:              int rowIndex = 1;
  98:   
  99:              // 取得一列的範圍 (A 欄位 到 C欄位)
 100:              // 在這裡麻煩的地方是 只要多加一個欄位 (例如D) 下面的取值就要多加一個 Cell
 101:              this.aRange = ws.get_Range("A" + rowIndex.ToString(), "C" + rowIndex.ToString());
 102:   
 103:              // 建立一個讀取 Excel匯入的表格
 104:              System.Data.DataTable dt = new System.Data.DataTable();
 105:   
 106:              // 自訂資料欄位
 107:              dt.Columns.Add("值一");
 108:              dt.Columns.Add("值二");
 109:              dt.Columns.Add("值三");
 110:   
 111:              // 判斷Row範圍裡第一格有值的話,迴圈就往下跑
 112:              while (((object[,])this.aRange.Value2)[1, 1] != null)//用this.aRange.Cells[1, 1]來取值的方式似乎會造成無窮迴圈?
 113:              {
 114:                  // 範圍裡第一格的值
 115:                  string cell1 = ((object[,])this.aRange.Value2)[1, 1] != null ? ((object[,])this.aRange.Value2)[1, 1].ToString() : "";
 116:   
 117:                  // 範圍裡第二格的值
 118:                  string cell2 = ((object[,])this.aRange.Value2)[1, 2] != null ? ((object[,])this.aRange.Value2)[1, 2].ToString() : "";
 119:   
 120:                  // 範圍裡第三格的值
 121:                  string cell3 = ((object[,])this.aRange.Value2)[1, 3] != null ? ((object[,])this.aRange.Value2)[1, 3].ToString() : "";
 122:   
 123:                  // 新增表格內的資料行
 124:                  System.Data.DataRow dr = dt.NewRow();
 125:   
 126:                  // 第一格資料
 127:                  dr[0] = cell1;
 128:                  // 第二格資料
 129:                  dr[1] = cell2;
 130:                  // 第三格資料
 131:                  dr[2] = cell3;
 132:   
 133:                  // 加入到表格內
 134:                  dt.Rows.Add(dr);
 135:   
 136:                  //往下抓一列 Excel 範圍
 137:                  rowIndex++;
 138:                  this.aRange = ws.get_Range("A" + rowIndex.ToString(), "C" + rowIndex.ToString());
 139:              }
 140:   
 141:              // 連結表格的資料到 GridView內
 142:              GridView1.DataSource = dt;
 143:              // 並繫結資料
 144:              GridView1.DataBind();
 145:          }
 146:      }
 147:  }

程式下載點