
using System;
using System.Data;
using System.IO;
using System.Text;
using System.Web;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;

namespace CallCenter.Utility
{
    public class NPOIHelper
    {
        private string _title;
        private string _sheetName;
        private string _filePath;

        /// <summary>
        /// 导出到Excel
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        public bool ToExcel(DataTable table, string[] columns = null)
        {
            FileStream fs = new FileStream(this._filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            IWorkbook workBook = new HSSFWorkbook();
            if (string.IsNullOrWhiteSpace(this._sheetName))
            {
                this._sheetName = "sheet1";
            }

            ISheet sheet = workBook.CreateSheet(this._sheetName);

            //处理表格标题
            IRow row = sheet.CreateRow(0);
            row.CreateCell(0).SetCellValue(this._title);
            sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, table.Columns.Count - 1));
            row.Height = 500;

            ICellStyle cellStyle = workBook.CreateCellStyle();
            IFont font = workBook.CreateFont();
            font.FontName = "微软雅黑";
            font.FontHeightInPoints = 17;
            cellStyle.SetFont(font);
            cellStyle.VerticalAlignment = VerticalAlignment.Center;
            cellStyle.Alignment = HorizontalAlignment.Center;
            row.Cells[0].CellStyle = cellStyle;

            //处理表格列头
            row = sheet.CreateRow(1);
            if (columns == null)
            {
                for (int i = 0; i < table.Columns.Count; i++)
                {
                    row.CreateCell(i).SetCellValue(table.Columns[i].ColumnName);
                    row.Height = 350;
                    sheet.AutoSizeColumn(i);
                }
            }
            else
            {
                for (int i = 0; i < columns.Length; i++)
                {
                    row.CreateCell(i).SetCellValue(columns[i]);
                    row.Height = 350;
                    sheet.AutoSizeColumn(i);
                }
            }




            //处理数据内容
            for (int i = 0; i < table.Rows.Count; i++)
            {
                row = sheet.CreateRow(2 + i);
                row.Height = 250;
                for (int j = 0; j < table.Columns.Count; j++)
                {
                    row.CreateCell(j).SetCellValue(table.Rows[i][j].ToString());
                    sheet.SetColumnWidth(j, 256 * 15);
                }
            }

            //写入数据流
            workBook.Write(fs);
            fs.Flush();
            fs.Close();

            return true;
        }

        /// <summary>
        /// 导出到Excel
        /// </summary>
        /// <param name="table"></param>
        /// <param name="title"></param>
        /// <param name="sheetName">空字符串或null的话默认sheet1</param>
        /// <param name="columns">自定义表格列头，默认null</param>
        /// <returns></returns>
        public bool ToExcel(DataTable table, string title, string sheetName, string filePath, string[] columns = null)
        {
            this._title = title;
            this._sheetName = sheetName;
            this._filePath = filePath;
            return ToExcel(table, columns);
        }

        /// <summary>
        /// 弹出下载框导出excel
        /// </summary>
        /// <param name="Name"></param>
        /// <param name="dt"></param>
        /// <returns></returns>
        public string ExportToExcel_old(string Name, DataTable dt, string[] cols = null)
        {
            try
            {
                HSSFWorkbook workbook = new HSSFWorkbook();
                ISheet sheet = workbook.CreateSheet("Sheet1");

                ICellStyle HeadercellStyle = workbook.CreateCellStyle();
                HeadercellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
                HeadercellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
                HeadercellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
                HeadercellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
                HeadercellStyle.Alignment = HorizontalAlignment.Center;
                HeadercellStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.SkyBlue.Index;
                HeadercellStyle.FillPattern = FillPattern.SolidForeground;
                HeadercellStyle.FillBackgroundColor = NPOI.HSSF.Util.HSSFColor.SkyBlue.Index;

                //字体
                NPOI.SS.UserModel.IFont headerfont = workbook.CreateFont();
                headerfont.Boldweight = (short)FontBoldWeight.Bold;
                headerfont.FontHeightInPoints = 12;
                HeadercellStyle.SetFont(headerfont);


                //用column name 作为列名
                int icolIndex = 0;
                IRow headerRow = sheet.CreateRow(0);
                if (cols == null || (cols != null && cols.Length == 0))
                {
                    foreach (DataColumn dc in dt.Columns)
                    {
                        ICell cell = headerRow.CreateCell(icolIndex);
                        cell.SetCellValue(dc.ColumnName);
                        cell.CellStyle = HeadercellStyle;
                        icolIndex++;
                    }
                }
                else
                {
                    foreach (string dc in cols)
                    {
                        ICell cell = headerRow.CreateCell(icolIndex);
                        cell.SetCellValue(dc);
                        cell.CellStyle = HeadercellStyle;
                        icolIndex++;
                    }
                }
                ICellStyle cellStyle = workbook.CreateCellStyle();

                //为避免日期格式被Excel自动替换，所以设定 format 为 『@』 表示一率当成text來看
                cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("@");
                cellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
                cellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
                cellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
                cellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;


                NPOI.SS.UserModel.IFont cellfont = workbook.CreateFont();
                cellfont.Boldweight = (short)FontBoldWeight.Normal;
                cellStyle.SetFont(cellfont);
                if (dt.Rows.Count > 0)
                {
                    //建立内容行
                    int iRowIndex = 0;
                    foreach (DataRow dr in dt.Rows)
                    {
                        int iCellIndex = 0;
                        IRow irow = sheet.CreateRow(iRowIndex + 1);
                        for (int i = 0; i < dt.Columns.Count; i++)
                        {
                            string strsj = string.Empty;
                            if (dr[i] != null)
                            {
                                strsj = dr[i].ToString();
                            }
                            ICell cell = irow.CreateCell(iCellIndex);
                            cell.SetCellValue(strsj);
                            cell.CellStyle = cellStyle;
                            iCellIndex++;
                        }
                        iRowIndex++;
                    }

                    //自适应列宽度
                    for (int i = 0; i < icolIndex; i++)
                    {
                        sheet.AutoSizeColumn(i);
                    }
                }
                using (MemoryStream ms = new MemoryStream())
                {
                    workbook.Write(ms);

                    HttpContext curContext = HttpContext.Current;


                    // 设置编码和附件格式
                    curContext.Response.ContentType = "application/vnd.ms-excel";
                    curContext.Response.ContentEncoding = Encoding.UTF8;
                    curContext.Response.Charset = "";
                    curContext.Response.AppendHeader("Content-Disposition",
                        "attachment;filename=" + HttpUtility.UrlEncode(Name + ".xls", Encoding.UTF8));

                    curContext.Response.BinaryWrite(ms.GetBuffer());

                    workbook = null;
                    ms.Close();
                    ms.Dispose();

                    curContext.Response.End();
                }

                return "";
            }
            catch
            {
                return "导出失败！";
            }
        }


        /// <summary>
        /// 弹出下载框导出excel => 创建多个Sheet：例如sheet1，sheet2...
        /// </summary>
        /// <param name="Name"></param>
        /// <param name="dt"></param>
        /// <returns></returns>
        public string ExportToExcel(string Name, DataTable dt, string[] cols = null)
        {
            try
            {
                HSSFWorkbook workbook = new HSSFWorkbook();
                //ISheet sheet = workbook.CreateSheet("Sheet1");
                
                //数据总数
                int count = dt.Rows.Count;
                //注意：1、Excel2003及以前版本65536行,256列;  2、Excel2007、2010版本1048576行,16384列
                int sheetpage = 50000;   //这里设置5w条
                //向上取整
                int sheetindexcount = int.Parse(Math.Ceiling(Convert.ToDecimal((double)count / sheetpage)).ToString());
                if(sheetindexcount == 0)
                    sheetindexcount = 1;

                for (int n = 1; n <= sheetindexcount; n++)
                {
                    ISheet sheet = workbook.CreateSheet("Sheet" + n);
                    ICellStyle HeadercellStyle = workbook.CreateCellStyle();
                    HeadercellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
                    HeadercellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
                    HeadercellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
                    HeadercellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
                    HeadercellStyle.Alignment = HorizontalAlignment.Center;
                    HeadercellStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.SkyBlue.Index;
                    HeadercellStyle.FillPattern = FillPattern.SolidForeground;
                    HeadercellStyle.FillBackgroundColor = NPOI.HSSF.Util.HSSFColor.SkyBlue.Index;

                    //字体
                    NPOI.SS.UserModel.IFont headerfont = workbook.CreateFont();
                    headerfont.Boldweight = (short)FontBoldWeight.Bold;
                    headerfont.FontHeightInPoints = 12;
                    HeadercellStyle.SetFont(headerfont);


                    //用column name 作为列名
                    int icolIndex = 0;
                    IRow headerRow = sheet.CreateRow(0);
                    if (cols == null || (cols != null && cols.Length == 0))
                    {
                        foreach (DataColumn dc in dt.Columns)
                        {
                            ICell cell = headerRow.CreateCell(icolIndex);
                            cell.SetCellValue(dc.ColumnName);
                            cell.CellStyle = HeadercellStyle;
                            icolIndex++;
                        }
                    }
                    else
                    {
                        foreach (string dc in cols)
                        {
                            ICell cell = headerRow.CreateCell(icolIndex);
                            cell.SetCellValue(dc);
                            cell.CellStyle = HeadercellStyle;
                            icolIndex++;
                        }
                    }
                    ICellStyle cellStyle = workbook.CreateCellStyle();

                    //为避免日期格式被Excel自动替换，所以设定 format 为 『@』 表示一率当成text來看
                    cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("@");
                    cellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
                    cellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
                    cellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
                    cellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;


                    NPOI.SS.UserModel.IFont cellfont = workbook.CreateFont();
                    cellfont.Boldweight = (short)FontBoldWeight.Normal;
                    cellStyle.SetFont(cellfont);
                    if (dt.Rows.Count > 0)
                    {
                        //建立内容行
                        int iRowIndex = 0;
                        #region 修改不用
                        //foreach (DataRow dr in dt.Rows)
                        //{
                        //    int iCellIndex = 0;
                        //    IRow irow = sheet.CreateRow(iRowIndex + 1);
                        //    for (int i = 0; i < dt.Columns.Count; i++)
                        //    {
                        //        string strsj = string.Empty;
                        //        if (dr[i] != null)
                        //        {
                        //            strsj = dr[i].ToString();
                        //        }
                        //        ICell cell = irow.CreateCell(iCellIndex);
                        //        cell.SetCellValue(strsj);
                        //        cell.CellStyle = cellStyle;
                        //        iCellIndex++;
                        //    }
                        //    iRowIndex++;
                        //}
                        #endregion

                        int startcount = (n - 1) * sheetpage;
                        int endcount = n * sheetpage;
                        if (sheetindexcount == n)
                            endcount = count;

                        //for (int x = 0; x < dt.Rows.Count; x++)
                        for (int x = startcount; x < endcount; x++)
                        {
                            int iCellIndex = 0;
                            IRow irow = sheet.CreateRow(iRowIndex + 1);
                            for (int i = 0; i < dt.Columns.Count; i++)
                            {
                                string strsj = string.Empty;
                                if (dt.Rows[x][i] != null)
                                {
                                    strsj = dt.Rows[x][i].ToString();
                                }
                                ICell cell = irow.CreateCell(iCellIndex);
                                cell.SetCellValue(strsj);
                                cell.CellStyle = cellStyle;
                                iCellIndex++;
                            }
                            iRowIndex++;
                        }

                        //自适应列宽度
                        for (int i = 0; i < icolIndex; i++)
                        {
                            sheet.AutoSizeColumn(i);
                        }
                    }
                }
                using (MemoryStream ms = new MemoryStream())
                {
                    workbook.Write(ms);
                    HttpContext curContext = HttpContext.Current;
                    // 设置编码和附件格式
                    curContext.Response.ContentType = "application/vnd.ms-excel";
                    curContext.Response.ContentEncoding = Encoding.UTF8;
                    curContext.Response.Charset = "";
                    curContext.Response.AppendHeader("Content-Disposition",
                        "attachment;filename=" + HttpUtility.UrlEncode(Name + ".xls", Encoding.UTF8));
                    curContext.Response.BinaryWrite(ms.GetBuffer());
                    workbook = null;
                    ms.Close();
                    ms.Dispose();
                    curContext.Response.End();
                }
                return "";
            }
            catch(Exception ex)
            {
                return "导出失败！" + ex.Message;
            }
        }
        /// <summary>
        /// 创建Sheet
        /// </summary>
        /// <param name="workBook"></param>
        /// <param name="sheetName"></param>
        /// <returns></returns>
        public ISheet CreateSheet(HSSFWorkbook workBook, string sheetName)
        {
            ISheet sheet = workBook.CreateSheet(sheetName);
            IRow RowHead = sheet.CreateRow(0);

            for (int iColumnIndex = 0; iColumnIndex < 10; iColumnIndex++)
            {
                RowHead.CreateCell(iColumnIndex).SetCellValue(Guid.NewGuid().ToString());
            }

            for (int iRowIndex = 0; iRowIndex < 20; iRowIndex++)
            {
                IRow RowBody = sheet.CreateRow(iRowIndex + 1);
                for (int iColumnIndex = 0; iColumnIndex < 10; iColumnIndex++)
                {
                    RowBody.CreateCell(iColumnIndex).SetCellValue(DateTime.Now.Millisecond);
                    sheet.AutoSizeColumn(iColumnIndex);
                }
            }
            return sheet;
        }

        /// <summary>
        /// 导入excel转换为datatable
        /// </summary>
        /// <param name="upfile"></param>
        /// <param name="headrow"></param>
        /// <returns></returns>
        public DataTable ExcelToTable(HttpPostedFile upfile, int headrow)
        {
            DataTable dt = new DataTable();

            IWorkbook workbook = null;

            Stream stream = upfile.InputStream;

            string suffix = upfile.FileName.Substring(upfile.FileName.LastIndexOf(".") + 1).ToLower();
            if (suffix == "xlsx") // 2007版本
            {
                workbook = new XSSFWorkbook(stream);
            }
            else if (suffix == "xls") // 2003版本
            {
                workbook = new HSSFWorkbook(stream);
            }

            //获取excel的第一个sheet
            ISheet sheet = workbook.GetSheetAt(0);

            //获取sheet的第一行
            IRow headerRow = sheet.GetRow(headrow);

            //一行最后一个方格的编号 即总的列数
            int cellCount = headerRow.LastCellNum;
            //最后一列的标号  即总的行数
            int rowCount = sheet.LastRowNum;
            //列名
            for (int i = 0; i < cellCount; i++)
            {
                dt.Columns.Add(headerRow.GetCell(i).ToString());
            }

            for (int i = (sheet.FirstRowNum + headrow); i <= sheet.LastRowNum; i++)
            {
                DataRow dr = dt.NewRow();

                IRow row = sheet.GetRow(i);
                for (int j = row.FirstCellNum; j < cellCount; j++)
                {
                    if (row.GetCell(j) != null)
                    {
                        dr[j] = row.GetCell(j).ToString();
                    }
                }

                dt.Rows.Add(dr);
            }

            sheet = null;
            workbook = null;

            return dt;
        }

        /// <summary>
        /// 上传excel文件，并且读取excel文件转换为datatable，  HttpPostedFileBase
        /// </summary>
        /// <param name="upfile"></param>
        /// <param name="headrow"></param>
        /// <returns></returns>
        public DataTable ExcelToTable(HttpPostedFileBase upfile, int headrow, out string filePath)
        {
            var ext = upfile.FileName.Substring(upfile.FileName.LastIndexOf(".") + 1).ToLower();
            var foldPath = $"{HttpContext.Current.Request.ApplicationPath}\\ExcelData\\{ DateTime.Now.ToString("yyyyMM")}";
            var server = HttpContext.Current.Server;
            if (!Directory.Exists(server.MapPath(foldPath)))
            {
                Directory.CreateDirectory(server.MapPath(foldPath));
            }
            filePath = server.MapPath($"{foldPath}\\") + Guid.NewGuid().ToString("N") + "." + ext;
            upfile.SaveAs(filePath);

            DataTable dt = new DataTable();
            IWorkbook workbook = null;
            Stream stream = upfile.InputStream;
            string suffix = ext;
            if (suffix == "xlsx") // 2007版本
            {
                workbook = new XSSFWorkbook(stream);
            }
            else if (suffix == "xls") // 2003版本
            {
                workbook = new HSSFWorkbook(stream);
            }

            //获取excel的第一个sheet
            ISheet sheet = workbook.GetSheetAt(0);

            //获取sheet的第一行
            IRow headerRow = sheet.GetRow(headrow);

            //一行最后一个方格的编号 即总的列数
            int cellCount = headerRow.LastCellNum;
            //最后一列的标号  即总的行数
            int rowCount = sheet.LastRowNum;
            //列名
            for (int i = 0; i < cellCount; i++)
            {
                dt.Columns.Add(headerRow.GetCell(i).ToString());
            }

            for (int i = (sheet.FirstRowNum + headrow + 1); i <= sheet.LastRowNum; i++)
            {
                DataRow dr = dt.NewRow();

                IRow row = sheet.GetRow(i);
                for (int j = row.FirstCellNum; j < cellCount; j++)
                {
                    if (row.GetCell(j) != null)
                    {
                        dr[j] = row.GetCell(j).ToString();
                    }
                }

                dt.Rows.Add(dr);
            }

            sheet = null;
            workbook = null;

            return dt;
        }

        /// <summary>
        /// 导入excel转换为datatable
        /// </summary>
        /// <param name="upfile"></param>
        /// <param name="headrow"></param>
        /// <returns></returns>
        public DataTable ExcelToTable(string fileName, int headrow)
        {
            DataTable dt = new DataTable();

            IWorkbook workbook = null;

            Stream stream = new FileStream(fileName, FileMode.OpenOrCreate);

            string suffix = fileName.Substring(fileName.LastIndexOf(".") + 1).ToLower();
            if (suffix == "xlsx") // 2007版本
            {
                workbook = new XSSFWorkbook(stream);
            }
            else if (suffix == "xls") // 2003版本
            {
                workbook = new HSSFWorkbook(stream);
            }

            //获取excel的第一个sheet
            ISheet sheet = workbook.GetSheetAt(0);

            //获取sheet的第一行
            IRow headerRow = sheet.GetRow(headrow);

            //一行最后一个方格的编号 即总的列数
            int cellCount = headerRow.LastCellNum;
            //最后一列的标号  即总的行数
            int rowCount = sheet.LastRowNum;
            //列名
            for (int i = 0; i < cellCount; i++)
            {
                dt.Columns.Add(headerRow.GetCell(i).ToString());
            }

            for (int i = (sheet.FirstRowNum + headrow + 1); i <= sheet.LastRowNum; i++)
            {
                DataRow dr = dt.NewRow();

                IRow row = sheet.GetRow(i);
                for (int j = row.FirstCellNum; j < cellCount; j++)
                {
                    if (row.GetCell(j) != null)
                    {
                        dr[j] = row.GetCell(j).ToString();
                    }
                }

                dt.Rows.Add(dr);
            }

            sheet = null;
            workbook = null;

            return dt;
        }
    }
}
