Asp.net Core MVC 导出execl

Asp.net Core MVC 导出execl


分享话语

之前不知道做了多少导入导出文档的功能,最熟悉的就是 通过post提交到后台,后台语言来处理。不过遇到很坑,博文写的很少,还请大家多多指教,一起学习,共同进步。

来吧,先上图

这里写图片描述

说一下功能,点击导入,选择要导入的exel文档,把execl中的文档插入到数据库中,在显示到页面中

首先说一下思路哈

A 通过<input type='file'> 表单form 来提交文档到后台

B 后台接收文档,保存到服务器
C 对文档进行处理,拿到数据,存储到数据

前台代码

@*
    For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
*@
@{
    ViewData["Title"] = "经营计划";
    var date = ViewBag.dateTime;
}
@section Header{
   <style>
       tr td {
        border:1px solid black;
       }
       td {
       text-align:center;
       height:40px;
       }
       tbody input {
       width:100%;
       border:none;
       height:100%;
       text-align:center;
       }
       .boxtobdy {
        border:2px solid red;
       }
    </style>
}
<section class="content">

        <div class="box box-success condition">
            <div class="box-header with-border">
                <h5 class="box-title"><i class="fa fa-book"></i> 查询条件</h5>
            </div>
            <!-- 查询条件表单 -->
            <div class="box-body">
                <div class="row">

                    <input type="hidden" id="reportname" name="reportname" value="" />
                    <input type="hidden" id="htmlTableStr" name="htmlTableStr" value="" />
                    <div class="col-md-3">
                        <div class="input-group">
                            <div class="input-group-addon">
                                <i class="fa"><span>计划年份</span></i>
                            </div>
                            <div>
                                <input class="layui-input" id="datetime" name="datetime" value="@date" onfocus="WdatePicker({ dateFmt: 'yyyy', readOnly: true });" type="text">
                            </div>
                        </div>
                    </div>
                    <div class="col-md-1">
                        <button class="btn btn-primary" type="button" id="btnSearch"><i class='fa fa-search'></i>查询</button>
                    </div>
                    @*<div class="col-md-4">


                         <div class="input-group ">

                                  <input id="txt_Path" type="text" class="form-control">


                                  <span id="btn_Browse" style="cursor:pointer;" onclick="$('input[id=fileUpload]').click();" class="input-group-addon">
                                  <i class="glyphicon glyphicon-folder-open"></i>&nbsp;&nbsp;&nbsp;浏览文件
                            </span>

                        </div>

                    </div>*@


                    <div class="col-md-1">
                        <form id="exelform" enctype="multipart/form-data" method="post" action="/Operate/Report/ExportExecl"  >
                            <input id="fileUpload" type="file" name="file" style="display:none">
                            <button class="btn btn-primary" type="button" id="btnReport"><i class='fa fa-search'></i>导入</button>
                        </form>
                    </div>

                    <div class="col-md-2">
                        <button class="btn btn-primary" type="button" id="btnEdit"><i class='fa fa-pencil'></i>编辑(开始、结束)</button>
                    </div>
                </div>
            </div>
        </div>
    <form id="planSubmit" name="planSubmit" method="post" action="/Operate/Report/SubmitProdPlan">
        <div class="box result tab-content" style="border-top:0" id="review">

            <table id="prodplan" style="width:100%">
                <thead>
                    <tr>
                        <td rowspan="2" style="width:200px">年月</td>
                        <td colspan="2">能源生产计划</td>
                        <td colspan="3">能源消耗计划</td>
                        <td colspan="8">经营计划</td>

                    </tr>
                    <tr>
                        <td>发电(kWh)</td>
                        <td>供冷(kWh)</td>
                        <td>耗气(Nm3)</td>
                        <td>耗电(kWh)</td>
                        <td>耗水(Nm3)</td>
                        <td>收入计划(元)</td>
                        <td>支出计划(元)</td>
                        <td>边际贡献计划(元)</td>
                        <td>补贴收入(元)</td>
                        <td>固定成本(元)</td>
                        <td>人工成本(元)</td>
                        <td>四项费用(元)</td>
                        <td>管理费用(元)</td>
                    </tr>
                </thead>
                <tbody></tbody>
            </table>

        </div>
    </form>
</section>
@section Scripts{

    <script src="~/lib/My97DatePicker/WdatePicker.js"></script>
    <script src="~/js/web/operate/report/prodplan.js"></script>
    <script src="~/lib/jquery-other/jquery.form.js"></script>
    <script src="~/lib/moment/moment.js"></script>
}

脚注

这里说明一下,因为原本的<input type='file'> 很丑,基本上没有愿意用,所有把他给隐藏了,只是一个承载文档容器,用form 提交到后台,在这里我遇到很多问题,给大家展示一下

先上图
这里写图片描述

注意:这里如果用 HttpPostedFileBase 来接收的话,会报错,因为这个是ASP.net FrameWork 支持的方法,先给大家展示一下错误,如下图
这里写图片描述

看到没有,练后台都不会进,直接就报错,在给你们截一下后台调试的图片
这里写图片描述

经过仔细研究.Net Core 里面没有HttpPostedFileBase 这个类,所以不能用这个方法接收,后来,我用想,要不要用HttpContext 来接收一下,看行不行,继续上图

这里写图片描述

换成HttpContext 来试试,看看能不能得到execl文档,调试走去

这里写图片描述

同样不进后台直接报错,错误信息如上图,面对这个问题,我查看关于.net Core 的资料,终于懂了,把正确的代码贴个大家,如下:

 /// <summary>
        /// execl导入
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ActionResult ExportExecl()
        {
            var file = Request.Form.Files;
            var filename = ContentDispositionHeaderValue.Parse(file[0].ContentDisposition).FileName.Trim('"');

            if (string.Empty.Equals(filename) || ".xlsx" != Path.GetExtension(filename))
            {
                throw new ArgumentException("当前文件格式不正确,请确保正确的Excel文件格式!");
            }
            var severPath = FileHelper.MapPath("~/wwwroot/prodplanfile/");//获取当前虚拟文件路径

            var savePath = Path.Combine(severPath, filename); //拼接保存文件路径

            try
            {
                using (FileStream fs = System.IO.File.Create(savePath))
                {
                    file[0].CopyTo(fs);
                    fs.Flush();
                }
                var stus = ReadExcelToEntityList<prodplan>(savePath);//插入数据
                if (stus != null)
                {
                    string time = stus[0].plan_date;
                    ViewBag.dateTime = Convert.ToDateTime(time).ToString("yyyy");
                }

                return View("PordPlan");
            }
            finally
            {
                System.IO.File.Delete(savePath);//每次上传完毕删除文件
            }

        }

注意:这用不用给方法带什么参数,直接用 Request.Form.Files 就能接收到你想要的文档,这个就Core类库的改变,第一个问题算是解决了。还有就是 把文件保存在服务器上不能用file.save()方法了,要换种思维using (FileStream fs = System.IO.File.Create(savePath))
{
file[0].CopyTo(fs);
fs.Flush();
}
这样可以了。
下面的问题就好说了,贴代码

把execl中的数据读取到table中

/// <summary>
        /// 把Execl中的代码读取到table中
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="filePath"></param>
        /// <returns></returns>

        public  IList<T> ReadExcelToEntityList<T>(string filePath) where T : class, new()
        {
            System.Data.DataTable tbl = ReadExcelToDataTable(filePath);//读取Excel数据到DataTable

            IList<T> list = DataTableToList<T>(tbl);

            return list;

        }
//Excel数据转DataTable 使用的oledb读取方式
        public System.Data.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工作表
            System.Data.DataTable table = new System.Data.DataTable("TempTable");
            adapter.Fill(table);

            System.Data.DataTable newTable = new System.Data.DataTable();
            newTable = table.Clone();//克伦架子
            foreach (DataColumn col in newTable.Columns)
            {
                if (col.DataType.FullName == "System.Double")
                {
                    col.DataType = Type.GetType("System.Decimal");
                }
            }

            newTable.Columns["计划日期"].ColumnName = "plan_date";
            newTable.Columns["发电量"].ColumnName = "power"; 
            newTable.Columns["供冷"].ColumnName = "cooling";
            //table.Columns["供冷"].DataType = Type.GetType("System.Decimal");
            newTable.Columns["耗气"].ColumnName = "gas_consumption";
            //table.Columns["耗气"].DataType = Type.GetType("System.Decimal");
            newTable.Columns["耗电"].ColumnName = "power_consumption";
            //table.Columns["耗电"].DataType = Type.GetType("System.Decimal");
            newTable.Columns["耗水"].ColumnName = "water_consumption";
            //table.Columns["耗水"].DataType = Type.GetType("System.Decimal");
            newTable.Columns["收入计划"].ColumnName = "income_plan";
            //table.Columns["收入计划"].DataType = Type.GetType("System.Decimal");
            newTable.Columns["支出计划"].ColumnName = "expenditure_paln";
            //table.Columns["支出计划"].DataType = Type.GetType("System.Decimal");
            newTable.Columns["边际贡献计划"].ColumnName = "contribution";
            //table.Columns["边际贡献计划"].DataType = Type.GetType("System.Decimal");
            newTable.Columns["供热量"].ColumnName = "heatingload";
            //table.Columns["供热量"].DataType = Type.GetType("System.Decimal");
            newTable.Columns["供蒸汽"].ColumnName = "steam_supply";
            //table.Columns["供蒸汽"].DataType = Type.GetType("System.Decimal");
            newTable.Columns["供热水"].ColumnName = "heatingwater";
            //table.Columns["供热水"].DataType = Type.GetType("System.Decimal");
            newTable.Columns["耗蒸汽"].ColumnName = "steam_consumption";
            //table.Columns["耗蒸汽"].DataType = Type.GetType("System.Decimal");
            newTable.Columns["补贴收入"].ColumnName = "subincome";
            //table.Columns["补贴收入"].DataType = Type.GetType("System.Decimal");
            newTable.Columns["固定成本"].ColumnName = "fixedcost";
            //table.Columns["固定成本"].DataType = Type.GetType("System.Decimal");
            newTable.Columns["人工成本"].ColumnName = "labourcost";
            //table.Columns["人工成本"].DataType = Type.GetType("System.Decimal");
            newTable.Columns["四项成本"].ColumnName = "fourcost";
            //table.Columns["四项成本"].DataType = Type.GetType("System.Decimal");
            newTable.Columns["管理费用"].ColumnName = "managecost";
            //table.Columns["管理费用"].DataType = Type.GetType("System.Decimal");
            newTable.Columns.Add("year");
            newTable.Columns.Add("month");
            //往新的table中添加数据
            foreach (DataRow row in table.Rows)
            {
                DataRow rowNew = newTable.NewRow();
                rowNew["plan_date"] = row["计划日期"];
                rowNew["power"] = row["发电量"];
                rowNew["cooling"] = row["供冷"];
                rowNew["gas_consumption"] = row["耗气"];
                rowNew["power_consumption"] = row["耗电"];
                rowNew["water_consumption"] = row["耗水"];
                rowNew["income_plan"] = row["收入计划"];
                rowNew["expenditure_paln"] = row["支出计划"];
                rowNew["contribution"] = row["边际贡献计划"];
                rowNew["heatingload"] = row["供热量"];
                rowNew["steam_supply"] = row["供蒸汽"];
                rowNew["heatingwater"] = row["供热水"];
                rowNew["steam_consumption"] = row["耗蒸汽"];
                rowNew["subincome"] = row["补贴收入"];
                rowNew["fixedcost"] = row["固定成本"];
                rowNew["labourcost"] = row["人工成本"];
                rowNew["fourcost"] = row["四项成本"];
                rowNew["managecost"] = row["管理费用"];
                rowNew["year"] = row["计划日期"].ToString().Split('-')[0];
                rowNew["month"] = Convert.ToInt32(row["计划日期"].ToString().Split('-')[1]).ToString();
                newTable.Rows.Add(rowNew);
            }
            return newTable;
        }

注意:因为execl中的列类型和实体列的类型不一致,所有我特意新建一个datatable,把列的类型也顺便修改了

 //DataTable转List<T>
        public List<T> DataTableToList<T>(System.Data.DataTable dt) where T : class, new()
        {
            if (dt == null) return 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))
                    {
                        try
                        {
                            if (pro.Name == "year")
                            {
                                object value = dr["plan_date"];

                                //value = Convert.ChangeType(value, pro.PropertyType);//强制转换类型
                                                                                    //如果非空,则赋给对象的属性  PropertyInfo
                                if (value != DBNull.Value)
                                {
                                    string year = value.ToString().Trim().Split('-')[0];
                                    pro.SetValue(t, year, null);
                                }
                            }
                            else if (pro.Name == "month")
                            {
                                object value = dr["plan_date"];
                                //value = Convert.ChangeType(value, pro.PropertyType);//强制转换类型
                                                                                    //如果非空,则赋给对象的属性  PropertyInfo
                                if (value != DBNull.Value)
                                {
                                    string month = Convert.ToInt32(value.ToString().Trim().Split('-')[1]).ToString();
                                    pro.SetValue(t, month, null);
                                }
                            }
                            else
                            {
                                object value = dr[pro.Name];
                                if (value != null)
                                {
                                    //value = Convert.ChangeType(value, pro.PropertyType);//强制转换类型                                                       
                                    //如果非空,则赋给对象的属性  PropertyInfo
                                    if (value != DBNull.Value)
                                    {
                                        if (pro.PropertyType.FullName == "System.String")
                                        {
                                            pro.SetValue(t, Convert.ToString(value), null);
                                        }
                                        else
                                        {
                                            pro.SetValue(t, Convert.ToDecimal(value), null);
                                        }
                                        //if (pro.PropertyType.FullName == "System.Decimal")
                                        //{
                                        //}
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            throw;
                        }
                    }
                }
                //对象添加到泛型集合中  
                list.Add(t);
            }
            return list;
          }

注意:不能使用value = Convert.ChangeType(value, pro.PropertyType);//强制转换类型
这样强转的话会报错,要改成if (pro.PropertyType.FullName == "System.String") { pro.SetValue(t, Convert.ToString(value), null); }这种方式去写,就会避免报错。


好了,就写到这里了,第一次,写的不好,请大家见谅!这个编辑器还没有用熟,多写写可能就好了。
欢迎大家批评和指导!


猜你喜欢

转载自blog.csdn.net/ccwm0129/article/details/74671849