• NPOI 操作 Excel 从入门到放弃(以 .xlsx 为例)


    PM> Install-Package NPOI -Version 2.5.5

    基础操作

    实例化 Workbook

    public static IWorkbook CreateWorkbook(string fileName, Stream ms = null)
    {
        var fileType = Path.GetExtension(fileName);
    
        var isSuffixMatched = new Func<string, string, bool>((extension, suffix) =>
            string.Equals(extension, suffix, StringComparison.OrdinalIgnoreCase));
    
        if (isSuffixMatched(fileType, ".xls"))
        {
            return ms == null ? new HSSFWorkbook() : new HSSFWorkbook(ms);
        }
    
        if (isSuffixMatched(fileType, ".xlsx"))
        {
            return ms == null ? new XSSFWorkbook() : new XSSFWorkbook(ms);
        }
    
        throw new NotSupportedException("不支持的文件类型");
    }
    

    基于模板实例化 Workbook

    using FileStream fs = File.OpenRead(fileName);
    Workbook = WorkbookFactory.Create(stream);
    

    基于 IFormFile 实例化 Workbook

    using var ms = new MemoryStream();
    file.CopyTo(ms);
    ms.Seek(0, SeekOrigin.Begin);
    Workbook = CreateWorkbook(_fileName, ms);
    
    # 保存为 FileContentResult
    using var ms = new MemoryStream();
    ms.Seek(0, SeekOrigin.Begin);
    Workbook.Write(ms);
    var bytes = ms.ToArray();
    var file = new FileContentResult(bytes, "application/vnd.ms-excel") { FileDownloadName = _fileName };
    

    Vue 下载 FileContentResult 类型的 Excel 文件

     download(){
         var fileBytes = this.File.FileContents
         var bytes = window.atob(fileBytes)
         var n = bytes.length
         var u8arr = new Uint8Array(n)
         while (n--) {
         u8arr[n] = bytes.charCodeAt(n)
         }
         this.download(u8arr,this.FileName)
     },
     download(file, fileName) {
         const blob = new Blob([file])
         if (window.navigator.msSaveBlob) {
             // IE10+ 使用的下载方式
             return window.navigator.msSaveBlob(blob, fileName)
         }
         // 其他浏览器下载方式
         const reader = new FileReader()
         reader.readAsDataURL(blob)
         reader.onload = e => {
             const a = document.createElement('a')
             a.download = fileName
             a.href = e.target.result
             document.body.appendChild(a)
             a.click()
             document.body.removeChild(a)
         }
     }
    

    进阶操作

    宽度设置

    //自适应宽度
    cell.Sheet.AutoSizeColumn(cell.ColumnIndex);
    //以 100 个字符长度为宽度
    cell.Sheet.SetColumnWidth(cell.ColumnIndex, 100 * 256);
    

    样式设置

    样式总数有不能超过65535,建议使用字典方式来缓存所有样式列表;同一个单元格的样式只能由一个;如果修改了一个单元格对应的引用样式,则所有引用该样式的单元格都会生效

    private static ICellStyle CreateBaseStyle(IWorkbook wb, Action<ICellStyle> styleAction,Action<IFont> fontAction)
    {
        var style = wb.CreateCellStyle();
    
        #region 边框设置
        style.BorderTop = BorderStyle.Thin;
        style.BorderBottom = BorderStyle.Thin;
        style.BorderLeft = BorderStyle.Thin;
        style.BorderRight = BorderStyle.Thin;
        #endregion
    
        #region 背景色设置
        style.FillForegroundColor = HSSFColor.White.Index;
        style.FillPattern = FillPattern.SolidForeground;
        #endregion
    
        #region 布局设置
        style.Alignment = HorizontalAlignment.Left;
        style.VerticalAlignment = VerticalAlignment.Center;
        #endregion
    
        styleAction?.Invoke(style);
    
        #region 字体设置
        var font = wb.CreateFont();
        font.Color = HSSFColor.Black.Index;
        font.FontName = "微软雅黑";
        font.IsBold = false;
        font.FontHeightInPoints = 10;
        font.Underline = FontUnderlineType.None;
        fontAction?.Invoke(font);
        style.SetFont(font);
        #endregion
    
        return style;
    }
    
    

    自定义背景色

    var style = CreateBaseStyle(wb, sa =>
    {
        try
        {
            sa.FillForegroundColor = 0;
            ((XSSFColor)sa.FillForegroundColorColor).SetRgb(new byte[] { 255, 199, 206 });
        }
        catch (Exception e)
        {
            Trace.WriteLine(e);
            sa.FillForegroundColor = HSSFColor.Rose.Index;
        }
    }, fa => { });
    

    设置超链接

    public static void SetHyperlink(ICell cell, string description, string address)
    {
        var hy = cell.Sheet.Workbook.GetCreationHelper().CreateHyperlink(HyperlinkType.Document);
        hy.Address = address;
        cell.Hyperlink = hy;
        cell.SetCellValue(description);
    }
    

    设置下拉框

    支持对非法数据校验,但是不支持空数据校验

    public static void SetDropDownList<TEnum>(ICell cell) where TEnum : struct, Enum
    {
        var attributes = typeof(TEnum).GetMembers()
            .SelectMany(member =>
                member.GetCustomAttributes(typeof(DescriptionAttribute), true).Cast<DescriptionAttribute>())
            .Select(x => x.Description).ToArray();
    
        if (Enum.TryParse(cell.StringCellValue, out TEnum result))
        {
            cell.SetCellValue(result.GetDescription());
        }
    
        var dvHelper = cell.Sheet.GetDataValidationHelper();
        var constraint = dvHelper.CreateExplicitListConstraint(attributes);
        var addressList = new CellRangeAddressList(
            cell.RowIndex,
            65535,
            cell.ColumnIndex,
            cell.ColumnIndex);
        var dataValidation = dvHelper.CreateValidation(constraint, addressList);
        dataValidation.CreateErrorBox("错误", "请选择符合要求的数值");
        dataValidation.ShowErrorBox = true;
        cell.Sheet.AddValidationData(dataValidation);
    }
    

    合并单元格

    设置合并区域样式时,需要设置每个单元格;取合并区域对应的数据时,只需要取左上角第一个单元格的值即可

    public static void AddMergedRegions(ISheet sheet,
        params (string cellValue, CellRangeAddress cellRangeAddress, ICellStyle style)[] regions)
    {
        for (var i = 0; i < regions.Length; i++)
        {
            var (cellValue, cellRangeAddress, style) = regions[i];
            for (var rowIndex = cellRangeAddress.FirstRow;
                rowIndex <= cellRangeAddress.LastRow;
                rowIndex++)
            {
                var row = sheet.GetRow(rowIndex) ?? sheet.CreateRow(rowIndex);
                for (var colIndex = cellRangeAddress.FirstColumn;
                    colIndex <= cellRangeAddress.LastColumn;
                    colIndex++)
                {
                    var cell = row.GetCell(colIndex) ?? row.CreateCell(colIndex, CellType.String);
                    if (cell.ColumnIndex == cellRangeAddress.FirstColumn &&
                        cell.RowIndex == cellRangeAddress.FirstRow)
                    {
                        cell.SetCellValue(cellValue);
                    }
    
                    cell.CellStyle = style;
                }
            }
    
            sheet.AddMergedRegion(cellRangeAddress);
        }
    }
    

    创建批注

    批注数量不能超过65535,建议总量不要超过1000

    public static void SetCellComment(ISheet sheet, int rowNum, int colNum, string message, ICellStyle cellStyle)
    {
        var row = sheet.GetRow(rowNum) ?? sheet.CreateRow(rowNum);
        var cell = row.GetCell(colNum) ?? row.CreateCell(colNum);
        cell.RemoveCellComment();
    
        var creationHelper = sheet.Workbook.GetCreationHelper();
        //使用批注默认位置
        //var anchor = creationHelper.CreateClientAnchor();
        //指定批注位置
        var anchor = drawing.CreateAnchor(
          0,
          0,
          0,
          0,
          colNum + 1,
          rowNum + 1,
          colNum + 4,
          rowNum + 4);
        var drawing = sheet.DrawingPatriarch ?? sheet.CreateDrawingPatriarch();
        var comment = drawing.CreateCellComment(anchor);
        comment.String = creationHelper.CreateRichTextString(message);
        comment.Author = "hippieZhou";
        comment.Visible = false;
        comment.Address = cell.Address;
        cell.CellComment = comment;
    
        cell.CellStyle = cellStyle;
    }
    
    // 移除批注
     var sheet = workbook.GetSheetAt(i);
     var comments = sheet.GetCellComments();
     if (comments.Any())
     {
         //移除批注
         foreach (var cell in comments.Select(comment =>
             sheet.GetRow(comment.Key.Row).GetCell(comment.Key.Column)))
         {
             cell?.RemoveCellComment();
         }
     }
    
  • 相关阅读:
    java并发编程 线程间协作
    博客园添加目录,导航,回到顶部
    汉诺塔递归实现
    java并发编程 线程基础
    Flink中算子进行Chain的规则分析(最新代码,源码版本大于1.11.2)
    Flink流处理程序在Local模式下的运行流程源码分析
    Flink-DataStream流处理应用(Local模式下)运行流程-源码分析
    Flink Streaming基于滚动窗口的事件时间分析
    Spark-2.3.2 Java SparkSQL的自定义HBase数据源
    Spark-2.3.2 HBase BulkLoad
  • 原文地址:https://www.cnblogs.com/hippieZhou/p/15221576.html
Copyright © 2020-2023  润新知