程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 讀取Excel的內容並實現數據批量上傳

讀取Excel的內容並實現數據批量上傳

編輯:關於.NET

企業應用中經常會遇到批量上傳數據的需求,客戶要求使用excel表格錄入一批數據,然後通過網頁上傳該excel表格,實現批量導入數據。這樣的需求其實主要就是處理Excel表格,把Excel表格中的內容讀取出來後,做一些必要的校驗,然後上傳校驗成功的數據,返回失敗數據的行號以及校驗失敗的信息。

如何讀取Excel表格,網上已經有很多方法,有些是通過oledb,有些是通過第三方組件。我參考了網上的一些代碼,加上自己的封裝,給大家提供一個改良後的版本。當然,為了做到通用,我沒有使用oledb的方式,而是使用了一個第三方組件。使用第三方組件的原因很簡單,因為有些服務器不一定安裝Excel,有些連oledb提供程序都沒有,所以哦,還是用第三方組件比較能夠通吃。

這個第三方組件叫做koogra,.NET實現的開源組件,比較好用。這裡是koogra項目地址:http://sourceforge.net/projects/koogra/

好了,開始我們的封裝過程,為了好用我希望的方式是四種,返回的結果都是DataTable對象。

1:傳入的參數包括工作簿地址、工作表名稱;

2:傳入的參數包括工作簿地址、工作表的索引(0表示第一個工作表);

3:傳入的參數包括內存流、工作表名稱;

4:傳入的參數包括內存流、工作表的索引(0表示第一個工作表)。

ok,開始上代碼,記得項目要引用Ionic.Utils.Zip.dll和Net.SourceForge.Koogra.dll

代碼

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using Net.SourceForge.Koogra.Excel;
namespace Gren.Framework.Office
{
     /// <summary>
     /// Excel工具類
     /// </summary>
     public class ExcelUtils
     {
         private Workbook book;
         public ExcelUtils(string path)
         {
             this.book = new Workbook(path);
         }
         public ExcelUtils(System.IO.Stream stream)
         {
             this.book = new Workbook(stream);
         }
         protected DataTable SaveAsDataTable(Worksheet sheet)
         {
             DataTable dt = new DataTable();
             uint minRow = sheet.Rows.MinRow;
             uint maxRow = sheet.Rows.MaxRow;
             Row firstRow = sheet.Rows[minRow];
             uint minCol = firstRow.Cells.MinCol;
             uint maxCol = firstRow.Cells.MaxCol;
             for (uint i = minCol; i <= maxCol; i++)
             {
                 dt.Columns.Add(firstRow.Cells[i].FormattedValue());
             }
             for (uint i = minRow + 1; i <= maxRow; i++)
             {
                 Row row = sheet.Rows[i];
                 if (row != null)
                 {
                     DataRow dr = dt.NewRow();
                     for (uint j = minCol; j <= maxCol; j++)
                     {
                         Cell cell = row.Cells[j];
                         if (cell != null)
                         {
                             dr[Convert.ToInt32(j)] = cell.Value != null ? cell.Value.ToString() : string.Empty;
                         }
                     }
                     dt.Rows.Add(dr);
                 }

             }
             return dt;
         }
         public DataTable ToDataTable(int index)
         {
             Worksheet sheet = this.book.Sheets[index];
             if (sheet == null)
             {
                 throw new ApplicationException(string.Format("索引[{0}]所指定的電子表格不存在!", index));
             }
             return this.SaveAsDataTable(sheet);
         }
         public DataTable ToDataTable(string sheetName)
         {
             Worksheet sheet = this.book.Sheets.GetByName(sheetName);
             if (sheet == null)
             {
                 throw new ApplicationException(string.Format("名稱[{0}]所指定的電子表格不存在!", sheetName));
             }
             return this.SaveAsDataTable(sheet);
         }
         #region 靜態方法
         /// <summary>
         /// 單元格格式為日期時間,使用此方法轉換為DateTime類型,若解析失敗則返回‘0001-01-01’
         /// </summary>
         public static DateTime ParseDateTime(string cellValue)
         {
             DateTime date = default(DateTime);
             double value = default(double);
             if (double.TryParse(cellValue, out value))
             {
                 date = DateTime.FromOADate(value);
             }
             else
             {
                 DateTime.TryParse(cellValue, out date);
             }
             return date;
         }
         /// <summary>
         /// 轉換為DataTable(文件路徑+表名)
         /// </summary>
         public static DataTable TranslateToTable(string path, string sheetName)
         {
             ExcelUtils utils = new ExcelUtils(path);
             return utils.ToDataTable(sheetName);
         }
         /// <summary>
         /// 轉換為DataTable(文件路徑+表索引)
         /// </summary>
         public static DataTable TranslateToTable(string path, int sheetIndex)
         {
             ExcelUtils utils = new ExcelUtils(path);
             return utils.ToDataTable(sheetIndex);
         }
         /// <summary>
         /// 轉換為DataTable(文件路徑)
         /// </summary>
         public static DataTable TranslateToTable(string path)
         {
             ExcelUtils utils = new ExcelUtils(path);
             return utils.ToDataTable(0);
         }
         /// <summary>
         /// 轉換為DataTable(內存流+表名)
         /// </summary>
         public static DataTable TranslateToTable(System.IO.Stream stream, string sheetName)
         {
             ExcelUtils utils = new ExcelUtils(stream);
             return utils.ToDataTable(sheetName);
         }
         /// <summary>
         /// 轉換為DataTable(內存流+表索引)
         /// </summary>
         public static DataTable TranslateToTable(System.IO.Stream stream, int sheetIndex)
         {
             ExcelUtils utils = new ExcelUtils(stream);
             return utils.ToDataTable(sheetIndex);
         }
         /// <summary>
         /// 轉換為DataTable(內存流)
         /// </summary>
         public static DataTable TranslateToTable(System.IO.Stream stream)
         {
             ExcelUtils utils = new ExcelUtils(stream);
             return utils.ToDataTable(0);
         }
         #endregion
     }
}

ParseDateTime這個靜態方法是用來處理日期時間類型單元格的,在Excel表格裡面日期時間類型讀取出來的時候是一個double類型的數據,使用這個方法可以得到正確的DataTime類型的值。仔細的人可以發現這個方法其實除了把double類型的數據轉換為DateTime之外,還會在轉換失敗的時候嘗試把該單元格的內容做為字符串轉換為DateTime,因為如果單元格是文本類型的話,那麼用戶輸入的日期時間就不是一個double了。

好了,讀取Excel的類就封裝好了,那麼在asp.net頁面中如何使用呢?再看下面的代碼,fileUpload1是文件上傳控件。

代碼

if (fileUpload1.HasFile)
{
     DataTable dt = null;
     try
     {
         using (System.IO.MemoryStream stream = new System.IO.MemoryStream(fileUpload1.FileBytes))
         {
             dt = Gren.Framework.Office.ExcelUtils.TranslateToTable(stream, "sheet1");
         }
         //得到DataTable對象後,做你自己的處理
     }
     catch (Exception ex)
     {
         lblMessage.Text = "<p><span class=\"c_red  ft_bold\">處理數據文件錯誤:</span></p>";
         lblMessage.Text += "<div class=\"c_red\">" + Server.HtmlEncode(ex.Message) + "</div>";
     }
}
else
{
     lblMessage.Text = "<p><span class=\"c_red  ft_bold\">請選擇數據文件</span></p>";
}

直接用內存流來處理上傳的文件還是比較快的,大家試試吧,有什麼問題記得給我留言。或者大家幫我優化增強後,也請告訴我,共同進步嘛。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved