1. 程式人生 > >EXCEL批量匯入資料MVC

EXCEL批量匯入資料MVC

using NPOI.HSSF.UserModel;
//批量匯入的頁面Action
public ActionResult ExcelAppendData()
{
    return View();
}

        /// 
        /// 匯入Excel方法
        /// 作者 劉建超:2017年10月16日17:32:11
        /// 
        /// 
        [HttpPost]
        public JsonResult LeadInMethod()
        {
            HttpPostedFileBase file = Request.Files["files"];
            try
            {
                string FileName;
                string savePath;

                //新增公有欄位,成功後傳給前臺,便於提示使用者:檔案匯入成功,不能重複匯入
                string fileFullName;
                #region 檢查檔案/儲存檔案
                if (file == null || file.ContentLength <= 0)
                {
                    return Json(new { result = false, message = "檔案不能為空,請先瀏覽選擇需要匯入的耗材表Excel檔案!" }, JsonRequestBehavior.AllowGet);
                }
                else
                {
                    string filename = Path.GetFileName(file.FileName);
                    int filesize = file.ContentLength;//獲取上傳檔案的大小單位為位元組byte
                    string fileEx = System.IO.Path.GetExtension(filename);//獲取上傳檔案的副檔名
                    string NoFileName = System.IO.Path.GetFileNameWithoutExtension(filename);//獲取無副檔名的檔名
                    int Maxsize = 20 * 1024 * 1024;//定義上傳檔案的最大空間大小為20M
                    string FileType = ".xls,.xlsx";//定義上傳檔案的型別字串

                    FileName = NoFileName + DateTime.Now.ToString("yyyyMMddhhmmss") + fileEx;
                    if (!FileType.Contains(fileEx))
                    {
                        return Json(new { result = false, message = "檔案型別不對,只能匯入xls和xlsx格式的檔案" }, JsonRequestBehavior.AllowGet);
                    }
                    if (filesize >= Maxsize)
                    {
                        return Json(new { result = false, message = "上傳檔案超過20M,不能上傳" }, JsonRequestBehavior.AllowGet);
                    }
                    string path = AppDomain.CurrentDomain.BaseDirectory + @"\Files\Excel";

                    savePath = Path.Combine(path, FileName);
                    fileFullName = filename;
                    #region 檔案儲存到伺服器
                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }
                    file.SaveAs(savePath);
                    #endregion
                }
                #endregion

                #region 將匯入的Excel轉換成Table   出現問題:不同IIS會出現版本問題,這裡註釋改成下面的相容性
                //string strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + savePath + ";" + "Extended Properties='Excel 12.0;IMEX=1'";
                //OleDbConnection conn = new OleDbConnection(strConn);
                //conn.Open();
                //OleDbDataAdapter myCommand = new OleDbDataAdapter("select * from [Sheet1$];", strConn);
                //DataSet myDataSet = new DataSet();
                //myCommand.Fill(myDataSet, "Sheet1$");
                //myCommand.Dispose();
                //conn.Close();
                //conn.Dispose();

                ////將資料錶轉換成datatable
                //System.Data.DataTable table = myDataSet.Tables["Sheet1$"].DefaultView.ToTable();
                #endregion

                System.Data.DataTable table = new DataTable();
                if (file.FileName.Substring(file.FileName.LastIndexOf(".") + 1).ToLower() == "xlsx")
                {
                    table = XlsxImport(savePath);
                }
                else
                {
                    table = XlsImport(savePath);
                }

                if (table != null && table.Rows.Count > 0)
                {
                    #region 判斷模板正確與否
                    var falseNum = 0;//判斷模板錯誤的列數
                    if (table.Columns.Count == 10)//判斷列數是否是十個
                    {
                        HM_ConsumableModel models = new HM_ConsumableModel();
                        //models.ConsNo = models.ConsName = models.ConsSpecification = models.ConsUnit = models.ConsPrice = models.ConsPayPrice = models.ConsSupplier;
                        string[] TemplateTitle = { "耗材編號", "耗材名稱", "耗材規格", "單位", "應售", "實售", "生產廠家", "拼音碼", "五筆碼", "自定義碼" };
                        string[] TemplateTitlel = { "ConsNo", "ConsName", "ConsSpecification", "ConsUnit", "ConsPrice", "ConsPayPrice", "ConsSupplier", "PYCode", "WBCode", "CustomCode" };
                        for (int k = 0; k < table.Columns.Count; k++)
                        {
                            if (TemplateTitle[k] != table.Columns[k].ColumnName.ToString().Trim())//判斷標題是否相同
                            {
                                falseNum++;
                            }
                            else
                            {
                                table.Columns[k].ColumnName = TemplateTitlel[k];//更換標題
                            }
                        }
                    }
                    else
                    {
                        falseNum++;
                    }
                    #endregion

                    #region 資料處理
                    if (falseNum == 0)
                    {
                        #region 刪除空行資料(耗材名稱,耗材規格和單位都為空的時候刪除此行資料)
                        List arrayRows = new List();//存放要刪除的行
                        for (int i = 0; i < table.Rows.Count; i++)
                        {
                            if (table.Rows[i][1].ToString() == "" && table.Rows[i][2].ToString() == "" && table.Rows[i][3].ToString() == "")
                            {
                                arrayRows.Add(i);
                            }
                        }
                        if (arrayRows.Count > 0)
                        {
                            for (int i = 0; i < arrayRows.Count; i++)
                            {
                                table.Rows.RemoveAt(i);//移除索引的行
                            }
                        }
                        #endregion

                        var tableRowsNum = table.Rows.Count;//初始行數
                        table.Columns.Add("IsValid", typeof(int));//加一列:有效
                        table.Columns.Add("HpId", typeof(int));//加一列:醫院ID 
                        table.Columns.Add("EpUid", typeof(Int64)); //加一列:企業使用者ID 
                        var hpID = Convert.ToInt32(currentLogin.HpId);
                        var epuID = currentLogin.EpUid;
                        //var hpID = 160;
                        //var epuID = 1;
                        #region 給table迴圈新增列和列的值
                        for (int i = 0; i < tableRowsNum; i++)
                        {
                            table.Rows[i]["IsValid"] = 1;
                            table.Rows[i]["HpId"] = hpID;
                            table.Rows[i]["EpUid"] = epuID;
                        }
                        #endregion

                        #region BulkCopy
                        SqlBulkCopyByDatatable(DBConfig.CustomerManage.HM_Consumable, table);
                        #endregion

                        return Json(new { result = true, message = "成功匯入" + tableRowsNum + "條資料!", fileFullName = fileFullName }, JsonRequestBehavior.AllowGet);
                    }
                    else
                    {
                        return Json(new { result = true, message = "模板錯誤請重新上傳!" }, JsonRequestBehavior.AllowGet);
                    }
                    #endregion
                }
                else
                {
                    return Json(new { result = false, message = "模板無資料!" }, JsonRequestBehavior.AllowGet);
                }
            }
            catch (Exception ex)
            {
                var values = ex.Message.ToString();
                var errorMessage = "";
                if (values == "列“ConsNo”不允許 DBNull.Value。")
                {
                    errorMessage += "匯入異常,原因是:耗材編號不能有空,請檢查模板資料表!";
                }
                else if (values == "列“ConsPrice”不允許 DBNull.Value。" || values == "列“ConsPayPrice”不允許 DBNull.Value。")
                {
                    errorMessage += "匯入異常,原因是:應售(或實售)不能有空,請檢查模板資料表!";
                }
                else if (values == "列“ConsSupplier”不允許 DBNull.Value。")
                {
                    errorMessage += "匯入異常,原因是:生產廠家不能有空,請檢查模板資料表!";
                }
                else
                {
                    errorMessage += values;
                }
                return Json(new { result = false, message = errorMessage }, JsonRequestBehavior.AllowGet);
            }
        }
        #endregion

        /// 讀取excel Xlsx
        /// 預設第一行為標頭
        /// 
        /// excel文件路徑
        /// 
        public static DataTable XlsxImport(string strFileName)
        {
            DataTable dt = new DataTable();

            NPOI.XSSF.UserModel.XSSFWorkbook hssfworkbook;
            using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read))
            {
                hssfworkbook = new NPOI.XSSF.UserModel.XSSFWorkbook(file);
            }
            var sheet = hssfworkbook.GetSheetAt(0);
            System.Collections.IEnumerator rows = sheet.GetRowEnumerator();

            var headerRow = sheet.GetRow(0);
            int cellCount = headerRow.LastCellNum;

            for (int j = 0; j < cellCount; j++)
            {
                var cell = headerRow.GetCell(j);
                dt.Columns.Add(cell.ToString());
            }

            for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++)
            {
                var row = sheet.GetRow(i);
                DataRow dataRow = dt.NewRow();

                for (int j = row.FirstCellNum; j < cellCount; j++)
                {
                    if (row.GetCell(j) != null)
                        dataRow[j] = row.GetCell(j).ToString();
                }

                dt.Rows.Add(dataRow);
            }
            return dt;
        }
        /// 讀取excel Xls
        /// 預設第一行為標頭
        /// 
        /// excel文件路徑
        /// 
        public static DataTable XlsImport(string strFileName)
        {
            DataTable dt = new DataTable();

            HSSFWorkbook hssfworkbook;
            using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read))
            {
                hssfworkbook = new HSSFWorkbook(file);
            }
            var sheet = hssfworkbook.GetSheetAt(0);
            System.Collections.IEnumerator rows = sheet.GetRowEnumerator();

            var headerRow = sheet.GetRow(0);
            int cellCount = headerRow.LastCellNum;

            for (int j = 0; j < cellCount; j++)
            {
                var cell = headerRow.GetCell(j);
                dt.Columns.Add(cell.ToString());
            }

            for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++)
            {
                var row = sheet.GetRow(i);
                DataRow dataRow = dt.NewRow();

                for (int j = row.FirstCellNum; j < cellCount; j++)
                {
                    if (row.GetCell(j) != null)
                        dataRow[j] = row.GetCell(j).ToString();
                }

                dt.Rows.Add(dataRow);
            }
            return dt;
        }





        /// 
        /// SqlBulkCopy批量匯入資料 Attention:SqlBulkCopy中列的名稱受大小寫敏感限制,因此在構造DataTable的時候應請注意列名要與表一致。
        /// 
        /// 資料庫目標表
        /// 源資料
        private void SqlBulkCopyByDatatable(string TableName, System.Data.DataTable dt)
        {
            using (var dbConnection = SqlDbHelper.CreateConnection())
            {

                var connectionString = ConfigurationManager.ConnectionStrings["SqlConnString"].ConnectionString;
                using (SqlBulkCopy sqlbulkcopy = new SqlBulkCopy(connectionString, SqlBulkCopyOptions.UseInternalTransaction))
                {
                    try
                    {
                        sqlbulkcopy.DestinationTableName = TableName;
                        for (int i = 0; i < dt.Columns.Count; i++)
                        {
                            sqlbulkcopy.ColumnMappings.Add(dt.Columns[i].ColumnName, dt.Columns[i].ColumnName);
                        }
                        sqlbulkcopy.WriteToServer(dt);
                    }
                    catch (System.Exception ex)
                    {
                        throw ex;
                    }
                }
            }
        }