C#、MVC的利用NPOI的Excel数据导入

C#、MVC的利用NPOI的Excel数据导入

1、关于MVC导入数据,这里用的是NPOI插件导入,该插件可以在VS软件中自行下载。
话不多说,直接上代码。

导入Excel数据
(1)导入数据,必须先要准备一个模板文件,供用户下载,然后在控制器 中写一个下载模板的方法
(2)在视图中通过window.open()方法调用控制器中的这个方法就好了

视图代码:

//======导入操作
 //1、下载导入模板文件
 function downImportTemplate()
 {
     window.open("@Url.Content("~/Main/DownImportTemplate")");
 }

控制器代码

public ActionResult DownImportTemplate()
 {
       //返回与web服务器上的指定虚拟路径相对应的文件物理路径
       string filePath = Server.MapPath("~/Document/用户导入模板.xls");
       //判断模板文件是否存在
       if (System.IO.File.Exists(filePath))
       {
            //获取文件的名称
             string strfileName = Path.GetFileName(filePath);
             /*File:返回一个文件    
                   参数一:具体返回文件(这里相当于声明一个文件类型FileStream(参数一:							文件物理路径,参数二:打开文件方式)),也可以是流
                    参数二:返回文件格式
                    参数三:返回文件名称
              */
            return File(new FileStream(filePath, FileMode.Open), 									"application/octet-stream", strfileName);
        }
       else
       {
           //Content:返回字符对象
          return Content("模板文件不存在,请练习系统运维人员。");
      }
 }

控制器代码二:

 public ActionResult ImportExcel(HttpPostedFileBase xlsFile)
 {
     ReturnJson msg = new ReturnJson();
     try
     {

         //获取文件的后缀
         string strExtension = Path.GetExtension(xlsFile.FileName);
         //检查文件是不是我们需要的格式
         if (".xls".Equals(strExtension, StringComparison.CurrentCultureIgnoreCase))
         {
             //2、把文件转换为二进制数组
             byte[] fileBytes = new byte[xlsFile.ContentLength];
             //2.2将上传的文件转换为二进制数组  
             xlsFile.InputStream.Read(fileBytes, 0, xlsFile.ContentLength);

             //3、将二进制数组转换为内存流
             MemoryStream excleMemoryStream = new MemoryStream(fileBytes);
             //利用NPOI把内存流中的数据读取成Excel
             NPOI.SS.UserModel.IWorkbook wokbook = new NPOI.HSSF.UserModel.HSSFWorkbook(excleMemoryStream);//HSSFWorkbook:将内容流转化工作簿

             //判断该工作簿是否有工作表  NumberOfSheets:判断工作表的
             if(wokbook.NumberOfSheets > 0)
             {
                 //获取第一个工作表
                 NPOI.SS.UserModel.ISheet sheet = wokbook.GetSheetAt(0);
                 //判断工作表是否存在行
                 if (sheet.PhysicalNumberOfRows > 0)
                 {
                     //创建一个临时表
                     DataTable dt = new DataTable();

                     //先获取表头行,为第二行,索引为1,因为第一行是说明
                     NPOI.SS.UserModel.IRow rowHeader = sheet.GetRow(1);
                     /*
                      FirstCellNum:获取某行第一个单元格下标
                      LastCellNum:获取某行的列数 !!!!!(只有这个获取的是数值,其它三个获取的都是索引)
                      FirstRowNum:获取第一个实际行的下标
                      LastRowNum:获取最后一个实际行的下标(获取当前行最后一个单元格的值)
                    */

                     //获取表格总列数 
                     int cellCount = rowHeader.LastCellNum;
                     //获取表格总行数
                     int rowCount = sheet.LastRowNum + 1;

                     //1、Excel表头作为dt的列
                     for (int i = rowHeader.FirstCellNum; i < cellCount; i++)
                     {
                         DataColumn dtColumn = new DataColumn(rowHeader.GetCell(i).StringCellValue.Trim());
                         //Columns:添加列
                         dt.Columns.Add(dtColumn);
                     }
                     //2、Excel数据作为dt的数据
                     for (int i = (sheet.FirstRowNum) + 2; i < rowCount; i++)
                     {
                         //获取行
                         NPOI.SS.UserModel.IRow row = sheet.GetRow(i);
                         DataRow dtRow = dt.NewRow();

                         if(row != null)
                         {
                             //第一次循环j是从第三行第一个单元格
                             for (int j = row.FirstCellNum; j < cellCount; j++)
                             {
                                 if(row.GetCell(j) != null)
                                 {
                                     dtRow[j] = row.GetCell(j).ToString();
                                 }
                             }
                         }
                         //将一行的数据添加到DataTable(临时表)中
                         dt.Rows.Add(dtRow);
                     }

                     //移除空行
                     removeEmptyRow(dt);

                     #region 数据验证
                     //查询学生表
                     List<S_Student> userStudent = (from tb in myModel.S_Student
                                                    select tb).ToList();
                     //查询班级表
                     List<S_Class> userClass = (from tb in myModel.S_Class
                                                  select tb).ToList();
                     //定义存放新增数据容器(用于保存新增的数据)
                     List<S_Student> saveUsers = new List<S_Student>();

                     //遍历DataTable(临时表)中的数据
                     for (int i = 0; i < dt.Rows.Count; i++)
                     {
                         try
                         {
                             DataRow dr = dt.Rows[i];
                             S_Student addStudent = new S_Student();

                             //1、编号
                             string studentNumber = dr["编号"].ToString().Trim();
                             int oldCount = userStudent.Count(o => o.studentNumber == studentNumber);
                             if(oldCount > 0)
                             {
                                 msg.Text = "第" + (i + 1) + "条数据的编号:【" + studentNumber + "】已存在,请修改";
                                 return Json(msg, JsonRequestBehavior.AllowGet);
                             }
                             addStudent.studentNumber = studentNumber;


                             //2、班级
                             string className = dr["班级"].ToString().Trim();
                             //根据班级名称 去到班级表 提取班级ID
                             addStudent.classID = userClass.Single(o => o.calssName == className).calssID;



                             //3、姓名
                             string studentName = dr["姓名"].ToString().Trim();
                             if (string.IsNullOrEmpty(studentName))
                             {
                                 msg.Text = "第" + (i + 1) + "条数据的姓名未填写,请检查";
                                 return Json(msg, JsonRequestBehavior.AllowGet);
                             }
                             addStudent.studentName = studentName;
                             //4、性别
                             string studentSex = dr["性别"].ToString().Trim();
                             if (string.IsNullOrEmpty(studentSex))
                             {
                                 msg.Text = "第" + (i + 1) + "条数据的性别未填写,请检查";
                                 return Json(msg, JsonRequestBehavior.AllowGet);
                             }
                             addStudent.studentSex = studentSex;
                             //5、手机号
                             string telephone = dr["手机号"].ToString().Trim();
                             if (string.IsNullOrEmpty(telephone))
                             {
                                 msg.Text = "第" + (i + 1) + "条数据的手机号未填写,请检查";
                                 return Json(msg, JsonRequestBehavior.AllowGet);
                             }
                             addStudent.telephone = telephone;
                             //6、身份证
                             string studentIDCard = dr["身份证号"].ToString().Trim();
                             int oldCount2 = userStudent.Count(o => o.studentIDCard == studentIDCard);
                             if (oldCount2 > 0)
                             {
                                 msg.Text = "第" + (i + 1) + "条数据的身份证:【" + studentIDCard + "】已存在,请修改";
                                 return Json(msg, JsonRequestBehavior.AllowGet);
                             }
                             addStudent.studentIDCard = studentIDCard;

                             //添加到要保存的列表中
                             saveUsers.Add(addStudent);
                             //添加到用于查看的列表allUseris
                             userStudent.Add(addStudent);
                         }
                         catch (Exception e)
                         {
                             Console.Write(e);
                             msg.Text = "第" + (i + 1) + "条数据不正确,请检查!";
                             return Json(msg, JsonRequestBehavior.AllowGet);
                         }
                     }
                     #endregion

                     #region 新增保存
                     //=============进行数据保存
                     try
                     {
                         //遍历新增数据
                         foreach (S_Student item in saveUsers)
                         {
                             //保存学生数据
                             myModel.S_Student.Add(item);
                             myModel.SaveChanges();
                         }
                         msg.State = true;
                         msg.Text = "数据导入成功,成功导入" + saveUsers.Count() + "条用户数据";
                     }
                     catch (Exception)
                     {
                         msg.Text = "数据导入保存失败";
                         return Json(msg, JsonRequestBehavior.AllowGet);
                     }
                     #endregion
                 }
                 else
                 {
                     msg.Text = "导入失败,请检查第一个工作表中是否存在数据!";
                 }
             }
             else
             {
                 msg.Text = "导入失败,请检查工作表是否存在";
             }
         }
         else
         {
             msg.Text = "导入失败,请上传.xls类型的文件";
         }
     }
     catch (Exception)
     {
         msg.Text = "导入失败,请检查是否有工作表,是否有数据,是否按照模板填写!";

     }

     return Json(msg, JsonRequestBehavior.AllowGet);
 }
/// <summary>
/// 5.3 去除datatable空行
/// </summary>
/// <param name="dt"></param>
private void removeEmptyRow(DataTable dt)
{
    //存放需要移除的DataRow
    List<DataRow> removeList = new List<DataRow>();
    //遍历所有的行
    for (int i = 0; i < dt.Rows.Count; i++)
    {
        bool rowDataIsEmpty = true;//标识是否是空行-默认为空行
        //遍历DataRow的所有列
        for (int j = 0; j < dt.Columns.Count; j++)
        {
            //判断数据是否为空
            if (!string.IsNullOrEmpty(dt.Rows[i][j].ToString().Trim()))
            {
                rowDataIsEmpty = false;
            }
        }
        //如果是空行,添加到removeList
        if (rowDataIsEmpty)
        {
            removeList.Add(dt.Rows[i]);
        }
    }
    //移除掉空行
    for (int i = 0; i < removeList.Count; i++)
    {
        dt.Rows.Remove(removeList[i]);
    }
}

ReturnJson 这个是封装的一个实体类,代码如下:

namespace PartOne.EntityClass
{
    public class ReturnJson
    {
        /// <summary>
        /// 状态
        /// </summary>
        public bool State { get; set; }
        /// <summary>
        /// 状态码
        /// </summary>
        public string Code { get; set; }
        /// <summary>
        /// 文本
        /// </summary>
        public String Text { get; set; }
        /// <summary>
        /// 附加数据
        /// </summary>
        public object Object { get; set; }
    }
}

最后说一下导入数据整体思路:

第一步:判断文件类型是否是.xls,判断正确后再执行下面操作
	1、获取上传的文件
	2、把文件转换为二进制数组
	3、将二进制数组转化为内存流
	4、利用NPOI把内存流中的数据读取成Excel
	5、使用NPOI读取数据
第二步:判断工作簿中是否有工作表
第三步:判断工作表中是否有数据
第四步:获取数据,保证数据的准确性和判断数据的重复性、移除空行
第五步:保存数据

最后:
其实不管是导出还是导入:都需要用到NPOI将表格数据转化为内存 流,在进行下一步
导出:将表格数据数据转化为内存流在导出
导入:将文件转化为二进制数组,在将二进制数组转化为内存流,然后将内存流的数据读取成Excel,在使用NPOI来读取数据

当修改模板的时候:选择另存为的时候,类型最好选这一个,因为这一个类型的兼容性是最好的

你可能感兴趣的:(MVC)