创建execl导入工具类的步骤
发布时间:2022-03-11 11:41:09
1、创建实体属性标记
public class CellAttribute : Attribute
{
/// <summary>
///
/// </summary>
/// <param name="displayName">显示名称</param>
/// <param name="hander"></param>
public CellAttribute(string displayName, Type hander = null)
{
DisplayName = displayName;
Hander = hander;
}
/// <summary>
/// 显示名称
/// </summary>
public string DisplayName { get; set; }
/// <summary>
/// 类型
/// </summary>
public Type Hander { get; set; }
}
2、创建通用处理方法
public class XlsFileHandler<T> where T : new()
{
private readonly string _path;
private readonly Dictionary<string, CellAttribute> _cellAttributes;
readonly Dictionary<string, string> _propDictionary;
public XlsFileHandler(string path)
{
_path = path;
_cellAttributes = new Dictionary<string, CellAttribute>();
_propDictionary = new Dictionary<string, string>();
CreateMappers();
}
/// <summary>
/// 创建映射
/// </summary>
private void CreateMappers()
{
foreach (var prop in typeof(T).GetProperties())
{
foreach (CellAttribute cellMapper in prop.GetCustomAttributes(false).OfType<CellAttribute>())
{
_propDictionary.Add(cellMapper.DisplayName, prop.Name);
_cellAttributes.Add(cellMapper.DisplayName, cellMapper);
}
}
}
/// <summary>
/// 获取整个xls文件对应行的T对象
/// </summary>
/// <returns></returns>
public List<T> ToData()
{
List<T> dataList = new List<T>();
using (FileStream stream = GetStream())
{
IWorkbook workbook = new HSSFWorkbook(stream);
ISheet sheet = workbook.GetSheetAt(0);
var rows = sheet.GetRowEnumerator();
int lastCell = 0;
int i = 0;
IRow headRow = null;
while (rows.MoveNext())
{
var row = sheet.GetRow(i);
if (i == 0)
{
headRow = sheet.GetRow(0);
lastCell = row.LastCellNum;
}
else
{
T t = GetData(workbook, headRow, row, lastCell);
dataList.Add(t);
}
i++;
}
stream.Close();
}
return dataList;
}
/// <summary>
/// 获取T对象
/// </summary>
/// <param name="workbook"></param>
/// <param name="headRow"></param>
/// <param name="currentRow"></param>
/// <param name="lastCell"></param>
/// <returns></returns>
private T GetData(IWorkbook workbook, IRow headRow, IRow currentRow, int lastCell)
{
T t = new T();
for (int j = 0; j < lastCell; j++)
{
var displayName = headRow.Cells[j].StringCellValue;
if (!_cellAttributes.ContainsKey(displayName) || !_propDictionary.ContainsKey(displayName))
{
continue;
}
var currentAttr = _cellAttributes[displayName];
var propName = _propDictionary[displayName];
ICell currentCell = currentRow.GetCell(j);
string value = currentCell != null ? GetCellValue(workbook, currentCell) : "";
if (currentAttr.Hander != null)
{
SetValue(ref t, propName, InvokeHandler(currentAttr.Hander, value));
}
else
{
SetValue(ref t, propName, value);
}
}
return t;
}
/// <summary>
/// 动态执行处理方法
/// </summary>
/// <param name="type"></param>
/// <param name="value"></param>
/// <returns></returns>
private static object InvokeHandler(Type type, object value)
{
System.Reflection.ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes);
if (constructor == null) throw new ArgumentNullException("type");
object mgConstructor = constructor.Invoke(null);
System.Reflection.MethodInfo method = type.GetMethod("GetResults");
return method.Invoke(mgConstructor, new[] { value });
}
/// <summary>
/// 获取文件流
/// </summary>
/// <returns></returns>
private FileStream GetStream()
{
if (!File.Exists(_path)) throw new FileNotFoundException("path");
return new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.Read);
}
/// <summary>
/// 获取xls文件单元格的值
/// </summary>
/// <param name="workbook"></param>
/// <param name="cell"></param>
/// <returns></returns>
private static string GetCellValue(IWorkbook workbook, ICell cell)
{
string value;
switch (cell.CellType)
{
case CellType.FORMULA:
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
value = evaluator.Evaluate(cell).FormatAsString();
break;
default:
value = cell.ToString();
break;
}
return value;
}
/// <summary>
/// 设置T属性值
/// </summary>
/// <param name="t"></param>
/// <param name="propName"></param>
/// <param name="value"></param>
private static void SetValue(ref T t, string propName, object value)
{
var typeName = t.GetType().GetProperty(propName).PropertyType.Name;
var property = t.GetType().GetProperty(propName);
switch (typeName)
{
case "Int32":
property.SetValue(t, Convert.ToInt32(value), null);
break;
case "DateTime":
property.SetValue(t, Convert.ToDateTime(value), null);
break;
case "Decimal":
property.SetValue(t, Convert.ToDecimal(value), null);
break;
default:
property.SetValue(t, value, null);
break;
}
}
}
3、创建Execl文件映射类
public class ReadMapper
{
[CellAttribute("测试1")]
public decimal Code { get; set; }
[CellAttribute("测试2")]
public int Name { get; set; }
[CellAttribute("测试3", typeof(ClassCellHander))]
public string Group { get; set; }
[CellAttribute("测试4")]
public DateTime AddTime { get; set; }
}
4、指定Execl文件路径,通过通用处理方法导出映射实体
[Test]
public void Read1()
{
const string filePath = @"C:\Users\zk\Desktop\1.xls";
XlsFileHandler<ReadMapper> handler = new XlsFileHandler<ReadMapper>(filePath);
List<ReadMapper> readMappers = handler.ToData();
Assert.AreEqual(readMappers.Count, 3);
}


猜你喜欢
- 一、搭建步骤1、导入jar包、创建项目包结构2、在web.xml中配置前端控制器3、编写springMvc核心配置文件4、编写pojo类和C
- 本文实例讲述了Java8新增的重复注解功能。分享给大家供大家参考,具体如下:一 点睛在Java 8以前,同一个程序元素前最多只能使用一个相同
- 本文实例为大家分享了android自定义环形统计图动画的具体代码,供大家参考,具体内容如下一、测试截图二、实现原理 package
- 由于需要访问MongoDB,但是本地开发环境不能直接连接MongoDB,需要通过SecureCRT使用127.0.0.2本地IP代理。但是程
- 以下是测试代码:新建一个classlibrary,包含两个类class1和class2,这两个类中分别有一个方法,都是返回一个字符串,代码如
- Spring @RequestParam对象绑定在Spring中,如果在方法参数列表中使用@RequestParam标注多个参数,会让映射方
- 序言在flutter开发中,我们使用 bloc 框架,基于状态变更进行响应式开发。本篇文章,小轰将 bloc 核心业务块进行拆解简化,聊一聊
- 前言自从 2017 年 C# 7.0 版本开始引入声明模式和常数模式匹配开始,到 2022 年的 C# 11 为止,最后一个板块列表模式和切
- Android M(6.0)API 23后加入了权限请求设置,APP需要使用某些权限需要主动申请。权限分为3类,一组是Normal权限,无需
- //创建excelobject missing = System.Reflection.Missing.Value;Excel.Applic
- 一、简介在Flutter应用开发过程中,多个页面的跳转需要使用路由,除了官方提供的Navigator外,我们还可以使用一些第三方路由框架来实
- 本文实例讲述了Android编程之分辨率处理相关代码段。分享给大家供大家参考,具体如下:1. 通常我们所说的屏幕分辨率如800x480、96
- 一、前言先使用一个模板图片,在图片上添加图片或者文字都可以。二、依赖<dependency> <
- 1、AOP基本总结连接点(JoinPoint):连接点是程序运行的某个阶段点,如方法调用、异常抛出等切入点(Pointcut):切入点是Jo
- ProgressBar有2个子控件:SeekBar 拖动条控件RatingBar 星级评分控
- 线程中run()和start()的区别:对于Thread对象来说,当你调用的是start(),线程会被放到等待队列,等待CPU调度,不一定马
- 1.spring-kafka<dependency> <groupId>org.springframe
- 描述输入一行字符串,分别统计出其中英文字母、空格、数字和其它字符的个数输入描述:控制台随机输入一串字符串输出描述:输出字符串中包含的英文字母
- 1.1 简介 1.1.1 概述 Feign 旨在使编写 Java Http 客户端变得更容易。在使用 Ribbon + Rest
- 引入依赖 <dependency> <g