C# 读取 Excel 最全最稳定的方式

采用 NPOI 和 Epplus 方式读取Excel,因为之前测试NPOI的时候发现对于 .xlsx 格式的文件读取不是很友好,所以才结合了两个。

废话少说,直接上代码:

public static class ExcelRead
{    
  
/// <summary>
/// Excel表格列标识
/// </summary>
public enum ExcelColumns
{
    Column_1 = 1,
    Column_2 = 2,
    Column_3 = 3,
    Column_4 = 4,
    Column_5 = 5,
    Column_6 = 6,
    Column_7 = 7,
    Column_8 = 8,
    Column_9 = 9,
    Column_10 = 10,
    Column_11 = 11,
    Column_12 = 12,
    Column_13 = 13,
    Column_14 = 14,
    Column_15 = 15,
    Column_16 = 16,
    Column_17 = 17,
    Column_18 = 18,
    Column_19 = 19,
    Column_20 = 20,
    Column_21 = 21,
    Column_22 = 22,
    Column_23 = 23,
    Column_24 = 24,
    Column_25 = 25,
    Column_26 = 26,
    Column_27 = 27,
    Column_28 = 28,
    Column_29 = 29,
    Column_30 = 30,
    Column_31 = 31,
    Column_32 = 32,
    Column_33 = 33,
    Column_34 = 34,
    Column_35 = 35,
    Column_36 = 36,
    Column_37 = 37,
    Column_38 = 38,
    Column_39 = 39,
    Column_40 = 40,
    Column_41 = 41,
    Column_42 = 42,
    Column_43 = 43,
    Column_44 = 44,
    Column_45 = 45,
    Column_46 = 46,
    Column_47 = 47,
    Column_48 = 48,
    Column_49 = 49,
    Column_50 = 50,
    Column_51 = 51,
    Column_52 = 52,
    Column_53 = 53,
    Column_54 = 54,
    Column_55 = 55,
    Column_56 = 56,
    Column_57 = 57,
    Column_58 = 58,
    Column_59 = 59,
    Column_60 = 60,
    Column_61 = 61,
    Column_62 = 62,
    Column_63 = 63,
    Column_64 = 64,
    Column_65 = 65,
    Column_66 = 66,
    Column_67 = 67,
    Column_68 = 68,
    Column_69 = 69,
    Column_70 = 70,
    Column_71 = 71,
    Column_72 = 72,
    Column_73 = 73,
    Column_74 = 74,
    Column_75 = 75,
    Column_76 = 76,
    Column_77 = 77,
    Column_78 = 78,
    Column_79 = 79,
    Column_80 = 80,
    Column_81 = 81,
    Column_82 = 82,
    Column_83 = 83,
    Column_84 = 84,
    Column_85 = 85,
    Column_86 = 86,
    Column_87 = 87,
    Column_88 = 88,
    Column_89 = 89,
    Column_90 = 90,
    Column_91 = 91,
    Column_92 = 92,
    Column_93 = 93,
    Column_94 = 94,
    Column_95 = 95,
    Column_96 = 96,
    Column_97 = 97,
    Column_98 = 98,
    Column_99 = 99,
    Column_100 = 100,
    Sys_NewGuid,
    Sys_DateTime,
    Sys_Empty
}
Excel表格列标识 
  
/// <summary>
/// 表格列数据类型
/// </summary>
public enum DataTableColumnType
{
    //Sys_String = "System.String";
    //Sys_Int32 = "System.Int32";
    //Sys_Decimal = "System.Decimal";
    //Sys_DateTime = "System.DateTime";
    //Sys_Long = "System.Int64";
    //Sys_Bool = "System.Boolean";

    Sys_String,
    Sys_Int32,
    Sys_Decimal,
    Sys_DateTime,
    Sys_Long,
    Sys_Bool
}

/// <summary>
/// 获取表格列数据类型
/// </summary>
/// <param name="dataTableColumnType"></param>
/// <returns></returns>
private static string GetDataTableColumnType(DataTableColumnType dataTableColumnType)
{
    string columnType = string.Empty;
    switch (dataTableColumnType)
    {
        case DataTableColumnType.Sys_String:
            columnType = "System.String";
            break;
        case DataTableColumnType.Sys_Int32:
            columnType = "System.Int32";
            break;
        case DataTableColumnType.Sys_Decimal:
            columnType = "System.Decimal";
            break;
        case DataTableColumnType.Sys_DateTime:
            columnType = "System.DateTime";
            break;
        case DataTableColumnType.Sys_Long:
            columnType = "System.Int64";
            break;
        case DataTableColumnType.Sys_Bool:
            columnType = "System.Boolean";
            break;
        default:
            break;
    }
    return columnType;
}
表格列数据类型
  
/// <summary>
/// 读取Excel文件,返回DataTable
/// </summary> 
/// <param name="filePath">文件路径</param>
/// <param name="sheetIndex">sheet页下标,从1开始</param>
/// <param name="startRow">开始行</param>
/// <param name="tableName">对应数据库的表名</param>
/// <param name="dtColumns">DataTable列定义</param>
/// <param name="dtExcelMap">DataTable和Excel的映射关系</param>
/// <returns></returns>
public static DataTable GetExcelContent(string filePath, int sheetIndex, int startRow, string tableName,
    Dictionary<string, DataTableColumnType> dtColumns, Dictionary<string, ExcelColumns> dtExcelMap)
{
    //声明表格控件,初始化表格列
    DataTable tblDatas = new DataTable(tableName);
    foreach (var item in dtColumns)
        tblDatas.Columns.Add(item.Key, Type.GetType(GetDataTableColumnType(item.Value)));

    FileStream fs = null;
    ExcelPackage package = null;
    try
    {
        // 2007版本   epplus 读取
        if (filePath.IndexOf(".xlsx") > 0)
        {
            #region 2007
            fs = new FileStream(filePath, FileMode.Open);
            using (package = new ExcelPackage(fs))
            {
                ExcelWorksheet sheet = package.Workbook.Worksheets[1];

                for (int i = startRow; i <= sheet.Dimension.End.Row; i++)
                {
                    //定义获取列值的委托
                    Func<ExcelColumns, object> func = delegate (ExcelColumns excelColumns)
                    {
                        return sheet.GetValue(i, (int)excelColumns);//读取第i行第excelColumns列数据
                    };
                    //获取与表格列对应的 行值 集合
                    object[] arrValue = GetDataTableRow(tblDatas, dtExcelMap, func);
                    //添加到表格中
                    tblDatas.Rows.Add(arrValue);
                }
            }

            #endregion
        }
        // 2003版本  
        else if (filePath.IndexOf(".xls") > 0)
        {
            #region 2003

            using (fs = File.OpenRead(filePath))
            {
                IWorkbook workbook = new HSSFWorkbook(fs);

                if (workbook != null)
                {
                    //读取第一个sheet,当然也可以循环读取每个sheet  
                    ISheet sheet = workbook.GetSheetAt(sheetIndex - 1);
                    if (sheet != null)
                    {
                        int rowCount = sheet.LastRowNum;//总行数  
                        for (int i = startRow - 1; rowCount > 0 && i <= rowCount; ++i)
                        {
                            //定义获取列值的委托
                            Func<ExcelColumns, object> func = delegate (ExcelColumns excelColumns)
                            {
                                IRow row = sheet.GetRow(i);
                                return row.GetCell((int)excelColumns - 1);//读取第i行第excelColumns列数据
                            };
                            //获取与表格列对应的 行值 集合
                            object[] arrValue = GetDataTableRow(tblDatas, dtExcelMap, func);
                            //添加到表格中
                            tblDatas.Rows.Add(arrValue);
                        }
                    }
                }
            }

            #endregion
        }

        return tblDatas;
    }
    catch (Exception ex)
    {
        return null;
    }
    finally
    {
        if (package != null)
        {
            package.Dispose();
        }
        if (fs != null)
        {
            fs.Close();
        }
    }
}
读取Excel文件,返回DataTable
  
/// <summary>
/// 获取表格行数据
/// </summary>
/// <param name="tblDatas"></param>
/// <param name="dtExcelMap"></param>
/// <param name="getExcelCellValue"></param>
/// <returns></returns>
private static object[] GetDataTableRow(DataTable tblDatas, Dictionary<string, ExcelColumns> dtExcelMap,
    Func<ExcelColumns, object> getExcelCellValue)
{
    int arrIndex = 0;
    object[] arrValue = new object[tblDatas.Columns.Count];
    //循环表格所有列
    foreach (DataColumn item in tblDatas.Columns)
    {
        //根据表格列和值枚举映射关系,由列得到值枚举
        ExcelColumns excelColumns = dtExcelMap[item.ColumnName];
        //判断值枚举是否为Guid
        if (excelColumns == ExcelColumns.Sys_NewGuid)
            arrValue[arrIndex] = Guid.NewGuid();
        //判断值枚举是否为DateTime
        else if (excelColumns == ExcelColumns.Sys_DateTime)
            arrValue[arrIndex] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        //根据值枚举下标,获取对应列的值
        else
            arrValue[arrIndex] = getExcelCellValue(excelColumns);

        arrIndex++;
    }

    return arrValue;
}
获取表格行数据
}

代码总体上没有达到完全体,还有非常多的优化空间,先Mark一下,赶下项目进度,后期进行优化了再更新。

具体使用方式如下:

string filePath = "文件完整的路径";
int sheetIndex = 1;//将要读取的Sheet页,从1开始
int startRow = 1;//开始读取的数据行,不包含表头,从1开始
string tableName = "对应数据库的名称,方便后续插入到数据库中";
//表格的列定义,想要输出多少列,就定义多少列
Dictionary<string, ExcelRead.DataTableColumnType> dtCols = new Dictionary<string, ExcelRead.DataTableColumnType>();
deMap.Add("列名", ExcelRead.ExcelColumns.Sys_DateTime);
//表格列 和 Excel表格列 的对应关系,必须和“表格的列定义”数量一致,且列名相同
//表格列 可以对应非 Excel表格列 的内容,目前仅支持 Guid 和 DataTime
Dictionary<string, ExcelRead.ExcelColumns> colsMap = new Dictionary<string, ExcelRead.ExcelColumns>();
deMap.Add("列名", ExcelRead.ExcelColumns.Column_1);

//开始调用,获取表格
DataTable data = ExcelRead.GetExcelContent(filePath, sheetIndex, startRow, tableName, dtCols, colsMap);

以上。

猜你喜欢

转载自www.cnblogs.com/Jiangdu/p/10789925.html