c#读取excel数据的两种方法实现
方法一:OleDb:用这种方法读取Excel速度还是非常的快的,但这种方式读取数据的时候不太灵活,不过可以在DataTable中对数据进行一些删减修改。
优点:读取方式简单、读取速度快
缺点:除了读取过程不太灵活之外,这种读取方式还有个弊端就是,当Excel数据量很大时。会非常占用内存,当内存不够时会抛出内存溢出的异常。
不过一般情况下还是非常不错的。
(代码比原文相较有所修改)
DataTableGetDataFromExcelByConn(boolhasTitle=false) { OpenFileDialogopenFile=newOpenFileDialog(); openFile.Filter="Excel(*.xlsx)|*.xlsx|Excel(*.xls)|*.xls"; openFile.InitialDirectory=Environment.GetFolderPath(Environment.SpecialFolder.Desktop); openFile.Multiselect=false; if(openFile.ShowDialog()==DialogResult.Cancel)returnnull; varfilePath=openFile.FileName; stringfileType=System.IO.Path.GetExtension(filePath); if(string.IsNullOrEmpty(fileType))returnnull; using(DataSetds=newDataSet()) { stringstrCon=string.Format("Provider=Microsoft.Jet.OLEDB.{0}.0;"+ "ExtendedProperties=\"Excel{1}.0;HDR={2};IMEX=1;\";"+ "datasource={3};", (fileType==".xls"?4:12),(fileType==".xls"?8:12),(hasTitle?"Yes":"NO"),filePath); stringstrCom="SELECT*FROM[Sheet1$]"; using(OleDbConnectionmyConn=newOleDbConnection(strCon)) using(OleDbDataAdaptermyCommand=newOleDbDataAdapter(strCom,myConn)) { myConn.Open(); myCommand.Fill(ds); } if(ds==null||ds.Tables.Count<=0)returnnull; returnds.Tables[0]; } }
方法二:Com组件的方式读取Excel
这种方式需要先引用Microsoft.Office.Interop.Excel。首选说下这种方式的优缺点
优点:可以非常灵活的读取Excel中的数据
缺点:如果是Web站点部署在IIS上时,还需要服务器机子已安装了Excel,有时候还需要为配置IIS权限。最重要的一点因为是基于单元格方式读取的,所以数据很慢(曾做过试验,直接读取千行、200多列的文件,直接读取耗时15分钟。即使采用多线程分段读取来提高CPU的利用率也需要8分钟。PS:CPUI3)
需要读取大文件的的童鞋们慎重。。。
(代码比原文相较有所修改)
DataTableGetDataFromExcelByCom(boolhasTitle=false) { OpenFileDialogopenFile=newOpenFileDialog(); openFile.Filter="Excel(*.xlsx)|*.xlsx|Excel(*.xls)|*.xls"; openFile.InitialDirectory=Environment.GetFolderPath(Environment.SpecialFolder.Desktop); openFile.Multiselect=false; if(openFile.ShowDialog()==DialogResult.Cancel)returnnull; varexcelFilePath=openFile.FileName; Excel.Applicationapp=newExcel.Application(); Excel.Sheetssheets; objectoMissiong=System.Reflection.Missing.Value; Excel.Workbookworkbook=null; DataTabledt=newDataTable(); try { if(app==null)returnnull; workbook=app.Workbooks.Open(excelFilePath,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong, oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong); sheets=workbook.Worksheets; //将数据读入到DataTable中 Excel.Worksheetworksheet=(Excel.Worksheet)sheets.get_Item(1);//读取第一张表 if(worksheet==null)returnnull; intiRowCount=worksheet.UsedRange.Rows.Count; intiColCount=worksheet.UsedRange.Columns.Count; //生成列头 for(inti=0;i原文的方法二还提供了多线程处理数据的代码,一并复制到此(此处出现了一个SheetOptions的类型,无法考证其来源,如果知晓,请留言,谢谢。):
//////使用COM,多线程读取Excel(1主线程、4副线程) /// ///路径 /// DataTabel publicSystem.Data.DataTableThreadReadExcel(stringexcelFilePath) { Excel.Applicationapp=newExcel.Application(); Excel.Sheetssheets=null; Excel.Workbookworkbook=null; objectoMissiong=System.Reflection.Missing.Value; System.Data.DataTabledt=newSystem.Data.DataTable(); try { if(app==null) { returnnull; } 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.Worksheetworksheet=(Excel.Worksheet)sheets.get_Item(1);//读取第一张表 if(worksheet==null) returnnull; stringcellContent; intiRowCount=worksheet.UsedRange.Rows.Count; intiColCount=worksheet.UsedRange.Columns.Count; Excel.Rangerange; //负责列头Start DataColumndc; intColumnID=1; range=(Excel.Range)worksheet.Cells[1,1]; //while(range.Text.ToString().Trim()!="") while(iColCount>=ColumnID) { dc=newDataColumn(); dc.DataType=System.Type.GetType("System.String"); stringstrNewColumnName=range.Text.ToString().Trim(); if(strNewColumnName.Length==0)strNewColumnName="_1"; //判断列名是否重复 for(inti=1;i500) { //开始多线程读取数据 //新建线程 intb2=(iRowCount-1)/10; DataTabledt1=newDataTable("dt1"); dt1=dt.Clone(); SheetOptionssheet1thread=newSheetOptions(worksheet,iColCount,2,b2+1,dt1); Threadothread1=newThread(newThreadStart(sheet1thread.SheetToDataTable)); othread1.Start(); //阻塞1毫秒,保证第一个读取dt1 Thread.Sleep(1); DataTabledt2=newDataTable("dt2"); dt2=dt.Clone(); SheetOptionssheet2thread=newSheetOptions(worksheet,iColCount,b2+2,b2*2+1,dt2); Threadothread2=newThread(newThreadStart(sheet2thread.SheetToDataTable)); othread2.Start(); DataTabledt3=newDataTable("dt3"); dt3=dt.Clone(); SheetOptionssheet3thread=newSheetOptions(worksheet,iColCount,b2*2+2,b2*3+1,dt3); Threadothread3=newThread(newThreadStart(sheet3thread.SheetToDataTable)); othread3.Start(); DataTabledt4=newDataTable("dt4"); dt4=dt.Clone(); SheetOptionssheet4thread=newSheetOptions(worksheet,iColCount,b2*3+2,b2*4+1,dt4); Threadothread4=newThread(newThreadStart(sheet4thread.SheetToDataTable)); othread4.Start(); //主线程读取剩余数据 for(intiRow=b2*4+2;iRow<=iRowCount;iRow++) { DataRowdr=dt.NewRow(); for(intiCol=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(DataRowdrindt.Rows) dt1.Rows.Add(dr.ItemArray); dt.Clear(); dt.Dispose(); foreach(DataRowdrindt2.Rows) dt1.Rows.Add(dr.ItemArray); dt2.Clear(); dt2.Dispose(); foreach(DataRowdrindt3.Rows) dt1.Rows.Add(dr.ItemArray); dt3.Clear(); dt3.Dispose(); foreach(DataRowdrindt4.Rows) dt1.Rows.Add(dr.ItemArray); dt4.Clear(); dt4.Dispose(); returndt1; } else { for(intiRow=2;iRow<=iRowCount;iRow++) { DataRowdr=dt.NewRow(); for(intiCol=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 returndt; } catch { returnnull; } 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(); } } 补充SheetOptions代码:
classSheetOptions { Microsoft.Office.Interop.Excel.Worksheetworksheet; intiColCount; intstar; intend; System.Data.DataTabledt; publicSheetOptions(Microsoft.Office.Interop.Excel.Worksheetworksheet,intiColCount,intstar,intend,System.Data.DataTabledt) { this.worksheet=worksheet; this.iColCount=iColCount; this.star=star; this.end=end; this.dt=dt; } publicvoidSheetToDataTable() { stringcellContent; Microsoft.Office.Interop.Excel.Rangerange; for(intiRow=star;iRow<=end;iRow++) { System.Data.DataRowdr=dt.NewRow(); for(intiCol=1;iCol<=iColCount;iCol++) { range=(Microsoft.Office.Interop.Excel.Range)worksheet.Cells[iRow,iCol]; cellContent=(range.Value2==null)?"":range.Text.ToString(); dr[iCol-1]=cellContent; } dt.Rows.Add(dr); } } }原文还提供了第三种方法,感兴趣的可以关心一下:
方法三:NPOI方式读取Excel,NPOI是一组开源的组件,类似Java的POI。包括:NPOI、NPOI.HPSF、NPOI.HSSF、NPOI.HSSF.UserModel、NPOI.POIFS、NPOI.Util,下载的时候别只下一个噢
优点:读取Excel速度较快,读取方式操作灵活性
缺点:只支持03的Excel,xlsx的无法读取。由于这点,使用这种方式的人不多啊,没理由要求客户使用03版Excel吧,再说03版Excel对于行数还有限制,只支持65536行。
(听他们的开发人员说会在2012年底推出新版,支持xlsx的读取。但一直很忙没时间去关注这个事情,有兴趣的同学可以瞧瞧去)
usingSystem; usingSystem.Data; usingSystem.IO; usingSystem.Web; usingNPOI; usingNPOI.HPSF; usingNPOI.HSSF; usingNPOI.HSSF.UserModel; usingNPOI.POIFS; usingNPOI.Util; usingSystem.Text; usingSystem.Configuration; publicclassNPOIHelper { privatestaticintExcelMaxRow=Convert.ToInt32(ConfigurationManager.AppSettings["ExcelMaxRow"]); //////由DataSet导出Excel /// ///要导出数据的DataTable /// 工作表名称 /// Excel工作表 privatestaticStreamExportDataSetToExcel(DataSetsourceDs) { HSSFWorkbookworkbook=newHSSFWorkbook(); MemoryStreamms=newMemoryStream(); for(inti=0;i///由DataSet导出Excel /// /// 要导出数据的DataTable /// 指定Excel工作表名称 /// Excel工作表 publicstaticvoidExportDataSetToExcel(DataSetsourceDs,stringfileName) { //检查是否有Table数量超过65325 for(intt=0;tExcelMaxRow) { DataSetds=GetdtGroup(sourceDs.Tables[t].Copy()); sourceDs.Tables.RemoveAt(t); //将得到的ds插入sourceDs中 for(intg=0;g ///由DataTable导出Excel /// /// 要导出数据的DataTable /// Excel工作表 privatestaticStreamExportDataTableToExcel(DataTablesourceTable) { HSSFWorkbookworkbook=newHSSFWorkbook(); MemoryStreamms=newMemoryStream(); HSSFSheetsheet=(HSSFSheet)workbook.CreateSheet(sourceTable.TableName); HSSFRowheaderRow=(HSSFRow)sheet.CreateRow(0); //handlingheader. foreach(DataColumncolumninsourceTable.Columns) headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName); //handlingvalue. introwIndex=1; foreach(DataRowrowinsourceTable.Rows) { HSSFRowdataRow=(HSSFRow)sheet.CreateRow(rowIndex); foreach(DataColumncolumninsourceTable.Columns) { dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString()); } rowIndex++; } workbook.Write(ms); ms.Flush(); ms.Position=0; sheet=null; headerRow=null; workbook=null; returnms; } //////由DataTable导出Excel /// ///要导出数据的DataTable /// 指定Excel工作表名称 /// Excel工作表 publicstaticvoidExportDataTableToExcel(DataTablesourceTable,stringfileName) { //如数据超过65325则分成多个Table导出 if(sourceTable.Rows.Count>ExcelMaxRow) { DataSetds=GetdtGroup(sourceTable); //导出DataSet ExportDataSetToExcel(ds,fileName); } else { MemoryStreamms=ExportDataTableToExcel(sourceTable)asMemoryStream; HttpContext.Current.Response.AppendHeader("Content-Disposition","attachment;filename="+fileName); HttpContext.Current.Response.BinaryWrite(ms.ToArray()); HttpContext.Current.ApplicationInstance.CompleteRequest(); //HttpContext.Current.Response.End(); ms.Close(); ms=null; } } //////传入行数超过65325的Table,返回DataSet /// ////// publicstaticDataSetGetdtGroup(DataTabledt) { stringtablename=dt.TableName; DataSetds=newDataSet(); ds.Tables.Add(dt); doublen=dt.Rows.Count/Convert.ToDouble(ExcelMaxRow); //创建表 for(inti=1;i ///由DataTable导出Excel /// /// 要导出数据的DataTable /// 指定Excel工作表名称 /// Excel工作表 publicstaticvoidExportDataTableToExcelModel(DataTablesourceTable,stringmodelpath,stringmodelName,stringfileName,stringsheetName) { introwIndex=2;//从第二行开始,因为前两行是模板里面的内容 intcolIndex=0; FileStreamfile=newFileStream(modelpath+modelName+".xls",FileMode.Open,FileAccess.Read);//读入excel模板 HSSFWorkbookhssfworkbook=newHSSFWorkbook(file); HSSFSheetsheet1=(HSSFSheet)hssfworkbook.GetSheet("Sheet1"); sheet1.GetRow(0).GetCell(0).SetCellValue("excelTitle");//设置表头 foreach(DataRowrowinsourceTable.Rows) {//双循环写入sourceTable中的数据 rowIndex++; colIndex=0; HSSFRowxlsrow=(HSSFRow)sheet1.CreateRow(rowIndex); foreach(DataColumncolinsourceTable.Columns) { xlsrow.CreateCell(colIndex).SetCellValue(row[col.ColumnName].ToString()); colIndex++; } } sheet1.ForceFormulaRecalculation=true; FileStreamfileS=newFileStream(modelpath+fileName+".xls",FileMode.Create);//保存 hssfworkbook.Write(fileS); fileS.Close(); file.Close(); } }到此这篇关于c#读取excel数据的两种方法实现的文章就介绍到这了,更多相关c#读取excel内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!