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

废话少说,直接上代码:

public static class ExcelReader
{    
  

/// <summary>
/// Excel表格列标识
/// </summary>
public enum ExcelColumns
{
Column_1 = ,
Column_2 = ,
Column_3 = ,
Column_4 = ,
Column_5 = ,
Column_6 = ,
Column_7 = ,
Column_8 = ,
Column_9 = ,
Column_10 = ,
Column_11 = ,
Column_12 = ,
Column_13 = ,
Column_14 = ,
Column_15 = ,
Column_16 = ,
Column_17 = ,
Column_18 = ,
Column_19 = ,
Column_20 = ,
Column_21 = ,
Column_22 = ,
Column_23 = ,
Column_24 = ,
Column_25 = ,
Column_26 = ,
Column_27 = ,
Column_28 = ,
Column_29 = ,
Column_30 = ,
Column_31 = ,
Column_32 = ,
Column_33 = ,
Column_34 = ,
Column_35 = ,
Column_36 = ,
Column_37 = ,
Column_38 = ,
Column_39 = ,
Column_40 = ,
Column_41 = ,
Column_42 = ,
Column_43 = ,
Column_44 = ,
Column_45 = ,
Column_46 = ,
Column_47 = ,
Column_48 = ,
Column_49 = ,
Column_50 = ,
Column_51 = ,
Column_52 = ,
Column_53 = ,
Column_54 = ,
Column_55 = ,
Column_56 = ,
Column_57 = ,
Column_58 = ,
Column_59 = ,
Column_60 = ,
Column_61 = ,
Column_62 = ,
Column_63 = ,
Column_64 = ,
Column_65 = ,
Column_66 = ,
Column_67 = ,
Column_68 = ,
Column_69 = ,
Column_70 = ,
Column_71 = ,
Column_72 = ,
Column_73 = ,
Column_74 = ,
Column_75 = ,
Column_76 = ,
Column_77 = ,
Column_78 = ,
Column_79 = ,
Column_80 = ,
Column_81 = ,
Column_82 = ,
Column_83 = ,
Column_84 = ,
Column_85 = ,
Column_86 = ,
Column_87 = ,
Column_88 = ,
Column_89 = ,
Column_90 = ,
Column_91 = ,
Column_92 = ,
Column_93 = ,
Column_94 = ,
Column_95 = ,
Column_96 = ,
Column_97 = ,
Column_98 = ,
Column_99 = ,
Column_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") > )
{
#region 2007
fs = new FileStream(filePath, FileMode.Open);
using (package = new ExcelPackage(fs))
{
ExcelWorksheet sheet = package.Workbook.Worksheets[]; 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") > )
{
#region 2003 using (fs = File.OpenRead(filePath))
{
IWorkbook workbook = new HSSFWorkbook(fs); if (workbook != null)
{
//读取第一个sheet,当然也可以循环读取每个sheet
ISheet sheet = workbook.GetSheetAt(sheetIndex - );
if (sheet != null)
{
int rowCount = sheet.LastRowNum;//总行数
for (int i = startRow - ; rowCount > && i <= rowCount; ++i)
{
//定义获取列值的委托
Func<ExcelColumns, object> func = delegate (ExcelColumns excelColumns)
{
IRow row = sheet.GetRow(i);
return row.GetCell((int)excelColumns - );//读取第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 = ;
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 = ;//将要读取的Sheet页,从1开始
int startRow = ;//开始读取的数据行,不包含表头,从1开始
string tableName = "对应数据库的名称,方便后续插入到数据库中";
//表格的列定义,想要输出多少列,就定义多少列
Dictionary<string, ExcelReader.DataTableColumnType> dtCols = new Dictionary<string, ExcelReader.DataTableColumnType>();
dtCols.Add("列名", ExcelReader.DataTableColumnType.Sys_DateTime);
//表格列 和 Excel表格列 的对应关系,必须和“表格的列定义”数量一致,且列名相同
//表格列 可以对应非 Excel表格列 的内容,目前仅支持 Guid 和 DataTime
Dictionary<string, ExcelReader.ExcelColumns> colsMap = new Dictionary<string, ExcelReader.ExcelColumns>();
colsMap.Add("列名", ExcelReader.ExcelColumns.Column_1); //开始调用,获取表格
DataTable data = ExcelReader.GetExcelContent(filePath, sheetIndex, startRow, tableName, dtCols, colsMap);

以上。

C# 读取 Excel 最全最稳定的方式的更多相关文章

  1. C# 读取Excel日期格式

    读取Excel日期数据,一种方式是在EXCEL中把你的日期列的格式设置一下,设成"文本"型. 如果单元格格式设置为date,则在后台读出的数值是一个数值,如2008-08-08读出 ...

  2. 无法读取Excel中的数据单元格。有数据,但是读出来全是空值

    C#读取Excel,取值为空的解决办法! C#读取Excel遇到无法读取的解决方法是什么呢?这样在C#读取Excel的过程中有很多问题,那么本文就向你介绍如何解决C#读取Excel遇到无法读取的解决方 ...

  3. 使用Aspose.Cells读取Excel

      最新更新请访问: http://denghejun.github.io Aspose.Cells读取Excel非常方便,以下是一个简单的实现读取和导出Excel的操作类: 以下是Aspose.Ce ...

  4. .Net读取Excel文件时丢失数据的问题 (转载)

    相信很多人都试过通过OleDB读取Excel文件,这种方法效率十分高,只是有一点会让人十分头痛,就是当一列中既有混合型数据,又有纯数据时,往往容易丢失数据. 百度过后,改连接字符串 “HDR=YES; ...

  5. OLDB读取excel的数据类型不匹配的解决方案(ZT)

    1 引言  在应用程序的设计中,经常需要读取Excel数据或将Excel数据导入转换到其他数据载体中,例如将Excel数据通过应用程序导入SQL Sever等数据库中以备使用.笔者在开发“汽车产业链A ...

  6. R语言读取excel文件的3种方法

    R读取excel文件中数据的方法: 电脑有一个excel文件,原始的文件路径是:E:\R workshop\mydata\biom excel数据为5乘2阶矩阵,元素为                ...

  7. Java Struts2读取Excel 2003/2007/2010例子

    Java读写Excel的包是Apache POI(项目地址:http://poi.apache.org/),因此需要先获取POI的jar包,本实验使用的是POI 3.9稳定版. Apache POI ...

  8. (转)ASP.NET(C#) 读取EXCEL ——另加解决日期问题

    使用OLEDB可以对excel文件进行读取,我们只要把该excel文件作为数据源即可. 一 在D盘创建excel文件test.xls: 二 将工作表Sheet1的内容读取到DataSet string ...

  9. ASP.NET(C#) 读取EXCEL ——另加解决日期问题

    转载:http://www.cnblogs.com/diony/archive/2011/09/08/2171133.html 使用OLEDB可以对excel文件进行读取,我们只要把该excel文件作 ...

随机推荐

  1. .NET core2.0 发布至IIS中

    .NET CORE和asp.net 发布时不太一样,ASP.NET Core不再是由IIS工作进程(w3wp.exe)托管,而是使用自托管Web服务器(Kestrel)运行,IIS则是作为反向代理的角 ...

  2. 关于当前Web前端技术的一些感悟和笔记

    最近这些年,随着前端应用技术突飞猛进,产生了很多新的前端框架,当然也引入了数不胜数的前端技术概念,前端不在是早期Web Form的拖拉处理方式,也不再是Ajax+HTML那么简单,随着前端技术的发展, ...

  3. 在Winform开发框架中对附件文件进行集中归档处理

    在我们Winform开发中,往往需要涉及到附件的统一管理,因此我倾向于把它们独立出来作为一个附件管理模块,这样各个模块都可以使用这个附件管理模块,更好的实现模块重用的目的.在涉及附件管理的场景中,一个 ...

  4. bboss oreach循环嵌套遍历map

    foreach循环嵌套遍历mapforeach嵌套dsl脚本定义 <property name="dynamicInnerDsl"> <![CDATA[{ ## ...

  5. MySQL存储过程--(1)

    /*参数模式:IN:该参数作为输入,该参数调用传入值out:该参数作为输出,该参数作为返回值INOUT:该参数即可作为输入,也可作为输出,该参数即可调用传入值,也可作为返回值delimiter:设置结 ...

  6. Google SRE

    SRE_百度百科 https://baike.baidu.com/item/SRE/1141123 我们离Google SRE还有多远? - 简书https://www.jianshu.com/p/6 ...

  7. JS 获取某个容器控件中id包含制定字符串的控件id列表

    //获取某容器控件中id包含某字符串的控件id列表 //参数:容器控件.要查找的控件的id关键字 function GetIdListBySubKey(container,subIdKey) { va ...

  8. git总结二、关于分支上——好好认识下分支是怎么回事

    同样需要先来明确两件事: HEAD指针指向的是当前分支 分支(master, dev)指向的是最新的提交 一开始,git 中只有一个master分支,严格来讲,HEAD不是指向提交而是指向master ...

  9. react 入坑笔记(六) - 组件的生命周期

    React 组件生命周期 详细参考: react 组件生命周期 组件的生命周期可分为三个状态: 1.Mounting:已经挂载/插入到真实 DOM 树上: 2.Updating:正在被重新渲染: 3. ...

  10. cocos 资源工作流程

    前面的话 本文将详细介绍 cocos 中的资源工作流程 概述 [同步性] 资源管理器中的资源和操作系统的文件管理器中看到的项目资源文件夹是同步的 在资源管理器中对资源的移动.重命名和删除,都会直接在用 ...