• C# NOPI常用方法(记录老项目的方法)


    最近在维护公司的十年老项目。写了一些nopi的方法,记录一下。

            /// <summary>
            /// DataTable转成Excel表格
            /// </summary>
            /// <returns></returns>
            public static byte[] DataTableToExcel(DataTable dt)
            {
                using (HSSFWorkbook hssfworkbook = new HSSFWorkbook())//建立Excel 2003对象
                using (HSSFSheet sheet = (HSSFSheet)hssfworkbook.CreateSheet("sheet1"))//新建一个名称为sheet1的工作簿
                using (MemoryStream stream = new MemoryStream()) //二进制流中介
                {
                    DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation();//配置文件属性
                    dsi.Company = string.Empty;
                    dsi.Category = string.Empty;//类别
                    dsi.Manager = string.Empty;//管理者
                    hssfworkbook.DocumentSummaryInformation = dsi;
                    SummaryInformation si = PropertySetFactory.CreateSummaryInformation();
                    si.Subject = string.Empty;//主题
                    si.Title = string.Empty;//标题
                    si.ApplicationName = string.Empty;//不知道是啥
                    si.Author = string.Empty;//作者
                    si.LastAuthor = string.Empty;//上一次保存者
                    si.Comments = string.Empty;//备注
                    si.CreateDateTime = DateTime.Now;
                    hssfworkbook.SummaryInformation = si;
    
                    //Func<HSSFWorkbook, string, short, HSSFCellStyle> setstyle =
                    //    (hssfwb, fontname, fontsize)
                    //     =>
                    //     {
                    //         HSSFFont font = (HSSFFont)hssfwb.CreateFont();
                    //         HSSFCellStyle style = (HSSFCellStyle)hssfwb.CreateCellStyle();
                    //         style.SetFont(font);
                    //         font.FontName = fontname;
                    //         font.FontHeightInPoints = fontsize;
                    //         return style;
                    //     };
    
                    ////表格设置
                    //sheet.SetColumnWidth(1, 30 * 256);//第二列较宽 
                    //sheet.DefaultColumnWidth = 13;
                    //HSSFCellStyle style0 = setstyle(hssfworkbook, "微软雅黑", 14);
                    //HSSFCellStyle style1 = setstyle(hssfworkbook, "微软雅黑", 12);
    
                    //设置列名
                    HSSFRow row = (HSSFRow)sheet.CreateRow(0);
                    for (int i = 0; i < dt.Columns.Count; i++)
                    {
                        Cell cell = row.CreateCell(i);
                        cell.SetCellValue(dt.Columns[i].ColumnName);
                        //cell.CellStyle = style0;
                    }
                    //单元格赋值
                    for (int i = 0; i < dt.Rows.Count; i++)
                    {
                        Row row1 = sheet.CreateRow(i + 1);
                        for (int j = 0; j < dt.Columns.Count; j++)
                        {
                            Cell cell = row1.CreateCell(j);
                            var value = dt.Rows[i][j];
                            if (value != null && value != DBNull.Value)
                            {
                                var valueType = value.GetType();
    
                                if (valueType == typeof(double) || valueType == typeof(decimal) || valueType == typeof(float) ||
                                    valueType == typeof(double?) || valueType == typeof(decimal?) || valueType == typeof(float?) ||
                                    valueType == typeof(byte) || valueType == typeof(int) || valueType == typeof(long) ||
                                    valueType == typeof(byte?) || valueType == typeof(int?) || valueType == typeof(long?)
                                    )
                                {
                                    cell.SetCellValue(Convert.ToDouble(value));
                                }
                                else
                                {
                                    cell.SetCellValue(value.ToString());
                                }
                            }
                            else
                            {
                                cell.SetCellValue(string.Empty);
                            }
                            //cell.CellStyle = style1;
                        }
                    }
                    hssfworkbook.Write(stream);
                    return stream.ToArray();
                }
            }
    
    //使用
    DataTable dt = GetDataTable();
    dt.TableName = "导出的Excel";
    DataTableToExcel(dt);
    
            /// <summary>
            /// 获取带数据的模版表格
            /// </summary>
            /// <param name="columns">Key为数据库的列名,Value为表格中显示的列名称。</param>
            /// <param name="templetePath">模版文件的路径</param>
            /// <param name="data">数据库中的数据</param>
            /// <returns></returns>
            public static byte[] GetDataTempleteExcel(Dictionary<string, string> columns, string templetePath, DataTable data)
            {
                using (FileStream fs = new FileStream(templetePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                using (HSSFWorkbook workbook = new HSSFWorkbook(fs))
                using (HSSFSheet sheet1 = workbook.GetSheetAt(0) as HSSFSheet)
                using (MemoryStream stream = new MemoryStream())
                {
                    HSSFRow headerRow = sheet1.GetRow(0) as HSSFRow;//获取sheet的首行
                    int cellCount = headerRow.LastCellNum;  //一行最后一个方格的编号 即总的列数
                    int cellRowsCount = sheet1.LastRowNum + 1;//这个好像是获取的下标,所以加一。
    
                    if (cellCount != columns.Count)
                    {
                        throw new ArgumentException(nameof(columns));
                    }
                    if (cellRowsCount < 1)
                    {
                        throw new ArgumentNullException(nameof(cellRowsCount));
                    }
    
                    //赋值前清除下数据
                    for (int i = 1; i < cellRowsCount; i++) if (sheet1.GetRow(i) == null) continue; else sheet1.RemoveRow(sheet1.GetRow(i));
    
                    DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation();//配置文件属性
                    dsi.Company = string.Empty;
                    dsi.Category = string.Empty;//类别
                    dsi.Manager = string.Empty;//管理者
                    workbook.DocumentSummaryInformation = dsi;
                    SummaryInformation si = PropertySetFactory.CreateSummaryInformation();
                    si.Subject = string.Empty;//主题
                    si.Title = string.Empty;//标题
                    si.ApplicationName = string.Empty;//不知道是啥
                    si.Author = string.Empty;//作者
                    si.LastAuthor = string.Empty;//上一次保存者
                    si.Comments = string.Empty;//备注
                    si.CreateDateTime = DateTime.Now;
                    workbook.SummaryInformation = si;
    
                    DataRow[] dataRows = data.AsEnumerable().ToArray();
                    string[] columnNames = columns.Keys.ToArray();
    
                    //数据库中的列名,按照Excel中的列顺序排列。
                    List<string> dbColumnNames = new List<string>();
                    var columnRow = sheet1.GetRow(0);
                    for (int i = 0; i < cellCount; i++)
                    {
                        var excelColumnName = columnRow.GetCell(i).ToString().Trim();
                        foreach (var colKey in columnNames)
                        {
                            if (string.Equals(columns[colKey], excelColumnName, StringComparison.OrdinalIgnoreCase))
                            {
                                dbColumnNames.Add(colKey);
                                break;
                            }
                        }
                    }
    
                    //转成数组使用,因为感觉这样后面使用快一点。
                    string[] dbColumnNamesArray = dbColumnNames.ToArray();
    
                    if (dbColumnNamesArray.Length != cellCount)
                    {
                        throw new ArgumentException(nameof(dbColumnNamesArray));
                    }
    
                    //单元格赋值
                    for (int i = 0, c = dataRows.Length; i < c; i++)
                    {
                        Row row1 = sheet1.CreateRow(i + 1);
                        for (int j = 0; j < cellCount; j++)
                        {
                            Cell cell = row1.CreateCell(j);
                            var value = dataRows[i][dbColumnNamesArray[j]];
                            if (value != null && value != DBNull.Value)
                            {
                                cell.SetCellValue(value.ToString());
                            }
                            else
                            {
                                cell.SetCellValue(string.Empty);
                            }
                        }
                    }
    
                    workbook.Write(stream);
                    return stream.ToArray();
                }
            }
    
    //使用
    var columns = new Dictionary<string, string>()
    {
      { "Name","名称" },
      { "Age","年龄" },
    };
    DataTable dt = GetDataTable();
    dt.TableName = "导出的Excel";
    DataTableToExcel(columns,Server.MapPath("~/template/test.xls"),dt);
    
            /// <summary>
            /// 获取excel单元格中的值
            /// </summary>
            /// <param name="cellObj"></param>
            /// <returns></returns>
            public static string GetExcelCellValue(Cell cellObj, NPOI.SS.UserModel.Workbook workbook)
            {
                if (cellObj == null) return string.Empty;
    
                string cellValue = null;
    
                switch (cellObj.CellType)
                {
                    case CellType.Unknown:
                        break;
                    case CellType.NUMERIC:
                        //NPOI中数字和日期都是NUMERIC类型的,这里对其进行判断是否是日期类型
                        if (DateUtil.IsCellDateFormatted(cellObj))//日期类型
                        {
                            var date = cellObj.DateCellValue;
                            if (date != default(DateTime) && date != DateTime.MinValue)
                            {
                                cellValue = date.ToString("yyyy/MM/dd HH:mm:ss");
                            }
                        }
                        else//其他数字类型
                        {
                            cellValue = cellObj.NumericCellValue.ToString();
                        }
                        break;
                    case CellType.STRING:
                        cellValue = cellObj.StringCellValue;
                        break;
                    case CellType.FORMULA:
                        var eva = new NPOI.HSSF.UserModel.HSSFFormulaEvaluator(workbook);
                        cellValue = eva.Evaluate(cellObj).StringValue;
                        break;
                    case CellType.BLANK:
                        break;
                    case CellType.BOOLEAN:
                        cellValue = cellObj.BooleanCellValue.ToString();
                        break;
                    case CellType.ERROR:
                        cellValue = cellObj.ErrorCellValue.ToString();
                        break;
                    default:
                        break;
                }
    
                cellValue = string.IsNullOrWhiteSpace(cellValue) ? string.Empty : cellValue.Trim();
    
                return cellValue;
            }
    
    
    /*下面的代码虽然是我写的,但是我不是很清楚啥作用了。而且是和业务以及asp的控件交织在一起的,所以这个也就记录下,不需要看懂。*/
    
            /// <summary>
            /// 上传Excel并且返回Excel中的数据
            /// </summary>
            /// <param name="columns">表列名和Excel中的列名字典</param>
            /// <param name="fuInvoiceFile">上传文件的控件</param>
            /// <returns>1:是否上传成功;2:上传成功后的数据;3:上传失败的错误消息;4:当前Excel的对象;5.文件上传后的地址</returns>
            protected Tuple<bool, DataTable, string, Workbook, string> GetExcelDataTable(Dictionary<string, string> columns, FileUpload fuInvoiceFile)
            {
                #region 文件校验、上传到服务器
    
                string fileName = fuInvoiceFile.ShortFileName.Replace(":", "_").Replace(" ", "_").Replace("\", "_").Replace("/", "_");
                if (fileName.LastIndexOf('.') <= 0)
                {
                    return new Tuple<bool, DataTable, string, Workbook, string>(false, null, "- 文件错误!", null, null);
                }
                string fileExt = fileName.Substring(fileName.LastIndexOf("."));
                // 文件验证
                if (fileExt != ".xls" && fileExt != ".xlsx")
                {
                    return new Tuple<bool, DataTable, string, Workbook, string>(false, null, "- 只能选择Excel文件导入!", null, null);
                }
                string onlyFileName = fileName.Substring(0, fileName.LastIndexOf(".") + 1);
                string dir = $@"{Server.MapPath(@"upfile")}{DateTime.Now:yyyy-MM-dd}";
                if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);  // 创建日期目录
                string filePath = $"{dir}{onlyFileName}{Guid.NewGuid().ToString().Replace("-", string.Empty)}{fileExt}"; // 获得文件保存在服务器上的路径
    
                // 保存文件到服务器
                fuInvoiceFile.PostedFile.SaveAs(filePath);
    
                #endregion
    
                #region 实例化一个Excel
    
                FileStream fs = new FileStream(filePath, FileMode.Open);
                NPOI.SS.UserModel.Workbook workbook = new NPOI.HSSF.UserModel.HSSFWorkbook(fs);
                fs.Dispose();
                NPOI.SS.UserModel.Sheet sheet = workbook.GetSheetAt(0);
                if (sheet == null)
                {
                    sheet = workbook.CreateSheet("Sheet1");
                }
    
                #endregion
    
                #region 文件校验
    
                if (sheet.PhysicalNumberOfRows < 2)
                {
                    return new Tuple<bool, DataTable, string, Workbook, string>(false, null, "- 未获取到数据,请检查数据文件!", null, null);
                }
    
                var headerRow = sheet.GetRow(0) as NPOI.HSSF.UserModel.HSSFRow;//获取sheet的首行
                int cellCount = headerRow.LastCellNum;  //一行最后一个方格的编号 即总的列数
                //int cellRowsCount = sheet.LastRowNum + 1;//这个好像是获取的下标,所以加一。
    
                if (cellCount != columns.Count)
                {
                    return new Tuple<bool, DataTable, string, Workbook, string>(false, null, "- 列数不正确,请检查Excel文件!", null, null);
                }
    
    
                DataTable dt = new DataTable();
                var columnsKeys = columns.Keys.ToArray();
                for (int j = 0, clos = columnsKeys.Length; j < clos; j++)
                {
                    var headerText = headerRow.GetCell(j).ToString();
    
                    bool isNotExits = true;
    
                    foreach (var headerKey in columnsKeys)
                    {
                        var columnName = columns[headerKey];
                        if (columnName == headerText)
                        {
                            dt.Columns.Add(headerKey, typeof(string));
                            isNotExits = false;
                            break;
                        }
                    }
    
                    if (isNotExits)
                    {
                        return new Tuple<bool, DataTable, string, Workbook, string>(false, null, $"- 列名称[{headerText}]无法匹配,请使用系统提供的Excel模版导入!", null, null);
                    }
                }
    
                #endregion
    
                #region 读取数据
    
                for (int i = 1, rows = sheet.PhysicalNumberOfRows; i < rows; i++)
                {
                    var dtRow = dt.NewRow();
                    for (int j = 0, clos = columnsKeys.Length; j < clos; j++)
                    {
                        Row excelRow = sheet.GetRow(i);
                        if (excelRow == null) excelRow = sheet.CreateRow(i);
                        Cell cellObj = excelRow.GetCell(j);
                        if (cellObj == null) cellObj = excelRow.CreateCell(j);
    
                        dtRow[j] = DataTableRenderToExcel.GetExcelCellValue(cellObj, workbook);
                    }
                    dt.Rows.Add(dtRow);
                }
    
    
                #endregion
    
                #region 数据处理
    
                /// <summary>
                /// 删除DataTable下方的空数据行
                /// </summary>
                /// <param name="dt">要删除下方空数据行的数据列表</param>
                /// <param name="startIndex">有效列开始下标</param>
                /// <param name="endIndex">有效列结束下标</param>
                void DeleteDataTableBelowNullData(DataTable dtd, int startIndex, int endIndex)
                {
                    if (dtd == null) return;
    
                    int colLength = endIndex - startIndex + 1;
    
                    for (int i = dtd.Rows.Count - 1; i >= 0; i--)
                    {
                        var row = dtd.Rows[i].ItemArray;
                        int j = 0;
                        for (int y = startIndex; y <= endIndex; y++)
                        {
                            if (string.IsNullOrWhiteSpace(row?[y]?.ToString()))
                            {
                                j++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        if (j == colLength)
                        {
                            dtd.Rows.RemoveAt(i);
                        }
                        else
                        {
                            break;
                        }
                    }
                }
    
                DeleteDataTableBelowNullData(dt, 1, dt.Columns.Count - 1);
    
                #endregion
    
                return new Tuple<bool, DataTable, string, Workbook, string>(true, dt, null, workbook, filePath);
            }
    
            /// <summary>
            /// 执行Excel导入错误校验
            /// </summary>
            /// <param name="workbook">需要写入的Excel对象</param>
            /// <param name="messages">错误消息集合</param>
            /// <param name="filePath">Excel文件地址</param>
            /// <returns></returns>
            protected Tuple<bool, string> ExeExcelErrorMessage(Workbook workbook, List<string> messages, string filePath)
            {
                var sheet = workbook.GetSheetAt(0);
    
                Row excelRowHead = sheet.GetRow(0);
    
                int errorColIndex = excelRowHead.LastCellNum + 1;
    
                if (excelRowHead == null) excelRowHead = sheet.CreateRow(0);
                Cell excelCellErrorTipHead = excelRowHead.GetCell(errorColIndex);
                if (excelCellErrorTipHead == null) excelCellErrorTipHead = excelRowHead.CreateCell(errorColIndex);
                excelCellErrorTipHead.SetCellValue("导入提示");
    
                bool hasError = false;
    
                for (int i = 0, count = messages.Count; i < count; i++)
                {
                    string errorMessage = messages[i];
                    Row excelRow = sheet.GetRow(i + 1);
                    if (errorMessage.Length > 0)
                    {
                        Cell cell = excelRow.GetCell(errorColIndex);
                        if (cell == null) cell = excelRow.CreateCell(errorColIndex);
                        cell.SetCellValue(errorMessage);
                        hasError = true;
                    }
                }
    
                string navigateUrl = null;
    
                if (hasError)
                {
                    navigateUrl = string.Format("~/upfile/{0}/{1}", DateTime.Now.ToString("yyyy-MM-dd"), filePath.Substring(filePath.LastIndexOf('\') + 1));
    
                    var fs = new FileStream(Server.MapPath(navigateUrl), FileMode.OpenOrCreate, FileAccess.ReadWrite);
                    workbook.Write(fs);
                    fs.Dispose();
    
                }
                else
                {
                    if (File.Exists(filePath)) File.Delete(filePath);
                }
                workbook.Dispose();
    
                return new Tuple<bool, string>(hasError, navigateUrl);
            }
    
  • 相关阅读:
    Hive学习之路 (十二)Hive SQL练习之影评案例
    Hive学习之路 (十一)Hive的5个面试题
    Guava Files 源码分析(二)
    Guava Files 源码分析(一)
    观察者模式与Guava EventBus
    Guava 源码分析之 Beta, GwtCompatible, GwtIncompatible, Charset, HashCode
    Java IO的简单示例
    从volatile说到i++的线程安全问题
    乐观锁与悲观锁
    SimpleDateFormat的线程安全问题与解决方案
  • 原文地址:https://www.cnblogs.com/cluyun/p/14752228.html
Copyright © 2020-2023  润新知