c#读取excel数据的两种方法(转)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

c#读取excel数据的两种⽅法(转)
转载⾃:,
⽅法⼀:OleDb:⽤这种⽅法读取Excel速度还是⾮常的快的,但这种⽅式读取数据的时候不太灵活,不过可以在 DataTable 中对数据进⾏⼀些删减修改。

优点:读取⽅式简单、读取速度快
缺点:除了读取过程不太灵活之外,这种读取⽅式还有个弊端就是,当Excel数据量很⼤时。

会⾮常占⽤内存,当内存不够时会抛出内存溢出的异常。

不过⼀般情况下还是⾮常不错的。

DataTable GetDataFromExcelByConn(bool hasTitle = false)
{
OpenFileDialog openFile = new OpenFileDialog();
openFile.Filter = "Excel(*.xlsx)|*.xlsx|Excel(*.xls)|*.xls";
openFile.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
openFile.Multiselect = false;
if (openFile.ShowDialog() == DialogResult.Cancel) return null;
var filePath = openFile.FileName;
string fileType = System.IO.Path.GetExtension(filePath);
if (string.IsNullOrEmpty(fileType)) return null;
using (DataSet ds = new DataSet())
{
string strCon = string.Format("Provider=Microsoft.Jet.OLEDB.{0}.0;" +
"Extended Properties=\"Excel {1}.0;HDR={2};IMEX=1;\";" +
"data source={3};",
(fileType == ".xls" ? 4 : 12), (fileType == ".xls" ? 8 : 12), (hasTitle ? "Yes" : "NO"), filePath);
string strCom = " SELECT * FROM [Sheet1$]";
using (OleDbConnection myConn = new OleDbConnection(strCon))
using (OleDbDataAdapter myCommand = new OleDbDataAdapter(strCom, myConn))
{
myConn.Open();
myCommand.Fill(ds);
}
if (ds == null || ds.Tables.Count <= 0) return null;
return ds.Tables[0];
}
}
⽅法⼆:Com组件的⽅式读取Excel
这种⽅式需要先引⽤ Microsoft.Office.Interop.Excel 。

⾸选说下这种⽅式的优缺点
优点:可以⾮常灵活的读取Excel中的数据
缺点:如果是Web站点部署在IIS上时,还需要服务器机⼦已安装了Excel,有时候还需要为配置IIS权限。

最重要的⼀点因为是基于单元格⽅式读取的,所以数据很慢(曾做过试验,直接读取千⾏、200多列的⽂件,直接读取耗时15分钟。

即使采⽤多线程分段读取来提⾼CPU的利⽤率也需要8分钟。

PS:CPU I3)
需要读取⼤⽂件的的童鞋们慎重。

DataTable GetDataFromExcelByCom(bool hasTitle = false)
{
OpenFileDialog openFile = new OpenFileDialog();
openFile.Filter = "Excel(*.xlsx)|*.xlsx|Excel(*.xls)|*.xls";
openFile.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
openFile.Multiselect = false;
if (openFile.ShowDialog() == DialogResult.Cancel) return null;
var excelFilePath = openFile.FileName;
Excel.Application app = new Excel.Application();
Excel.Sheets sheets;
object oMissiong = System.Reflection.Missing.Value;
Excel.Workbook workbook = null;
DataTable dt = new DataTable();
try
{
if (app == null) return null;
workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong,
oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong);
sheets = workbook.Worksheets;
//将数据读⼊到DataTable中
Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1);//读取第⼀张表
if (worksheet == null) return null;
int iRowCount = edRange.Rows.Count;
int iColCount = edRange.Columns.Count;
//⽣成列头
for (int i = 0; i < iColCount; i++)
{
var name = "column" + i;
if (hasTitle)
{
var txt = ((Excel.Range)worksheet.Cells[1, i + 1]).Text.ToString();
if (!string.IsNullOrWhiteSpace(txt)) name = txt;
}
while (dt.Columns.Contains(name)) name = name + "_1";//重复⾏名称会报错。

dt.Columns.Add(new DataColumn(name, typeof(string)));
}
//⽣成⾏数据
Excel.Range range;
int rowIdx = hasTitle ? 2 : 1;
for (int iRow = rowIdx; iRow <= iRowCount; iRow++)
{
DataRow dr = dt.NewRow();
for (int iCol = 1; iCol <= iColCount; iCol++)
{
range = (Excel.Range)worksheet.Cells[iRow, iCol];
dr[iCol - 1] = (range.Value2 == null) ? "" : range.Text.ToString();
}
dt.Rows.Add(dr);
}
return dt;
}
catch { return null; }
finally
{
workbook.Close(false, oMissiong, oMissiong);
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
workbook = null;
app.Workbooks.Close();
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
app = null;
}
}
原⽂的⽅法⼆还提供了多线程处理数据的代码,⼀并复制到此(此处出现了⼀个SheetOptions的类型,⽆法考证其来源,如果知晓,请留⾔,谢谢。

):
///<summary>
///使⽤COM,多线程读取Excel(1 主线程、4 副线程)
///</summary>
///<param name="excelFilePath">路径</param>
///<returns>DataTabel</returns>
public System.Data.DataTable ThreadReadExcel(string excelFilePath)
{
Excel.Application app = new Excel.Application();
Excel.Sheets sheets = null;
Excel.Workbook workbook = null;
object oMissiong = System.Reflection.Missing.Value;
System.Data.DataTable dt = new System.Data.DataTable();
try
{
if (app == null)
{
return null;
}
workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong,
oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong);
//将数据读⼊到DataTable中——Start
sheets = workbook.Worksheets;
Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1);//读取第⼀张表
if (worksheet == null)
return null;
string cellContent;
int iRowCount = edRange.Rows.Count;
int iColCount = edRange.Columns.Count;
Excel.Range range;
//负责列头Start
DataColumn dc;
int ColumnID = 1;
range = (Excel.Range)worksheet.Cells[1, 1];
//while (range.Text.ToString().Trim() != "")
while (iColCount >= ColumnID)
{
dc = new DataColumn();
dc.DataType = System.Type.GetType("System.String");
string strNewColumnName = range.Text.ToString().Trim();
if (strNewColumnName.Length == 0) strNewColumnName = "_1";
//判断列名是否重复
for (int i = 1; i < ColumnID; i++)
{
if (dt.Columns[i - 1].ColumnName == strNewColumnName)
strNewColumnName = strNewColumnName + "_1";
}
dc.ColumnName = strNewColumnName;
dt.Columns.Add(dc);
range = (Excel.Range)worksheet.Cells[1, ++ColumnID];
}
//End
//数据⼤于500条,使⽤多进程进⾏读取数据
if (iRowCount - 1 > 500)
{
//开始多线程读取数据
//新建线程
int b2 = (iRowCount - 1) / 10;
DataTable dt1 = new DataTable("dt1");
dt1 = dt.Clone();
SheetOptions sheet1thread = new SheetOptions(worksheet, iColCount, 2, b2 + 1, dt1);
Thread othread1 = new Thread(new ThreadStart(sheet1thread.SheetToDataTable));
othread1.Start();
//阻塞 1 毫秒,保证第⼀个读取 dt1
Thread.Sleep(1);
DataTable dt2 = new DataTable("dt2");
dt2 = dt.Clone();
SheetOptions sheet2thread = new SheetOptions(worksheet, iColCount, b2 + 2, b2 * 2 + 1, dt2);
Thread othread2 = new Thread(new ThreadStart(sheet2thread.SheetToDataTable));
othread2.Start();
DataTable dt3 = new DataTable("dt3");
dt3 = dt.Clone();
SheetOptions sheet3thread = new SheetOptions(worksheet, iColCount, b2 * 2 + 2, b2 * 3 + 1, dt3); Thread othread3 = new Thread(new ThreadStart(sheet3thread.SheetToDataTable));
othread3.Start();
DataTable dt4 = new DataTable("dt4");
dt4 = dt.Clone();
SheetOptions sheet4thread = new SheetOptions(worksheet, iColCount, b2 * 3 + 2, b2 * 4 + 1, dt4); Thread othread4 = new Thread(new ThreadStart(sheet4thread.SheetToDataTable));
othread4.Start();
//主线程读取剩余数据
for (int iRow = b2 * 4 + 2; iRow <= iRowCount; iRow++)
{
DataRow dr = dt.NewRow();
for (int iCol = 1; iCol <= iColCount; iCol++)
{
range = (Excel.Range)worksheet.Cells[iRow, iCol];
cellContent = (range.Value2 == null) ? "" : range.Text.ToString();
dr[iCol - 1] = cellContent;
}
dt.Rows.Add(dr);
}
othread1.Join();
othread2.Join();
othread3.Join();
othread4.Join();
//将多个线程读取出来的数据追加⾄ dt1 后⾯
foreach (DataRow dr in dt.Rows)
dt1.Rows.Add(dr.ItemArray);
dt.Clear();
dt.Dispose();
foreach (DataRow dr in dt2.Rows)
dt1.Rows.Add(dr.ItemArray);
dt2.Clear();
dt2.Dispose();
foreach (DataRow dr in dt3.Rows)
dt1.Rows.Add(dr.ItemArray);
dt3.Clear();
dt3.Dispose();
foreach (DataRow dr in dt4.Rows)
dt1.Rows.Add(dr.ItemArray);
dt4.Clear();
dt4.Dispose();
return dt1;
}
else
{
for (int iRow = 2; iRow <= iRowCount; iRow++)
{
DataRow dr = dt.NewRow();
for (int iCol = 1; iCol <= iColCount; iCol++)
{
range = (Excel.Range)worksheet.Cells[iRow, iCol];
cellContent = (range.Value2 == null) ? "" : range.Text.ToString();
dr[iCol - 1] = cellContent;
}
dt.Rows.Add(dr);
}
}
//将数据读⼊到DataTable中——End
return dt;
}
catch
{
return null;
}
finally
{
workbook.Close(false, oMissiong, oMissiong);
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets);
workbook = null;
app.Workbooks.Close();
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
app = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
原⽂还提供了第三种⽅法,感兴趣的可以关⼼⼀下:
⽅法三:NPOI⽅式读取Excel,NPOI是⼀组开源的组件,类似Java的 POI。

包括:NPOI、NPOI.HPSF、NPOI.HSSF、
erModel、NPOI.POIFS、NPOI.Util,下载的时候别只下⼀个噢
优点:读取Excel速度较快,读取⽅式操作灵活性
缺点:只⽀持03的Excel,xlsx的⽆法读取。

由于这点,使⽤这种⽅式的⼈不多啊,没理由要求客户使⽤03版Excel吧,再说03版Excel对于⾏数还有限制,只⽀持65536⾏。

(听他们的开发⼈员说会在2012年底推出新版,⽀持xlsx的读取。

但⼀直很忙没时间去关注这个事情,有兴趣的同学可以瞧瞧去)
using System;
using System.Data;
using System.IO;
using System.Web;
using NPOI;
using NPOI.HPSF;
using NPOI.HSSF;
using erModel;
using NPOI.POIFS;
using NPOI.Util;
using System.Text;
using System.Configuration;
public class NPOIHelper
{
private static int ExcelMaxRow = Convert.ToInt32(ConfigurationManager.AppSettings["ExcelMaxRow"]);
///<summary>
///由DataSet导出Excel
///</summary>
///<param name="sourceTable">要导出数据的DataTable</param>
///<param name="sheetName">⼯作表名称</param>
///<returns>Excel⼯作表</returns>
private static Stream ExportDataSetToExcel(DataSet sourceDs)
{
HSSFWorkbook workbook = new HSSFWorkbook();
MemoryStream ms = new MemoryStream();
for (int i = 0; i < sourceDs.Tables.Count; i++)
{
HSSFSheet sheet = (HSSFSheet)workbook.CreateSheet(sourceDs.Tables[i].TableName);
HSSFRow headerRow = (HSSFRow)sheet.CreateRow(0);
// handling header.
foreach (DataColumn column in sourceDs.Tables[i].Columns)
headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);
// handling value.
int rowIndex = 1;
foreach (DataRow row in sourceDs.Tables[i].Rows)
{
HSSFRow dataRow = (HSSFRow)sheet.CreateRow(rowIndex);
foreach (DataColumn column in sourceDs.Tables[i].Columns)
{
dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
}
rowIndex++;
}
}
workbook.Write(ms);
ms.Flush();
ms.Position = 0;
workbook = null;
return ms;
}
///<summary>
///由DataSet导出Excel
///</summary>
///<param name="sourceTable">要导出数据的DataTable</param>
///<param name="fileName">指定Excel⼯作表名称</param>
///<returns>Excel⼯作表</returns>
public static void ExportDataSetToExcel(DataSet sourceDs, string fileName)
{
//检查是否有Table数量超过65325
for (int t = 0; t < sourceDs.Tables.Count; t++)
{
if (sourceDs.Tables[t].Rows.Count > ExcelMaxRow)
{
DataSet ds = GetdtGroup(sourceDs.Tables[t].Copy());
sourceDs.Tables.RemoveAt(t);
//将得到的ds插⼊ sourceDs中
for (int g = 0; g < ds.Tables.Count; g++)
{
DataTable dt = ds.Tables[g].Copy();
sourceDs.Tables.Add(dt);
}
t--;
}
}
MemoryStream ms = ExportDataSetToExcel(sourceDs) as MemoryStream;
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + fileName); HttpContext.Current.Response.BinaryWrite(ms.ToArray());
pleteRequest();
//HttpContext.Current.Response.End();
ms.Close();
ms = null;
}
///<summary>
///由DataTable导出Excel
///</summary>
///<param name="sourceTable">要导出数据的DataTable</param>
///<returns>Excel⼯作表</returns>
private static Stream ExportDataTableToExcel(DataTable sourceTable)
{
HSSFWorkbook workbook = new HSSFWorkbook();
MemoryStream ms = new MemoryStream();
HSSFSheet sheet = (HSSFSheet)workbook.CreateSheet(sourceTable.TableName);
HSSFRow headerRow = (HSSFRow)sheet.CreateRow(0);
// handling header.
foreach (DataColumn column in sourceTable.Columns)
headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);
// handling value.
int rowIndex = 1;
foreach (DataRow row in sourceTable.Rows)
{
HSSFRow dataRow = (HSSFRow)sheet.CreateRow(rowIndex);
foreach (DataColumn column in sourceTable.Columns)
{
dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
}
rowIndex++;
}
workbook.Write(ms);
ms.Flush();
ms.Position = 0;
sheet = null;
headerRow = null;
workbook = null;
return ms;
}
///<summary>
///由DataTable导出Excel
///</summary>
///<param name="sourceTable">要导出数据的DataTable</param>
///<param name="fileName">指定Excel⼯作表名称</param>
///<returns>Excel⼯作表</returns>
public static void ExportDataTableToExcel(DataTable sourceTable, string fileName)
{
//如数据超过65325则分成多个Table导出
if (sourceTable.Rows.Count > ExcelMaxRow)
{
DataSet ds = GetdtGroup(sourceTable);
//导出DataSet
ExportDataSetToExcel(ds, fileName);
}
else
{
MemoryStream ms = ExportDataTableToExcel(sourceTable) as MemoryStream;
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + fileName); HttpContext.Current.Response.BinaryWrite(ms.ToArray());
pleteRequest();
//HttpContext.Current.Response.End();
ms.Close();
ms = null;
}
}
///<summary>
///传⼊⾏数超过65325的Table,返回DataSet
///</summary>
///<param name="dt"></param>
///<returns></returns>
public static DataSet GetdtGroup(DataTable dt)
{
string tablename = dt.TableName;
DataSet ds = new DataSet();
ds.Tables.Add(dt);
double n = dt.Rows.Count / Convert.ToDouble(ExcelMaxRow);
//创建表
for (int i = 1; i < n; i++)
{
DataTable dtAdd = dt.Clone();
dtAdd.TableName = tablename + "_" + i.ToString();
ds.Tables.Add(dtAdd);
}
//分解数据
for (int i = 1; i < ds.Tables.Count; i++)
{
//新表⾏数达到最⼤或基表数量不⾜
while (ds.Tables[i].Rows.Count != ExcelMaxRow && ds.Tables[0].Rows.Count != ExcelMaxRow)
{
ds.Tables[i].Rows.Add(ds.Tables[0].Rows[ExcelMaxRow].ItemArray);
ds.Tables[0].Rows.RemoveAt(ExcelMaxRow);
}
}
return ds;
}
///<summary>
///由DataTable导出Excel
///</summary>
///<param name="sourceTable">要导出数据的DataTable</param>
///<param name="fileName">指定Excel⼯作表名称</param>
///<returns>Excel⼯作表</returns>
public static void ExportDataTableToExcelModel(DataTable sourceTable, string modelpath, string modelName, string fileName, string sheetName) {
int rowIndex = 2;//从第⼆⾏开始,因为前两⾏是模板⾥⾯的内容
int colIndex = 0;
FileStream file = new FileStream(modelpath + modelName + ".xls", FileMode.Open, FileAccess.Read);//读⼊excel模板
HSSFWorkbook hssfworkbook = new HSSFWorkbook(file);
HSSFSheet sheet1 = (HSSFSheet)hssfworkbook.GetSheet("Sheet1");
sheet1.GetRow(0).GetCell(0).SetCellValue("excelTitle"); //设置表头
foreach (DataRow row in sourceTable.Rows)
{ //双循环写⼊sourceTable中的数据
rowIndex++;
colIndex = 0;
HSSFRow xlsrow = (HSSFRow)sheet1.CreateRow(rowIndex);
foreach (DataColumn col in sourceTable.Columns)
{
xlsrow.CreateCell(colIndex).SetCellValue(row[col.ColumnName].ToString());
colIndex++;
}
}
sheet1.ForceFormulaRecalculation = true;
FileStream fileS = new FileStream(modelpath + fileName + ".xls", FileMode.Create);//保存
hssfworkbook.Write(fileS);
fileS.Close();
file.Close();
}
}。

相关文档
最新文档