Asp.NET MVC 导入Excel数据教程 手把手教你系列!!! http://www.cnblogs.com/Lxy-/p/5791721.html – 高达 – 博客园

2018年6月11日 分类: 开发笔记

来源: Asp.NET MVC 导入Excel数据教程 手把手教你系列!!! http://www.cnblogs.com/Lxy-/p/5791721.html – 高达 – 博客园

复制代码
复制代码
@section scripts{
    <script type="text/javascript">
        $('input[id=fileUpload]').change(function () {
            $('#txt_Path').val($(this).val());
            $('#form_Upload').submit();
        });
    </script>}
复制代码
复制代码

 

 

这段JS代码功能就是在<input id=”fileUpload” type=”file” name=”file” style=”display:none”>选择文件后就把文件路径赋给我们自己构造的文本框里,然后就是提交表单,上传它的选择的文件到我们的服务器。

请注意灰色那段代码是如何用我们自己构建的按钮绑定到fileUpload的功能上

 

1  @*浏览本地文件按钮*@
2     <span id="btn_Browse" style="cursor:pointer;" onclick="$('input[id=fileUpload]').click();" class="input-group-addon">
3         <i class="glyphicon glyphicon-folder-open"></i>&nbsp;&nbsp;&nbsp;浏览文件
4     </span>

 

现在就来测试下我们写的代码能不能跑!F5运行!如果是以下效果就是正确的

 

 

 

为了浏览文件有响应的效果,我们在视图页加一小段CSS代码

复制代码
复制代码
 1 @section scripts{
 2 
 3 
 4     <style type="text/css">
 5         #btn_Browse:hover {
 6             color: #3C763D;
 7         }
 8     </style>
 9 
10     <script type="text/javascript">
11         $('input[id=fileUpload]').change(function () {
12             $('#txt_Path').val($(this).val());
13             $('#form_Upload').submit();
14         });
15 
16 
17     
18     </script>}
复制代码
复制代码

 

第五步

到了这里我们的文件已经可以上传到我们服务了,如果不信你在Browse操作打个断点,看看file参数是不是已经接受了文件,如果接受到了说明已经成功一半了!我们还是先不写Browse操作处理Excel文件的代码,焦点还是在视图页上,在本博客第一张效果图里,大家看到浏览文件下面有张table表格吗?小弟创建这个表格只是为了更好的交互效果,让使用的人更直观而已。而且也很简单!

接下来我们来构建它,在视图页新增table表格的代码

 

复制代码
复制代码
@model Student
@using School.Entity


<table class="table  table-striped  table-hover table-bordered">
    <tr>
        <th>@Html.DisplayNameFor(model => model.Name)</th>
        <th>@Html.DisplayNameFor(model => model.Age)</th>
        <th>@Html.DisplayNameFor(model => model.ChineseScore)</th>
        <th>@Html.DisplayNameFor(model => model.EnglishScore)</th>
        <th>@Html.DisplayNameFor(model => model.MathScore)</th>
    </tr>

    @if (ViewBag.Data != null)
    {
        //生成前10条数据 填充表格table
        foreach (var item in (ViewBag.Data as IEnumerable<Student>).Take(10))
        {
            <tr>
                <td>@Html.DisplayFor(model => item.Name)</td>
                <td>@Html.DisplayFor(model => item.Age)</td>
                <td>@Html.DisplayFor(model => item.ChineseScore)</td>
                <td>@Html.DisplayFor(model => item.EnglishScore)</td>
                <td>@Html.DisplayFor(model => item.MathScore)</td>
            </tr>
        }
    }
</table>
<h5 class="text-info">
    默认显示前10条记录
</h5>
复制代码
复制代码

在这里我依然用的@HTML辅助方法,如果你还不会使用它,赶紧花一天学习它,入门非常简单!非常强大! 设想如果没有@Html扩展方法 小弟得写多少硬编码啊!

 

然后再次按F5运行先看看效果

 

 

这里的表头是英文的,如果你想变成中文的话,可以在实体上加上数据注解特性(如下)

 

复制代码
复制代码
1 public class Student
2   {
3 
4         [Display(Name="中文成绩")]
5         public int ChineseScore { get; set; }
6 
7    }
复制代码
复制代码

 

 

 

对了还忘了一个东西,就是上传提交按钮,我们现在来构建它!在视图页form表单下面添加如下代码

 

复制代码
复制代码
1 @using (Html.BeginForm("Browse", "UploadExcel", FormMethod.Post, new { enctype = "multipart/form-data", id = "form_Upload" }))
2 {
3     @Html.AntiForgeryToken()
4     <input id="fileUpload" type="file" name="file" style="display:none"> 
5 }
6 
//红色部分是我构建的上传提交按钮
7 <div class="input-group pull-right" style="margin:0 0 5px 0">
8     @Html.RouteLink("开始提交", new { action = "Upload" }, new { id="submit", @class = "btn  btn-primary ladda-button ", data_style = "expand-right" })
9 </div>
复制代码
复制代码

 

 

 

@Html.RouteLink扩展方法会根据我定义的路由生成一个<a>锚标签,最后生成如下html标记

<a id=”submit” class=”btn  btn-primary ladda-button” data-style=”expand-right” href=”/UploadExcel/Upload” >开始提交</a>

 

在这里我把它伪装成了一个button按钮

 

 

data-style=”expand-right”这些属性是我用bootstrap加了个5毛钱的特效,你也可以不用管,也可以使用自己的特效。这个上传提交按钮的功能就是最后一个功能,把经过Browse操作转换成List<T>的数  据导入到我们的数据库。到现在为止我们的导入Excel的页面已经全部完成了,当然我的审美观和前端技术就是渣渣,所以请原谅小弟! href=”/UploadExcel/Upload” 这个<a>锚标签会访问UploadExcelController控制器的Upload操作,所以我再添加最后一个操作。在控制器添加如下代码

 

复制代码
复制代码
 public class UploadExcelController : Controller
    {
        // GET: /UploadExcel
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        [HandleError(View = "~/Views/Shared/Error.cshtml")]
        public ActionResult Browse(HttpPostedFileBase file)
        {

            return null;
        }

        //红色部分是我新增的Action操作,这个操作的作用是把Browse操作转换好的List<T> 通过业务服务层 导入我们数据库
        [HandleError(View = "~/Views/Shared/Error.cshtml")]
        public ActionResult Upload()
        {
            return View("UploadSuccess"); //导入成功的页面 这个页面就留给大家自己设计吧
        }

      }
复制代码
复制代码

 

 

现在我们来检查下我们构造好的页面,F5运行。如果是下面的样子我们就全部完成视图页面了

 

 

现在我们把重点放在Excel文件的逻辑处理上了,我们先从Browse操作下手,因为此操作负责把我们上传的Excel文件转换成List Entity对象,只要转换成这个集合对象你后面就可以想怎么插入就怎么插入了 !想插入MSSQL MYSQL 等不同数据都可以呵呵!因为我们用的ORM框架!

按照我上传的那个思维图,我想我先处理验证!先判断文件的格式是不是Excel的格式。(Excel的格式是根据版本来的 2007-2010 是xlsx,2003是xls)这里我只默认了2007-2010 。

在Browse操作添加如下代码

 

复制代码
复制代码
 1         [HttpPost]
 2         [ValidateAntiForgeryToken]
 3         [HandleError(View = "~/Views/Shared/Error.cshtml")]
 4         public ActionResult Browse(HttpPostedFileBase file)
 5         {
 6 
 7             if (string.Empty.Equals(file.FileName) || ".xlsx" != Path.GetExtension(file.FileName))
 8             {
 9                 throw new ArgumentException("当前文件格式不正确,请确保正确的Excel文件格式!");
10             }
11 
12             var severPath = this.Server.MapPath("/files/"); //获取当前虚拟文件路径
13 
14             var savePath = Path.Combine(severPath, file.FileName); //拼接保存文件路径
15 
16             try
17             {
18                 file.SaveAs(savePath);
19                 stus = ExcelHelper.ReadExcelToEntityList<Student>(savePath);
20                 ViewBag.Data = stus;
21                 return View("Index");
22             }
23             finally
24             {
25                 System.IO.File.Delete(savePath);//每次上传完毕删除文件
26             }
27 
28         }
复制代码
复制代码

 

我在MVC项目的根目录创建了个files的文件夹,用来保存上传的Excel文件。然后读取文件转换成List Entity对象,然后把它传给我们创建的视图。这样就可以一选择Excel文件就把数据显示在页面上了,转换数据的核心是这句代码

stus = ExcelHelper.ReadExcelToEntityList<Student>(savePath);

ExcelHelper是我自己封装的一个工具库,我现在来创建它。在根目录添加一个文件夹,然后添加一个类

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
ppublic class ExcelHelper
   {
       //Excel数据转List<T>
       public static IList<T> ReadExcelToEntityList<T>(string filePath) where T : classnew()
       {
           DataTable tbl = ReadExcelToDataTable(filePath);//读取Excel数据到DataTable
           IList<T> list = DataTableToList<T>(tbl);
           return list;
       }
       //Excel数据转DataTable 使用的oledb读取方式
       public static DataTable ReadExcelToDataTable(string filePath)
       {
           if (filePath == string.Empty) throw new ArgumentNullException("路径参数不能为空");
           string ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0; Persist Security Info=False;Data Source=" + filePath + "; Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'";
           OleDbDataAdapter adapter = new OleDbDataAdapter("select * From[Sheet1$]", ConnectionString); //默认读取的Sheet1,你也可以把它封装变量,动态读取你的Sheet工作表
           DataTable table = new DataTable("TempTable");
           adapter.Fill(table);
           return table;
       }
       //DataTable转List<T>
       public static List<T> DataTableToList<T>(DataTable dt) where T : classnew()
       {
           if (dt == nullreturn null;
           List<T> list = new List<T>();
           //遍历DataTable中所有的数据行 
           foreach (DataRow dr in dt.Rows)
           {
               T t = new T();
               PropertyInfo[] propertys = t.GetType().GetProperties();
               foreach (PropertyInfo pro in propertys)
               {
                   //检查DataTable是否包含此列(列名==对象的属性名)   
                   if (dt.Columns.Contains(pro.Name))
                   {
                       object value = dr[pro.Name];
                       value = Convert.ChangeType(value, pro.PropertyType);//强制转换类型
                       //如果非空,则赋给对象的属性  PropertyInfo
                       if (value != DBNull.Value)
                       {
                           pro.SetValue(t, value, null);
                       }
                   }
               }
               //对象添加到泛型集合中 
               list.Add(t);
           }
           return list;
       }
   }

 

 

代码很简单我就不翻译了,就是读取Excel数据转各种C#对象,但是这是教学代码不是产品代码,我很粗暴的封装了。你如果要用到生成环境,得还要加上各种逻辑验证和测试!

好了到了这步,我们就可以出现下面的效果了:

 

写到这里,感觉最后一个功能把List<T>集合导入数据库大家应该都会,我就不想再继续往下写了。但是还是要说下注意的地方就是导入数据一定要支持事物回滚功能,就是哪怕前面已经导入了几十条数据了,如果发生一条脏数据导致插入异常,也必须回滚判定全部导入失败。避免重复导入,导致数据库脏数据。

我贴最后导入数据库的代码就是Upload操作,我在DAL层是使用了事物处理的,支持回滚!

 

复制代码
复制代码
        [HandleError(View = "~/Views/Shared/Error.cshtml")]
        public ActionResult Upload()
        {
            var result= Ioc.Service.IocBll<IStudentBll>.Provide.Insert(stus);

            if(string.Empty!=result.Success)  
                ViewBag.Info = result.Info;

            return View("UploadSuccess");

        }
复制代码
复制代码

 


标签:
本文的评论功能被关闭了.
备案信息冀ICP 0007948