前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LinqToExcel.Extend 源码分析

LinqToExcel.Extend 源码分析

作者头像
happlyfox
发布2018-10-31 14:47:45
6170
发布2018-10-31 14:47:45
举报
文章被收录于专栏:技术开源分享技术开源分享

废话不多说,我们直接来分析源码,首先我们查看目录结构

目录结构.png

目录结构功能

  • Extend 通用扩展方法
  • Parameter 公共实体类
  • Parser 解析器
  • Validate 验证工具集

目录结构展开.png

展开目录结构,我们能够更加请详细的分析出每个目录所完成的功能模块。 这里主要讲解工具集中最重要的一个模块Validate


要设计,我们就一定要知道自己想怎么做。 如果我对外提供接口调用,怎么样的方式是最方便,让人容易理解的,我就是朝着这个方向做的。 我希望的结果是 实例化验证对象,参数是验证文件的路径 调用验证方法,可以区分工作表验证,可以选择添加或不添加逻辑验证 验证成功或失败都返回一个对象,如果验证失败,返回的对象中要包含出错的信息(尽可能细化)


基于上述的设计理念 我定义了三个对象 RowValidate 行验证 WorkSheetValidate 工作表验证 WorkBookValidate 工作簿验证

RowValidate 行验证

RowValidate对象执行的调用方是WorkSheetValidate Validate<T>执行返回值为 得到当前行的的出错信息集合

代码语言:javascript
复制
    /// <summary>
    /// 行验证
    /// </summary>
    public class RowValidate
    {
        public static string GetCellStation(int rowIndex, int columnIndex)
        {
            int i = columnIndex % 26;
            string cellRef = Convert.ToChar(65 + i).ToString() + (rowIndex + 1);
            return cellRef;
        }

        public static List<ErrCell> Validate<T>(int rowIndex, List<string> colNames, List<int> colIndexs, List<string> rowCellValues)
        {
            List<ErrCell> errCells = new List<ErrCell>();
            T singleT = Activator.CreateInstance<T>();

            foreach (PropertyInfo pi in singleT.GetType().GetProperties())
            {
                var propertyAttribute = (Attribute.GetCustomAttribute(pi, typeof(ExcelColumnAttribute)));
                if (propertyAttribute == null)
                {
                    continue;
                }
                var proName = ((ExcelColumnAttribute)propertyAttribute).ColumnName;
                for (int colIndex = 0; colIndex < colNames.Count; colIndex++)
                {
                    try
                    {
                        if (proName.Equals(colNames[colIndex], StringComparison.OrdinalIgnoreCase))
                        {
                            string fieldName = pi.PropertyType.GetUnderlyingType().Name;
                            string cellValue = rowCellValues[colIndex];

                            if (!String.IsNullOrWhiteSpace(cellValue))
                            {
                                //如果是日期类型,特殊判断
                                if (fieldName.Equals("DateTime"))
                                {
                                    string data = "";
                                    try
                                    {
                                        data = cellValue.ToDateTimeValue();
                                    }
                                    catch (Exception)
                                    {
                                        data = DateTime.Parse(cellValue).ToString();
                                    }
                                }
                                cellValue.CastTo(pi.PropertyType);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        errCells.Add(new ErrCell()
                        {
                            RowIndex = rowIndex,
                            ColumnIndex = colIndexs[colIndex],
                            Name = GetCellStation(rowIndex, colIndexs[colIndex]),
                            ErrMsg = ex.Message
                        });
                    }
                }
            }
            return errCells;
        }
    }

WorkBookValidate 工作簿验证

WorkBookValidate是根的验证对象。我们首先看构造函数,参数为filePath,在构造函数中,我们做的操作是:实例化N个WorkSheetValidate对象。 定义索引器,这样可以通过外部调用WorkSheetValidate的验证方法

代码语言:javascript
复制
   /// <summary>
    /// 工作簿验证
    /// </summary>
    public class WorkBookValidate
    {
        public string FilePath { get; set; }

        private List<WorkSheetValidate> _workSheetList = new List<WorkSheetValidate>();

        public List<WorkSheetValidate> WorkSheetList
        {
            get { return _workSheetList; }
            set { _workSheetList = value; }
        }

        public WorkSheetValidate this[string sheetName]
        {
            get
            {
                foreach (WorkSheetValidate sheetParameterContainer in _workSheetList)
                {
                    if (sheetParameterContainer.SheetName.Equals(sheetName))
                    {
                        return sheetParameterContainer;
                    }
                }
                throw new Exception("工作表不存在");
            }
        }

        public WorkSheetValidate this[int sheetIndex]
        {
            get
            {
                foreach (WorkSheetValidate sheetParameterContainer in _workSheetList)
                {
                    if (sheetParameterContainer.SheetIndex.Equals(sheetIndex))
                    {
                        return sheetParameterContainer;
                    }
                }
                throw new Exception("工作表不存在");
            }
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="filePath">路径</param>
        public WorkBookValidate(string filePath)
        {
            FilePath = filePath;
            var excel = new ExcelQueryFactory(filePath);
            List<string> worksheetNames = excel.GetWorksheetNames().ToList();

            int sheetIndex = 0;
            foreach (var sheetName in worksheetNames)
            {
                WorkSheetList.Add(new WorkSheetValidate(filePath, sheetName, sheetIndex++));
            }
        }
    }

WorkSheetValidate 工作表验证

这是这三个验证模块中最复杂的一个,代码就不贴全部的图了,主要讲解一下重要的地方。 首先也是构造函数,这个构造函数主要是给WorkBookVaidate调用

代码语言:javascript
复制
      public WorkSheetValidate(string filePath, string sheetName, int sheetIndex)
        {
            FilePath = filePath;
            SheetName = sheetName;
            SheetIndex = sheetIndex;

            TootarIndex = 0;
        }

验证方法说明 这是一个泛型方法,方法逻辑很简单 首先验证数据有效性 ValidateParameter 如果返回的错误集合为空,验证逻辑有效性ValidateMatching 最后返回验证集合

代码语言:javascript
复制
    public Verification StartValidate<T>(List<CellMatching<T>> rowValidates = null)
        {
            List<ErrCell> errCells = this.ValidateParameter<T>(TootarIndex);
            if (!errCells.Any())
            {
                TootarIndex += 1;
                errCells.AddRange(this.ValidateMatching<T>(rowValidates, TootarIndex));
            }

            Verification validate = new Verification();

            if (errCells.Any())
            {
                validate = new Verification()
                {
                    IfPass = false,
                    ErrCells = errCells
                };
            }
            else
            {
                validate = new Verification()
                {
                    IfPass = true,
                    ErrCells = errCells
                };
            }

            return validate;
        }

验证数据有效性

这个模块相对复杂,看不懂的小伙伴可以多看几遍理解消化吸收下。 首先调用LinqToExcel的WorksheetNoHeader方法获得除了标题的集合数据 然后得到当前标题行和Excel列的映射关系 调用GetErrCellByParameter方法进行验证

GetErrCellByParameter说明 得到所有列名称集合,得到所有列名称索引 遍历行数据,调用RowValidate的静态方法RowValidate.Validate<T> 传递的参数是,行索引,列名称集合,列索引集合,行数据集合

代码语言:javascript
复制
  private List<ErrCell> GetErrCellByParameter<T>(List<RowNoHeader> rows, int startRowIndex)
        {
            List<string> colNames = _propertyCollection.Values.Select(u => u.ColName).ToList();
            List<int> colIndexs = _propertyCollection.Values.Select(u => u.ColIndex).ToList();

            List<ErrCell> errCells = new List<ErrCell>();
            for (int rowIndex = startRowIndex; rowIndex < rows.Count; rowIndex++)
            {
                List<string> rowValues = rows[rowIndex].Where((u, index) => colIndexs.Any(p => p == index)).Select(u => u.ToString()).ToList();
                errCells.AddRange(RowValidate.Validate<T>(rowIndex, colNames, colIndexs, rowValues));
            }
            return errCells;
        }
代码语言:javascript
复制
    private List<ErrCell> ValidateParameter<T>(int startRowIndex)
        {
            //第一步 得到集合
            var excel = new ExcelQueryFactory(FilePath);
            var rows = (from c in excel.WorksheetNoHeader(SheetIndex)
                        select c).ToList();
            //第二步 获得标题行和Excel列的映射关系
                 方法体省略

            //第二步 调用验证方法
            return GetErrCellByParameter<T>(rows, startRowIndex);
        }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.07.11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • RowValidate 行验证
  • WorkBookValidate 工作簿验证
  • WorkSheetValidate 工作表验证
  • 验证数据有效性
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档