时隔两年再次操刀NPOI合并单元格

  一:前言

    时隔两年再次操刀对象NPOI的合并单元格。廉颇老矣尚能饭否,NPOI小小插件大大能量,黄口小儿,唧唧呱呱。

    NPOI相对与以前来说两年有了一点儿小的进步,去识别泛型。更简易的代码书写方式,更多的去思考,去实践。想两年前,初出江湖。大山一座座。连最基本的api都不能看懂,一波三折,觉得其难之又难。

  二:反射和泛型实现ListToDataTable和获取特性定义的文字做列头,废话少说点,上代码

  由于本人是写的Demo就用的类库,所以这里的特性继承的是FlagsAttribute(其实他也是继承自Attribute),这是一个简单的列名的特性,方便数据填充

 [AttributeUsage(AttributeTargets.Property, Inherited = true)]
    public class EnitityAttribute: FlagsAttribute
    {

        private string columnName;
        /// <summary>
        /// 列名
        /// </summary>
        public string ColumnName
        {
            get { return columnName; }
            set { columnName = value; }
        }
    }
View Code

  三:ListToDataTable(感觉Table才是NPOI的绝配吧)

    /// <summary>
        /// 讲list集合转换成datatable
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public static DataTable ListToDataTable(IList list)
        {
            DataTable result = new System.Data.DataTable();
            if (list.Count > 0)
            {
                PropertyInfo[] propertys = list[0].GetType().GetProperties();
                foreach (PropertyInfo pi in propertys)
                {
                    //获取类型
                    Type colType = pi.PropertyType;
                    //当类型为Nullable<>时
                    if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                    {
                        colType = colType.GetGenericArguments()[0];
                    }
                    //判断是否含有EnitityAttribute
                    if (pi.IsDefined(typeof(EnitityAttribute),true))
                    {
                        //获取EnitityAttribute所对应的ColumnName值
                        var objecet = pi.GetCustomAttribute(typeof(EnitityAttribute), true);
                        EnitityAttribute attr = objecet as EnitityAttribute;
                        result.Columns.Add(attr.ColumnName, colType);
                    }
                    else
                    {
                        result.Columns.Add(pi.Name, colType);
                    }

                  
                }
                for (int i = 0; i < list.Count; i++)
                {
                    ArrayList tempList = new ArrayList();
                    foreach (PropertyInfo pi in propertys)
                    {
                        object obj = pi.GetValue(list[i], null);
                        tempList.Add(obj);
                    }
                    object[] array = tempList.ToArray();
                    result.LoadDataRow(array, true);
                }
            }
            return result;
        }
View Code

  四:去实现单元格的合并

  

            HSSFWorkbook book = new HSSFWorkbook();
            NPOI.SS.UserModel.ISheet sheet = book.CreateSheet("Sheet1");
            NPOI.SS.UserModel.IRow headerrow = sheet.CreateRow(0);
            ICellStyle style = book.CreateCellStyle();
            style.Alignment = HorizontalAlignment.Center;
            style.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.DarkTeal.Index;
            var font = book.CreateFont();
            font.FontHeightInPoints = 10;
            font.IsBold = true;
            style.SetFont(font);
            //添加列名
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                ICell cell = headerrow.CreateCell(i);
                
                cell.SetCellValue(dt.Columns[i].ColumnName);
                cell.CellStyle = style;

            }



            //添加第一行数据
            IRow row = sheet.CreateRow(1);
            for (int j = 0; j < dt.Columns.Count; j++)
            {
                string cellText = dt.Rows[0][j].ToString();
                if (!string.IsNullOrWhiteSpace(cellText))
                    row.CreateCell(j).SetCellValue(cellText);
                else row.CreateCell(j).SetCellValue("-");


            }
            //从第二行开始循环,和上一行进行判断,如果相同,则合并
            for (int i = 1; i < dt.Rows.Count; i++)
            {
                row = sheet.CreateRow(i + 1);
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    string cellText = dt.Rows[i][j].ToString();
                    if (!string.IsNullOrWhiteSpace(cellText))
                        row.CreateCell(j).SetCellValue(cellText);
                    else row.CreateCell(j).SetCellValue("-");
                }
            }


            //合并单元格样式
            ICellStyle cellstyle = book.CreateCellStyle();
            cellstyle.VerticalAlignment = VerticalAlignment.Center;
            cellstyle.Alignment = HorizontalAlignment.Center;


            //合并行
            //总计单元行数
            int count = dt.Rows.Count+1;
            for (int k = 0; k < dt.Columns.Count; k++)
            {
                for (int i = 1; i < count; i++)
                {
                    //获取当前行第0列
                    string value = sheet.GetRow(i).GetCell(k).StringCellValue;

                    int end = i;
                    //找到结束为止
                    for (int j = i + 1; j < count; j++)
                    {
                        //获取下一行行第0列
                        string value1 = sheet.GetRow(j).GetCell(k).StringCellValue;

                        if (value != value1)
                        {
                            end = j - 1;
                            break;
                        }
                        else if (value == value1 || j == dt.Rows.Count)
                        {
                            if (!string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(value1) && !value.Equals("-") && !value1.Equals("-"))
                            {
                                end = j;
                            }
                        }
                    }
                    if (i != end)
                    {
                        sheet.AddMergedRegion(new CellRangeAddress(i, end, k, k));//和并单元格
                    }
                    var cell = sheet.GetRow(i).GetCell(k);
                    cell.CellStyle = cellstyle;
                    i = end;
                }
            }

            style.Alignment = HorizontalAlignment.Center;
            style.VerticalAlignment = VerticalAlignment.Center;
            FileStream fileStream = new FileStream($"D:\{title}.xls", FileMode.CreateNew, FileAccess.ReadWrite, FileShare.ReadWrite);

            book.Write(fileStream);
          
            fileStream.Close();
View Code

基本上照着抄就应该可以实现了。少Copy多写代码

原文地址:https://www.cnblogs.com/geekX/p/15061237.html