方法一:利用OleDb直接连接Excel文件进行读取数据。
//获取Excel路径
string fileUrl = GetExcel(fuImportStudent);
//适合老旧版本的xls文件
const string cmdText = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1;\"";
//适合新版的xlsx文件
//const string cmdText = "Provider=Microsoft.Ace.OleDb.12.0;Data Source={0};Extended Properties='Excel 12.0; HDR=Yes; IMEX=1'";
System.Data.DataTable dt = null;
//建立连接
OleDbConnection connOleDb = new OleDbConnection(string.Format(cmdText, fileUrl));
//打开连接
if (connOleDb.State == ConnectionState.Broken || connOleDb.State == ConnectionState.Closed)
{
connOleDb.Open();
}
System.Data.DataTable schemaTable = connOleDb.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
//获取Excel的第一个Sheet名称
string sheetName = schemaTable.Rows[0]["TABLE_NAME"].ToString().Trim();
//查询sheet中的数据
string strSql = "select * from [" + sheetName + "]";
OleDbDataAdapter da = new OleDbDataAdapter(strSql, connOleDb);
DataSet ds = new DataSet();
da.Fill(ds);
//将Excel数据转写成DataTable
dt = ds.Tables[0];
//关闭连接
connOleDb.Close();
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
//这里进行写入数据库操作
//获取数据:dt.Rows[i]["表头名称"].ToString()
}
}
如果是用Microsoft.Jet.OLEDB.4.0连接的,需要设置IIS允许32位程序:
优点:适合简单固定格式的Excel表格,只要表头名称对上就行,不用管顺序问题。
缺点:如果直接读取MyXls导出的Excel会出现只能读取第一列的问题(重新编辑一下或者另存xls又可以解决这个问题)。
方法二:利用MyXls读取Excel数据。
//获取Excel路径
string fileUrl = GetExcel(fuImportContact);
//加载要导入的Excel
XlsDocument xls = new XlsDocument(fileUrl);
//获得Excel中的指定一个工作页
Worksheet sheet = xls.Workbook.Worksheets[0];
//读取数据 循环每sheet工作页的每一行,不读取前1行
for (int i = 2; i < sheet.Rows.Count; i++)
{
//这里进行写入数据库操作
//获取数据:sheet.Rows[ushort.Parse(i.ToString())].GetCell(1).Value.ToString()
}
优点:不依赖服务器,可以读取MyXls导出的Excel文件。
缺点:必须按照Excel列的顺序获取字段数据,对时间格式要求严格,会出现数字格式的日期,需要转换一下。如果列的数据为空也可能导致读取不了列的情况,比较不稳定。
方法三:调用Microsoft.Office.Interop.Excel组件读取Excel数据。
Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook workbook;
Microsoft.Office.Interop.Excel.Worksheet worksheet;
object oMissing = System.Reflection.Missing.Value;//相当null
workbook = excel.Workbooks.Open(filename, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing);
worksheet = (Worksheet)workbook.Worksheets[1];
//int rowCount = int.Parse(txtRow1.Text.Trim()) + 1;// worksheet.UsedRange.Rows.Count;
int colCount = worksheet.UsedRange.Columns.Count;
Microsoft.Office.Interop.Excel.Range range1;
System.Data.DataTable dt = new System.Data.DataTable();
for (int i = 0; i < colCount; i++)
{
range1 = worksheet.Range[worksheet.Cells[1, i + 1], worksheet.Cells[1, i + 1]];
if (range1.Value2 != null)
{
dt.Columns.Add(range1.Value2.ToString());
}
}
for (int j = 1; j < rowCount; j++)
{
SetCount(j, label);
DataRow dr = dt.NewRow();
for (int i = 0; i < colCount; i++)
{
range1 = worksheet.Range[worksheet.Cells[j + 1, i + 1], worksheet.Cells[j + 1, i + 1]];
if (range1.Value2 != null)
{
dr[i] = range1.Value2.ToString();
}
}
dt.Rows.Add(dr);
}
excel.Quit();
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
//这里进行写入数据库操作
//获取数据:dt.Rows[i]["表头名称"].ToString()
}
}
优点:可以读取复杂的Excel表格数据,读取列时不用管顺序。
缺点:依赖服务器组件,服务器需要安装Excel组件。
如果遇到时间字段变成数字,如:
需要转换一下:
private string ToDateTimeValue(string strNumber)
{
if (!string.IsNullOrWhiteSpace(strNumber))
{
Decimal tempValue;
//先检查 是不是数字;
if (Decimal.TryParse(strNumber, out tempValue))
{
//天数,取整
int day = Convert.ToInt32(Math.Truncate(tempValue));
//这里也不知道为什么. 如果是小于32,则减1,否则减2
//日期从1900-01-01开始累加
// day = day < 32 ? day - 1 : day - 2;
DateTime dt = new DateTime(1900, 1, 1).AddDays(day < 32 ? (day - 1) : (day - 2));
//小时:减掉天数,这个数字转换小时:(* 24)
Decimal hourTemp = (tempValue - day) * 24;//获取小时数
//取整.小时数
int hour = Convert.ToInt32(Math.Truncate(hourTemp));
//分钟:减掉小时,( * 60)
//这里舍入,否则取值会有1分钟误差.
Decimal minuteTemp = Math.Round((hourTemp - hour) * 60, 2);//获取分钟数
int minute = Convert.ToInt32(Math.Truncate(minuteTemp));
//秒:减掉分钟,( * 60)
//这里舍入,否则取值会有1秒误差.
Decimal secondTemp = Math.Round((minuteTemp - minute) * 60, 2);//获取秒数
int second = Convert.ToInt32(Math.Truncate(secondTemp));
//时间格式:00:00:00
string resultTimes = string.Format("{0}:{1}:{2}",
(hour < 10 ? ("0" + hour) : hour.ToString()),
(minute < 10 ? ("0" + minute) : minute.ToString()),
(second < 10 ? ("0" + second) : second.ToString()));
if (day > 0)
return string.Format("{0} {1}", dt.ToString("yyyy-MM-dd"), resultTimes);
else
return resultTimes;
}
}
return string.Empty;
}