打开 导入Excel文件 (异步)

引用 类库:

using NPOI.SS.UserModel;
using System.Threading;

object lockObject = new object();
int CurrentSheetIndex = 0;//当前选择的Sheet;
DateTime dateStart = DateTime.Now;//开始导入的时间
ISheet Currentsheet = null;//当前的Sheet;
int Step = 3000;//每个线程处理的行数
int MaxThreadQty = 6;//取大子线程数
int currentThreadQty = 0;//当前的子线程数
int ShowMessageCount = 50;//多少行才提示
int CurrentValue = 0;
DataTable dtPreview = null;//预览的数据
string resultByExcelToDB = "";//导入batch检查长度
Dictionary<string, int> Columns = new Dictionary<string, int>();//记录字段在当前表格中的顺序
Thread ttMain;
Thread tt;

        /// <summary>
        /// 选择文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpenFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog open = new OpenFileDialog();

            open.Filter = "Excel File|*.xls;*.xlsx";
            if (open.ShowDialog() == DialogResult.OK)
            {
                this.txtPath.Text = open.FileName;
                string s = txtPath.Text;
                //this.txtTableName.Text = s.Substring(s.LastIndexOf('\') + 1).Replace(".xls", "");

                try
                {
                    //尝试新的读方法
                    IWorkbook hssfworkbook;
                    using (FileStream file = new FileStream(open.FileName, FileMode.Open, FileAccess.Read))
                    {
                        hssfworkbook = WorkbookFactory.Create(file);
                        file.Dispose();
                    }
                    ISheet sheet = hssfworkbook.GetSheetAt(0);
                    comSheet.Items.Clear();
                    for (int i = 0; i < hssfworkbook.NumberOfSheets; i++)
                    {
                        comSheet.Items.Add(hssfworkbook.GetSheetName(i));
                    }


                    comSheet.SelectedIndex = 0;

                }
                catch (Exception ee)
                {
                    MessageBox.Show(ee.Message);
                }

            }


        }
        /// <summary>
        /// Sheet 选择切换事件,加载预览数据,这里只加载1千行,防止太多,加载太慢
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comSheet_SelectedIndexChanged(object sender, EventArgs e)
        {
            CurrentSheetIndex = comSheet.SelectedIndex;
            backgroundWorker1.RunWorkerAsync();
            labMsg.Text = "加载数据中,请耐心等待";
        }
        /// <summary>
        /// 读取excel 到DataTable 中
        /// 
        /// </summary>
        /// <param name="strFilePath">excel文档路径 这里是绝对路径,如果不是绝对路径</param>
        /// <param name="StartRowIndex">开始的行下标(包括标题行),起始值是0</param>
        /// <param name="SheetIndex">Shoee的下标,默认是0起始值是0</param>
        /// <param name="returnRowCount">返回指定行数的数据,主要是为了获取预览数据,0表示返回所有数据,否则就是指定的行数</param>
        /// <param name="FrisRowToColumn">第一行是否当作转换成数据表的列</param>
        /// <returns></returns>
        public DataTable Import(string strFilePath, int StartRowIndex, int SheetIndex = 0, int returnRowCount = 0, bool FrisRowToColumn = true)
        {
            Columns = new Dictionary<string, int>();//初始化
            DataTable dt = new DataTable();

            IWorkbook hssfworkbook;
            using (FileStream file = new FileStream(strFilePath, FileMode.Open, FileAccess.Read))
            {
                hssfworkbook = WorkbookFactory.Create(file);
            }
            Currentsheet = hssfworkbook.GetSheetAt(SheetIndex);
            //progressBar.Maximum = Currntsheet.LastRowNum;
            //labMsg.Text = Currntsheet.LastRowNum.ToString();
            if (Currentsheet.LastRowNum < Step)
            {
                ShowMessageCount = 50;
            }
            else if (Currentsheet.LastRowNum > Step && Currentsheet.LastRowNum < 10000)
            {
                ShowMessageCount = 100;
            }
            else
            {
                ShowMessageCount = 1000;
            }
            System.Collections.IEnumerator rows = Currentsheet.GetRowEnumerator();
            IRow headerRow = Currentsheet.GetRow(StartRowIndex);
            if (headerRow == null) return dt;//这里为什么读不到数据,还要再看一下
            int cellCount = headerRow.LastCellNum;
            if (FrisRowToColumn)//第一行转换成字段
            {
                for (int j = 0; j < cellCount; j++)
                {
                    ICell cell = headerRow.GetCell(j);
                    if (cell != null)
                    {
                        Columns[cell.ToString().Trim()] = j;
                        dt.Columns.Add(cell.ToString());
                    }
                    else
                    {
                        dt.Columns.Add("F" + j);
                    }
                }
                #region 验证表头是否正确
                try
                {
                    int ii = Columns["Material"];
                    // ii = Columns["Material Description"];
                    ii = Columns["Material Description"];
                    ii = Columns["Batch"];
                    ii = Columns["Storage Location"];
                    ii = Columns["Movement type"];
                    ii = Columns["Order"];
                    ii = Columns["Posting Date"];
                    ii = Columns["Purchase order"];
                    ii = Columns["Quantity"];
                    ii = Columns["Material Doc.Item"];
                    ii = Columns["Material Document"];
                }
                catch
                {
                    MessageBox.Show("请将表头设置成正确的值");
                }
                #endregion
                StartRowIndex++;
            }
            else
            {
                for (int j = 0; j < cellCount; j++)
                {
                    dt.Columns.Add("F" + j);
                }
            }
            int rowCount = 0;
            for (int i = StartRowIndex; i <= Currentsheet.LastRowNum; i++)
            {
                IRow row = Currentsheet.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);
                //如果已经到达要求的行数,返回
                rowCount++;
                if (returnRowCount > 0 && rowCount >= returnRowCount)
                {
                    break;
                }
            }
            return dt;
        }

        /// <summary>
        /// 导入按钮 执行删除导入到数据库里
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btndeleteImport_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(txtPath.Text.Trim()))
            {
                
                try
                {
                    Step = Convert.ToInt32(txt_Step.Text.Trim());
                    MaxThreadQty = Convert.ToInt32(txt_MaxThredQty.Text.Trim());
                }
                catch (Exception ee)
                {
                    MessageBox.Show(ee.Message);
                    return;
                }
                //初始化各数据
                progressBar.Value = 0;
                labMsg.Text = "";
                dateStart = DateTime.Now;
                CurrentValue = 0;
                currentThreadQty = 0;
                btndeleteImport.Enabled = false;
                btnCompute.Enabled = false;
                btnOpenFile.Enabled = false;
                btndel.Enabled = false;
                comSheet.Enabled = false;
                 ttMain = new Thread(() =>
                {
                    int taskCount;
                    try
                    {
                        taskCount = Currentsheet.LastRowNum / Step;//整除运算
                    }
                    catch (Exception)
                    {
                        MessageBox.Show("请耐心等待,数据加载完成再导入!");
                        return;
                    }
                    

                    for (int i = 0; i < taskCount + 1; i++)
                    {
                        int index = i;
                         tt = new Thread(() =>
                        {
                            DoAsyncImport(index * Step, index * Step + Step);

                        });

                        tt.IsBackground = true;
                        tt.Start();
                        currentThreadQty++;
                        Thread.Sleep(100);//防止线程扎堆
                        while (currentThreadQty >= MaxThreadQty)
                        {
                            Thread.Sleep(200);
                        }

                    }
                });

                ttMain.Start();
            }
            else
            {
                MessageBox.Show("请选择Excel表格!");
            }
        }



        /// <summary>
        /// 执行异步导入动作
        /// </summary>
        private void DoAsyncImport(int startIndex, int endIndex)
        {

            if (endIndex > Currentsheet.LastRowNum) endIndex = Currentsheet.LastRowNum + 1;
           

            for (int i = startIndex; i < endIndex; i++)
            {
                IRow row = Currentsheet.GetRow(i);
                if (i == 0 || row == null)//第一行是表头,不处理 
                {
                    continue;
                
                }
                DoInsertDB("WMTL_ITEM_BATCH", row);
                //lock (lockObject)
                //{
                    CurrentValue++;
                //}
                //减少显示信息的次数
                if (CurrentValue % ShowMessageCount == 0 || CurrentValue == Currentsheet.LastRowNum)
                {
                    if (this.progressBar.InvokeRequired)
                    {
                        this.progressBar.BeginInvoke(new SetMessageCallback(SetMesage), new object[] { CurrentValue, startIndex + "/" + endIndex });
                    }
                    else
                    {
                        SetMesage(CurrentValue, startIndex + "/" + endIndex);
                    }
                }
            }
            currentThreadQty--;


        }
        /// <summary>
        /// 处理单行数据,将数据插入到数据库中
        /// </summary>
        /// <param name="Table"></param>
        /// <param name="row"></param>
        private void DoInsertDB(string Table, IRow row)
        {
            string PostingDate = "";
            if (row.GetCell(Columns["Posting Date"]) != null)
            {
                try
                {
                    if (row.GetCell(Columns["Posting Date"]).CellType == CellType.STRING)
                {
                    PostingDate = DateTime.ParseExact(row.GetCell(Columns["Posting Date"]).StringCellValue, "dd.MM.yyyy", System.Globalization.CultureInfo.GetCultureInfo("en-US")).ToString("yyyy-MM-dd");
                    //  PostingDate = Convert.ToDateTime(row.GetCell(Columns["Posting Date"]).StringCellValue).ToString("yyyy-MM-dd");
                }
                else
                {
                        string strDate = DateTime.FromOADate(row.GetCell(Columns["Posting Date"]).NumericCellValue).ToString("d");
                        PostingDate = Convert.ToDateTime(strDate).ToString("yyyy-MM-dd");
                }
                }
                catch (Exception)
                {
                    MessageBox.Show(row.GetCell(Columns["Posting Date"]).NumericCellValue + "日期格式不合法");

                }
            }
            string MATERIAL = Convert.ToString(row.GetCell(Columns["Material"]));
            string MATERIAL_DESC = Convert.ToString(row.GetCell(Columns["Material Description"]));
            string BATCH = Convert.ToString(row.GetCell(Columns["Batch"]));
            //对batch  判断   如果开头为“00”,则为不合法数据 王万香2019年7月8日12:33:02
            string val = BATCH.Substring(0, 2);
            if (val == "00")
            {
                resultByExcelToDB += "" + row.RowNum + "行数据"+ BATCH + "常度不合法!
";
                return;
            }
            string STORAGE_LOCATION = Convert.ToString(row.GetCell(Columns["Storage Location"]));
            string MOVEMENT_TYPE = Convert.ToString(row.GetCell(Columns["Movement type"]));
            string ORDER_PO = Convert.ToString(row.GetCell(Columns["Order"]));
            string PURCHASE_ORDER = Convert.ToString(row.GetCell(Columns["Purchase order"]));
            string MATERIAL_DOC = Convert.ToString(row.GetCell(Columns["Material Document"]));
            string MATERIAL_DOC_ITEM = Convert.ToString(row.GetCell(Columns["Material Doc.Item"]));
            int QUANTITY = Convert.ToInt32( row.GetCell(Columns["Quantity"]).NumericCellValue);
            string POSTING_DATE = PostingDate;
            string USER_ID = FrmLogin.user_ID;
            string IMPORT_TIME = DateTime.Now.ToString("yyyy-MM-dd:HH:mm:ss");
            string sqlstr = " INSERT INTO " + Table + " SELECT '" + MATERIAL + "','" + MATERIAL_DESC + "','" + BATCH + "','" + STORAGE_LOCATION +
                            "','" + MOVEMENT_TYPE + "','" + ORDER_PO + "','" + PURCHASE_ORDER + "','" + MATERIAL_DOC + 
                             "','" + MATERIAL_DOC_ITEM + "'," + QUANTITY+",'"+ POSTING_DATE + "','" + USER_ID + "','" + IMPORT_TIME + "'";
            SqlServerHelper.ExeSql(sqlstr);
            //sqlstr += " WHERE NOT EXISTS(SELECT 'X' FROM " + Table + " T WHERE T.BATCH='" + BATCH + "')";
            //if (!SqlServerHelper.ExeSql(sqlstr))
            //{
            //    sqlstr = " UPDATE " + Table + "  SET MATERIAL='" + MATERIAL + "',MATERIAL_DESC='" + MATERIAL_DESC + "',BATCH='" + BATCH + "',MOVEMENT_TYPE='" + MOVEMENT_TYPE + "',ORDER_PO='" + ORDER_PO +
            //        "',PURCHASE_ORDER='" + PURCHASE_ORDER + "',MATERIAL_DOC='" + MATERIAL_DOC + "',POSTING_DATE='" + POSTING_DATE + "',QUANTITY=" + QUANTITY + ",USER_ID='" + USER_ID + "',IMPORT_TIME='" + IMPORT_TIME +
            //        "',STORAGE_LOCATION='"+ STORAGE_LOCATION + "',MATERIAL_DOC_ITEM='"+ MATERIAL_DOC_ITEM + "' WHERE BATCH='" + BATCH + "'";
            //}
        }

        /// <summary>
        /// 执行插入数据库的的动作,这个方法不使用了
        /// </summary>
        //   private void DoInsertDB(IRow row)
        //   {


        //       string sqlstr = @"INSERT INTO WMTL_ITEM_BATCH(
        //           MATERIAL,MATERIAL_DESC,BATCH,MOVEMENT_TYPE,ORDER_PO,PURCHASE_ORDER,
        //           COST_CENTER,MATERIAL_DOC,POSTING_DATE,DOCUMENT_DATE) 
        //VALUES('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}','{9}')";
        //       //for (int j = row.FirstCellNum; j < row.LastCellNum; j++)
        //       //{

        //       //}
        //       int ii = Columns["Material"];
        //       ii = Columns["Material Description"];
        //       ii = Columns["Batch"];
        //       ii = Columns["Movement type"];
        //       ii = Columns["Order"];
        //       ii = Columns["Purchase order"];
        //       //ii = Columns["Cost Center"];
        //       ii = Columns["Material Document"];

        //       //将两个时间的格式转换
        //       string PostingDate = "";
        //       if (row.GetCell(Columns["Posting Date"]) != null)
        //       {
        //           if (row.GetCell(Columns["Posting Date"]).CellType == CellType.STRING)
        //           {
        //               PostingDate = DateTime.ParseExact(row.GetCell(Columns["Posting Date"]).StringCellValue, "dd.MM.yyyy", System.Globalization.CultureInfo.GetCultureInfo("en-US")).ToString("yyyy-MM-dd");
        //               //  PostingDate = Convert.ToDateTime(row.GetCell(Columns["Posting Date"]).StringCellValue).ToString("yyyy-MM-dd");
        //           }
        //           else
        //           {
        //               string strDate = DateTime.FromOADate(row.GetCell(Columns["Posting Date"]).NumericCellValue).ToString("d");
        //               PostingDate = Convert.ToDateTime(strDate).ToString("yyyy-MM-dd");
        //           }
        //       }
        //       string DocumentDate = "";
        //       //if (row.GetCell(Columns["Document Date"]) != null)
        //       //{
        //       //    string strDate = DateTime.FromOADate(row.GetCell(Columns["Document Date"]).NumericCellValue).ToString("d");
        //       //    DocumentDate = Convert.ToDateTime(strDate).ToString("yyyy-MM-dd");
        //       //}


        //       sqlstr = string.Format(sqlstr, row.GetCell(Columns["Material"]), row.GetCell(Columns["Material Description"]), row.GetCell(Columns["Batch"]),
        //           row.GetCell(Columns["Movement type"]), row.GetCell(Columns["Order"]),
        //           row.GetCell(Columns["Purchase order"]), "",
        //           row.GetCell(Columns["Material Document"]), PostingDate, DocumentDate);
        //       SqlServerHelper.ExeSql(sqlstr);
        //   }
        delegate void SetMessageCallback(int value, string message);

        private void SetMesage(int value, string message)
        {

            this.progressBar.Value = CurrentValue;
            TimeSpan ts = DateTime.Now.Subtract(dateStart);
            this.labMsg.Text = CurrentValue + "/" + Currentsheet.LastRowNum + " 用时:" + ts.Minutes + "" + ts.Seconds + "";
            /// textBox1.Text = this.labMsg.Text + "
" + textBox1.Text;
            if (CurrentValue == Currentsheet.LastRowNum)
            {
                btndeleteImport.Enabled = true;
                btnCompute.Enabled = true;
                btnOpenFile.Enabled = true;
                btndel.Enabled = true;
                comSheet.Enabled = true;

                MessageBox.Show("导入完成");
                if (resultByExcelToDB!=null)
                {
                    MessageBox.Show(resultByExcelToDB,"提示");
                }
               
            }

        }
原文地址:https://www.cnblogs.com/x666066/p/11468571.html