其他分享
首页 > 其他分享> > .NET通过NPOI构建带下拉框验证的Excel模板并下载(不是级联下拉框)

.NET通过NPOI构建带下拉框验证的Excel模板并下载(不是级联下拉框)

作者:互联网

环境VS2022+.NET6,Nuget引用包NPOI(2.5.6)

创建类ExcelHelper

using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;

namespace Demo.Common
{
    public class ExcelHelper
    {

        /// <summary>
        /// 获取Excel模板
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public XSSFWorkbook GetTemplate()
        {
            string typeSheetName = "Type";

            //列名集合
            var clmList = GetColumnTitileList();
            //下拉选项字典集合
            var ddlDic = GetDDLDic();

            //创建工作簿
            XSSFWorkbook workbook = new XSSFWorkbook();
            //创建模板Sheet页
            ISheet useSheet = workbook.CreateSheet("导入模板");
            //创建下拉框Sheet页并隐藏
            ISheet typeSheet = workbook.CreateSheet(typeSheetName);
            workbook.SetSheetHidden(workbook.GetSheetIndex(typeSheet), true);

            //创建下拉框Sheet页行
            IRow row = useSheet.CreateRow(0);
            int maxRowNum = ddlDic.Max(t => t.Value.Count);
            for (int i = 0; i < maxRowNum + 1; i++)
            {
                IRow typeRow = typeSheet.CreateRow(i);
            }

            if (clmList == null || clmList.Count == 0)
                throw new Exception("列名集合不能为空");
            //循环每一列进行添加操作
            for (int i = 0; i < clmList.Count; i++)
            {
                //在模板页添加表头
                row.CreateCell(i).SetCellValue(clmList[i]);

                //如果再下拉框字典中存在这个列则需要将值放到下拉框Sheet页里面,然后在模板页绑定下拉框并加上验证
                if (ddlDic.ContainsKey(clmList[i]))
                {
                    IRow tmpRow = typeSheet.GetRow(0);
                    tmpRow.CreateCell(i).SetCellValue(clmList[i]);
                    string[] tmpArr = ddlDic[clmList[i]].ToArray();
                    for (int j = 0; j < tmpArr.Length; j++)
                    {
                        typeSheet.GetRow(j + 1).CreateCell(i).SetCellValue(tmpArr[j]);
                    }
                    string colName = GetExcelColumnName(i + 1);
                    XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper(useSheet as XSSFSheet);
                    XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint)dvHelper.CreateFormulaListConstraint(string.Format("{2}!${0}$2:${0}${1}", colName, tmpArr.Length+1, typeSheetName));
                    CellRangeAddressList cellRegions = new CellRangeAddressList(1, 500, i, i);
                    XSSFDataValidation validation = (XSSFDataValidation)dvHelper.CreateValidation(dvConstraint, cellRegions);
                    validation.SuppressDropDownArrow = true;
                    validation.CreateErrorBox("输入不合法", "请选择下拉列表中的值。");
                    validation.ShowErrorBox = true;
                    useSheet.AddValidationData(validation);
                }
            }
            useSheet.DefaultColumnWidth = 20;

            return workbook;
        }

        /// <summary>
        /// 构建下拉选项的数据--测试数据,手动构建,可以替换成从数据库取数
        /// </summary>
        /// <returns></returns>
        private Dictionary<string, List<string>> GetDDLDic()
        {
            Dictionary<string, List<string>> keyValues = new Dictionary<string, List<string>>();
            keyValues.Add("年级", new List<string>() { "一年级", "二年级", "三年级" });
            keyValues.Add("性别", new List<string>() { "男", "女" });
            keyValues.Add("学校", new List<string>() { "学校1", "学校2", "学校3", "学校4" });
            return keyValues;
        }

        /// <summary>
        /// 获取Excel标题行名称集合
        /// </summary>
        /// <returns></returns>
        private List<string> GetColumnTitileList()
        {
            return new List<string>() { "学号", "姓名", "性别", "学校", "年级" };
        }

        /// <summary>
        /// 获取Excel列名
        /// </summary>
        /// <param name="columnNumber">列的序号,如:A、B、C、AA、BB</param>
        /// <returns></returns>
        private static string GetExcelColumnName(int columnNumber)
        {
            int dividend = columnNumber;
            string columnName = String.Empty;
            int modulo;
            while (dividend > 0)
            {
                modulo = (dividend - 1) % 26;
                columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
                dividend = (int)((dividend - modulo) / 26);
            }
            return columnName;
        }

    }
}

创建控制器TemplateController

using Demo.Common;
using Microsoft.AspNetCore.Mvc;

namespace Demo.Controllers
{
    public class TemplateController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// 下载模板
        /// </summary>
        /// <returns></returns>
        public FileResult Download()
        {
            var workbook = new ExcelHelper().GetTemplate();
            var ms = new NpoiMemoryStream();
            ms.AllowClose = false;
            workbook.Write(ms);
            ms.Flush();
            ms.Seek(0, SeekOrigin.Begin);
            ms.AllowClose = true;
            string filename = "模板" + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".xlsx";
            return File(ms, "application/vnd.ms-excel", filename);
        }
    }
}

添加类NpoiMemoryStream

namespace Demo.Common
{
    public class NpoiMemoryStream : MemoryStream
    {
        public NpoiMemoryStream()
        {
            AllowClose = true;
        }

        public bool AllowClose { get; set; }

        public override void Close()
        {
            if (AllowClose)
                base.Close();
        }
    }
}

 

标签:Excel,NPOI,public,clmList,ms,workbook,new,下拉框
来源: https://www.cnblogs.com/LTQ151/p/16394175.html