ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

EPPlus扩展封装

2022-02-18 19:01:21  阅读:161  来源: 互联网

标签:set 封装 get int EPPlus 扩展 var return public


  开发过程中难免会遇到读取excel的上百个title所有列的数据,而这种我们可以采用简单除暴的方式,直接通过epplus取sheel的行和列的位置,但是这种实现可读性非常差。

针对这种情况,我通过可配置mapping的方式实现,通过excel的title的标题与Entity对象做个映射读取到DataTable,然后操作DataTable已读取好的excel数据。

以下实现支持excel的title多行合并配置

1、首先定义接口类

    public interface IProcessExcel
    {
        ProcessExcel SetWorksheetIndex(int positionId);
        DataTable Execute(ExcelPackage excelPackage);
        Task<dynamic> ExcelLoadProcess(IFormFile formFile, Func<ExcelPackage, IProcessExcel, Task<dynamic>> func, CancellationToken cancellationToken);
        void SetProperty<T>(T entity, DataRow dataRow, string prefix = "") where T : class;
    }

2、继承IProcessExcel 实现抽象接口的对应方法

 public class ProcessExcel : IProcessExcel
    {
        private int PositionId { get; set; }
        private int FromRow { get; set; }
        private int FromCol { get; set; }
        private int ToRow { get; set; }
        private bool IsOffset { get; set; }
        private int StartFromRow { get; set; }
        private ConcurrentDictionary<string, string> FieldsMapping { get; set; } = new ConcurrentDictionary<string, string>();
        private string SheetName { get; set; }

        public ProcessExcel SetWorksheetIndex(int positionId)
        {
            PositionId = positionId;
            return this;
        }

        public ProcessExcel SetExcelRange(int fromRow, int fromCol, int toRow)
        {
            FromRow = fromRow;
            FromCol = fromCol;
            ToRow = toRow;
            return this;
        }

        public ProcessExcel SetExcelRange(int startFromRow)
        {
            StartFromRow = startFromRow;
            return this;
        }

        public ProcessExcel SetOffset(bool isOffset)
        {
            IsOffset = isOffset;
            return this;
        }

        public ProcessExcel SetMapping(ConcurrentDictionary<string, string> fieldsMapping)
        {
            FieldsMapping = fieldsMapping;
            return this;
        }

        public ProcessExcel SetSheetName(string sheetName)
        {
            SheetName = sheetName;
            return this;
        }

        public async Task<dynamic> ExcelLoadProcess(IFormFile formFile, Func<ExcelPackage, IProcessExcel, Task<dynamic>> func, CancellationToken cancellationToken)
        {
            await using var stream = new MemoryStream();
            await formFile.CopyToAsync(stream, cancellationToken);
            using var package = new ExcelPackage(stream);
            return await func(package, this);
        }

        public DataTable Execute(ExcelPackage excelPackage)
        {
            var worksheet = excelPackage.Workbook.Worksheets[PositionId];
            if (!string.IsNullOrEmpty(SheetName))
            {
                if (!worksheet.Name.Contains(SheetName)) throw new xxException($"未知的模板:{worksheet.Name},请检查!");
            }
            if (worksheet.Dimension == null) throw new xxException($"{worksheet.Name}没有数据");

            var column = worksheet.Dimension.End.Column;
            var rows = worksheet.Dimension.Rows;

            if (rows <= 0 || column <= 0) throw new xxException($"{worksheet.Name}没有数据");

            var dt = new DataTable(worksheet.Name);
            var headerName = string.Empty;
            foreach (var cell in worksheet.Cells[FromRow, FromCol, ToRow, column])
            {
                if (IsOffset)
                {
                    var headerValue = cell.Offset(cell.Rows - FromRow, cell.Columns - ToRow).Text;
                    if (!string.IsNullOrEmpty(headerValue))
                    {
                        headerName = headerValue.Trim();
                    }
                }

                var columnName = cell.Text.Trim();
                columnName = string.IsNullOrEmpty(columnName) ? headerName : $"{headerName}-{columnName}";

                if (FieldsMapping.Any() && FieldsMapping.TryGetValue(columnName, out var field) && !string.IsNullOrEmpty(field))
                {
                    columnName = field.ToLower();
                }

                if (!dt.Columns.Contains(columnName) && !string.IsNullOrEmpty(columnName))
                {
                    dt.Columns.Add(columnName);
                }
            }

            for (var i = StartFromRow; i <= worksheet.Dimension.End.Row; i++)
            {
                var row = worksheet.Cells[i, 1, i, column];
                var newRow = dt.NewRow();

                foreach (var cell in row)
                {
                    if ((cell.Style.Numberformat.Format.IndexOf("mm-dd-yy", StringComparison.Ordinal) > -1 || cell.Style.Numberformat.Format.IndexOf("yyyy", StringComparison.Ordinal) > -1) && cell.Value != null)
                    {
                        newRow[cell.Start.Column - 1] = cell.GetValue<DateTime>();
                    }
                    else
                    {
                        newRow[cell.Start.Column - 1] = cell.Text;
                    }
                }

                dt.Rows.Add(newRow);
            }

            return dt;
        }

3、实体字段映射关系,这里采用反射的方式处理的(如果考虑更高性能可以采用Expression表达式树的方式)

 public void SetProperty<T>(T entity, DataRow dataRow, string prefix = "") where T : class
        {
            var type = entity.GetType();
            foreach (var property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                var attributeName = $"{prefix}{property.GetCustomAttribute<ColumnAttribute>()?.Name}".ToLower();
                if (!FieldsMapping.Values.Contains(attributeName)) continue;

                var value = dataRow[attributeName];
                value = value is DBNull ? "" : value;

                if (typeof(string) == property.PropertyType)
                {
                    property.SetValue(entity, value, null);
                    continue;
                }

                if (typeof(bool) == property.PropertyType)
                {
                    property.SetValue(entity, Equals(value, "1") || Equals(value, "是"), null);
                }
            }
        }
    }

以上代码没有提供完整,仅提供部分核心代码仅供参考

 

标签:set,封装,get,int,EPPlus,扩展,var,return,public
来源: https://www.cnblogs.com/sunxuchu/p/15910974.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有