读取Excel文件的两种方法
第一種方法:傳統(tǒng)方法,采用OleDB讀取EXCEL文件,
優(yōu)點(diǎn):寫法簡單,缺點(diǎn):服務(wù)器必須安有此組件才能用,不推薦使用
private DataSet GetConnect_DataSet2(string fileName)
{
DataSet myDataSet = new DataSet();
//創(chuàng)建一個數(shù)據(jù)鏈接
string strCon = " Provider = Microsoft.Jet.OLEDB.4.0 ; Data Source = " + fileName + ";Extended Properties=Excel 8.0";
OleDbConnection myConn = new OleDbConnection(strCon);
string strCom = " SELECT * FROM [Sheet1$] ";
//try
//{
myConn.Open();
//打開數(shù)據(jù)鏈接,得到一個數(shù)據(jù)集
OleDbDataAdapter myCommand = new OleDbDataAdapter(strCom, myConn);
//創(chuàng)建一個 DataSet對象
myDataSet = new DataSet();
//得到自己的DataSet對象
myCommand.Fill(myDataSet, "CodeTable");
//關(guān)閉此數(shù)據(jù)鏈接
myConn.Close();
//}
//catch (Exception ex)
//{
//}
return myDataSet;
}
第二種方法:用第三方組件:NPOI組件,推薦使用此方法
先去官網(wǎng):http://npoi.codeplex.com/下載需要引入dll(可以選擇.net2.0或者.net4.0的dll),然后在網(wǎng)站中添加引用。
NPOI 是 POI 項(xiàng)目的 .NET 版本。POI是一個開源的Java讀寫Excel、WORD等微軟OLE2組件文檔的項(xiàng)目。
使用 NPOI 你就可以在沒有安裝 Office 或者相應(yīng)環(huán)境的機(jī)器上對 WORD/EXCEL 文檔進(jìn)行讀寫。
NPOI采用的是Apache 2.0許可證(poi也是采用這個許可證),這意味著它可以被用于任何商業(yè)或非商業(yè)項(xiàng)目,你不用擔(dān)心因?yàn)槭褂盟仨氶_放你自己的源代碼,所以它對于很多從事業(yè)務(wù)系統(tǒng)開發(fā)的公司來說絕對是很不錯的選擇。
當(dāng)然作為一個開源許可證,肯定也是有一些義務(wù)的,例如如果你在系統(tǒng)中使用NPOI,你必須保留NPOI中的所有聲明信息。對于源代碼的任何修改,必須做出明確的標(biāo)識。
//config中配置的上傳的Excel路徑
static object basePath = ConfigurationManager.AppSettings["FilePath"];
#region 讀取Excel文件
/// <summary>
/// 讀取Excel文件到table中
/// </summary>
/// <param name="filePath">excel文件路徑</param>
/// <returns></returns>
public static DataTable ReadExcel(string fileName)
{
DataTable dt = new DataTable();
string filePath = "";
if (basePath != null)
{
filePath = HostingEnvironment.MapPath((basePath.ToString() + fileName));
dt = ImportExcelFile(filePath);
}
//文件是否存在
if (System.IO.File.Exists(filePath))
{
}
return dt;
}
public static DataTable ImportExcelFile(string filePath)
{
HSSFWorkbook hssfworkbook;
#region//初始化信息
try
{
using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
hssfworkbook = new HSSFWorkbook(file);
}
}
catch (Exception e)
{
throw e;
}
#endregion
NPOI.SS.UserModel.ISheet sheet = hssfworkbook.GetSheetAt(0);
System.Collections.IEnumerator rows = sheet.GetRowEnumerator();
DataTable dt = new DataTable();
rows.MoveNext();
HSSFRow row = (HSSFRow)rows.Current;
for (int j = 0; j < (sheet.GetRow(0).LastCellNum); j++)
{
//dt.Columns.Add(Convert.ToChar(((int)'A') + j).ToString());
//將第一列作為列表頭
dt.Columns.Add(row.GetCell(j).ToString ());
}
while (rows.MoveNext())
{
row = (HSSFRow)rows.Current;
DataRow dr = dt.NewRow();
for (int i = 0; i < row.LastCellNum; i++)
{
NPOI.SS.UserModel.ICell cell = row.GetCell(i);
if (cell == null)
{
dr[i] = null;
}
else
{
dr[i] = cell.ToString();
}
}
dt.Rows.Add(dr);
}
return dt;
}
#endregion
Npoi是對Excel(或者叫office比較合適)進(jìn)行操作的一個類庫框架,我們可以不再使用office提供的那個惡心的接口(速度慢)來操作了,我們對于office的操作解放了?,F(xiàn)在最新版的應(yīng)該是1.2.5.如果你安裝了NuGet的話,可以很容易的獲取。
因?yàn)镋xcel 2003極其以前的版本采用的底層代碼和Excel 2007 及其以后的不同,所以對于這個分界點(diǎn)是需要我們注意的。為什么會出現(xiàn)這個分界點(diǎn),大家想一下,現(xiàn)在微軟的所有東西都在.net 架構(gòu)之下,以前的Excel版本和這個架構(gòu)肯定是不同的。
我們重點(diǎn)來說excel。畢竟這是在我們的工作中用的最多的一個,Excel包括 文件(file,在Npoi.net中稱為workBook 工作簿)、工作表(sheet)以及里面的單元格,按照從大到小的分類就是文件中包含若干個sheet,每個sheet中包含很多單元格。這是Excel 的分類。
為了操作Excel,npoi.net當(dāng)然也需要對應(yīng)的類來對應(yīng)不同的分類,其中
HSSFWorkbook對應(yīng)的就是Excel文件 工作簿,
HSSFSheet對應(yīng)的就是Excel中sheet 工作表,
HSSFCell對應(yīng)的就是Excel的單元格,
HSSFRow對應(yīng)的就是Excel的行。
有了這幾個不同的類,我們就可以創(chuàng)建Excel文件,創(chuàng)建sheet,給sheet重命名或刪除sheet,創(chuàng)建行,添加單元格,為單元格設(shè)置格式,我個人感覺其他的都很簡單,唯獨(dú)這個給單元格設(shè)置格式的做法很令人討厭,沒辦法用的別人的,只能有苦自己承受了。
public class NpoiNet
{
public void CreateWorkBook()
{
string filePath = HttpContext.Current.Server.MapPath("~/npoi.xls");
//表示一個文件流
FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite);
HSSFWorkbook workBook = new HSSFWorkbook();//相當(dāng)于創(chuàng)建了一個內(nèi)存中的Excel 只是還沒有寫到硬盤上
try
{
/*按照約定在每個Excel文件中至少要包含一個sheet,如果沒有任何sheet,打開Excel文件的時候會報(bào)錯。
在以前的npoi版本中,如果不是自己手動的創(chuàng)建一個sheet,npoi框架是不會自動創(chuàng)建一個的,但是在最新版的1.2.5中,
我發(fā)現(xiàn)即使你忘記了創(chuàng)建sheet的操作,框架會自動創(chuàng)建一個sheet,當(dāng)然如果你手動創(chuàng)建了一個sheet,則框架就不會
自動的創(chuàng)建一個sheet,這就像構(gòu)造函數(shù),如果沒有寫任何一個,.Net會默認(rèn)存在一個,但是你創(chuàng)建了一個構(gòu)造函數(shù),則
* 框架就不會自動創(chuàng)建了
* */
workBook.CreateSheet("guozhiqi");//sheet的名稱為guozhiqi
workBook.CreateSheet();//sheet的名稱為sheet1 從1開始命名
workBook.CreateSheet("yuanjinzhou");
workBook.CreateSheet();//這個sheet的名稱應(yīng)該為什么?答案是sheet3
//創(chuàng)建了sheet 下面我們來創(chuàng)建單元格
HSSFSheet sheetGuozhiqi = (HSSFSheet)workBook.GetSheet("guozhiqi");//獲取到sheet名稱為guozhiqi的那個工作簿
//創(chuàng)建了工作簿 添加單元格之前首先要添加行
//在這里請注意 行和列的下標(biāo)都是從0開始的 而不是Excel文件中的1
for (int i = 0; i <= 10; i++)
{
sheetGuozhiqi.CreateRow(i);//創(chuàng)建了11行
}
//創(chuàng)建了行之后 就要在每個行中創(chuàng)建單元格
//如果沒有在之前創(chuàng)建行
// HSSFRow newRow = (HSSFRow)sheetGuozhiqi.GetRow(12);這是錯誤的 程序會報(bào)異常 這就告訴我們 如果行還沒有創(chuàng)建
//就不可以獲取
HSSFRow newRow = (HSSFRow)sheetGuozhiqi.GetRow(0);
HSSFCell[] cells = new HSSFCell[11];
//在第0行的位置創(chuàng)建單元格
for (int i = 0; i <= 10; i++)
{
cells[i] = (HSSFCell)newRow.CreateCell(i);//為第0行創(chuàng)建了10個單元格
}
//這里取得單元格的異常出現(xiàn)位置相同 就是如果沒有創(chuàng)建就不要試圖獲取
HSSFCell newCell = (HSSFCell)newRow.GetCell(0);//取得第0行第0個單元格
//獲取到了單元格 賦值 為了方便說明 我多獲取幾個單元格的值
//Excel單元格有很多類型 例如字符串 數(shù)字 bool等類型,
cells[0].SetCellValue(false);//賦值為bool型
cells[1].SetCellValue(DateTime.Now);//賦值為日期型
cells[2].SetCellValue(3.1415926);//賦值為double類型
cells[3].SetCellValue("guozhiqi");//賦值為字符串guozhiqi
//為單元格賦值以后 我們就要開始取值了
bool cell0 = cells[0].BooleanCellValue;
// string cell00 = cells[0].StringCellValue; 錯誤 這句話的意思就是說存儲的時候是什么類型 就必須用對應(yīng)的
//取值方法取值
DateTime dateTime = cells[1].DateCellValue;
double cell2 = cells[2].NumericCellValue;
string cell3 = cells[3].StringCellValue;
//可以正常創(chuàng)建單元格 從單元格取值是遠(yuǎn)遠(yuǎn)不夠的 還有就是客戶可能會要求合并單元格 為單元格設(shè)置樣式
//合并單元格的操作不必要創(chuàng)建所有的行或列,只需要制定范圍即可
sheetGuozhiqi.AddMergedRegion(new NPOI.SS.Util.Region(1,1,20,20));//合并單元格
HSSFCellStyle cellStyle = (HSSFCellStyle)workBook.CreateCellStyle();
cellStyle.Alignment = HorizontalAlignment.CENTER;//居中顯示
cellStyle.FillBackgroundColor = 244;
cellStyle.FillPattern = FillPatternType.BRICKS;//填充模式
cellStyle.IsHidden = false;//單元格是否隱藏
cellStyle.IsLocked = false;//單元格是否鎖定
cellStyle.VerticalAlignment = VerticalAlignment.CENTER;//垂直居中
//設(shè)置單元格字體
HSSFFont font =(HSSFFont) workBook.CreateFont();
font.Color = 200;
font.FontHeight = 18;//設(shè)置字體大小
font.FontName = "黑體";//設(shè)置字體為黑體
font.IsItalic = false;//是否是斜體
font.IsStrikeout = true;//是否有中間線
font.Underline = (byte)FontUnderlineType.DOUBLE;//設(shè)置下劃線
cellStyle.SetFont(font);
//將設(shè)置好的樣式應(yīng)用到對應(yīng)的單元格上 否則是沒有效果的
cells[0].CellStyle = cellStyle;
if (!workBook.IsWriteProtected)
{
workBook.Write(fileStream);
}
}
catch (Exception ex)
{
HttpContext.Current.Response.Write(ex.Message+ex.Source+ex.StackTrace);
}
finally
{
if (fileStream != null)
{
fileStream.Close();
}
}
}
}
總結(jié),既然這篇博客是Npoi.net的總結(jié),那么我不可能就是舉了一個例子就算了事,畢竟博客園中園友們舉得例子已經(jīng)夠多了,下面我就把在使用npoi.net會遇到的一些小問題總結(jié)一下。
在實(shí)例化了一個WorkBook之后,最好添加一個sheet,雖然在最新版的Npoi.net中自動添加了,但是遇到遷移到原來版本就會出現(xiàn)問題。所以我建議還是最少添加一個sheet
在從單元格取值時要注意單元格的類型,一定要用對應(yīng)的類型的方法來取單元格中的對應(yīng)類型的值,如果不確定,那只能是強(qiáng)制轉(zhuǎn)換成為string類型,畢竟string類型是excel中其他類型都可以轉(zhuǎn)換過來的
在獲取sheet中的某一行或者某一行的某一個單元格的時候,還要注意就是一定要確保創(chuàng)建了該行,并且取單元格還要確保創(chuàng)建了單元格,否則會報(bào)Null reference not to object 這個我們經(jīng)常會看到的異常信息。在外層一定要加上try捕獲異常
合并單元格是sheet的工作,因此需要獲取對應(yīng)的sheet,然后調(diào)用其AddMergedRegion方法合并單元格,在合并單元格的時候,我們不需要確保該單元格已經(jīng)存在或創(chuàng)建。
在為單元格設(shè)置樣式的過程中,我們會發(fā)現(xiàn)所有和樣式相關(guān)的類的創(chuàng)建都是通過workBook.Create(Font)..這種方式來執(zhí)行的,我們不可以直接new一個類的實(shí)例。
如果前面的工作都已經(jīng)做好,需要把內(nèi)存中的excel表寫到硬盤上時,需要調(diào)用 workBook.write()方法,傳入一個文件流進(jìn)行創(chuàng)建。在這里有可能會出現(xiàn)一個問題,就是你要創(chuàng)建的文件你已經(jīng)打開了,這時程序就會出現(xiàn)異常, 因此我們在調(diào)試程序的時候一定要記得打開了excel文件以后要關(guān)閉
最后需要注意的就是文件流,在我們把excel寫到硬盤上以后,要顯式的調(diào)用其close()方法關(guān)閉文件流。因?yàn)槿绻魂P(guān)閉文件流的話,以后就會出現(xiàn)無法重新創(chuàng)建該文件的錯誤,并且會提示 某文件正由另一進(jìn)程使用,因此該進(jìn)程無法訪問此文件。
總結(jié)
以上是生活随笔為你收集整理的读取Excel文件的两种方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Elsevier系旗下期刊论文投稿流程
- 下一篇: 什么是标准模式与混杂模式?