Excel转化成DataTable实现:NPOI和OLEDb

使用两种方式实现的excel数据转化成DataSet,再结合前一篇的DataTable转化为实体,就可以解决excel到实体之间的转化。

代码如下:

首先定义一个接口:

    public interface IExcelAccess
    {
        DataSet Load(ExcelConfig config);
    }
public class ExcelConfig
    {
        /// <summary>
        /// 文件存储路径
        /// </summary>
        public string Path { get; set; }

        /// <summary>
        /// 文件表头所在行索引
        /// </summary>
        public int HeaderIndex { get; set; }
    }

再来看一下使用NPOI的实现:

public class NpoiExcelAccess : IExcelAccess
    {
        /// <summary>
        /// 根据文件扩展名,获取workbook实例
        /// </summary>
        /// <param name="ext"></param>
        /// <returns></returns>
        private IWorkbook GetWorkBook(string ext, Stream stream)
        {
            IWorkbook workbook = null;

            switch (ext)
            {
                case ".xlsx":
                    workbook = new XSSFWorkbook(stream);
                    break;
                case ".xls":
                    workbook = new HSSFWorkbook(stream);
                    break;
                default:
                    break;
            }

            return workbook;
        }

        /// <summary>
        /// 加载数据,可设置跳过前几行
        /// </summary>
        /// <param name="path"></param>
        /// <param name="skipRows"></param>
        /// <returns></returns>
        public DataSet Load(ExcelConfig config)
        {
            using (var fileStream = new FileStream(config.Path, FileMode.Open, FileAccess.Read))
            {
                var ds = new DataSet();
                var ext = Path.GetExtension(config.Path);

                // 新建IWorkbook对象 
                var workbook = this.GetWorkBook(ext, fileStream);

                for (int i = 0; i < workbook.NumberOfSheets; i++)
                {
                    ISheet sheet = workbook.GetSheetAt(i);
                    DataTable dt = GetDataTable(sheet, config.HeaderIndex);
                    ds.Tables.Add(dt);
                }

                return ds;
            }
        }

        private DataTable GetDataTable(ISheet sheet, int headerIndex)
        {
            var dt = new DataTable();
            // 获取表头行
            var headerRow = sheet.GetRow(headerIndex);
            var cellCount = GetCellCount(sheet, headerIndex);

            // 设置表头
            for (int i = 0; i < cellCount; i++)
            {
                if (headerRow.GetCell(i) != null)
                {
                    dt.Columns.Add(headerRow.GetCell(i).StringCellValue, typeof(string));
                }
            }
            
            for (int i = headerIndex + 1; i <= sheet.LastRowNum; i++)
            {
                IRow row = sheet.GetRow(i);
                DataRow dr = dt.NewRow();
                FillDataRow(row, ref dr);
                dt.Rows.Add(dr);
            }

            dt.TableName = sheet.SheetName;
            return dt;

        }

        private void FillDataRow(IRow row, ref DataRow dr)
        {
            if (row != null)
            {
                for (int j = 0; j < dr.Table.Columns.Count; j++)
                {
                    ICell cell = row.GetCell(j);

                    if (cell != null)
                    {
                        switch (cell.CellType)
                        {
                            case CellType.Blank:
                                dr[j] = DBNull.Value;
                                break;
                            case CellType.Boolean:
                                dr[j] = cell.BooleanCellValue;
                                break;
                            case CellType.Numeric:
                                if (DateUtil.IsCellDateFormatted(cell))
                                {
                                    dr[j] = cell.DateCellValue;
                                }
                                else
                                {
                                    dr[j] = cell.NumericCellValue;
                                }
                                break;
                            case CellType.String:
                                dr[j] = cell.StringCellValue;
                                break;
                            case CellType.Error:
                                dr[j] = cell.ErrorCellValue;
                                break;
                            case CellType.Formula:
                                // cell = evaluator.EvaluateInCell(cell) as HSSFCell;
                                dr[j] = cell.ToString();
                                break;
                            default:
                                throw new NotSupportedException(string.Format("Catched unhandle CellType[{0}]", cell.CellType));
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 获取表头列数
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="skipRows"></param>
        /// <returns></returns>
        private int GetCellCount(ISheet sheet, int headerIndex)
        {
            var headerRow = sheet.GetRow(headerIndex);

            return headerRow.LastCellNum;
        }
    }

 

最后看一下使用OLEDB的实现,这里,我只实现了excel2003的版本,07版本的总是失败,查了原因,是需要在本机安装一个组件才能支持导入.xlsx文件。

 public class OleDbExcelAccess : IExcelAccess
    {
        private string strConn;

        public OleDbExcelAccess()
        {
            //TODO 需要根据扩展名,来决定 使用哪一种连接字符串
            strConn = " Provider = Microsoft.Jet.OLEDB.4.0 ; Data Source = {0};Extended Properties='Excel 8.0;IMEX=1;HDR=NO'";
        }

        public DataSet Load(ExcelConfig config)
        {
            var ds = new DataSet();
            var sheets = GetSheetNames(config.Path);
            var strConnTmp = string.Format(strConn, config.Path);

            foreach (string sheet in sheets)
            {
                using (var oleConn = new OleDbConnection(strConnTmp))
                {
                    var strsql = "SELECT * FROM [" + sheet + "]";
                    var oleDaExcel = new OleDbDataAdapter(strsql, oleConn);
                    oleConn.Open();
                    oleDaExcel.Fill(ds, sheet);
                }
            }

            return ds;
        }

        /// <summary>
        /// 获取Excel的所有的sheet
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private string[] GetSheetNames(string path)
        {
            DataTable dt = new DataTable();
            if (File.Exists(path))
            {
                string strConnTmp = string.Format(strConn, path);
                using (var conn = new OleDbConnection(strConnTmp))
                {
                    conn.Open();
                    //返回Excel的架构,包括各个sheet表的名称,类型,创建时间和修改时间等    
                    dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "Table" });
                }
                //包含excel中表名的字符串数组
                var sheetNames = new List<string>();
                for (int k = 0; k < dt.Rows.Count; k++)
                {
                    string tableName = dt.Rows[k]["TABLE_NAME"].ToString();
                    //修正出现兼容性视图名称时过滤表名
                    if (!tableName.Substring(tableName.Length - 1).Equals("_"))
                    {
                        sheetNames.Add(tableName);
                    }
                }
                return sheetNames.ToArray();

            }
            return null;

        }
    }

 

最后看一下客户端的调用 :

 private void TestExcelImport()
        {
            var excelFile = Path.Combine("C:\\Users\\hankk\\Desktop\\ICON", "2003版本.xls");

            ExcelConfig config = new ExcelConfig()
            {
                Path = excelFile,
                HeaderIndex = 1
            };

            IExcelAccess npoiAccess = new NpoiExcelAccess();
            var npoiDs = npoiAccess.Load(config);

            IExcelAccess oleDbAccess = new OleDbExcelAccess();
            var oleDs = oleDbAccess.Load(config);
        }

 

代码已上传到github: https://github.com/hankuikuide/ExcelAccessor

 

posted @ 2017-12-24 15:22  二奎  阅读(455)  评论(0编辑  收藏  举报