NPOI 常用方法封装

NOPI使用常用方法封装

1、将ISheet转为List

/// <summary>
/// 工作表转List
/// </summary>
/// <typeparam name="T">需要转换的泛型类</typeparam>
/// <param name="sheet">工作表</param>
/// <param name="rowStartIndex">起始索引</param>
/// <returns></returns>
public static List<T> SheetToList<T>(ISheet sheet, int rowStartIndex = 1) where T : class, new()
{
    var list = new List<T>();
    var workType = sheet.Workbook.GetType().Name;
    var rows = sheet.GetRowEnumerator();
    if (rows == null) return null;
    IRow row = null;
    while (rows.MoveNext())
    {
        switch (workType)
        {
            case "XSSFWorkbook":
                row = (XSSFRow)rows.Current;
                break;
            case "HSSFWorkbook":
                row = (XSSFRow)rows.Current;
                break;
        }
        if (row == null || row.RowNum < rowStartIndex) continue;
        var t = Activator.CreateInstance(typeof(T)) as T;
        var props = t.GetType().GetProperties().ToArray();
        for (var i = 0; i < row.LastCellNum; i++)
        {
            var cell = row.GetCell(i);
            if (cell == null) continue;
            var type = props[i].PropertyType;
            var value = GetCellValue(type, cell.ToString());
            props[i].SetValue(t, value);
        }
        list.Add(t);
    }
    return list;
}


 /// <summary>
 /// 获取单元格的值
 /// </summary>
 /// <param name="valueType"></param>
 /// <param name="value"></param>
 /// <returns></returns>
 private static object GetCellValue(Type valueType, string value)
 {
     if (valueType == typeof(int))
     {
         return int.Parse(value);
     }
     else if (valueType == typeof(float))
     {
         return float.Parse(value);
     }
     else if (valueType == typeof(DateTime))
     {
         return DateTime.Parse(value);
     }
     else if (valueType == typeof(decimal))
     {
         return decimal.Parse(value);
     }
     else
     {
         return value;
     }
 }

// 对应扩展
/// <summary>
///  将数据表转为泛型对象
/// </summary>
/// <typeparam name="T">与工作表列对应数量的泛型实体类</typeparam>
/// <param name="sheet">休要转换工作表</param>
/// <param name="rowIndex">工作表中有效数据的起始索引</param>
/// <returns></returns>
public static List<T> TryTransToList<T>(this ISheet sheet, int rowIndex = 0) where T : class,new()
{
    try
    {
        return ExcelHelper.ExcelHelper.SheetToList<T>(sheet, rowIndex);
    }
    catch (Exception e)
    {
        throw new ArgumentNullException(paramName: nameof(TryTransToList), "数据转换异常,请检查源文件");
    }
}

说明:目前只支持的泛型类是根据工作表的实际模板生成,对复杂的表头还需扩展处理

2、IWorkbook 转 byte[]

/// <summary>
/// 将表格<seealso cref="IWorkbook"/>转为<seealso cref="Byte[]"/>流
/// </summary>
/// <param name="workbook"></param>
/// <returns></returns>
public static Byte[] ConvertToBytes(this IWorkbook workbook)
{
    try
    {
        var stream = new MemoryStream();
        workbook.Write(stream);
        return stream.ToArray();
    }
    catch (Exception ex)
    {
        return new byte[0]{};
    }
}

3、给ISheet新增一列

/// <summary>
/// 给指定工作表添加信息列
/// </summary>
/// <param name="sheet">信息表</param>
/// <param name="infos">错误信息</param>
/// <param name="colTitle">列标题</param>
/// <param name="titleRowIndex">列标题行起始索引</param>
/// <param name="backgroundColor">标记行的背景色</param>
/// <param name="foregroundColor">标记行的前景色</param>
/// <returns></returns>
public static Stream AddInfoColumn(
    ISheet sheet,
    List<WrongInfo> infos,
    string colTitle,
    int titleRowIndex=0,
    short backgroundColor = HSSFColor.Red.Index,
    short foregroundColor = HSSFColor.White.Index
    )
{
    if (sheet == null) return null;
    try
    {
        // 获取工作表得最后一列
        var firstRow = sheet.GetRow(titleRowIndex);
        var newColNum = firstRow.LastCellNum + 1;
        firstRow.CreateCell(firstRow.LastCellNum + 1).SetCellValue(colTitle); // 设置标题

        // 根据错误信息中行索引进行添加数据
        infos?.ForEach(a =>
        {
            var row = sheet.GetRow(a.RowIndex);
            row?.CreateCell(newColNum).SetCellValue(a.WrongMsg);
            //  改变这一行的文字颜色及背景色
            SetCellStyle(row, backgroundColor, foregroundColor);
        });
        return sheet.ConvertToStream();
    }
    catch (Exception e)
    {
        return null;
    }
}


/// <summary>
/// 设置单元格样式
/// </summary>
/// <param name="row"></param>
/// <param name="backgroundColor"></param>
/// <param name="foregroundColor"></param>
private static void SetCellStyle(
    IRow row,
    short backgroundColor=HSSFColor.Red.Index,
    short foregroundColor=HSSFColor.White.Index)
{
    if (row == null) return;
    foreach (var cell in row.Cells)
    {
        cell.CellStyle.FillBackgroundColor = backgroundColor;
        cell.CellStyle.FillForegroundColor = foregroundColor;
    }
}

4、通过Stream获取WorkBook

 /// <summary>
 /// 获取工作表空间
 /// </summary>
 /// <param name="stream">文件流</param>
 /// <param name="fileName">文件名称</param>
 /// <returns></returns>
 public static IWorkbook GetWorkbookByStream(Stream stream,string fileName)
 {
     // 判断是不是文件
     if (fileName.EndsWith(".xlsx"))
     {
         return new XSSFWorkbook(stream);
     }else if (fileName.EndsWith(".xls"))
     {
         return new HSSFWorkbook(stream);
     }
     else
     {
         return null;
     }
 }

5、给Row 中的Cell添加前景色和背景色

private static void SetCellStyle(
    IRow row)
{
    short background;
    short foreground;
    var workType = row.GetWorkbookType();
    switch (workType)
    {
        case ExcelFileType.Xlsx:
            background = new XSSFColor(Color.Red).Index;
            foreground = new XSSFColor(Color.Black).Index;
            break;
        case ExcelFileType.Xls:
            background = HSSFColor.Red.Index;
            foreground = HSSFColor.Black.Index;
            break;
        default:
            throw new ArgumentOutOfRangeException();
    }

    if (row == null) return;
    foreach (var cell in row.Cells)
    {
        cell.CellStyle.FillBackgroundColor = background;
        cell.CellStyle.FillForegroundColor = foreground;
    }
}

6、获取workbook的类型(2003/2007)

 /// <summary>
 /// 获取工作表的了类型
 /// </summary>
 /// <param name="sheet"></param>
 /// <returns></returns>
 public static ExcelFileType GetWorkbookType(this ISheet sheet)
 {
     var workType = sheet.Workbook.GetType().Name;
     switch (workType)
     {
         case "XSSFWorkbook":
             return ExcelFileType.Xlsx;
         case "HSSFWorkbook":
             return ExcelFileType.Xls;
         default: return default;
     }
 }

7、读取 File文件流扩展及校验

public static Stream ReadFileStream(this FileUploadDto fileDto) => fileDto.File?.OpenReadStream();

8、文件转换为IWorkbook 对象扩展

 /// <summary>
 /// 将文件dto 转换成工作表
 /// <see cref="ReadFileStream"/> or <seealso cref="CheckNull"/>
 /// </summary>
 /// <param name="fileDto">上传的文件</param>
 /// <returns></returns>
 public static IWorkbook ConvertToWorkbook(FileUploadDto fileDto)
 {
     try
     {
         var stream = fileDto.ReadFileStream().CheckNull();
         var fileName = fileDto.File.FileName;
         return ExcelHelper.ExcelHelper.GetWorkbookByStream(stream, fileName);
     }
     catch (Exception e)
     {
         throw new ArgumentNullException(paramName: nameof(ConvertToWorkbook), "文件流为空");
     }
 }

9、CheckNull 扩展集

/// <summary>
/// 检查转换后集合是否为空
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <returns></returns>
public static List<T> CheckNull<T>(this List<T> list)=>
    list ?? throw new ArgumentNullException(paramName: nameof(CheckNull), "未将对象实例化");

/// <summary>
/// 检查文件流是否为空
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public static Stream CheckNull(this Stream stream) =>
    stream ?? throw new ArgumentNullException(paramName: nameof(stream),"文件流为空");
posted @ 2020-11-10 17:52  easten  阅读(459)  评论(0编辑  收藏  举报