本文示例代碼下載: 鏈接:http://pan.baidu.com/s/1jHBdgCA 密碼:hzh7
ps:Vs數據庫腳本在解壓目錄下,修改web.config數據庫鏈接,示例代碼包含:導入,導出,上傳
導入導出實在多例子,很多成熟的組建都分裝了導入和導出,這一節演示利用LinqToExcel組件對Excel的導入,這個是一個極其簡單的例子。
我并不是說導入的簡單。而是LinqToExcel讓我們對Excel操作更加簡單!
最后我們將利用ClosedXML輸出Excel。這個比現流行NPOI與EPPlus更加優秀的組件,以Open XML SDK為基礎,所以只支持xlsx,不支持xls格式(現階段誰沒有個office2007以上版本)
他導出的Excel根據官方描述,兼容性遠超同行對手
如果你不是使用本架構只看2,3,4點,使用BLL層的代碼,這同樣適用你的MVC程序
LinqToExcel組件讀取Excel文件
ClosedXML組件輸出Excel
一張演示的數據庫表
安裝LinqToExcel NuGet包
文件上傳樣例
CloseXML導出Excel
CREATE TABLE [dbo].[Spl_Person]( [Id] [nvarchar](50) NOT NULL, --ID [Name] [nvarchar](50) NULL, --姓名 [Sex] [nchar](10) NULL, --性別 [Age] [int] NULL, --年齡 [IDCard] [nvarchar](50) NULL, --IDCard [Phone] [nvarchar](50) NULL, --電話 [Email] [nvarchar](200) NULL, --郵件 [Address] [nvarchar](300) NULL, --地址 [CreateTime] [datetime] NOT NULL, --創建時間 [Region] [nvarchar](50) NULL, --區域 [Category] [nvarchar](50) NULL, --類別 CONSTRAINT [PK_Spl_Person] PRIMARY KEY CLUSTERED ( [Id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]GO
如何使用這個框架?
按照之前的做法,更新到EF。并利用T4生成DAL,BLL,MODEL。再用代碼生成器生成界面復制進解決方案,一步到位
配置好訪問地址和權限,直接運行

再手動在工具欄添加導入和導出的按鈕(別忘記添加權限)

@Html.ToolButton("btnImport", "fa fa-level-down", Resource.Import, perm, "Import", true) @Html.ToolButton("btnExport", "fa fa-level-up", Resource.Export, perm, "Export", true)因為我們讀取Excel放在BLL層,所有在BLL層安裝LinqToExcel包

(這一點簡單帶過,可以到網上下載上傳代碼植入到自己系統中)
或者下載第32節的源碼 或者下載本節的示例代碼都可以
我這里使用普通的form上傳功能
添加導入前端代碼
<div id="uploadExcel" class="easyui-window" data-options="modal:true,closed:true,minimizable:false,shadow:false">
<form name="form1" method="post" id="form1">
<table>
<tr>
<th style=" padding:20px;">Excel:</th>
<td style=" padding:20px;">
<input name="ExcelPath" type="text" maxlength="255" id="txtExcelPath" readonly="readonly" style="width:200px" class="txtInput normal left">
<a href="javascript:$('#FileUpload').trigger('click').void(0);;" class="files">@Resource.Browse</a>
<input class="displaynone" type="file" id="FileUpload" name="FileUpload" onchange="Upload('ExcelFile', 'txtExcelPath', 'FileUpload');">
<span class="uploading">@Resource.Uploading</span>
</td>
</tr>
</table>
<div class="endbtndiv">
<a id="btnSave" href="javascript:ImportData()" class="easyui-linkbutton btns">Save</a>
<a id="btnReturn" href="javascript:$('#uploadExcel').window('close')" class="easyui-linkbutton btnc">Close</a>
</div>
</form>
</div>導入按鈕事件只要彈出上傳框就好
$("#btnImport").click(function () {
$("#uploadExcel").window({ title: '@Resource.Import', width: 450, height: 160, iconCls: 'icon-details' }).window('open');
});
保證上傳是成功的。

直接查看源碼的C#上傳代碼
-------------------------------------------------------------------------------------------------------上面只是前期的準備工作--------------------------------------------------------------
在業務層添加以下代碼


using Apps.Common;
using Apps.Models;
using Apps.Models.Spl;
using LinqToExcel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Apps.Spl.BLL
{
public partial class Spl_ProductBLL
{
/// <summary>
/// 校驗Excel數據
/// </summary>
public bool CheckImportData( string fileName, List<Spl_PersonModel> personList,ref ValidationErrors errors )
{
var targetFile = new FileInfo(fileName);
if (!targetFile.Exists)
{
errors.Add("導入的數據文件不存在");
return false;
}
var excelFile = new ExcelQueryFactory(fileName);
//對應列頭
excelFile.AddMapping<Spl_PersonModel>(x => x.Name, "Name");
excelFile.AddMapping<Spl_PersonModel>(x => x.Sex, "Sex");
excelFile.AddMapping<Spl_PersonModel>(x => x.Age, "Age");
excelFile.AddMapping<Spl_PersonModel>(x => x.IDCard, "IDCard");
excelFile.AddMapping<Spl_PersonModel>(x => x.Phone, "Phone");
excelFile.AddMapping<Spl_PersonModel>(x => x.Email, "Email");
excelFile.AddMapping<Spl_PersonModel>(x => x.Address, "Address");
excelFile.AddMapping<Spl_PersonModel>(x => x.Region, "Region");
excelFile.AddMapping<Spl_PersonModel>(x => x.Category, "Category");
//SheetName
var excelContent = excelFile.Worksheet<Spl_PersonModel>(0);
int rowIndex = 1;
//檢查數據正確性
foreach (var row in excelContent)
{
var errorMessage = new StringBuilder();
var person = new Spl_PersonModel();
person.Id =
person.Name = row.Name;
person.Sex = row.Sex;
person.Age = row.Age;
person.IDCard = row.IDCard;
person.Phone = row.Phone;
person.Email = row.Email;
person.Address = row.Address;
person.Region = row.Region;
person.Category = row.Category;
if (string.IsNullOrWhiteSpace(row.Name))
{
errorMessage.Append("Name - 不能為空. ");
}
if (string.IsNullOrWhiteSpace(row.IDCard))
{
errorMessage.Append("IDCard - 不能為空. ");
}
//=============================================================================
if (errorMessage.Length > 0)
{
errors.Add(string.Format(
"第 {0} 列發現錯誤:{1}{2}",
rowIndex,
errorMessage,
"<br/>"));
}
personList.Add(person);
rowIndex += 1;
}
if (errors.Count > 0)
{
return false;
}
return true;
}
/// <summary>
/// 保存數據
/// </summary>
public void SaveImportData(IEnumerable<Spl_PersonModel> personList)
{
try
{
DBContainer db = new DBContainer();
foreach (var model in personList)
{
Spl_Person entity = new Spl_Person();
entity.Id = ResultHelper.NewId;
entity.Name = model.Name;
entity.Sex = model.Sex;
entity.Age = model.Age;
entity.IDCard = model.IDCard;
entity.Phone = model.Phone;
entity.Email = model.Email;
entity.Address = model.Address;
entity.CreateTime = ResultHelper.NowTime;
entity.Region = model.Region;
entity.Category = model.Category;
db.Spl_Person.Add(entity);
}
db.SaveChanges();
}
catch (Exception ex)
{
throw;
}
}
}
}BLL


public class ValidationErrors : List<ValidationError>
{
/// <summary>
/// 添加錯誤
/// </summary>
/// <param name="errorMessage">信息描述</param>
public void Add(string errorMessage)
{
base.Add(new ValidationError { ErrorMessage = errorMessage });
}
/// <summary>
/// 獲取錯誤集合
/// </summary>
public string Error
{
get {
string error = "";
this.All(a => {
error += a.ErrorMessage;
return true;
});
return error;
}
}
}ValidationError
代碼包含兩個方法
public bool CheckImportData( string fileName, List<Spl_PersonModel> personList,ValidationErrors errors )
fileName為我們上傳的文件。
personList為承接數據List
ValidationErrors 錯誤集合
public void SaveImportData(IEnumerable<Spl_PersonModel> personList)
保存數據
別忘記添加接口
public partial interface ISpl_PersonBLL
{ bool CheckImportData(string fileName, List<Spl_PersonModel> personList, ref ValidationErrors errors); void SaveImportData(IEnumerable<Spl_PersonModel> personList);
}簡單明白,直接看代碼,不再解析。OK這樣控制器就可以直接調用了
public ActionResult Import(string filePath)
{ var personList = new List<Spl_PersonModel>(); //校驗數據is bool checkResult = m_BLL.CheckImportData(filePath, personList, ref errors); //校驗通過直接保存 if (checkResult)
{
m_BLL.SaveImportData(personList);
LogHandler.WriteServiceLog(GetUserId(),"導入成功", "成功", "導入", "Spl_Person"); return Json(JsonHandler.CreateMessage(1, Resource.InsertSucceed));
} else
{ string ErrorCol = errors.Error;
LogHandler.WriteServiceLog(GetUserId(), ErrorCol, "失敗", "導入", "Spl_Person"); return Json(JsonHandler.CreateMessage(0, Resource.InsertFail + ErrorCol));
}
}最后前端還需要把路徑給回來。
function ImportData()
{
$.post("@Url.Action("Import")?filePath=" + $("#txtExcelPath").val(), function (data) { if (data.type == 1) {
$("#List").datagrid('load');
$('#uploadExcel').window('close');
}
$.messageBox5s('@Resource.Tip', data.message);
}, "json");
}OK測試一下!建立一個新的excel格式

一般情況下我們是提供模版給用戶下載供用戶輸入數據,來確保格式的正確性

--------------------------------------------------------------------------------------導出功能------------------------------------------------------------------------------

在控制器添加以下代碼:
public ActionResult Export()
{ var exportSpource = this.GetExportData(); var dt = JsonConvert.DeserializeObject<DataTable>(exportSpource.ToString()); var exportFileName = string.Concat( "Person",
DateTime.Now.ToString("yyyyMMddHHmmss"), ".xlsx"); return new ExportExcelResult
{
SheetName = "人員列表",
FileName = exportFileName,
ExportData = dt
};
} private JArray GetExportData()
{
List<Spl_PersonModel> list = m_BLL.GetList(ref setNoPagerAscById, "");
JArray jObjects = new JArray(); foreach (var item in list)
{ var jo = new JObject();
jo.Add("Id", item.Id);
jo.Add("Name", item.Name);
jo.Add("Sex", item.Sex);
jo.Add("Age", item.Age);
jo.Add("IDCard", item.IDCard);
jo.Add("Phone", item.Phone);
jo.Add("Email", item.Email);
jo.Add("Address", item.Address);
jo.Add("CreateTime", item.CreateTime);
jo.Add("Region", item.Region);
jo.Add("Category", item.Category);
jObjects.Add(jo);
} return jObjects;
}注意:ExportExcelResult
此類是使用ClosedXML.Excel,已經封裝好了。大家直接拿來用就可以。把關注點都放在業務中
using ClosedXML.Excel;using System;using System.Data;using System.IO;using System.Text;using System.Web;using System.Web.Mvc;namespace Apps.Web.Core
{ public class ExportExcelResult : ActionResult
{ public string SheetName { get; set; } public string FileName { get; set; } public DataTable ExportData { get; set; } public ExportExcelResult()
{
} public override void ExecuteResult(ControllerContext context)
{ if (ExportData == null)
{ throw new InvalidDataException("ExportData");
} if (string.IsNullOrWhiteSpace(this.SheetName))
{ this.SheetName = "Sheet1";
} if (string.IsNullOrWhiteSpace(this.FileName))
{ this.FileName = string.Concat( "ExportData_",
DateTime.Now.ToString("yyyyMMddHHmmss"), ".xlsx");
} this.ExportExcelEventHandler(context);
} /// <summary> /// Exports the excel event handler. /// </summary> /// <param name="context">The context.</param> private void ExportExcelEventHandler(ControllerContext context)
{ try
{ var workbook = new XLWorkbook(); if (this.ExportData != null)
{
context.HttpContext.Response.Clear(); // 編碼
context.HttpContext.Response.ContentEncoding = Encoding.UTF8; // 設置網頁ContentType
context.HttpContext.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; // 導出名字 var browser = context.HttpContext.Request.Browser.Browser; var exportFileName = browser.Equals("Firefox", StringComparison.OrdinalIgnoreCase) ? this.FileName
: HttpUtility.UrlEncode(this.FileName, Encoding.UTF8);
context.HttpContext.Response.AddHeader( "Content-Disposition", string.Format("attachment;filename={0}", exportFileName)); // Add all DataTables in the DataSet as a worksheets
workbook.Worksheets.Add(this.ExportData, this.SheetName); using (var memoryStream = new MemoryStream())
{
workbook.SaveAs(memoryStream);
memoryStream.WriteTo(context.HttpContext.Response.OutputStream);
memoryStream.Close();
}
}
workbook.Dispose();
} catch (Exception ex)
{ throw;
}
}
}
}
本節知識點,全部聚集在CheckImportData方法上。
對應列頭是模版xlsx的列頭

1.如果模版需要是是中文的,如Name=名字,那么方法應該這么寫
excelFile.AddMapping<Spl_PersonModel>(x => x.Name, "名字");
2.導入第幾個sheet工作薄可以這么寫
我這里寫0是指第一個sheet工作薄??梢灾苯又付üぷ鞅?/p>
var excelContent = excelFile.Worksheet<Spl_PersonModel>("Sheet1");
3.檢查正確性可以確保數據的來源??梢越o出用戶正確的修改提示。
4.借助ClosedXML,導出實際只需要幾行代碼。哈哈..這是如此的簡單。
return new ExportExcelResult
{
SheetName = "人員列表",
FileName = exportFileName,
ExportData = dt
};

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。