NPOI使用手冊

出處:http://blog.csdn.net/pan_junbiao/article/details/39717443php

NPOI使用手冊html

目錄git

1.認識NPOI算法

 

2. 使用NPOI生成xls文件apache

2.1 建立基本內容編程

2.1.1建立Workbook和Sheet數組

2.1.2建立DocumentSummaryInformation和SummaryInformation服務器

2.1.3建立單元格編程語言

2.1.5建立批註函數

2.1.6建立頁眉和頁腳

 

2.2 單元格操做

2.2.1設置格式

2.2.2合併單元格

2.2.3對齊相關設置

2.2.4使用邊框

2.2.5字體設置

2.2.6背景和紋理

2.2.7設置寬度和高度

 

2.3 使用Excel公式

2.3.1基本計算

2.3.2 SUM函數

2.3.3日期函數

2.3.4字符串相關函數

2.3.5 IF函數

2.3.6 CountIf和SumIf函數

2.3.7 Lookup函數

2.3.8隨機數函數

2.3.9經過NPOI得到公式的返回值

 

2.4 建立圖形

2.4.1畫線

2.4.2畫矩形

2.4.3畫圓形

2.4.4畫Grid

2.4.5插入圖片

 

2.5打印相關設置

  
2.6 高級功能

2.6.1調整表單顯示比例

2.6.2設置密碼

2.6.3組合行、列

2.6.4鎖定列

2.6.5顯示/隱藏網格線

2.6.6設置初始視圖的行、列

2.6.7數據有效性

2.6.8生成下拉式菜單

 

3. 項目實踐

3.1基於.xls模板生成Excel文件

3.2生成九九乘法表

3.3生成一張工資單

3.4從xls文件中抽取文本

3.5巧妙使用ExcelChart

3.6導入Excel文件

 

NPOI 1.2教程 - 1 認識NPOI

本章將介紹NPOI的一些基本信息,包括如下幾個部分

·        什麼是NPOI

·        版權說明

·        相關資源

·        團隊介紹

·        將來展望

·        各Assembly的做用

 

1.1 什麼是NPOI

NPOI,顧名思義,就是POI的.NET版本。那POI又是什麼呢?POI是一套用Java寫成的庫,可以幫助開發者在沒有安裝微軟Office的狀況下讀寫Office 97-2003的文件,支持的文件格式包括xls, doc, ppt等。在本文發佈時,POI的最新版本是3.5 beta 6。

NPOI 1.x是基於POI 3.x版本開發的,與poi 3.2對應的版本是NPOI 1.2,目前最新發布的版本是1.2.1,在該版本中僅支持讀寫Excel文件和Drawing格式,其餘文件格式將在之後的版本中獲得支持。

 

1.2 版權說明

NPOI採用的是Apache 2.0許可證(poi也是採用這個許可證),這意味着它能夠被用於任何商業或非商業項目,你不用擔憂由於使用它而必須開放你本身的源代碼,因此它對於不少從事業務系統開發的公司來講絕對是很不錯的選擇。

固然做爲一個開源許可證,確定也是有一些義務的,例如若是你在系統中使用NPOI,你必須保留NPOI中的全部聲明信息。對於源代碼的任何修改,必須作出明確的標識。

完整的apache 2.0許可證請見http://www.phpx.com/man/Apache-2/license.html

 

1.3 相關資源

官方網站:http://npoi.codeplex.com/

POIFS Browser 1.2

下載地址:http://npoi.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24305

QQ交流羣:  78142590

 

1.4 團隊介紹

Tony Qu來自於中國上海,是這個項目的發起人和開發人員,時區是GMT+8,2008年9月開始了NPOI的開發,負責NPOI全部底層庫的開發、測試和bug修復。

我的blog地址爲http://tonyqus.cnblogs.com/

 

HüseyinTüfekçilerli來自於土耳其的伊斯坦布爾,也是這個項目的開發人員,時區是GMT+2,2008年11月參與了NPOI的開發,主要負責POIFS Browser 1.0的開發工做。

我的blog地址爲http://huseyint.com/

 

aTao.Xiang,來自中國,2009年8月開始參與該項目,主要參與了NPOI 1.2中文版的撰寫工做和推廣工做

我的blog地址爲http://www.cnblogs.com/atao/

 

1.5 回顧與展望

目前POI版本中的HWPF(用於Word的讀寫庫)還不是很穩定,並不是正式發佈版本,且負責HWPF的關鍵開發人員已經離開,因此NPOI可能考慮本身從新開發HWPF。另外,目前微軟正在開發Open XML Format SDK,NPOI可能會放棄對ooxml的支持,固然這取決於用戶的需求和Open XML Format SDK的穩定性和速度。從目前而言,NPOI有幾大優點

第一,徹底基於.NET 2.0,而非.NET 3.0/3.5。

第二,讀寫速度快(有個國外的兄弟回覆說,他原來用ExcelPackage生成用了4-5個小時,如今只須要4-5分鐘)

第三,穩定性好(相對於用Office OIA而言,畢竟那東西是基於Automation作的,在Server上跑個Automation的東西,想一想都以爲可怕),跑過了將近1000個測試用例(來自於POI的testcase目錄)

第四,API簡單易用,固然這得感謝POI的設計師們

第五,完美支持Excel 2003格式(聽說myxls沒法正確讀取xls模板,但NPOI能夠),之後也許是全部Office 2003格式

但願NPOI把這些優點繼續發揚下去,這樣NPOI纔會更有競爭力。

 

1.6 NPOI 1.2中各Assembly的做用

NPOI目前有好幾個assembly,每一個的做用各有不一樣,開發人員能夠按需加載相應的assembly。在這裏大概羅列一下:

NPOI.Util  基礎輔助庫
NPOI.POIFS   OLE2格式讀寫庫
NPOI.DDF   Microsoft Drawing格式讀寫庫
NPOI.SS   Excel公式計算庫
NPOI.HPSF   OLE2的Summary Information和Document Summary Information屬性讀寫庫
NPOI.HSSF   Excel BIFF格式讀寫庫

 

NPOI 1.2教程 - 2.1.1 建立Workbook和Sheet

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

  

建立Workbook說白了就是建立一個Excel文件,固然在NPOI中更準確的表示是在內存中建立一個Workbook對象流。

本節做爲第2章的開篇章節,將作較爲詳細的講解,以幫助NPOI的學習者更好的理解NPOI的組成和使用。

NPOI.HSSF是專門負責Excel BIFF格式的命名空間,供開發者使用的對象主要位於NPOI.HSSF.UserModel和NPOI.HSSF.Util命名空間下,下面咱們要講到的Workbook的建立用的就是NPOI.HSSF.UserModel.HSSFWorkbook類,這個類負責建立.xls文檔。

在開始建立Workbook以前,咱們先要在項目中引用一些必要的NPOI assembly,以下所示:

NPOI.dll

NPOI.POIFS.dll

NPOI.HSSF.dll

NPOI.Util.dll

 

要建立一個新的xls文件其實很簡單,只要咱們初始化一個新的HSSFWorkbook實例就好了,以下所示:

using NPOI.HSSF.UserModel;

...

HSSFWorkbookhssfworkbook =newHSSFWorkbook();

是否是很方便啊,沒有任何參數或設置,但這麼建立有一些限制,這樣建立出來的Workbook在Excel中打開是會報錯的,由於Excel規定一個Workbook必須至少帶1個Sheet,這也是爲何在Excel界面中,新建一個Workbook默認都會新建3個Sheet。因此必須加入下面的建立Sheet的代碼才能保證生成的文件正常:

HSSFSheetsheet = hssfworkbook.CreateSheet("newsheet");

若是要建立標準的Excel文件,即擁有3個Sheet,能夠用下面的代碼:

hssfworkbook.CreateSheet("Sheet1");

hssfworkbook.CreateSheet("Sheet2");

hssfworkbook.CreateSheet("Sheet3");

最後就是把這個HSSFWorkbook實例寫入文件了,代碼也很簡單,以下所示:

FileStreamfile =new FileStream(@"test.xls", FileMode.Create);

hssfworkbook.Write(file);

file.Close();

 

這裏假設文件名是test.xls,,在建立完FileStream以後,直接調用HSSFWorkbook類的Write方法就能夠了。

最後你能夠打開test.xls文件確認一下,是否是有3個空的Sheet。

相關範例請見NPOI 1.2正式版中的CreateEmptyExcelFile項目。

 

NPOI 1.2教程 - 2.1.2 建立DocumentSummaryInformation和SummaryInformation

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

昨天收到了很多回復,有msn上的,也有blog上的,我表明NPOI Team向全部支持和關注NPOI的兄弟表示感謝,讓咱們共同完善NPOI。

 

前一節中咱們講解了如何建立一個新的Workbook,但在此過程當中你們也許會發現一個細節,這些文件沒有包括DocummentSummaryInformation和SummaryInformation頭。若是你還不是很清楚我在說什麼,能夠看POIFS Browser打開test.xls文件後的截圖:

 

你會發現只有Workbook目錄,其餘什麼都沒有,但事實上一個正常的xls文件,好比說Excel生成的xls文件是相似下面的結構:

 

是否是多出來DocumentSummaryInformation和SummaryInformation兩個頭?不少人可能對DocumentSummaryInformation和SummaryInformation很陌生,可能第一次據說這玩意,沒事,這很正常,由於普通用戶不多會去使用這些東西,但它們其實比想象中有用。

 

請看上圖中的信息,如做者、標題、標記、備註、主題等信息,其實這些信息都是存儲在DocummentSummaryInformation和SummaryInformation裏面的,這麼一說我想你們應該明白了吧,這些信息是爲了快速提取文件信息準備。在Windows XP中,也有對應的查看和修改界面,只是沒有Vista這麼方便,以下所示:

 

這恐怕也是不少人對於這些信息不聞不問的緣由吧,由於沒有人願意經過右擊文件->屬性這樣複雜的操做去查看一些摘要信息。

 

提示

DocummentSummaryInformation和SummaryInformation並非Office文件的專利,只要是OLE2格式,均可以擁有這兩個頭信息,主要目的就是爲了在沒有完整讀取文件數據的狀況下得到文件的摘要信息,同時也可用做桌面搜素的依據。要了解DocummentSummaryInformation的所有屬性請見http://msdn.microsoft.com/en-us/library/aa380374(VS.85).aspx;要了解SummaryInformation的所有屬性請見http://msdn.microsoft.com/en-us/library/aa369794(VS.85).aspx

 

好了,說到這裏,我想你們對於接下來咱們要建立的內容有了初步的認識,下面咱們就立刻動手建立。

首先引用如下這些命名空間:

using NPOI.HSSF.UserModel;

using NPOI.HPSF;

using NPOI.POIFS.FileSystem;

其中與DocummentSummaryInformation和SummaryInformation密切相關的是HPSF命名空間。

首先建立Workbook

HSSFWorkbookhssfworkbook =newHSSFWorkbook();

而後建立DocumentSummaryInformation

DocumentSummaryInformationdsi = PropertySetFactory.CreateDocumentSummaryInformation();

dsi.Company ="NPOI Team";

再建立SummaryInformation

SummaryInformationsi = PropertySetFactory.CreateSummaryInformation();

si.Subject ="NPOI SDK Example";

由於是範例,這裏僅各設置了一個屬性,其餘都沒有設置。

如今咱們把建立好的對象賦給Workbook,這樣才能保證這些信息被寫入文件。

hssfworkbook.DocumentSummaryInformation= dsi;

hssfworkbook.SummaryInformation= si;

最後和2.1.1節同樣,咱們把Workbook經過FileStream寫入文件。

 

相關範例請見NPOI 1.2正式版中的CreatePOIFSFileWithProperties

 

NPOI 1.2教程 - 2.1.3 建立單元格

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

 

用過Excel的人都知道,單元格是Excel最有意義的東西,咱們作任何操做恐怕都要和單元格打交道。在Excel中咱們要添加一個單元格只須要點擊任何一個單元格,而後輸入內容就是了,可是Excel底層其實沒有這麼簡單,不一樣的單元格是有不一樣的類型的,好比說數值單元格是用NumberRecord表示,文本單元格是用LabelSSTRecord表示,空單元格是用BlankRecord表示。這也就意味着,在設置單元格時,你必須告訴NPOI你須要建立哪一種類型的單元格。

要建立單元格首先要建立單元格所在的行,好比,下面的代碼建立了第0行:

HSSFSheetsheet1 = hssfworkbook.CreateSheet("Sheet1");

HSSFRowrow1=sheet1.CreateRow(0);

行建好了,就能夠建單元格了,好比建立A1位置的單元格:

row1.CreateCell(0).SetCellValue(1);

這裏要說明一下,SetCellValue有好幾種重載,你能夠設置單元格爲bool、double、DateTime、string和HSSFRichTextString類型。其中對於string類型的重載調用的就是HSSFRichTextString類型的重載,因此是同樣的,HSSFRichTextString可用於有字體或者Unicode的文本。

若是你以爲每一行要聲明一個HSSFRow很麻煩,能夠用下面的方式:

sheet1.CreateRow(0).CreateCell(0).SetCellValue("This is a Sample");

這麼用有個前提,那就是第0行還沒建立過,不然得這麼用:

sheet1.GetRow(0).CreateCell(0).SetCellValue("This is a Sample");

 

注意:這裏的行在Excel裏是從1開始的,可是NPOI內部是從0開始的;列在Excel裏面是用字母表示的,而NPOI中也是用從0開始的數字表示的,因此要注意轉換。

 

若是你要得到某一個已經建立的單元格對象,能夠用下面的代碼:

sheet1.GetRow(row_index).GetCell(column_index);

 

本節僅講解最基本的單元格建立,有關單元格格式設置、樣式等高級話題請見:2.2節單元格相關操做。

相關範例請見NPOI 1.2正式版中的SetCellValuesInXls項目。

 

NPOI 1.2教程 - 2.1.4 建立批註

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

 

不少人不怎麼用Excel中的批註,因此我特意截了張圖,讓你們知道本節咱們要建立的究竟是什麼東西。

 

在過去,咱們恐怕沒有辦法實現這一功能,由於不管是cvs法、html法、oledb法都沒有提供這樣的接口,固然Office PIA法能夠作到,可是性能實在太差,並且穩定性很差,常常莫名其妙crash(這是某某兄弟給個人反饋,我引用了下,呵呵)。在之後的教程中,你將看到更多在過去沒法經過傳統方法實現的東西,好戲纔剛剛開始。

批註主要有三個屬性須要設置,一個是批註的位置和大小、一個是批註的文本、還有一個是批註的做者。

 

批註的位置和大小,在Excel中是與單元格密切相關的,NPOI中經過HSSFClientAnchor的實例來表示,它的構造函數比較複雜,有8個參數,它們分別是

參數

說明

dx1

第1個單元格中x軸的偏移量

dy1

第1個單元格中y軸的偏移量

dx2

第2個單元格中x軸的偏移量

dy2

第2個單元格中y軸的偏移量

col1

第1個單元格的列號

row1

第1個單元格的行號

col2

第2個單元格的列號

row2

第2個單元格的行號

 

例如,若是咱們打算讓註釋顯示在B3和E5之間,就應該這麼寫:

HSSFPatriarchpatr = sheet.CreateDrawingPatriarch();

HSSFCommentcomment1 = patr.CreateComment(new HSSFClientAnchor(0, 0, 0, 0, 1, 2 , 4, 4));

下面咱們設置這個批註的內容和做者,這個比較簡單:

comment1.String=newHSSFRichTextString("Hello World");

comment1.Author="NPOI Team";

最後一步就是把批註賦給某個單元格:

HSSFCell cell= sheet.CreateRow(1).CreateCell(1);

cell.CellComment= comment1;

對於批註,你有兩種選擇,一種是隱藏(默認),一種是顯示(即表單一打開就顯示該批註),能夠經過comment1.Visible屬性來控制。

 

看了上面這張圖你們就應該明白了,這裏有2個批註,下面那個是顯示的,上面那個是隱藏的。

相關範例請見NPOI 1.2正式版中的SetCellCommentInXls。

 

NPOI 1.2教程 - 2.1.6 建立頁眉和頁腳

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

 

不少人並不知道Excel的頁眉和頁腳功能,由於在界面上是顯示不了頁眉和頁腳的,必須在打印頁面中才能看到,這也直接致使了其設置界面也顯得更隱祕,你必須進入頁面設置 –>頁眉和頁腳才能設置。如下是Office 2007中的設置界面。

 

當你按「自定義頁眉」或「自定義頁腳」時,你會看到如下界面,Excel把頁眉、頁腳分紅了左中右三部分,這一點絕非單純體如今界面上,在底層的存儲中也是如此。若是你設置的是「左」的內容,底層的存儲字符串就會在開頭加上&L,若是是「右」的內容則會加上&R,因此HeaderRecord中的字符串看上去是這樣的:"&C&LFooter A&R」,這個字符串的意思是僅設置了「左」的內容,內容是Footer A。

 

看了這些我想你應該對頁眉和頁腳有所瞭解了,回過頭來講NPOI,NPOI中主要是靠HSSFSheet.Header和HSSFSheet.Footer來設置的,這兩個屬性分別是HSSFHeader和HSSFFooter類型的。

 

參考代碼以下:

HSSFSheet s1= hssfworkbook.CreateSheet("Sheet1");

s1.CreateRow(0).CreateCell(1).SetCellValue(123);

 

//set headertext

s1.Header.Center="This is a test sheet";

//set footertext

s1.Footer.Left="Copyright NPOI Team";

s1.Footer.Right="created by Tony Qu(瞿傑)";

 

以上代碼中我添加了頁眉的Center內容,Footer的Left和Right內容,在打印預覽中看到的效果大概是這樣的:

頁眉

 

頁腳

 

至於一些Excel特殊字符,好比說頁碼能夠用&P,當前日期能夠用&D,其餘的東西你就本身研究吧。

 

本範例完整代碼請見NPOI.Examples中的CreateHeaderFooterInXls項目。

 

NPOI 1.2教程 - 2.2.1 設置單元格格式

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

 

在Excel中咱們常常要設置格式,好比說日期格式(yyyymmdd)、小數點格式(1.20)、貨幣格式($2000)、百分比格式(99.99%)等等,這些東西在過去咱們恐怕只能在服務器端生成好,不但增長了服務器端的代碼量,還形成了沒必要要的字符串替換操做,現在NPOI將讓服務器從這種徹底沒有必要的操做中解放出來,一切都將由Excel在客戶端處理。

使用NPOI時要注意,全部的格式都是經過CellStyle.DataFormat賦給單元格的,而不是直接賦給單元格。

案例一 日期格式

假設咱們如今須要顯示的日期的格式爲2008年5月5日,能夠用下面的代碼生成:

HSSFSheetsheet = hssfworkbook.CreateSheet("newsheet");

HSSFCell cell= sheet.CreateRow(0).CreateCell(0);

cell.SetCellValue(newDateTime(2008,5,5));

//set dateformat

HSSFCellStylecellStyle = hssfworkbook.CreateCellStyle();

HSSFDataFormatformat = hssfworkbook.CreateDataFormat();

cellStyle.DataFormat= format.GetFormat("yyyy年m月d日");

cell.CellStyle=cellStyle;

因爲這裏的「yyyy年m月d日」屬於自定義格式(區別於Excel內嵌的格式),因此必須用hssfworkbook.CreateDataFormat()建立一個HSSFDataFormat實例,而後使用format.GetFormat來獲取相應的格式,只要是Excel支持的格式表示方式,這種方式都可以實現。

案例二保留2位小數

假設咱們有個單元格的值爲1.2,怎麼顯示成1.20呢?在Excel中能夠用「0.00」來表示,因此下面的代碼就能完成:

// Create arow and put some cells in it. Rows are 0 based.

HSSFCell cell= sheet.CreateRow(0).CreateCell(0);

//set valuefor the cell

cell.SetCellValue(1.2);

//numberformat with 2 digits after the decimal point - "1.20"

HSSFCellStylecellStyle = hssfworkbook.CreateCellStyle();

cellStyle.DataFormat= HSSFDataFormat.GetBuiltinFormat("0.00");

cell.CellStyle= cellStyle;

 

這裏與上面有所不一樣,用的是HSSFDataFormat.GetBuiltinFormat()方法,之因此用這個,是由於0.00是Excel內嵌的格式,完整的Excel內嵌格式列表你們能夠看這個窗口中的自定義列表:

 

這裏就不一一列出了。

案例三貨幣格式

貨幣格式在金融的項目中常常用到,好比說人民幣符號¥,美圓符號$等,這裏能夠用下面的代碼表示:

HSSFCellcell2 = sheet.CreateRow(1).CreateCell(0);

cell2.SetCellValue(20000);

HSSFCellStylecellStyle2 = hssfworkbook.CreateCellStyle();

HSSFDataFormatformat = hssfworkbook.CreateDataFormat();

cellStyle2.DataFormat= format.GetFormat("¥#,##0");

cell2.CellStyle= cellStyle2;

 

注意,這裏還加入了千分位分隔符,因此是#,##,至於爲何這麼寫,你得去問微軟,呵呵。

案例四百分比

百分比在報表中也很經常使用,其實基本上和上面同樣,只是格式表示是0.00%,代碼以下:

cellStyle4.DataFormat= HSSFDataFormat.GetBuiltinFormat("0.00%");

因爲這裏是內嵌格式,因此直接用HSSFDataFormat.GetBuiltinFormat便可。

案例五中文大寫

在表示金額時,咱們時常會用到,我也見過很多兄弟實現了數字轉中文大小寫的工具類,之後你能夠嘗試讓Excel去處理這一切,代碼和剛纔差很少,也是改格式的表示:

HSSFDataFormatformat = hssfworkbook.CreateDataFormat();

cellStyle6.DataFormat= format.GetFormat("[DbNum2][$-804]0");

 

因爲是自定義格式,因此用了HSSFDataFormat.GetFormat,相信你對這兩種獲取格式的形式的區別愈來愈熟悉了。

案例六科學計數法

這東西數學課上咱們都學過,雖然用的很少,可是既然Excel支持,這裏也提一下:

cellStyle3.DataFormat= HSSFDataFormat.GetBuiltinFormat("0.00E+00");

 

下面展現下以上這些例子的顯示效果:

 

最後總結一下HSSFDataFormat.GetFormat和HSSFDataFormat.GetBuiltinFormat的區別:

當使用Excel內嵌的(或者說預約義)的格式時,直接用HSSFDataFormat.GetBuiltinFormat靜態方法便可。

當使用本身定義的格式時,必須先調用HSSFWorkbook.CreateDataFormat(),由於這時在底層會先找有沒有匹配的內嵌FormatRecord,若是沒有就會新建一個FormatRecord,因此必須先調用這個方法,而後你就能夠用得到的HSSFDataFormat實例的GetFormat方法了,固然相對而言這種方式比較麻煩,因此內嵌格式仍是用HSSFDataFormat.GetBuiltinFormat靜態方法更加直接一些。不過自定義的格式也不是天馬行空隨便定義,仍是要參照Excel的格式表示來定義,具體請看相關的Excel教程。

注意:自定義的FormatRecord是嵌入xls文件內部的,因此不用擔憂對方Excel中有沒有定義過這種格式,都是可以正常使用的。

 

相關範例請參考NPOI 1.2正式版中的NumberFormatInXls項目。

 

NPOI 1.2教程 - 2.2.2 單元格合併

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

 

合併單元格在製做表格時頗有用,好比說表格的標題就常常是把第一行的單元格合併居中。那麼在NPOI中應該如何實現單元格的合併呢?

爲了實現這一功能,NPOI引入了新的概念,即Region,由於合併單元格,其實就是設定一個區域。下面說一下Region類的參數,Region總共有4個參數,以下所示

Region的參數

說明

FirstRow

區域中第一個單元格的行號

FirstColumn

區域中第一個單元格的列號

LastRow

區域中最後一個單元格的行號

LastColumn

區域中最後一個單元格的列號

因爲單元格的合併都是在表的基礎上創建的,因此咱們得先建Sheet:

HSSFWorkbookhssfworkbook =newHSSFWorkbook();

HSSFSheetsheet = hssfworkbook.CreateSheet("newsheet");

接下來咱們根據實際場景來作一些演示。

 

場景一標題行的合併

這種場景是最多見的,好比說咱們要創建一張銷售狀況表,英文叫Sales Report

 

咱們先設置居中和字體樣式,這裏咱們採用20號字體,代碼以下:

HSSFRow row =sheet.CreateRow(0);

HSSFCell cell= row.CreateCell(0);

cell.SetCellValue("Sales Report");

HSSFCellStylestyle = hssfworkbook.CreateCellStyle();

style.Alignment= HSSFCellStyle.ALIGN_CENTER;

HSSFFont font= hssfworkbook.CreateFont();

font.FontHeight= 20*20;

style.SetFont(font);

cell.CellStyle= style;

要產生圖中的效果,即把A1:F1這6個單元格合併,而後添加合併區域:

sheet.AddMergedRegion(new Region(0, 0, 0,5));

 

場景二多行合併

看完場景一,你可不要認爲多行合併就須要一行一行作,其實也只須要一行代碼,好比說咱們要把C3:E5合併爲一個單元格,那麼就能夠用下面的代碼:

 

sheet.AddMergedRegion(new Region(2, 2, 4,4));

提示即便你沒有用CreateRow和CreateCell建立過行或單元格,也徹底能夠直接建立區域而後把這一區域合併,Excel的區域合併信息是單獨存儲的,和RowRecord、ColumnInfoRecord不存在直接關係。

 

相關範例請參考NPOI 1.2正式版中的MergedCellInXls項目。

 

NPOI 1.2教程 - 2.2.3 單元格對齊相關設置

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

 

本節將圍繞「對齊」選項卡中的設置展開,雖然實際上你會發現該選項卡中的不少設置和對齊沒有什麼關係。合併單元格已經在2.2.2節講過了,這裏就不提了。

 

首先咱們用代碼建立必要的單元格,代碼以下:

HSSFWorkbookhssfworkbook =new HSSFWorkbook();

HSSFSheetsheet1 = hssfworkbook.CreateSheet("Sheet1");

HSSFRow row =sheet1.CreateRow(0);

row.CreateCell(0).SetCellValue("Test");

這裏咱們假設在A0單元格中加入了文本Test。

 

請注意接下來咱們要作的全部操做都是在CellStyle的基礎上完成的,因此咱們建立一個HSSFCellStyle:

HSSFCellStylestyle=hssfworkbook.CreateCellStyle();

 

水平對齊

這裏用的是HSSFCellStyle.Alignment,默認值天然是常規,即HSSFCellStyle.ALIGN_GENERAL。

若是是左側對齊就是

style.Alignment= HSSFCellStyle.ALIGN_LEFT;

若是是居中對齊就是

style.Alignment= HSSFCellStyle.ALIGN_CENTER;

若是是右側對齊就是

style.Alignment= HSSFCellStyle.ALIGN_RIGHT;

若是是跨列舉中就是

style.Alignment= HSSFCellStyle.ALIGN_CENTER_SELECTION;

若是是兩端對齊就是

style.Alignment= HSSFCellStyle.ALIGN_JUSTIFY;

若是是填充就是

style.Alignment= HSSFCellStyle.ALIGN_FILL;

 

注意:以上選項僅當有足夠的寬度時才能產生效果,不設置寬度恐怕看不出區別。

 

垂直對齊

這裏用的是HSSFCellStyle.VerticalAlignment,默認值爲居中,即HSSFCellStyle.VERTICAL_CENTER

若是是靠上就是

style.VerticalAlignment=HSSFCellStyle.VERTICAL_TOP

若是是居中就是

style.VerticalAlignment=HSSFCellStyle.VERTICAL_CENTER

若是是靠下就是

style.VerticalAlignment=HSSFCellStyle.VERTICAL_BOTTOM

若是是兩端對齊就是

style.VerticalAlignment=HSSFCellStyle.VERTICAL_JUSTIFY

注意:以上選項僅當有足夠的高度時才能產生效果,不設置高度恐怕看不出區別。

 

自動換行

自動換行翻譯成英文其實就是Wrap的意思,因此這裏咱們應該用WrapText屬性,這是一個布爾屬性

style.WrapText=true;

效果以下所示:

 

 

文本縮進

 

這是一個不太引人注意的選項,因此這裏給張圖出來,讓你們知道是什麼,縮進說白了就是文本前面的空白,咱們一樣能夠用屬性來設置,這個屬性叫作Indention。

style.Indention= 3;

 

文本旋轉

文本方向你們必定在Excel中設置過,上圖中就是調整界面,主要參數是度數,那麼咱們如何在NPOI中設置呢?

style.Rotation=(short)90;

以上代碼是把單元格A1中的文本逆時針旋轉90度,等同於下圖中的設置:

   

 

請注意,這裏的Rotation取值是從-90到90,而不是0-180度。

 

最後別忘了把樣式變量style賦給HSSFCellStyle.CellStyle,不然就前功盡棄了,呵呵!

 

以上的一些功能,好比文本旋轉和自動換行,使用傳統的cvs和html法恐怕是沒法實現的。隨着學習的不斷深刻,你將愈來愈意識到使用NPOI生成Excel其實如此簡單。

相關範例請參考NPOI 1.2正式版中的SetAlignmentInXls和RotateTextInXls。

NPOI 1.2教程 - 2.2.4 設置單元格邊框

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

 

不少表格中都要使用邊框,本節將爲你重點講解NPOI中邊框的設置和使用。

邊框和其餘單元格設置同樣也是在HSSFCellStyle上操做的,HSSFCellStyle有2種和邊框相關的屬性,分別是:

邊框相關屬性

說明

範例

Border+方向

邊框類型

BorderTop, BorderBottom,BorderLeft, BorderRight

方向+BorderColor

邊框顏色

TopBorderColor,BottomBorderColor, LeftBorderColor, RightBorderColor

 

其中邊框類型分爲如下幾種:

邊框範例圖

對應的靜態值

 

HSSFCellStyle.BORDER_DOTTED

 

HSSFCellStyle.BORDER_HAIR

 

HSSFCellStyle.BORDER_DASH_DOT_DOT

 

HSSFCellStyle.BORDER_DASH_DOT

 

HSSFCellStyle.BORDER_DASHED

 

HSSFCellStyle.BORDER_THIN

 

HSSFCellStyle.BORDER_MEDIUM_DASH_DOT_DOT

 

HSSFCellStyle.BORDER_SLANTED_DASH_DOT

 

HSSFCellStyle.BORDER_MEDIUM_DASH_DOT

 

HSSFCellStyle.BORDER_MEDIUM_DASHED

 

HSSFCellStyle.BORDER_MEDIUM

 

HSSFCellStyle.BORDER_THICK

 

HSSFCellStyle.BORDER_DOUBLE

至於顏色那就不少了,所有在HSSFColor下面,如HSSFColor.GREEN,HSSFColor.RED,都是靜態實例,能夠直接引用。

下面咱們假設咱們要把一個單元格的四周邊框都設置上,能夠用下面的代碼:

HSSFSheetsheet = hssfworkbook.CreateSheet("newsheet");

 

// Create arow and put some cells in it. Rows are 0 based.

HSSFRow row =sheet.CreateRow(1);

// Create acell and put a value in it.

HSSFCell cell= row.CreateCell(1);

// Style thecell with borders all around.

HSSFCellStylestyle = hssfworkbook.CreateCellStyle();

style.BorderBottom=HSSFCellStyle.BORDER_THIN;

style.BorderLeft=HSSFCellStyle.BORDER_THIN;

style.BorderRight=HSSFCellStyle.BORDER_THIN;

style.BorderTop= HSSFCellStyle.BORDER_THIN ;

cell.CellStyle=style;

這段代碼使用了最普通的細邊框,使得這個單元格看上去像塊空心磚頭。

 

注意:這裏咱們沒有設置邊框的顏色,但這不會影響最終的效果,由於Excel會用默認的黑色給邊框上色。

 

若是要設置顏色的話,也很簡單,以下:

style.BottomBorderColor=HSSFColor.GREEN.index;

以上代碼將底部邊框設置爲綠色,要注意,不是直接把HSSFColor.GREEN賦給XXXXBorderColor屬性,而是把index的值賦給它。

 

相關範例請參考NPOI 1.2正式版中的SetBorderStyleInXls項目。

 

NPOI 1.2教程 - 2.2.5 設置單元格字體

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

 

本節咱們將繼續使用NPOI來設置單元格格式,這一節咱們主要講如何設置「字體」。

 

 

在設置字體以前,咱們首先要作的就是建立字體對象,這和建立數字格式很類似。

HSSFFont font= hssfworkbook.CreateFont();

這句話會在Excel文件內部建立相應的FontRecord,因此你不用客戶由於本身機器上的Excel沒有相應的字體設置而致使設置丟失。

字體在設置完成後,咱們就能夠把它賦給單元格樣式,代碼以下:

HSSFCellStylestyle1 = hssfworkbook.CreateCellStyle();

style1.SetFont(font);

cell1.CellStyle=style1;

這裏的cell1是HSSFCell的一個實例。

 

好了,下面咱們就開始對字體進行設置。

字體名稱

這裏的字體名稱是經過HSSFFont.FontName進行設置的,至於具體的名稱,只要是經常使用字體均可以,好比說Arial, Verdana等,固然也能夠是中文字體名,如宋體、黑體等。不過設置字體名稱有個前提,那就是假設打開這個xls文件的客戶機上有這種字體,若是沒有,Excel將使用默認字體。

下面就是設置字體名稱爲「宋體」的代碼:

font.FontName="宋體";

字號

與字號有關的屬性有兩個,一個是FontHeight,一個是FontHeightInPoints。區別在於,FontHeight的值是FontHeightInPoints的20倍,一般咱們在Excel界面中看到的字號,好比說12,對應的是FontHeightInPoints的值,而FontHeight要產生12號字體的大小,值應該是240。因此一般建議你用FontHeightInPoint屬性。

若是要設置字號爲12,代碼就是

font.FontHeightInPoints= 12;

 

字體顏色

這裏可能會與CellStyle上的ForegroundColor和BackgroundColor產生混淆,其實全部的字體顏色都是在HSSFFont的實例上設置的,CellStyle的ForegroundColor和BackgroundColor分別指背景填充色和填充圖案的顏色,和文本顏色無關。

要設置字體顏色,咱們能夠用HSSFFont.Color屬性,顏色能夠經過HSSFColor得到,代碼以下所示:

font.Color =HSSFColor.RED.index;

這行代碼把文本設置爲紅色。

 

下劃線

一般咱們所說的下劃線都是單線條的,其實Excel支持好幾種下劃線,以下所示:

類型

對應的值

單下劃線

HSSFFont.U_SINGLE

雙下劃線

HSSFFont.U_DOUBLE

會計用單下劃線

HSSFFont.U_SINGLE_ACCOUNTING

會計用雙下劃線

HSSFFont.U_DOUBLE_ACCOUNTING

無下劃線

HSSFFont.U_NONE

當你要設置下劃線時,能夠用HSSFFont.Underline屬性,這是一個byte類型的值,例如

font.Underline=HSSFFont.U_SINGLE

這行代碼就是設置單下劃線的代碼。

上標下標

設置這東西能夠用HSSFFont.TypeOffset屬性,值有如下幾種:

TypeOffset的值

說明

HSSFFont.SS_SUPER

上標

HSSFFont.SS_SUB

下標

HSSFFont.SS_NONE

普通,默認值

因此若是你要上標的話,能夠用下面的代碼:

font.TypeOffset=HSSFFont.SS_SUPER;

刪除線

設置這東西能夠用HSSFFont.IsStrikeout屬性,當爲true時,表示有刪除線;爲false則表示沒有刪除線。

 

相關範例請參考NPOI 1.2正式版中的ApplyFontInXls的項目。

NPOI 1.2教程 - 2.2.6設置單元格的背景和圖案

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

 

本節咱們將用NPOI來爲單元格添加背景和圖案。

 

在以前的教程中,咱們已經提到HSSFCellStyle有兩個背景顏色屬性,一個叫FillBackgroundColor,另外一個叫FillForegroundColor,但其實這指的都是背景顏色,那爲何還有ForegroundColor呢?爲了可以幫助你們理解,咱們舉一個實際的例子,下面這個圖案是Excel的一個單元格:

 

線是白色的,背景是紅色的。這裏的線其實就是下面的Excel界面中的圖案:

 

 

至於線的顏色則是圖案顏色,即白色。

因此以上單元格若是要用NPOI來設置就能夠用如下代碼完成:

//fillbackground

HSSFCellStylestyle8 = hssfworkbook.CreateCellStyle();

style8.FillForegroundColor= NPOI.HSSF.Util.HSSFColor.WHITE.index;

style8.FillPattern= HSSFCellStyle.SQUARES;

style8.FillBackgroundColor= NPOI.HSSF.Util.HSSFColor.RED.index;

sheet1.CreateRow(7).CreateCell(0).CellStyle= style8;

如今是否是清楚一些了,這裏的FillPattern就圖案樣式,全部的枚舉值都是HSSFCellStyle的常量;FillForegroundColor就是圖案的顏色,而FillBackgroundColor則是背景的顏色,即紅色。

下面羅列一下圖案樣式及其對應的值:

圖案樣式

常量

 

HSSFCellStyle.NO_FILL

 

HSSFCellStyle.ALT_BARS

 

HSSFCellStyle.FINE_DOTS

 

HSSFCellStyle.SPARSE_DOTS

 

HSSFCellStyle.LESS_DOTS

 

HSSFCellStyle.LEAST_DOTS

 

HSSFCellStyle.BRICKS

 

HSSFCellStyle.BIG_SPOTS

 

HSSFCellStyle.THICK_FORWARD_DIAG

 

HSSFCellStyle.THICK_BACKWARD_DIAG

 

HSSFCellStyle.THICK_VERT_BANDS

 

HSSFCellStyle.THICK_HORZ_BANDS

 

HSSFCellStyle.THIN_HORZ_BANDS

 

HSSFCellStyle.THIN_VERT_BANDS

 

HSSFCellStyle.THIN_BACKWARD_DIAG

 

HSSFCellStyle.THIN_FORWARD_DIAG

 

HSSFCellStyle.SQUARES

 

HSSFCellStyle.DIAMONDS

經過這張表,你將很容易找到本身須要的樣式,不用再去一個一個猜想了。

 

相關範例請參考NPOI 1.2正式版中的ColorfullMatrixTable和FillBackgroundInXls。

 

NPOI 1.2教程 - 2.2.7 設置單元格的寬度和高度

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

 

在Excel中,單元格的寬度其實就是列的寬度,由於Excel假設這一列的單元格的寬度確定一致。因此要設置單元格的寬度,咱們就得從列的寬度下手,HSSFSheet有個方法叫SetColumnWidth,共有兩個參數:一個是列的索引(從0開始),一個是寬度。

如今假設你要設置B列的寬度,就能夠用下面的代碼:

HSSFWorkbookhssfworkbook =newHSSFWorkbook();

HSSFSheetsheet1 = hssfworkbook.CreateSheet("Sheet1");

sheet1.SetColumnWidth(1,100 * 256);

這裏你會發現一個有趣的現象,SetColumnWidth的第二個參數要乘以256,這是怎麼回事呢?其實,這個參數的單位是1/256個字符寬度,也就是說,這裏是把B列的寬度設置爲了100個字符。

剛纔說的是如何設置,那如何去讀取一個列的寬度呢?直接用GetColumnWidth方法,這個方法只有一個參數,那就是列的索引號。以下所示:

int col1width = sheet1.GetColumnWidth(1);

 

說完寬度,咱們來講高度,在Excel中,每一行的高度也是要求一致的,因此設置單元格的高度,其實就是設置行的高度,因此相關的屬性也應該在HSSFRow上,它就是HSSFRow.Height和HeightInPoints,這兩個屬性的區別在於HeightInPoints的單位是點,而Height的單位是1/20個點,因此Height的值永遠是HeightInPoints的20倍。

要設置第一行的高度,能夠用以下代碼:

sheet1.CreateRow(0).Height= 200*20;

或者

sheet1.CreateRow(0).HeightInPoints= 200;

若是要得到某一行的行高,能夠直接拿HSSFRow.Height屬性的返回值。

 

你可能以爲一行一行設置行高或者一列一列設置列寬很麻煩,那你能夠考慮使用HSSFSheet.DefaultColumnWidth、HSSFSheet.DefaultRowHeight和HSSFSheet.DefaultRowHeightInPoints屬性。

一旦設置了這些屬性,若是某一行或者某一列沒有設置寬度,就會使用默認寬度或高度。代碼以下:

sheet1.DefaultColumnWidth=100*256;

sheet1.DefaultRowHeight=30*20;

 

相關範例請見NPOI 1.2正式版中的SetWidthAndHeightInXls項目

 

2.3.1用NPOI操做EXCEL--基本計算

從這節開始,咱們將開始學習Excel高級一點的功能--公式。爲某個單元格指定公式後,單元格中的類容將根據公式計算得出,如圖:

圖中設置的是一個基本表達式」1+2*3」,單元格A1中將顯示此表達式計算的結果」7」,如圖所示。對應的C#生成代碼也很簡單,以下:

 

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");

HSSFRow row1=sheet1.CreateRow(0);
HSSFCell cel1 = row1.CreateCell(0);
HSSFCell cel2 = row1.CreateCell(1);
HSSFCell cel3 = row1.CreateCell(2);
cel1.SetCellFormula("1+2*3");
cel2.SetCellValue(5);

一樣,NPOI也支持單元格引用類型的公式設置,以下圖中的C1=A1*B1。

對應的公式設置代碼爲:

cel3.SetCellFormula("A1*B1");


是否是很簡單呢?但要注意,在利用NPOI寫程序時,行和列的計數都是從0開始計算的,但在設置公式時又是按照Excel的單元格命名規則來的。

 

2.3.2用NPOI操做EXCEL--SUM函數

這節咱們開始學習Excel中最經常使用的函數—Sum求和函數。

首先,咱們先看一上最簡單的Sum函數:Sum(num1,num2,...)。使用效果如圖

圖中的E1=Sum(A1,C1)表示將A1與C1的和填充在E1處,與公式」E1=A1+C1」等效。對應的生成代碼與上一節中的基本計算公式相似:

 

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
HSSFRow row1 = sheet1.CreateRow(0);
HSSFCell cel1 = row1.CreateCell(0);
HSSFCell cel2 = row1.CreateCell(1);
HSSFCell cel3 = row1.CreateCell(2);
HSSFCell celSum1 = row1.CreateCell(3);
HSSFCell celSum2 = row1.CreateCell(4);
HSSFCell celSum3 = row1.CreateCell(5);

cel1.SetCellValue(1);
cel2.SetCellValue(2);
cel3.SetCellValue(3);
celSum2.SetCellFormula("sum(A1,C1)");

 固然,把每個單元格做爲Sum函數的參數很容易理解,但若是要求和的單元格不少,那麼公式就會很長,既不方便閱讀也不方便書寫。因此Excel提供了另一種多個單元格求和的寫法:

如上圖中的「Sum(A1:C1)」表示求從A1到C1全部單元格的和,至關於A1+B1+C1。
對應的代碼爲:

 

celSum1.SetCellFormula("sum(A1:C1)");


最後,還有一種求和的方法。就是先定義一個區域,如」range1」,而後再設置Sum(range1),此時將計算區域中全部單元格的和。
定義區域的代碼爲:

HSSFName range = hssfworkbook.CreateName();
range.Reference = "Sheet1!$A1:$C1";
range.NameName = "range1";

執行此代碼後的Excel文件將在的公式菜單下的名稱管理器(Excel2007的菜單路徑,2003稍有不一樣)中看到以下區域定義:
 
給單元格F1加上公式:

celSum3.SetCellFormula("sum(range1)");

生成的Excel以下圖所示:
 

 

2.3.3用NPOI操做EXCEL--日期函數

Excel中有很是豐富的日期處理函數,在NPOI中一樣獲得了很好的支持。以下圖:
對應的與前面的基本公式設置相似:

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
HSSFRow row1 = sheet1.CreateRow(0);
HSSFRow row2 = sheet1.CreateRow(1);
row1.CreateCell(0).SetCellValue("姓名");
row1.CreateCell(1).SetCellValue("參加工做時間");
row1.CreateCell(2).SetCellValue("當前日期");
row1.CreateCell(3).SetCellValue("工做年限");

HSSFCell cel1 = row2.CreateCell(0);
HSSFCell cel2 = row2.CreateCell(1);
HSSFCell cel3 = row2.CreateCell(2);
HSSFCell cel4 = row2.CreateCell(3);

cel1.SetCellValue("aTao.Xiang");
cel2.SetCellValue(new DateTime(2004, 7, 1));
cel3.SetCellFormula("TODAY()");
cel4.SetCellFormula("CONCATENATE(DATEDIF(B2,TODAY(),\"y\"),\"年\",DATEDIF(B2,TODAY(),\"ym\"),\"個月\")");

//在poi中日期是以double類型表示的,因此要格式化
HSSFCellStyle cellStyle = hssfworkbook.CreateCellStyle();
HSSFDataFormat format = hssfworkbook.CreateDataFormat();
cellStyle.DataFormat = format.GetFormat("yyyy-m-d");

cel2.CellStyle = cellStyle;
cel3.CellStyle = cellStyle;

下面對上例中用到的幾個主要函數做一些說明:
TODAY():取得當前日期;
DATEDIF(B2,TODAY(),"y"):取得B2單元格的日期與前日期以年爲單位的時間間隔。(「Y」:表示以年爲單位,」m」表示以月爲單位;」d」表示以天爲單位);
CONCATENATE(str1,str2,...):鏈接字符串。

另外附上Excel中經常使用的日期函數列表,只須要將此句代碼做適當修改便可:

cel4.SetCellFormula("CONCATENATE(DATEDIF(B2,TODAY(),\"y\"),\"年\",DATEDIF(B2,TODAY(),\"ym\"),\"個月\")");

函數名

函數說明

語法

DATE

返回表明特定日期的系列數。

DATE(year,month,day)

DATEDIF

計算兩個日期之間的天數、月數或年數。

DATEDIF(start_date,end_date,unit)

DATEVALUE

函數 DATEVALUE的主要功能是將以文字表示的日期轉換成一個系列數。

DATEVALUE(date_text)

DAY

返回以系列數表示的某日期的天數,用整數 1到 31表示。

DAY(serial_number)

DAYS360

按照一年 360天的算法(每月以 30天計,一年共計 12 個月),返回兩日期間相差的天數。

DAYS360(start_date,end_date,method)

EDATE

返回指定日期 (start_date)以前或以後指定月份數的日期系列數。使用函數 EDATE能夠計算與發行日處於一月中同一天的到期日的日期。

EDATE(start_date,months)

EOMONTH

返回 start-date以前或以後指定月份中最後一天的系列數。用函數 EOMONTH可計算特定月份中最後一天的時間系列數,用於證券的到期日等計算。

EOMONTH(start_date,months)

HOUR

返回時間值的小時數。即一個介於 0 (12:00 A.M.)到 23 (11:00 P.M.)之間的整數。

HOUR(serial_number)

MINUTE

返回時間值中的分鐘。即一個介於 0到 59之間的整數。

MINUTE(serial_number)

MONTH

返回以系列數表示的日期中的月份。月份是介於 1(一月)和 12(十二月)之間的整數。

MONTH(serial_number)

NETWORKDAYS

返回參數 start-data和 end-data之間完整的工做日數值。工做日不包括週末和專門指定的假期

NETWORKDAYS(start_date,end_date,holidays)

NOW

返回當前日期和時間所對應的系列數。

NOW( )

SECOND

返回時間值的秒數。返回的秒數爲 0至 59之間的整數。

SECOND(serial_number)

TIME

返回某一特定時間的小數值,函數 TIME返回的小數值爲從 0到 0.99999999 之間的數值,表明從 0:00:00 (12:00:00 A.M)到 23:59:59 (11:59:59 P.M)之間的時間。

TIME(hour,minute,second)

TIMEVALUE

返回由文本串所表明的時間的小數值。該小數值爲從 0到 0.999999999的數值,表明從0:00:00 (12:00:00 AM)到 23:59:59 (11:59:59 PM)之間的時間。

TIMEVALUE(time_text)

TODAY

返回當前日期的系列數,系列數是 Microsoft Excel用於日期和時間計算的日期-時間代碼。

TODAY( )

WEEKDAY

返回某日期爲星期幾。默認狀況下,其值爲 1(星期天)到 7(星期六)之間的整數。

WEEKDAY(serial_number,return_type)

WEEKNUM

返回一個數字,該數字表明一年中的第幾周。

WEEKNUM(serial_num,return_type)

WORKDAY

返回某日期(起始日期)以前或以後相隔指定工做日的某一日期的日期值。工做日不包括週末和專門指定的假日。

WORKDAY(start_date,days,holidays)

YEAR

返回某日期的年份。返回值爲 1900到 9999之間的整數。

YEAR(serial_number)

YEARFRAC

返回 start_date和 end_date之間的天數佔整年天數的百分比。

YEARFRAC(start_date,end_date,basis)

 

 

2.3.4用NPOI操做EXCEL--字符串函數

      這一節咱們開始學習Excel另外一類很是常見的函數—字符串函數。在Excel中提供了很是豐富的字符串函數,在NPOI中一樣獲得了很好的支持。
1、 大小寫轉換類函數
      LOWER(String):將一個文字串中的全部大寫字母轉換爲小寫字母。
      UPPER(String):將文本轉換成大寫形式。
      PROPER(String):將文字串的首字母及任何非字母字符以後的首字母轉換成大寫。將其他的字母轉換成小寫。
      對應的C#代碼與前幾節講的設置公式的代碼相似:

HSSFRow row1 = sheet1.CreateRow(0);
row1.CreateCell(0).SetCellValue("待操做字符串");
row1.CreateCell(1).SetCellValue("操做函數");
row1.CreateCell(2).SetCellValue("操做結果");

HSSFRow row2 = sheet1.CreateRow(1);
row2.CreateCell(0).SetCellValue("This is a NPOI example!");
row2.CreateCell(1).SetCellValue("LOWER(A2)");
//將此句中的「LOWER(A2)」換成UPPER (A2)、PROPER (A2)能夠看到不一樣效果。
row2.CreateCell(2).SetCellFormula("LOWER(A2)");

2、 取出字符串中的部分字符
      LEFT(text,num_chars):LEFT(text,num_chars)其中Text是包含要提取字符的文本串。Num_chars指定要由LEFT 所提取的字符數。

      MID(text,start_num,num_chars):MID(text,start_num,num_chars)其中Text是包含要提取字符的文本串。Start_num是文本中要提取的第一個字符的位置,num_chars表示要提取的字符的數。

      RIGHT(text,num_chars):RIGHT(text,num_chars)其中Text是包含要提取字符的文本串。Num_chars指定但願RIGHT 提取的字符數。
      代碼與上面相似,就不寫了。

3、 去除字符串的空白
      TRIM(text):其中Text爲須要清除其中空格的文本。須要注意的是,與C#中的Trim不一樣,Excel中的Trim函數不只會刪除字符串頭尾的字符,字符串中的多餘字符也會刪除,單詞之間只會保留一個空格。

4、 字符串的比較
      EXACT(text1,text2):比較兩個字符串是否相等,區分大小寫。

      執行效果以下:


      在此只簡單的講了一下經常使用的函數,Excel中還有不少的字符串函數,在此附上,讀者能夠一個一個去測試。

函數名

函數說明

語法

ASC

將字符串中的全角(雙字節)英文字母更改成半角(單字節)字符。

ASC(text)

CHAR

返回對應於數字代碼的字符,函數 CHAR可將其餘類型計算機文件中的代碼轉換爲字符。

CHAR(number)

CLEAN

刪除文本中不能打印的字符。對從其餘應用程序中輸入的字符串使用 CLEAN函數,將刪除其中含有的當前操做系統沒法打印的字符。例如,能夠刪除一般出如今數據文件頭部或尾部、沒法打印的低級計算機代碼。

CLEAN(text)

CODE

返回文字串中第一個字符的數字代碼。返回的代碼對應於計算機當前使用的字符集。

CODE(text)

CONCATENATE

將若干文字串合併到一個文字串中。

CONCATENATE (text1,text2,...)

DOLLAR

依照貨幣格式將小數四捨五入到指定的位數並轉換成文字。

DOLLAR 或 RMB(number,decimals)

EXACT

該函數測試兩個字符串是否徹底相同。若是它們徹底相同,則返回 TRUE;不然,返回 FALSE。函數 EXACT 能區分大小寫,但忽略格式上的差別。利用函數 EXACT能夠測試輸入文檔內的文字。

EXACT(text1,text2)

FIND

FIND 用於查找其餘文本串 (within_text)內的文本串 (find_text),並從 within_text的首字符開始返回 find_text的起始位置編號。

FIND(find_text,within_text,start_num)

FIXED

按指定的小數位數進行四捨五入,利用句點和逗號,以小數格式對該數設置格式,並以文字串形式返回結果。

FIXED(number,decimals,no_commas)

JIS

將字符串中的半角(單字節)英文字母或片假名更改成全角(雙字節)字符。

JIS(text)

LEFT

LEFT 基於所指定的字符數返回文本串中的第一個或前幾個字符。
LEFTB 基於所指定的字節數返回文本串中的第一個或前幾個字符。此函數用於雙字節字符。

LEFT(text,num_chars)
LEFTB(text,num_bytes)

LEN

LEN 返回文本串中的字符數。
LENB 返回文本串中用於表明字符的字節數。此函數用於雙字節字符。

LEN(text)
LENB(text)

LOWER

將一個文字串中的全部大寫字母轉換爲小寫字母。

LOWER(text)

MID

MID 返回文本串中從指定位置開始的特定數目的字符,該數目由用戶指定。
MIDB 返回文本串中從指定位置開始的特定數目的字符,該數目由用戶指定。此函數用於雙字節字符。

MID(text,start_num,num_chars)
MIDB(text,start_num,num_bytes)

PHONETIC

提取文本串中的拼音 (furigana)字符。

PHONETIC(reference)

PROPER

將文字串的首字母及任何非字母字符以後的首字母轉換成大寫。將其他的字母轉換成小寫。

PROPER(text)

REPLACE

REPLACE 使用其餘文本串並根據所指定的字符數替換某文本串中的部分文本。
REPLACEB 使用其餘文本串並根據所指定的字符數替換某文本串中的部分文本。此函數專爲雙字節字符使用。

REPLACE(old_text,start_num,num_chars,new_text)
REPLACEB(old_text,start_num,num_bytes,new_text)

REPT

按照給定的次數重複顯示文本。能夠經過函數 REPT來不斷地重複顯示某一文字串,對單元格進行填充。

REPT(text,number_times)

RIGHT

RIGHT 根據所指定的字符數返回文本串中最後一個或多個字符。
RIGHTB 根據所指定的字符數返回文本串中最後一個或多個字符。此函數用於雙字節字符。

RIGHT(text,num_chars)
RIGHTB(text,num_bytes)

SEARCH

SEARCH 返回從 start_num開始首次找到特定字符或文本串的位置上特定字符的編號。使用 SEARCH可肯定字符或文本串在其餘文本串中的位置,這樣就可以使用 MID或 REPLACE 函數更改文本。
SEARCHB 也可在其餘文本串 (within_text)中查找文本串 (find_text),並返回 find_text的起始位置編號。此結果是基於每一個字符所使用的字節數,並從 start_num開始的。此函數用於雙字節字符。此外,也可以使用 FINDB在其餘文本串中查找文本串。

SEARCH(find_text,within_text,start_num)
SEARCHB(find_text,within_text,start_num)

SUBSTITUTE

在文字串中用 new_text替代 old_text。若是須要在某一文字串中替換指定的文本,請使用函數 SUBSTITUTE;若是須要在某一文字串中替換指定位置處的任意文本,請使用函數 REPLACE。

SUBSTITUTE(text,old_text,new_text,instance_num)

T

將數值轉換成文本。

T(value)

TEXT

將一數值轉換爲按指定數字格式表示的文本。

TEXT(value,format_text)

TRIM

除了單詞之間的單個空格外,清除文本中全部的空格。在從其餘應用程序中獲取帶有不規則空格的文本時,可使用函數 TRIM。

TRIM(text)

UPPER

將文本轉換成大寫形式。

UPPER(text)

VALUE

將表明數字的文字串轉換成數字。

VALUE(text)

WIDECHAR

將單字節字符轉換爲雙字節字符。

WIDECHAR(text)

YEN

使用¥(日圓)貨幣格式將數字轉換成文本,並對指定位置後的數字四捨五入。

YEN(number,decimals)

 

 

2.3.5用NPOI操做EXCEL--If函數

      在Excel中,IF(logical_test,value_if_true,value_if_false)用來用做邏輯判斷。其中Logical_test表示計算結果爲TRUE 或 FALSE 的任意值或表達式 ; value_if_true表示當表達式Logical_test的值爲TRUE時的返回值;value_if_false表示當表達式Logical_test的值爲FALSE時的返回值。一樣在NPOI中也能夠利用這個表達式進行各類邏輯運算。以下代碼分別設置了B2和D2單元格的用於邏輯判斷的公式。

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");

HSSFRow row1 = sheet1.CreateRow(0);
row1.CreateCell(0).SetCellValue("姓名");
row1.CreateCell(1).SetCellValue("身份證號");
row1.CreateCell(2).SetCellValue("性別");
row1.CreateCell(3).SetCellValue("語文");
row1.CreateCell(4).SetCellValue("是否合格");

HSSFRow row2 = sheet1.CreateRow(1);
row2.CreateCell(0).SetCellValue("令狐沖");
row2.CreateCell(1).SetCellValue("420821198808101014");
row2.CreateCell(2).SetCellFormula("IF(MOD(MID(B2,18,1),2)=0,\"男\",\"女\")");
row2.CreateCell(3).SetCellValue(85);
row2.CreateCell(4).SetCellFormula("IF(D2>60,IF(D2>90,\"優秀\",\"合格\"),\"不合格\")");

其中最關鍵的兩句執行結果以下:

row2.CreateCell(2).SetCellFormula("IF(MOD(MID(B2,18,1),2)=0,\"男\",\"女\")");

 

row2.CreateCell(4).SetCellFormula("IF(D2>60,IF(D2>90,\"優秀\",\"合格\"),\"不合格\")");

 

下面分別對這幾個函數做一些說明:
      MOD(MID(B2,18,1),2):咱們知道18位身份證號的第18位表示性別,偶數爲男性,奇數爲女性,因此用了MID(B2,18,1)取第18位數字(與C#中通常從0計數不一樣,第二個參數是從1算起,有關MID函數的更多信息,請參見字符串函數),用MOD取餘函數判斷奇偶。在Excel中對數據類型的控制沒有C#中那麼嚴格,如此例中我截取出來的是字符串,但當我作取餘運算時Excel會自動轉換。
      IF(D2>60,IF(D2>90,"優秀","合格"),"不合格"):這是IF的嵌套使用,表示90分以上爲優秀,60分以上爲合格,不然爲不合格。

 

2.3.6用NPOI操做EXCEL--COUNTIF和SUMIF函數

1、COUNTIF 
     這一節,咱們一塊兒來學習Excel中另外一個經常使用的函數--COUNTIF函數,看函數名就知道這是一個用來在作知足某條件的計數的函數。先來看一看它的語法:COUNTIF(range,criteria),參數說明以下:

Range

須要進行讀數的計數

Criteria

條件表達式,只有當知足此條件時才進行計數

接下來看一個例子,代碼以下:

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");

HSSFRow row1 = sheet1.CreateRow(0);
row1.CreateCell(0).SetCellValue("姓名");
row1.CreateCell(1).SetCellValue("成績");

HSSFRow row2 = sheet1.CreateRow(1);
row2.CreateCell(0).SetCellValue("令狐沖");
row2.CreateCell(1).SetCellValue(85);

HSSFRow row3 = sheet1.CreateRow(2);
row3.CreateCell(0).SetCellValue("任盈盈");
row3.CreateCell(1).SetCellValue(90);

HSSFRow row4 = sheet1.CreateRow(3);
row4.CreateCell(0).SetCellValue("任我行");
row4.CreateCell(1).SetCellValue(70);

HSSFRow row5 = sheet1.CreateRow(4);
row5.CreateCell(0).SetCellValue("左冷嬋");
row5.CreateCell(1).SetCellValue(45);

HSSFRow row6 = sheet1.CreateRow(5);
row6.CreateCell(0).SetCellValue("嶽不羣");
row6.CreateCell(1).SetCellValue(50);

HSSFRow row7 = sheet1.CreateRow(6);
row7.CreateCell(0).SetCellValue("合格人數:");
row7.CreateCell(1).SetCellFormula("COUNTIF(B2:B6,\">60\")");

執行結果以下:

      咱們能夠看到,CountIf函數成功的統計出了區域「B2:B6」中成績合格的人數(這裏定義成績大於60爲合格)。

2、SUMIF

      接下來,順便談談另外一個與CountIF相似的函數—SumIf函數。此函數用於統計某區域內知足某條件的值的求和(CountIf是計數)。與CountIF不一樣,SumIF有三個參數,語法爲SumIF(criteria_range, criteria,sum_range),各參數的說明以下:

criteria_range

條件測試區域,第二個參數Criteria中的條件將與此區域中的值進行比較

criteria

條件測試值,知足條件的對應的sum_range項將進行求和計算

sum_range

彙總數據所在區域,求和時會排除掉不知足Criteria條件的對應的項

咱們仍是以例子來加以說明:

Code
HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");

HSSFRow row1 = sheet1.CreateRow(0);
row1.CreateCell(0).SetCellValue("姓名");
row1.CreateCell(1).SetCellValue("月份");
row1.CreateCell(2).SetCellValue("銷售額");

HSSFRow row2 = sheet1.CreateRow(1);
row2.CreateCell(0).SetCellValue("令狐沖");
row2.CreateCell(1).SetCellValue("一月");
row2.CreateCell(2).SetCellValue(1000);

HSSFRow row3 = sheet1.CreateRow(2);
row3.CreateCell(0).SetCellValue("任盈盈");
row3.CreateCell(1).SetCellValue("一月");
row3.CreateCell(2).SetCellValue(900);

HSSFRow row4 = sheet1.CreateRow(3);
row4.CreateCell(0).SetCellValue("令狐沖");
row4.CreateCell(1).SetCellValue("二月");
row4.CreateCell(2).SetCellValue(2000);

HSSFRow row5 = sheet1.CreateRow(4);
row5.CreateCell(0).SetCellValue("任盈盈");
row5.CreateCell(1).SetCellValue("二月");
row5.CreateCell(2).SetCellValue(1000);

HSSFRow row6 = sheet1.CreateRow(5);
row6.CreateCell(0).SetCellValue("令狐沖");
row6.CreateCell(1).SetCellValue("三月");
row6.CreateCell(2).SetCellValue(3000);

HSSFRow row7 = sheet1.CreateRow(6);
row7.CreateCell(0).SetCellValue("任盈盈");
row7.CreateCell(1).SetCellValue("三月");
row7.CreateCell(2).SetCellValue(1200);

HSSFRow row8 = sheet1.CreateRow(7);
row8.CreateCell(0).SetCellValue("令狐沖一季度銷售額:");
row8.CreateCell(2).SetCellFormula("SUMIF(A2:A7,\"=令狐沖\",C2:C7)");

HSSFRow row9 = sheet1.CreateRow(8);
row9.CreateCell(0).SetCellValue("任盈盈一季度銷售額:");
row9.CreateCell(2).SetCellFormula("SUMIF(A2:A7,\"=任盈盈\",C2:C7)");

執行結果以下:

如上圖,SUMIF統計出了不一樣人一季度的銷售額。

 

2.3.7用NPOI操做EXCEL--LOOKUP函數

      今天,咱們一塊兒學習Excel中的查詢函數--LOOKUP。其基本語法形式爲LOOKUP(lookup_value,lookup_vector,result_vector)。仍是以例子加以說明更容易理解:

Code
HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
HSSFRow row1 = sheet1.CreateRow(0);
row1.CreateCell(0).SetCellValue("收入最低");
row1.CreateCell(1).SetCellValue("收入最高");
row1.CreateCell(2).SetCellValue("稅率");

HSSFRow row2 = sheet1.CreateRow(1);
row2.CreateCell(0).SetCellValue(0);
row2.CreateCell(1).SetCellValue(3000);
row2.CreateCell(2).SetCellValue(0.1);

HSSFRow row3 = sheet1.CreateRow(2);
row3.CreateCell(0).SetCellValue(3001);
row3.CreateCell(1).SetCellValue(10000);
row3.CreateCell(2).SetCellValue(0.2);

HSSFRow row4 = sheet1.CreateRow(3);
row4.CreateCell(0).SetCellValue(10001);
row4.CreateCell(1).SetCellValue(20000);
row4.CreateCell(2).SetCellValue(0.3);

HSSFRow row5 = sheet1.CreateRow(4);
row5.CreateCell(0).SetCellValue(20001);
row5.CreateCell(1).SetCellValue(50000);
row5.CreateCell(2).SetCellValue(0.4);

HSSFRow row6 = sheet1.CreateRow(5);
row6.CreateCell(0).SetCellValue(50001);
row6.CreateCell(2).SetCellValue(0.5);


HSSFRow row8 = sheet1.CreateRow(7);
row8.CreateCell(0).SetCellValue("收入");
row8.CreateCell(1).SetCellValue("稅率");

HSSFRow row9 = sheet1.CreateRow(8);
row9.CreateCell(0).SetCellValue(7800);
row9.CreateCell(1).SetCellFormula("LOOKUP(A9,$A$2:$A$6,$C$2:$C$6)");


      這是一個根據工資查詢相應稅率的例子。咱們首先建立了不一樣工資區間對應稅率的字典,而後根據具體的工資在字典中找出對應的稅率。執行後生成的Excel以下:
 
下面對各參數加以說明:
第一個參數:須要查找的內容,本例中指向A9單元格,也就是7800;
第二個參數:比較對象區域,本例中的工資須要與$A$2:$A$6中的各單元格中的值進行比較;第三個參數:查找結果區域,若是匹配到會將此區域中對應的數據返回。如本例中返回$C$2:$C$6中對應的值。
可能有人會問,字典中沒有7800對應的稅率啊,那麼Excel中怎麼匹配的呢?答案是模糊匹配,而且LOOKUP函數只支持模糊匹配。Excel會在$A$2:$A$6中找小於7800的最大值,也就是A3對應的3001,而後將對應的$C$2:$C$6區域中的C3中的值返回,這就是最終結果0.2的由來。這下明白了吧:)

VLOOKUP
      另外,LOOKUP函數還有一位大哥--VLOOKUP。兩兄弟有不少類似之處,但大哥本領更大。Vlookup用對比數與一個「表」進行對比,而不是Lookup函數的某1列或1行,而且Vlookup能夠選擇採用精確查詢或是模糊查詢方式,而Lookup只有模糊查詢。
將上例中設置公式的代碼換成:

row9.CreateCell(1).SetCellFormula("VLOOKUP(A9,$A$2:$C$6,3,TRUE)");

執行後生成的Excel樣式以下:

第一個參數:須要查找的內容,這裏是A9單元格;
第二個參數:須要比較的表,這裏是$A$2:$C$6,注意VLOOKUP匹配時只與表中的第一列進行匹配。
第三個參數:匹配結果對應的列序號。這裏要對應的是稅率列,因此爲3。
第四個參數:指明是否模糊匹配。例子中的TRUE表示模糊匹配,與上例中同樣。匹配到的是第三行。若是將此參數改成FALSE,由於在表中的第1列中找不到7800,因此會報「#N/A」的計算錯誤。

      另外,還有與VLOKUP相似的HLOOKUP。不一樣的是VLOOKUP用於在表格或數值數組的首列查找指定的數值,並由此返回表格或數組當前行中指定列處的數值。而HLOOKUP用於在表格或數值數組的首行查找指定的數值,並由此返回表格或數組當前列中指定行處的數值。讀者能夠自已去嘗試。

 

2.3.8用NPOI操做EXCEL--隨機數函數

      咱們知道,在大多數編程語言中都有隨機數函數。在Excel中,一樣存在着這樣一個函數—RAND()函數,用於生成隨機數。先來看一個最簡單的例子:

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
sheet1.CreateRow(0).CreateCell(0).SetCellFormula("RAND()");

RAND()函數將返回一個0-1之間的隨機數,執行後生成的Excel文件以下:

這只是最簡單直接的RAND()函數的應用,只要咱們稍加修改,就能夠做出不少種變換。如
取0-100以前的隨機整數,可設置公式爲:

sheet1.CreateRow(0).CreateCell(0).SetCellFormula("int(RAND()*100)");

取10-20之間的隨機實數,可設置公式爲:

sheet1.CreateRow(0).CreateCell(0).SetCellFormula("rand()*(20-10)+10");

隨機小寫字母:

sheet1.CreateRow(0).CreateCell(0).SetCellFormula("CHAR(INT(RAND()*26)+97)");

隨機大寫字母:

sheet1.CreateRow(0).CreateCell(0).SetCellFormula("CHAR(INT(RAND()*26)+65)")

隨機大小寫字母:

sheet1.CreateRow(0).CreateCell(0).SetCellFormula("CHAR(INT(RAND()*26)+if(INT(RAND()*2)=0,65,97))");


      上面幾例中除了用到RAND函數之外,還用到了CHAR函數用來將ASCII碼換爲字母,INT函數用來取整。值得注意的是INT函數不會四捨五入,不管小數點後是多少都會被捨去。
      這裏只是RAND函數的幾個簡單應用,還有不少隨機數的例子均可以根據這些,再結合不一樣的其它函數引伸出來。

 

2.3.9用NPOI操做EXCEL--經過NPOI得到公式的返回值

      前面咱們學習了經過NPOI向Excel中設置公式,那麼有些讀者可能會問:「NPOI能不能獲取公式的返回值呢?」,答案是能夠!
1、獲取模板文件中公式的返回值
如在D盤中有一個名爲text.xls的Excel文件,其內容以下:

注意C1單元格中設置的是公式「$A1*$B1」,而不是值「12」。利用NPOI,只須要寫簡單的幾句代碼就能夠取得此公式的返回值:

HSSFWorkbook wb = new HSSFWorkbook(new FileStream("d:/test.xls",FileMode.Open));
HSSFCell cell = wb.GetSheet("Sheet1").GetRow(0).GetCell(2);
System.Console.WriteLine(cell.NumericCellValue);

輸出結果爲:

可見NPOI成功的「解析」了此.xls文件中的公式。注意NumericCellValue屬性會自動根據單元格的類型處理,若是爲空將返0,若是爲數值將返回數值,若是爲公式將返回公式計算後的結果。單元格的類型能夠經過CellType屬性獲取。

2、獲取NPOI生成的Excel文件中公式的返回值
      上例中是從一個已經存在的Excel文件中獲取公式的返回值,那麼若是Excel文件是經過NPOI建立的,直接用上面的方法獲取,可能得不到想要的結果。如:

1 HSSFWorkbook hssfworkbook = new HSSFWorkbook();
2 HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
3 HSSFRow row = sheet1.CreateRow(0);
4 row.CreateCell(0).SetCellValue(3);
5 row.CreateCell(1).SetCellValue(4);
6 HSSFCell cell = row.CreateCell(2);

8 cell.SetCellFormula("$A1+$B1");
9 System.Console.WriteLine(cell.NumericCellValue);

      執行上面代碼,將輸出結果「0」,而不是咱們想要的結果「7」。那麼將如何解決呢?這時要用到HSSFFormulaEvaluator類。在第8行後加上這兩句就能夠了:

HSSFFormulaEvaluator e = new HSSFFormulaEvaluator(hssfworkbook);
cell = e.EvaluateInCell(cell);

運行結果以下:

 

 

2.4.1用NPOI操做EXCEL--畫線

之全部說NPOI強大,是由於經常使用的Excel操做她均可以經過編程的方式完成。這節開始,咱們開始學習NPOI的畫圖功能。先從最簡單的開始,畫一條直線:

對應的代碼爲:

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
HSSFPatriarch patriarch = sheet1.CreateDrawingPatriarch();
HSSFClientAnchor a1 = new HSSFClientAnchor(255, 125, 1023, 150, 0, 0,2, 2);
HSSFSimpleShape line1 = patriarch.CreateSimpleShape(a1);

line1.ShapeType = HSSFSimpleShape.OBJECT_TYPE_LINE;
line1.LineStyle = HSSFShape.LINESTYLE_SOLID;
//在NPOI中線的寬度12700表示1pt,因此這裏是0.5pt粗的線條。
line1.LineWidth = 6350;

一般,利用NPOI畫圖主要有如下幾個步驟:
1. 建立一個Patriarch;
2. 建立一個Anchor,以肯定圖形的位置;
3. 調用Patriarch建立圖形;
4. 設置圖形類型(直線,矩形,圓形等)及樣式(顏色,粗細等)。

關於HSSFClientAnchor(dx1,dy1,dx2,dy2,col1,row1,col2,row2)的參數,有必要在這裏說明一下:
dx1:起始單元格的x偏移量,如例子中的255表示直線起始位置距A1單元格左側的距離;
dy1:起始單元格的y偏移量,如例子中的125表示直線起始位置距A1單元格上側的距離;
dx2:終止單元格的x偏移量,如例子中的1023表示直線起始位置距C3單元格左側的距離;
dy2:終止單元格的y偏移量,如例子中的150表示直線起始位置距C3單元格上側的距離;
col1:起始單元格列序號,從0開始計算;
row1:起始單元格行序號,從0開始計算,如例子中col1=0,row1=0就表示起始單元格爲A1;
col2:終止單元格列序號,從0開始計算;
row2:終止單元格行序號,從0開始計算,如例子中col2=2,row2=2就表示起始單元格爲C3;

最後,關於LineStyle屬性,有以下一些可選值,對應的效果分別如圖所示:

 

2.4.2用NPOI操做EXCEL--畫矩形

上一節咱們講了NPOI中畫圖的基本步驟:
1. 建立一個Patriarch;
2. 建立一個Anchor,以肯定圖形的位置;
3. 調用Patriarch建立圖形;
4. 設置圖形類型(直線,矩形,圓形等)及樣式(顏色,粗細等)。

這一節咱們將按照這個步驟建立一個矩形。廢話少說,上代碼:

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
HSSFPatriarch patriarch = sheet1.CreateDrawingPatriarch();
HSSFClientAnchor a1 = new HSSFClientAnchor(255, 125, 1023, 150, 0, 0, 2, 2);
HSSFSimpleShape rec1 = patriarch.CreateSimpleShape(a1);
//此處設置圖形類型爲矩形
rec1.ShapeType = HSSFSimpleShape.OBJECT_TYPE_RECTANGLE;
//設置填充色
rec1.SetFillColor(125, 125, 125);
//設置邊框樣式
rec1.LineStyle = HSSFShape.LINESTYLE_DASHGEL;
//設置邊框寬度
rec1.LineWidth = 25400;
//設置邊框顏色
rec1.SetLineStyleColor(100, 0, 100);

 

代碼執行效果:
 
其中SetFillColor和SetLineStyleColor函數的三個參數分別是RGB三色值,具體表示什麼顏色,找個Photoshop試試:)
關於HSSFClientAnchor參數說明、邊框樣式,邊框寬度的說明能夠參見前一篇博文:
http://www.cnblogs.com/atao/archive/2009/09/13/1565645.html

 

2.4.3用NPOI操做EXCEL--畫圓形

      前面咱們學習了NPOI中的畫簡單直線和矩形的功能,今天咱們一塊兒學習一下它支持的另外一種簡單圖形--圓形。一樣,按照前面所講的繪圖「四步曲」:
1. 建立一個Patriarch;
2. 建立一個Anchor,以肯定圖形的位置;
3. 調用Patriarch建立圖形;
4. 設置圖形類型(直線,矩形,圓形等)及樣式(顏色,粗細等)。
仍是以例子加以說明:

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
HSSFPatriarch patriarch = sheet1.CreateDrawingPatriarch();
HSSFClientAnchor a1 = new HSSFClientAnchor(0, 0, 1023, 0, 0, 0, 1, 3);
HSSFSimpleShape rec1 = patriarch.CreateSimpleShape(a1);
rec1.ShapeType = HSSFSimpleShape.OBJECT_TYPE_OVAL;

rec1.SetFillColor(125, 125, 125);
rec1.LineStyle = HSSFShape.LINESTYLE_DASHGEL;
rec1.LineWidth = 12700;
rec1.SetLineStyleColor(100, 0, 100);
WriteToFile();


      這裏rec1.ShapeType =HSSFSimpleShape.OBJECT_TYPE_OVAL;表示圖形爲橢圓。適當調整HSSFClientAnchor的各參數能夠獲得圓形。
      關於HSSFClientAnchor構造函數和邊框、填充色等前兩節都有介紹,這裏再也不重述。詳情情見:畫矩形畫線

上面代碼執行生成的Excel以下:

 

2.4.4用NPOI操做EXCEL--畫Grid

  在NPOI中,自己沒有畫Grid的方法。但咱們知道Grid其實就是由橫線和豎線構成的,所在咱們能夠經過畫線的方式來模擬畫Grid。

 

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");

HSSFRow row = sheet1.CreateRow(2);
row.CreateCell(1);
row.HeightInPoints = 240;
sheet1.SetColumnWidth(2, 9000);
int linesCount = 20;

HSSFPatriarch patriarch = sheet1.CreateDrawingPatriarch();
//由於HSSFClientAnchor中dx只能在0-1023之間,dy只能在0-255之間,因此這裏採用比例的方式
double xRatio = 1023.0 / (linesCount*10);
double yRatio = 255.0 / (linesCount*10);

//畫豎線
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 200;
for (int i = 0; i < linesCount; i++)
{
    HSSFClientAnchor a2 = new HSSFClientAnchor();
    a2.SetAnchor((short)2, 2, (int)(x1 * xRatio), (int)(y1 * yRatio),
            (short)2, 2, (int)(x2 * xRatio), (int)(y2 * yRatio));
    HSSFSimpleShape shape2 = patriarch.CreateSimpleShape(a2);
    shape2.ShapeType = (HSSFSimpleShape.OBJECT_TYPE_LINE);

    x1 += 10;
    x2 += 10;
}

//畫橫線
x1 = 0;
y1 = 0;
x2 = 200;
y2 = 0;
for (int i = 0; i < linesCount; i++)
{
    HSSFClientAnchor a2 = new HSSFClientAnchor();
    a2.SetAnchor((short)2, 2, (int)(x1 * xRatio), (int)(y1 * yRatio),
            (short)2, 2, (int)(x2 * xRatio), (int)(y2 * yRatio));
    HSSFSimpleShape shape2 = patriarch.CreateSimpleShape(a2);
    shape2.ShapeType = (HSSFSimpleShape.OBJECT_TYPE_LINE);

    y1 += 10;
    y2 += 10;
}

請注意HSSFClientAnchor對象中的dx只能取0-1023之間的數,dy只能取0-255之間的數。咱們能夠理解爲是將單元格的寬和高平分紅了1023和255份,設置dx和dy時至關於按比例取對應的座標。最終生成的Excel以下:

 

 

2.4.5用NPOI操做EXCEL--插入圖片

      咱們知道,在Excel中是能夠插入圖片的。操做菜單是「插入->圖片」,而後選擇要插入圖片,能夠很容易地在Excel插入圖片。一樣,在NPOI中,利用代碼也能夠實現一樣的效果。在NPOI中插入圖片的方法與畫圖的方法有點相似:

//add picture data to this workbook.
byte[] bytes = System.IO.File.ReadAllBytes(@"D:\MyProject\NPOIDemo\ShapeImage\image1.jpg");
int pictureIdx = hssfworkbook.AddPicture(bytes, HSSFWorkbook.PICTURE_TYPE_JPEG);

//create sheet
HSSFSheet sheet = hssfworkbook.CreateSheet("Sheet1");

// Create the drawing patriarch.  This is the top level container for all shapes. 
HSSFPatriarch patriarch = sheet.CreateDrawingPatriarch();

//add a picture
HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 1023, 0, 0, 0, 1, 3);
HSSFPicture pict = patriarch.CreatePicture(anchor, pictureIdx);

      與畫簡單圖形不一樣的是,首先要將圖片讀入到byte數組,而後添加到workbook中;最後調用的是patriarch.CreatePicture(anchor, pictureIdx)方法顯示圖片,而不是patriarch.CreateSimpleShape(anchor)方法。上面這段代碼執行後生成的Excel文件樣式以下:


      咱們發現,插入的圖片被拉伸填充在HSSFClientAnchor指定的區域。有時可能咱們並不須要拉伸的效果,怎麼辦呢?很簡單,在最後加上這樣一句用來自動調節圖片大小:

pict.Resize();

添加代碼後再執行上述代碼,生成的Excel樣式以下:

圖片已經自動伸縮到原始大小了。

 

NPOI 1.2教程 - 2.5 打印相關設置

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

 

打印設置主要包括方向設置、縮放、紙張設置、頁邊距等。NPOI 1.2支持大部分打印屬性,可以讓你輕鬆知足客戶的打印須要。

 

首先是方向設置,Excel支持兩種頁面方向,即縱向和橫向。

 

在NPOI中如何設置呢?你能夠經過HSSFSheet.PrintSetup.Landscape來設置,Landscape是布爾類型的,在英語中是橫向的意思。若是Landscape等於true,則表示頁面方向爲橫向;不然爲縱向。

 

接着是縮放設置,

 

 

這裏的縮放比例對應於HSSFSheet.PrintSetup.Scale,而頁寬和頁高分別對應於HSSFSheet.PrintSetup.FitWidth和HSSFSheet.PrintSetup.FitHeight。要注意的是,這裏的PrintSetup.Scale應該被設置爲0-100之間的值,而不是小數。

 

 

接下來就是紙張設置了,對應於HSSFSheet.PrintSetup.PaperSize,但這裏的PaperSize並非隨便設置的,而是由一些固定的值決定的,具體的值與對應的紙張以下表所示:

紙張

1

US Letter 8 1/2 x 11 in

2

US Letter Small 8 1/2 x 11 in

3

US Tabloid 11 x 17 in

4

US Ledger 17 x 11 in

5

US Legal 8 1/2 x 14 in

6

US Statement 5 1/2 x 8 1/2 in

7

US Executive 7 1/4 x 10 1/2 in

8

A3 297 x 420 mm

9

A4 210 x 297 mm

10

A4 Small 210 x 297 mm

11

A5 148 x 210 mm

12

B4 (JIS) 250 x 354

13

B5 (JIS) 182 x 257 mm

14

Folio 8 1/2 x 13 in

15

Quarto 215 x 275 mm

16

10 x 14 in

17

11 x 17 in

18

US Note 8 1/2 x 11 in

19

US Envelope #9 3 7/8 x 8 7/8

20

US Envelope #10 4 1/8 x 9 1/2

21

US Envelope #11 4 1/2 x 10 3/8

22

US Envelope #12 4 \276 x 11

23

US Envelope #14 5 x 11 1/2

24

C size sheet

25

D size sheet

26

E size sheet

27

Envelope DL 110 x 220mm

28

Envelope C5 162 x 229 mm

29

Envelope C3 324 x 458 mm

30

Envelope C4 229 x 324 mm

31

Envelope C6 114 x 162 mm

32

Envelope C65 114 x 229 mm

33

Envelope B4 250 x 353 mm

34

Envelope B5 176 x 250 mm

35

Envelope B6 176 x 125 mm

36

Envelope 110 x 230 mm

37

US Envelope Monarch 3.875 x 7.5 in

38

6 3/4 US Envelope 3 5/8 x 6 1/2 in

39

US Std Fanfold 14 7/8 x 11 in

40

German Std Fanfold 8 1/2 x 12 in

41

German Legal Fanfold 8 1/2 x 13 in

42

B4 (ISO) 250 x 353 mm

43

Japanese Postcard 100 x 148 mm

44

9 x 11 in

45

10 x 11 in

46

15 x 11 in

47

Envelope Invite 220 x 220 mm

48

RESERVED--DO NOT USE

49

RESERVED--DO NOT USE

50

US Letter Extra 9 \275 x 12 in

51

US Legal Extra 9 \275 x 15 in

52

US Tabloid Extra 11.69 x 18 in

53

A4 Extra 9.27 x 12.69 in

54

Letter Transverse 8 \275 x 11 in

55

A4 Transverse 210 x 297 mm

56

Letter Extra Transverse 9\275 x 12 in

57

SuperA/SuperA/A4 227 x 356 mm

58

SuperB/SuperB/A3 305 x 487 mm

59

US Letter Plus 8.5 x 12.69 in

60

A4 Plus 210 x 330 mm

61

A5 Transverse 148 x 210 mm

62

B5 (JIS) Transverse 182 x 257 mm

63

A3 Extra 322 x 445 mm

64

A5 Extra 174 x 235 mm

65

B5 (ISO) Extra 201 x 276 mm

66

A2 420 x 594 mm

67

A3 Transverse 297 x 420 mm

68

A3 Extra Transverse 322 x 445 mm

69

Japanese Double Postcard 200 x 148 mm

70

A6 105 x 148 mm

71

Japanese Envelope Kaku #2

72

Japanese Envelope Kaku #3

73

Japanese Envelope Chou #3

74

Japanese Envelope Chou #4

75

Letter Rotated 11 x 8 1/2 11 in

76

A3 Rotated 420 x 297 mm

77

A4 Rotated 297 x 210 mm

78

A5 Rotated 210 x 148 mm

79

B4 (JIS) Rotated 364 x 257 mm

80

B5 (JIS) Rotated 257 x 182 mm

81

Japanese Postcard Rotated 148 x 100 mm

82

Double Japanese Postcard Rotated 148 x 200 mm

83

A6 Rotated 148 x 105 mm

84

Japanese Envelope Kaku #2 Rotated

85

Japanese Envelope Kaku #3 Rotated

86

Japanese Envelope Chou #3 Rotated

87

Japanese Envelope Chou #4 Rotated

88

B6 (JIS) 128 x 182 mm

89

B6 (JIS) Rotated 182 x 128 mm

90

12 x 11 in

91

Japanese Envelope You #4

92

Japanese Envelope You #4 Rotated

93

PRC 16K 146 x 215 mm

94

PRC 32K 97 x 151 mm

95

PRC 32K(Big) 97 x 151 mm

96

PRC Envelope #1 102 x 165 mm

97

PRC Envelope #2 102 x 176 mm

98

PRC Envelope #3 125 x 176 mm

99

PRC Envelope #4 110 x 208 mm

100

PRC Envelope #5 110 x 220 mm

101

PRC Envelope #6 120 x 230 mm

102

PRC Envelope #7 160 x 230 mm

103

PRC Envelope #8 120 x 309 mm

104

PRC Envelope #9 229 x 324 mm

105

PRC Envelope #10 324 x 458 mm

106

PRC 16K Rotated

107

PRC 32K Rotated

108

PRC 32K(Big) Rotated

109

PRC Envelope #1 Rotated 165 x 102 mm

110

PRC Envelope #2 Rotated 176 x 102 mm

111

PRC Envelope #3 Rotated 176 x 125 mm

112

PRC Envelope #4 Rotated 208 x 110 mm

113

PRC Envelope #5 Rotated 220 x 110 mm

114

PRC Envelope #6 Rotated 230 x 120 mm

115

PRC Envelope #7 Rotated 230 x 160 mm

116

PRC Envelope #8 Rotated 309 x 120 mm

117

PRC Envelope #9 Rotated 324 x 229 mm

118

PRC Envelope #10 Rotated 458 x 324 mm

(此表摘自《Excel Binary File Format (.xls) Structure Specification.pdf》)

HSSFSheet下面定義了一些xxxx_PAPERSIZE的常量,但都是很是經常使用的紙張大小,若是知足不了你的須要,能夠根據上表本身給PaperSize屬性賦值。因此,若是你要設置紙張大小能夠用這樣的代碼:

HSSFSheet.PrintSetup.PaperSize=HSSFSheet.A4_PAPERSIZE;

HSSFSheet.PrintSetup.PaperSize=9;(A4 210*297mm)

 

 

再下來就是打印的起始頁碼,它對應於HSSFSheet.PrintSetup.PageStart和HSSFSheet.PrintSetup.UsePage,若是UsePage=false,那麼就至關於「自動」,這時PageStart不起做用;若是UsePage=true,PageStart纔會起做用。因此在設置PageStart以前,必須先把UsePage設置爲true。

 

 

「打印」欄中的「網格線」設置對應於HSSFSheet.IsPrintGridlines,請注意,這裏不是HSSFSheet.PrintSetup下面,因此別搞混了。這裏之因此不隸屬於PrintSetup是由底層存儲該信息的record決定的,底層是把IsGridsPrinted放在GridsetRecord裏面的,而不是PrintSetupRecord裏面的,儘管界面上是放在一塊兒的。另外還有一個HSSFSheet.IsGridsPrinted屬性,這個屬性對應於底層的gridset Record,但這個record是保留的,從微軟的文檔顯示沒有任何意義,因此這個屬性請不要去設置。

「單色打印」則對應於HSSFSheet.PrintSetup.NoColors,這是布爾類型的,值爲true時,表示單色打印。

「草稿品質」對應於HSSFSheet.PrintSetup.IsDraft,也是布爾類型的,值爲true時,表示用草稿品質打印。

這裏的打印順序是由HSSFSheet.PrintSetup.LeftToRight決定的,它是布爾類型的,當爲true時,則表示「先行後列」;若是是false,則表示「先列後行」。

 

在NPOI 1.2中,「行號列標」、「批註」和「錯誤單元格打印爲」、「頁邊距」暫不支持,將在之後的版本中支持。

 

有關打印的範例能夠參考NPOI 1.2正式版中的 SetPrintSettingsInXls項目。

 

2.6.1用NPOI操做EXCEL--調整表單顯示比例

在Excel中,能夠經過調整右下角的滾動條來調整Sheet的顯示比例。如圖:

在NPOI中,也能經過代碼實現這樣的功能,而且代碼很是簡單:

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
sheet1.CreateRow(0).CreateCell(0).SetCellValue("This is a test.");
//50% zoom
sheet1.SetZoom(1,2); 

咱們發現,SetZoom有兩個參數。其中第一個參數表示縮放比例的分子,第二個參數表示縮放比例的分母,因此SetZoom(1,2)就表示縮小到1/2,也就是50%。代碼執行後生成的Excel樣式以下:


若是將SetZoom的參數改爲(2,1),代碼執行後生成的Excel樣式以下,表示擴大兩倍:

 

 

2.6.2用NPOI操做EXCEL--設置密碼

      有時,咱們可能須要某些單元格只讀,如在作模板時,模板中的數據是不能隨意讓別人改的。在Excel中,能夠經過「審閱->保護工做表」來完成,以下圖:
     
 那麼,在NPOI中有沒有辦法經過編碼的方式達到這一效果呢?答案是確定的。

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");

HSSFRow row1 = sheet1.CreateRow(0);
HSSFCell cel1 = row1.CreateCell(0);
HSSFCell cel2 = row1.CreateCell(1);

HSSFCellStyle unlocked = hssfworkbook.CreateCellStyle();
unlocked.IsLocked = false;

HSSFCellStyle locked = hssfworkbook.CreateCellStyle();
locked.IsLocked = true;

cel1.SetCellValue("沒被鎖定");
cel1.CellStyle = unlocked;

cel2.SetCellValue("被鎖定");
cel2.CellStyle = locked;

sheet1.ProtectSheet("password");

正如代碼中所看到的,咱們經過設置CellStype的ISLocked爲True,表示此單元格將被鎖定。至關於在Excel中執行了以下操做:

而後經過ProtectSheet設置密碼。

執行結果以下:

沒被鎖定的列能夠任意修改。
 

被鎖定的列不能修改。
 


輸入密碼能夠解除鎖定。

 

NPOI 1.2教程 - 組合行、列

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

 

Excel 2007中有一個面板是專門用於設置組合功能的,叫作「分級顯示」面板,以下所示:

 

可能咱們在過去生成Excel文件的時候根本不會用這個功能,也沒辦法用,由於cvs法和html法沒辦法控制這些東西。這裏簡單的介紹一下什麼叫作組合:

組合分爲行組合和列組合,所謂行組合,就是讓n行組合成一個集合,可以進行展開和合攏操做,在Excel中顯示以下:

 

圖中左側就是用於控制行組合摺疊的圖標,圖中上部就是用於控制列組合的,是否是有點像TreeView中的摺疊節點?不少時候因爲數據太多,爲了讓用戶對於大量數據一目瞭然,咱們可使用行列組合來解決顯示大綱,這和Visual Studio 裏面的region的概念是相似的。

細心的朋友可能已經注意到了,咱們其實能夠對一行作屢次組合操做,這就是分級顯示的概念,圖中就把行2-3分爲2個組合,第2行到第4行爲一個組合,第2行到第5行一個組合,因此是分兩級。

在NPOI中,要實現分組其實並不難,你只須要調用HSSFSheet.GroupRow和HSSFSheet.GroupColumn這兩個方法就能夠了。

 

首先咱們來看HSSFSheet.GroupRow,GroupRow有2個參數,分別是fromRow和toRow,表示起始行號和結束行號,這些行號都是從0開始算起的。

HSSFWorkbookhssfworkbook =newHSSFWorkbook();

HSSFSheet s =hssfworkbook.CreateSheet("Sheet1");

s.GroupRow(1,3);

上面的代碼把第2行到第4行作了組合。

要組合列,其實代碼很類似,以下所示:

s.GroupColumn(1,3)

上面的代碼把B至D列作了組合。

 

正如上圖中Excel的「分級顯示」面板所示,有「組合」,也必定有「取消組合」,NPOI中你能夠用HSSFSheet.UngroupRow和HSSFSheet.UngroupColumn,參數和GroupXXX是同樣的,若是要取消第2到第4行的組合,就能夠用下面的代碼:

s.UngroupColumn(1,3)

 

相關範例請見NPOI 1.2正式版中的GroupRowAndColumnInXls項目。

 

2.6.4用NPOI操做EXCEL--鎖定列

      在Excel中,有時可能會出現列數太多或是行數太多的狀況,這時能夠經過鎖定列來凍結部分列,不隨滾動條滑動,方便查看。在Excel中設置凍結列的方法以下:


一樣,利用NPOI,經過代碼也能實現上面的效果:

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
HSSFRow row1 = sheet1.CreateRow(0);
row1.CreateCell(0).SetCellValue("凍結列");
sheet1.CreateFreezePane(1, 0, 1, 0);


代碼執行結果以下:

下面對CreateFreezePane的參數做一下說明:
第一個參數表示要凍結的列數;
第二個參數表示要凍結的行數,這裏只凍結列因此爲0;
第三個參數表示右邊區域可見的首列序號,從1開始計算;
第四個參數表示下邊區域可見的首行序號,也是從1開始計算,這裏是凍結列,因此爲0;

舉例說明也許更好理解,將各參數設置爲以下:

sheet1.CreateFreezePane(2,0,5,0);

 

獲得的效果以下圖:

注意圖中C、D和E列默認是看不到的,滾動纔看獲得,這就是第三個參數5起了做用,是否是很好理解了呢:)

接下來,看一下凍結行的效果。將上面的代碼稍做修改:

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
HSSFRow row1 = sheet1.CreateRow(0);
row1.CreateCell(0).SetCellValue("凍結行");
sheet1.CreateFreezePane(0, 1, 0, 1);

執行後生成的Excel文件效果見下圖:


那麼,若是要行和列同時凍結該怎麼作呢?聰明的你必定能想獲得,呵呵~~

 

NPOI 1.2教程 - 顯示/隱藏Excel網格線

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

 

有些時候,咱們須要網格線,而有些時候咱們不須要,這取決於實際的業務需求。前兩天inmegin兄就問我,怎麼把網格給去掉,由於他們要把Excel文檔當Word使,也許是由於Excel排版方便吧。

Excel中的網格線設置是以表(Sheet)爲單位進行管理的,這也就意味着你可讓一個表顯示網格線,而另外一個表不顯示,這是不衝突的。

 

在Excel 2007中,咱們一般用「工做表選項」面板來設置這個屬性:

 

 

在面板中,你會發現有2個多選框,一個是查看,一個是打印,也就是說Excel是把查看和打印網格線做爲兩個設置來處理的,存儲的Record也是不一樣的。

在NPOI中,若是要讓網格線在查看時顯示/隱藏,你能夠HSSFSheet.DisplayGridlines屬性,默認值爲true(這也是爲何默認狀況下咱們可以看到網格線)。下面的代碼就是讓網格線在查看時不可見的:

HSSFWorkbookhssfworkbook =newHSSFWorkbook();

HSSFSheet s1= hssfworkbook.CreateSheet("Sheet1");

s1.DisplayGridlines=false;

若是要在打印時顯示/隱藏網格線,你能夠用HSSFSheet.IsGridlinesPrinted屬性,默認值爲false(這就是默認狀況下打印看不到網格線的緣由)。代碼和上面差很少:

s1.IsGridsPrinted=true;

上面的代碼將在打印時顯示網格線,打印的效果以下所示。

 

 

 

在此也提醒你們,若是這個Excel最終客戶有打印意向,可別忘了把IsGridPrinted屬性也設置上。

 

相關範例能夠參考NPOI 1.2正式版中的DisplayGridlinesInXls項目。

 

2.6.6用NPOI操做EXCEL--設置初始視圖的行、列

    有些時候,咱們可能但願生成的Excel文件在被打開的時候自動將焦點定位在某個單元格或是選中某個區域中。在NPOI中能夠經過SetAsActiveCell和SetActiveCellRange等幾個方法實現。

首先咱們看一下設置初始視圖中選中某個單元格的方法:

//use HSSFCell.SetAsActiveCell() to select B6 as the active column
HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet A");
CreateCellArray(sheet1);
sheet1.GetRow(5).GetCell(1).SetAsActiveCell();
//set TopRow and LeftCol to make B6 the first cell in the visible area
sheet1.TopRow = 5;
sheet1.LeftCol = 1;

其中CreateCellArray(sheet1)方法用來寫示範數據,其代碼爲(下同):

static void CreateCellArray(HSSFSheet sheet)
{
    for (int i = 0; i < 300; i++)
    {
        HSSFRow row=sheet.CreateRow(i);
        for (int j = 0; j < 150; j++)
        {
            HSSFCell cell = row.CreateCell(j);
            cell.SetCellValue(i*j);
        }
    }
}

生成的Excel打開時效果以下,注意B6爲默認選中狀態,TopRow和LeftCol設置B6爲當前可見區域的第一個單元格:

若是不設置TopRow和LeftCol屬性,默認的可見域的第一個單元格爲A1,以下是另外一種設置活動單元格的方法,但沒有設置此Sheet的TopRow和LeftCol:

HSSFSheet sheet2 = hssfworkbook.CreateSheet("Sheet B");
sheet2.Sheet.SetActiveCell(1, 5);

對應生成的Excel顯示爲:

除了設置某個單元格爲選中狀態外,還NPOI能夠設置某個區域爲選中狀態:

 

//use Sheet.SetActiveCellRange to select a cell range
HSSFSheet sheet3 = hssfworkbook.CreateSheet("Sheet C");
CreateCellArray(sheet3);
sheet3.Sheet.SetActiveCellRange(2, 5, 1, 5);

以上代碼設置了Sheet C的選中區域爲B3:F6:

還有更強大的,設置多個選中區域:

//use Sheet.SetActiveCellRange to select multiple cell ranges
HSSFSheet sheet4 = hssfworkbook.CreateSheet("Sheet D");
CreateCellArray(sheet4);
List<CellRangeAddress8Bit> cellranges = new List<CellRangeAddress8Bit>();
cellranges.Add(new CellRangeAddress8Bit(1,3,2,5));
cellranges.Add(new CellRangeAddress8Bit(6,7,8,9));
sheet4.Sheet.SetActiveCellRange(cellranges,1,6,9);

若是一個Excel文件中有多個Sheet,還能夠經過以下語句設置打開時的初始Sheet:

hssfworkbook.ActiveSheetIndex = 2;

 

 

2.6.7用NPOI操做EXCEL--數據有效性

      在有些狀況下(好比Excel引入),咱們可能不容許用戶在Excel隨意輸入一些無效數據,這時就要在模板中加一些數據有效性的驗證。在Excel中,設置數據有效性的方步驟以下:
(1)先選定一個區域;
數據有效性」中設置數據有效性驗證(如圖)。à(2)在菜單「數據


一樣,利用NPOI,用代碼也能夠實現:

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");

sheet1.CreateRow(0).CreateCell(0).SetCellValue("日期列");
CellRangeAddressList regions1 = new CellRangeAddressList(1, 65535, 0, 0);
DVConstraint constraint1 = DVConstraint.CreateDateConstraint(DVConstraint.OperatorType.BETWEEN, "1900-01-01", "2999-12-31", "yyyy-MM-dd");
HSSFDataValidation dataValidate1 = new HSSFDataValidation(regions1, constraint1);
dataValidate1.CreateErrorBox("error", "You must input a date.");
sheet1.AddValidationData(dataValidate1);

上面是一個在第一列要求輸入1900-1-1至2999-12-31之間日期的有效性驗證的例子,生成的Excel效果以下,當輸入非法時將給出警告:


下面對剛纔用到的幾個方法加以說明:
      CellRangeAddressList類表示一個區域,構造函數中的四個參數分別表示起始行序號,終止行序號,起始列序號,終止列序號。因此第一列所在區域就表示爲:

//全部序號都從零算起,第一行標題行除外,因此第一個參數是1,65535是一個Sheet的最大行數
new CellRangeAddressList(1, 65535, 0, 0);

      另外,CreateDateConstraint的第一個參數除了設置成DVConstraint.OperatorType.BETWEEN外,還能夠設置成以下一些值,你們能夠本身一個個去試看看效果:

      最後,dataValidate1.CreateErrorBox(title,text),用來建立出錯時的提示信息。第一個參數表示提示框的標題,第二個參數表示提示框的內容。

理解了上面這些,建立一個整數類型的有效性驗證也不難實現:

sheet1.CreateRow(0).CreateCell(1).SetCellValue("數值列");
CellRangeAddressList regions2 = new CellRangeAddressList(1, 65535, 1, 1);
DVConstraint constraint2 = DVConstraint.CreateNumericConstraint(DVConstraint.ValidationType.INTEGER,DVConstraint.OperatorType.BETWEEN, "0", "100");
HSSFDataValidation dataValidate2 = new HSSFDataValidation(regions2, constraint2);
dataValidate2.CreateErrorBox("error", "You must input a numeric between 0 and 100.");
sheet1.AddValidationData(dataValidate2);

 

生成的Excel效果爲:


下一節咱們將學習利用數據有效性建立下拉列表的例子。

 

2.6.8用NPOI操做EXCEL--生成下拉列表

      上一節咱們講了簡單的數據有效性驗證,這一節咱們學習一下數據有效性的另外一個應用--下拉列表。在Excel中,並無相似Web中的下拉控件,其下拉效果是經過數據有效性來實現的。設置步驟爲:
(1)選定一個要生成下拉列表的區域;
(2)設置數據有效性爲序列,並在來源中填充可選下拉的值,用「,」隔開(如圖)。

對應的效果爲:


一樣,利用NPOI代碼也能夠實現上面的效果:

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");

CellRangeAddressList regions = new CellRangeAddressList(0, 65535, 0, 0);
DVConstraint constraint = DVConstraint.CreateExplicitListConstraint(new string[] { "itemA", "itemB", "itemC" });
HSSFDataValidation dataValidate = new HSSFDataValidation(regions, constraint);
sheet1.AddValidationData(dataValidate);

下面對代碼做一下簡要說明:
先設置一個須要提供下拉的區域,關於CellRangeAddressList構造函數參數的說明請參見上一節

CellRangeAddressList regions = new CellRangeAddressList(0, 65535, 0, 0);

而後將下拉項做爲一個數組傳給CreateExplicitListConstraint做爲參數建立一個約束,根據要控制的區域和約束建立數據有效性就能夠了。

      可是這樣會有一個問題:Excel中容許輸入的序列來源長度最大爲255個字符,也就是說當下拉項的總字符串長度超過255是將會出錯。那麼若是下拉項不少的狀況下應該怎麼處理呢?答案是經過引用的方式。步驟以下:
先建立一個Sheet專門用於存儲下拉項的值,並將各下拉項的值寫入其中:

HSSFSheet sheet2 = hssfworkbook.CreateSheet("ShtDictionary");
sheet2.CreateRow(0).CreateCell(0).SetCellValue("itemA");
sheet2.CreateRow(1).CreateCell(0).SetCellValue("itemB");
sheet2.CreateRow(2).CreateCell(0).SetCellValue("itemC");

而後定義一個名稱,指向剛纔建立的下拉項的區域:

HSSFName range = hssfworkbook.CreateName();
range.Reference = "ShtDictionary!$A1:$A3";
range.NameName = "dicRange";

最後,設置數據約束時指向這個名稱而不是字符數組:

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
CellRangeAddressList regions = new CellRangeAddressList(0, 65535, 0, 0);

DVConstraint constraint = DVConstraint.CreateFormulaListConstraint("dicRange");
HSSFDataValidation dataValidate = new HSSFDataValidation(regions, constraint);
sheet1.AddValidationData(dataValidate);

執行這段代碼,生成的Excel效果以下:

在名稱管理器中會發現有一個名爲"dicRange"的名稱,指向"ShtDictionary!$A1:$A3"的下拉項區域:

在數據有效性中會發現來源變成了"=dicRange",指向上面定義的名稱。而不是之前的"itemA,itemB,itemC":

 

 

NPOI 1.2教程 – 3.1 基於.xls模板生成Excel文件

做者:Tony Qu

NPOI官方網站:http://npoi.codeplex.com/

NPOI QQ交流羣: 78142590 

 

儘管NPOI可以從頭開始生成Excel文件,但在實際生產環境中有不少現成的表格,咱們不可能沒事就去從頭開始生成一個Excel,更多時候咱們更願意選擇比較偷懶的方法——那就是用模板文件。NPOI一大特點之一就是可以輕鬆讀取Office Excel 97-2003的格式,即便裏面有NPOI不支持的VBA宏、圖表以及Pivot表之類的高級記錄,NPOI也可以保證不丟失數據(說實話,要徹底可以識別全部的Excel內部記錄幾乎是不可能的,更況且現在又多出了Office Excel 2007binary file,即.xlsb)。

如今咱們轉入正題,出於演示目的,我作了一個簡單的銷售量表,裏面應用了文字顏色、背景色、文本居中、公式、千分位分隔符、邊框等效果,固然實際的生產環境裏可能還有更加複雜的Excel模板。以下圖

 

咱們的程序就是要填充12個月的銷售量,Total可以自動根據填充的值計算出總量。

(這裏要提一下,以往若是咱們用HTML方式輸出xls,咱們必須在服務器端作Total計算,而且這個值在下載後永遠都是靜態的,沒有公式,即便用戶要修改裏面的數據,總值也不會改變。這也是爲何NPOI一直提倡生成真正的Excel文件。)

代碼其實很簡單:

//read thetemplate via FileStream, it is suggested to use FileAccess.Read to prevent filelock.

//book1.xlsis an Excel-2007-generated file, so some new unknown BIFF records are added.

FileStreamfile =new FileStream(@"template/book1.xls", FileMode.Open,FileAccess.Read);

HSSFWorkbook hssfworkbook = new HSSFWorkbook(file);
HSSFSheet sheet1 = hssfworkbook.GetSheet("Sheet1");
sheet1.GetRow(1).GetCell(1).SetCellValue(200200);
sheet1.GetRow(2).GetCell(1).SetCellValue(300);
sheet1.GetRow(3).GetCell(1).SetCellValue(500050);
sheet1.GetRow(4).GetCell(1).SetCellValue(8000);
sheet1.GetRow(5).GetCell(1).SetCellValue(110);
sheet1.GetRow(6).GetCell(1).SetCellValue(100);
sheet1.GetRow(7).GetCell(1).SetCellValue(200);
sheet1.GetRow(8).GetCell(1).SetCellValue(210);
sheet1.GetRow(9).GetCell(1).SetCellValue(2300);
sheet1.GetRow(10).GetCell(1).SetCellValue(240);
sheet1.GetRow(11).GetCell(1).SetCellValue(180123);
sheet1.GetRow(12).GetCell(1).SetCellValue(150);

//Force excel to recalculate all the formulawhile open

sheet1.ForceFormulaRecalculation=true;

FileStreamfile = new FileStream(@"test.xls", FileMode.Create);
hssfworkbook.Write(file);
file.Close();

首先打開模板文件時要使用FileAccess.Read,這樣能夠保證文件不被佔用。

這裏的ForceFormulaRecalculation是強制要求Excel在打開時從新計算的屬性,在擁有公式的xls文件中十分有用,你們使用時可別忘了設。

 

是否是比你想象的簡單?你甚至不用去了解它是在什麼時候讀取文件內容的,對於NPOI的使用者來講基本上和讀取普通文件沒有什麼兩樣。

 

最終生成的效果以下所示:

 

 

 

發覺沒,就連千分位分隔符也都保留着,一切就像人工填寫的同樣。

 

本範例完整代碼請見NPOI.Examples中的GenerateXlsFromXlsTemplate項目。

 

3.2用NPOI操做EXCEL--生成九九乘法表

      還記得小學時候學的九九乘法表嗎?這節咱們一塊兒學習利用NPOI經過C#代碼生成一張Excel的九九乘法表。要生成九九乘法表,循環確定是少不了的,以下:

HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
HSSFRow row;
HSSFCell cell;
for (int rowIndex = 0; rowIndex < 9; rowIndex++)
{
     row = sheet1.CreateRow(rowIndex);
     for (int colIndex = 0; colIndex <= rowIndex; colIndex++)
     {
           cell = row.CreateCell(colIndex);
           cell.SetCellValue(String.Format("{0}*{1}={2}", rowIndex + 1, colIndex + 1, (rowIndex + 1) * (colIndex + 1)));
     }
}


      代碼其實很簡單,就是循環調用cell.SetCellValue(str)寫入9行數據,每一行寫的單元格數量隨行數遞增。執行完後生成的Excel樣式以下:


完整的代碼以下:

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NPOI.HSSF.UserModel;
using System.IO;
using NPOI.HPSF;

namespace TimesTables
{
    public class Program
    {
        static HSSFWorkbook hssfworkbook;

        static void Main(string[] args)
        {
            InitializeWorkbook();

            HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
            HSSFRow row;
            HSSFCell cell;
            for (int rowIndex = 0; rowIndex < 9; rowIndex++)
            {
                row = sheet1.CreateRow(rowIndex);
                for (int colIndex = 0; colIndex <= rowIndex; colIndex++)
                {
                    cell = row.CreateCell(colIndex);
                    cell.SetCellValue(String.Format("{0}*{1}={2}", rowIndex + 1, colIndex + 1, (rowIndex + 1) * (colIndex + 1)));
                }
            }

            WriteToFile();
        }

        static void WriteToFile()
        {
            //Write the stream data of workbook to the root directory
            FileStream file = new FileStream(@"test.xls", FileMode.Create);
            hssfworkbook.Write(file);
            file.Close();
        }

        static void InitializeWorkbook()
        {
            hssfworkbook = new HSSFWorkbook();

            //create a entry of DocumentSummaryInformation
            DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation();
            dsi.Company = "NPOI Team";
            hssfworkbook.DocumentSummaryInformation = dsi;

            //create a entry of SummaryInformation
            SummaryInformation si = PropertySetFactory.CreateSummaryInformation();
            si.Subject = "NPOI SDK Example";
            hssfworkbook.SummaryInformation = si;
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NPOI.HSSF.UserModel;
using System.IO;
using NPOI.HPSF;

namespace TimesTables
{
    public class Program
    {
        static HSSFWorkbook hssfworkbook;

        static void Main(string[] args)
        {
            InitializeWorkbook();

            HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
            HSSFRow row;
            HSSFCell cell;
            for (int rowIndex = 0; rowIndex < 9; rowIndex++)
            {
                row = sheet1.CreateRow(rowIndex);
                for (int colIndex = 0; colIndex <= rowIndex; colIndex++)
                {
                    cell = row.CreateCell(colIndex);
                    cell.SetCellValue(String.Format("{0}*{1}={2}", rowIndex + 1, colIndex + 1, (rowIndex + 1) * (colIndex + 1)));
                }
            }

            WriteToFile();
        }

        static void WriteToFile()
        {
            //Write the stream data of workbook to the root directory
            FileStream file = new FileStream(@"test.xls", FileMode.Create);
            hssfworkbook.Write(file);
            file.Close();
        }

        static void InitializeWorkbook()
        {
            hssfworkbook = new HSSFWorkbook();

            //create a entry of DocumentSummaryInformation
            DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation();
            dsi.Company = "NPOI Team";
            hssfworkbook.DocumentSummaryInformation = dsi;

            //create a entry of SummaryInformation
            SummaryInformation si = PropertySetFactory.CreateSummaryInformation();
            si.Subject = "NPOI SDK Example";
            hssfworkbook.SummaryInformation = si;
        }
    }
}

 

3.3用NPOI操做EXCEL--生成一張工資單

      這一節,咱們將綜合NPOI的經常使用功能(包括建立和填充單元格、合併單元格、設置單元格樣式和利用公式),作一個工資單的實例。先看建立標題行的代碼:

//寫標題文本
HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
HSSFCell cellTitle = sheet1.CreateRow(0).CreateCell(0);
cellTitle.SetCellValue("XXX公司2009年10月工資單");

//設置標題行樣式
HSSFCellStyle style = hssfworkbook.CreateCellStyle();
style.Alignment = HSSFCellStyle.ALIGN_CENTER;
HSSFFont font = hssfworkbook.CreateFont();
font.FontHeight = 20 * 20;
style.SetFont(font);

cellTitle.CellStyle = style;

//合併標題行
sheet1.AddMergedRegion(new Region(0, 0, 1, 6));


其中用到了咱們前面講的設置單元格樣式和合並單元格等內容。接下來咱們循環建立公司每一個員工的工資單:


DataTable dt=GetData();
HSSFRow row;
HSSFCell cell;
HSSFCellStyle celStyle=getCellStyle();

HSSFPatriarch patriarch = sheet1.CreateDrawingPatriarch();
HSSFClientAnchor anchor;
HSSFSimpleShape line;
int rowIndex;
for (int i = 0; i < dt.Rows.Count; i++)
{
    //表頭數據
    rowIndex = 3 * (i + 1);
    row = sheet1.CreateRow(rowIndex);

    cell = row.CreateCell(0);
    cell.SetCellValue("姓名");
    cell.CellStyle = celStyle;

    cell = row.CreateCell(1);
    cell.SetCellValue("基本工資");
    cell.CellStyle = celStyle;

    cell = row.CreateCell(2);
    cell.SetCellValue("住房公積金");
    cell.CellStyle = celStyle;

    cell = row.CreateCell(3);
    cell.SetCellValue("績效獎金");
    cell.CellStyle = celStyle;

    cell = row.CreateCell(4);
    cell.SetCellValue("社保扣款");
    cell.CellStyle = celStyle;

    cell = row.CreateCell(5);
    cell.SetCellValue("代扣個稅");
    cell.CellStyle = celStyle;

    cell = row.CreateCell(6);
    cell.SetCellValue("實發工資");
    cell.CellStyle = celStyle;


    DataRow dr = dt.Rows[i];
    //設置值和計算公式
    row = sheet1.CreateRow(rowIndex + 1);
    cell = row.CreateCell(0);
    cell.SetCellValue(dr["FName"].ToString());
    cell.CellStyle = celStyle;

    cell = row.CreateCell(1);
    cell.SetCellValue((double)dr["FBasicSalary"]);
    cell.CellStyle = celStyle;

    cell = row.CreateCell(2);
    cell.SetCellValue((double)dr["FAccumulationFund"]);
    cell.CellStyle = celStyle;

    cell = row.CreateCell(3);
    cell.SetCellValue((double)dr["FBonus"]);
    cell.CellStyle = celStyle;

    cell = row.CreateCell(4);
    cell.SetCellFormula(String.Format("$B{0}*0.08",rowIndex+2));
    cell.CellStyle = celStyle;

    cell = row.CreateCell(5);
    cell.SetCellFormula(String.Format("SUM($B{0}:$D{0})*0.1",rowIndex+2));
    cell.CellStyle = celStyle;

    cell = row.CreateCell(6);
    cell.SetCellFormula(String.Format("SUM($B{0}:$D{0})-SUM($E{0}:$F{0})",rowIndex+2));
    cell.CellStyle = celStyle;


    //繪製分隔線
    sheet1.AddMergedRegion(new Region(rowIndex+2, 0, rowIndex+2, 6));
    anchor = new HSSFClientAnchor(0, 125, 1023, 125, 0, rowIndex + 2, 6, rowIndex + 2);
    line = patriarch.CreateSimpleShape(anchor);
    line.ShapeType = HSSFSimpleShape.OBJECT_TYPE_LINE;
    line.LineStyle = HSSFShape.LINESTYLE_DASHGEL;

}

其中爲了文件打印爲單元格增長了黑色邊框的樣式(若是不設置邊框樣式,打印出來後是沒有邊框的)。另外,注意循環過程當中excel中的行號隨數據源中的行號變化處理。完整代碼以下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NPOI.HSSF.UserModel;
using System.IO;
using NPOI.HPSF;
using NPOI.HSSF.Util;
using System.Data;

namespace Payroll
{
    public class Program
    {
        static HSSFWorkbook hssfworkbook;

        static void Main(string[] args)
        {
            InitializeWorkbook();

            //寫標題文本
            HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
            HSSFCell cellTitle = sheet1.CreateRow(0).CreateCell(0);
            cellTitle.SetCellValue("XXX公司2009年10月工資單");

            //設置標題行樣式
            HSSFCellStyle style = hssfworkbook.CreateCellStyle();
            style.Alignment = HSSFCellStyle.ALIGN_CENTER;
            HSSFFont font = hssfworkbook.CreateFont();
            font.FontHeight = 20 * 20;
            style.SetFont(font);

            cellTitle.CellStyle = style;

            //合併標題行
            sheet1.AddMergedRegion(new Region(0, 0, 1, 6));

            DataTable dt=GetData();
            HSSFRow row;
            HSSFCell cell;
            HSSFCellStyle celStyle=getCellStyle();

            HSSFPatriarch patriarch = sheet1.CreateDrawingPatriarch();
            HSSFClientAnchor anchor;
            HSSFSimpleShape line;
            int rowIndex;
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                //表頭數據
                rowIndex = 3 * (i + 1);
                row = sheet1.CreateRow(rowIndex);

                cell = row.CreateCell(0);
                cell.SetCellValue("姓名");
                cell.CellStyle = celStyle;

                cell = row.CreateCell(1);
                cell.SetCellValue("基本工資");
                cell.CellStyle = celStyle;

                cell = row.CreateCell(2);
                cell.SetCellValue("住房公積金");
                cell.CellStyle = celStyle;

                cell = row.CreateCell(3);
                cell.SetCellValue("績效獎金");
                cell.CellStyle = celStyle;

                cell = row.CreateCell(4);
                cell.SetCellValue("社保扣款");
                cell.CellStyle = celStyle;

                cell = row.CreateCell(5);
                cell.SetCellValue("代扣個稅");
                cell.CellStyle = celStyle;

                cell = row.CreateCell(6);
                cell.SetCellValue("實發工資");
                cell.CellStyle = celStyle;


                DataRow dr = dt.Rows[i];
                //設置值和計算公式
                row = sheet1.CreateRow(rowIndex + 1);
                cell = row.CreateCell(0);
                cell.SetCellValue(dr["FName"].ToString());
                cell.CellStyle = celStyle;

                cell = row.CreateCell(1);
                cell.SetCellValue((double)dr["FBasicSalary"]);
                cell.CellStyle = celStyle;

                cell = row.CreateCell(2);
                cell.SetCellValue((double)dr["FAccumulationFund"]);
                cell.CellStyle = celStyle;

                cell = row.CreateCell(3);
                cell.SetCellValue((double)dr["FBonus"]);
                cell.CellStyle = celStyle;

                cell = row.CreateCell(4);
                cell.SetCellFormula(String.Format("$B{0}*0.08",rowIndex+2));
                cell.CellStyle = celStyle;

                cell = row.CreateCell(5);
                cell.SetCellFormula(String.Format("SUM($B{0}:$D{0})*0.1",rowIndex+2));
                cell.CellStyle = celStyle;

                cell = row.CreateCell(6);
                cell.SetCellFormula(String.Format("SUM($B{0}:$D{0})-SUM($E{0}:$F{0})",rowIndex+2));
                cell.CellStyle = celStyle;


                //繪製分隔線
                sheet1.AddMergedRegion(new Region(rowIndex+2, 0, rowIndex+2, 6));
                anchor = new HSSFClientAnchor(0, 125, 1023, 125, 0, rowIndex + 2, 6, rowIndex + 2);
                line = patriarch.CreateSimpleShape(anchor);
                line.ShapeType = HSSFSimpleShape.OBJECT_TYPE_LINE;
                line.LineStyle = HSSFShape.LINESTYLE_DASHGEL;

            }

            WriteToFile();
        }

        static DataTable GetData()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("FName",typeof(System.String));
            dt.Columns.Add("FBasicSalary",typeof(System.Double));
            dt.Columns.Add("FAccumulationFund", typeof(System.Double));
            dt.Columns.Add("FBonus", typeof(System.Double));

            dt.Rows.Add("令狐沖", 6000, 1000, 2000);
            dt.Rows.Add("任盈盈", 7000, 1000, 2500);
            dt.Rows.Add("林平之", 5000, 1000, 1500);
            dt.Rows.Add("嶽靈珊", 4000, 1000, 900);
            dt.Rows.Add("任我行", 4000, 1000, 800);
            dt.Rows.Add("風清揚", 9000, 5000, 3000);

            return dt;
        }

        
        static HSSFCellStyle getCellStyle()
        {
            HSSFCellStyle cellStyle = hssfworkbook.CreateCellStyle();
            cellStyle.BorderBottom = HSSFCellStyle.BORDER_THIN;
            cellStyle.BorderLeft = HSSFCellStyle.BORDER_THIN;
            cellStyle.BorderRight = HSSFCellStyle.BORDER_THIN;
            cellStyle.BorderTop = HSSFCellStyle.BORDER_THIN;
            return cellStyle;
        }

        static void WriteToFile()
        {
            //Write the stream data of workbook to the root directory
            FileStream file = new FileStream(@"test.xls", FileMode.Create);
            hssfworkbook.Write(file);
            file.Close();
        }

        static void InitializeWorkbook()
        {
            hssfworkbook = new HSSFWorkbook();

            //create a entry of DocumentSummaryInformation
            DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation();
            dsi.Company = "NPOI Team";
            hssfworkbook.DocumentSummaryInformation = dsi;

            //create a entry of SummaryInformation
            SummaryInformation si = PropertySetFactory.CreateSummaryInformation();
            si.Subject = "NPOI SDK Example";
            hssfworkbook.SummaryInformation = si;
        }
    }
}

生成的Excel文件樣式以下:

 

 

3.4用NPOI操做EXCEL--從Excel中抽取文本

  咱們知道,搜索引擎最擅長處理的就是文本,而Excel中的內容並非以文本方式存儲的。那麼若是想要搜索引擎爬蟲可以抓取到Excel中的內容是比較困難的,除非搜索引擎爬蟲對Excel格式進行專門的處理。那麼有沒有辦法解決此問題呢?有,經過NPOI將Excel內容文本化!

  以下,有這樣一張Excel,若是想讓它被搜索引擎收錄,經常使用的方式是以HTML形式展示,但將一個個這樣的Excel手工作成HTML頁面顯然比較麻煩。接下來,咱們將提供一種方案,自動將Excel中的內容以HTML形式展示。

  其實基本思想也很簡單,就是經過NPOI讀取每一個Cell中的內容,而後以HTML的形式輸出。但要保證輸出的HTML頁面佈局與Excel中的一致,還有點小技巧。下面是構造Table的代碼:

private HSSFSheet sht;
protected String excelContent;

protected void Page_Load(object sender, EventArgs e)
{
    HSSFWorkbook wb = new HSSFWorkbook(new FileStream(Server.MapPath("App_Data/quotation.xls"), FileMode.Open));
    sht = wb.GetSheet("Sheet1");

    //取行Excel的最大行數
    int rowsCount = sht.PhysicalNumberOfRows;
    //爲保證Table佈局與Excel同樣,這裏應該取全部行中的最大列數(須要遍歷整個Sheet)。
    //爲少一交全Excel遍歷,提升性能,咱們能夠人爲把第0行的列數調整至全部行中的最大列數。
    int colsCount = sht.GetRow(0).PhysicalNumberOfCells;

    int colSpan;
    int rowSpan;
    bool isByRowMerged;

    StringBuilder table = new StringBuilder(rowsCount * 32);

    table.Append("<table border='1px'>");
    for (int rowIndex = 0; rowIndex < rowsCount; rowIndex++)
    {
        table.Append("<tr>");
        for (int colIndex = 0; colIndex < colsCount; colIndex++)
        {
            GetTdMergedInfo(rowIndex, colIndex, out colSpan, out rowSpan, out isByRowMerged);
            //若是已經被行合併包含進去了就不輸出TD了。
            //注意被合併的行或列不輸出的處理方式不同,見下面一處的註釋說明了列合併後不輸出TD的處理方式。
            if (isByRowMerged)
            {
                continue;
            }
            
            table.Append("<td");
            if (colSpan > 1)
                table.Append(string.Format(" colSpan={0}", colSpan));
            if (rowSpan > 1)
                table.Append(string.Format(" rowSpan={0}", rowSpan));
            table.Append(">");

            table.Append(sht.GetRow(rowIndex).GetCell(colIndex));

            //列被合併以後此行將少輸出colSpan-1個TD。
            if (colSpan > 1)
                colIndex += colSpan - 1;

            table.Append("</td>");

        }
        table.Append("</tr>");
    }
    table.Append("</table>");

    this.excelContent = table.ToString();
}

  其中用到的GetTdMergedInfo方法代碼以下:

/// <summary>
///  獲取Table某個TD合併的列數和行數等信息。與Excel中對應Cell的合併行數和列數一致。
/// </summary>
/// <param name="rowIndex">行號</param>
/// <param name="colIndex">列號</param>
/// <param name="colspan">TD中須要合併的行數</param>
/// <param name="rowspan">TD中須要合併的列數</param>
/// <param name="rowspan">此單元格是否被某個行合併包含在內。若是被包含在內,將不輸出TD。</param>
/// <returns></returns>
private void GetTdMergedInfo(int rowIndex, int colIndex, out int colspan, out int rowspan, out bool isByRowMerged)
{
    colspan = 1;
    rowspan = 1;
    isByRowMerged = false;
    int regionsCuont = sht.NumMergedRegions;
    Region region;
    for (int i = 0; i < regionsCuont; i++)
    {
        region = sht.GetMergedRegionAt(i);
        if (region.RowFrom == rowIndex && region.ColumnFrom == colIndex)
        {
            colspan = region.ColumnTo - region.ColumnFrom + 1;
            rowspan = region.RowTo - region.RowFrom + 1;

            return;
        }
        else if (rowIndex > region.RowFrom && rowIndex <= region.RowTo && colIndex>=region.ColumnFrom && colIndex<=region.ColumnTo)
        {
            isByRowMerged = true;
        }
    }
}

最後在apsx頁面中輸出構建好的Table:

<%=excelContent %>

執行效果以下:

 

咱們發現,與Excel中的佈局徹底同樣(這裏沒有處理單元格的樣式,只處理了內容,有興趣的讀者也能夠將Excel中單元格的樣式也應用在HTML中)。這裏爲保證佈局一致,主要是將Excel中的Region信息解析成Table的colSpan和rowSpan屬性,若是對這兩個屬性不太瞭解,能夠結合如下代碼和示例加以瞭解:

<table width="300px" border="1px">
<tr>
    <td colspan="2" rowspan="2">0,0</td>
    <td>0,3</td>
</tr>
<tr>
    <td>1,3</td>
</tr>
<tr>
    <td rowspan="2">2,0</td>
    <td colspan="2">2,1</td>
</tr>
<tr>
    <td>3,1</td>
    <td>3,2</td>
</tr>
</table>

 以上HTML代碼對應的Table展示爲:

 

3.5用NPOI操做EXCEL--巧妙使用Excel Chart

  在NPOI中,自己並不支持Chart等高級對象的建立,但經過l模板的方式能夠巧妙地利用Excel強大的透視和圖表功能,請看如下例子。

首先創建模板文件,定義兩列以及指向此區域的名稱「sales」:

建立數據表,數據來源填入剛纔定義的區域:

最後生成的數據透視表所在Sheet的樣式以下:

至此,模板已經建好,另存爲「D:\MyProject\NPOIDemo\Chart\Book2.xls」。咱們發現,模板就至關於一個「空架子」,僅僅有操做方式沒並無任何數據。下一步,咱們往這個「空架子」中填入數據。咱們經過以下代碼往這個「空架子」中寫入數據:

static void Main(string[] args)
{
    HSSFWorkbook wb = new HSSFWorkbook(new FileStream(@"D:\MyProject\NPOIDemo\Chart\Book2.xls", FileMode.Open));

    HSSFSheet sheet1 = wb.GetSheet("Sheet1");

    HSSFRow row = sheet1.CreateRow(1);
    row.CreateCell(0).SetCellValue("令狐沖");
    row.CreateCell(1).SetCellValue(50000);

    row = sheet1.CreateRow(2);
    row.CreateCell(0).SetCellValue("任盈盈");
    row.CreateCell(1).SetCellValue(30000);

    row = sheet1.CreateRow(3);
    row.CreateCell(0).SetCellValue("風清揚");
    row.CreateCell(1).SetCellValue(80000);

    row = sheet1.CreateRow(4);
    row.CreateCell(0).SetCellValue("任我行");
    row.CreateCell(1).SetCellValue(20000);

    //Write the stream data of workbook to the root directory
    FileStream file = new FileStream(@"test.xls", FileMode.Create);
    wb.Write(file);
    file.Close();
}

打開生成的test.xls文件,發現數據已經被填進去了:

再看數據透視表,也有數據了:

 

總結:
Excel有着強大的報表透視和圖表功能,並且簡單易用,利用NPOI,能夠對其進行充分利用。在作圖形報表、透視報表時將很是有用!

 

NPOI實踐: .NET導入Excel文件的另外一種選擇

做者:Tony Qu

官方網站:http://npoi.codeplex.com | NPOI QQ交流羣:  78142590

 

NPOI之因此強大,並非由於它支持導出Excel,而是由於它支持導入Excel,並能「理解」OLE2文檔結構,這也是其餘一些Excel讀寫庫比較弱的方面。一般,讀入並理解結構遠比導出來得複雜,由於導入你必須假設一切狀況都是可能的,而生成你只要保證知足你本身需求就能夠了,若是把導入需求和生成需求比作兩個集合,那麼生成需求一般都是導入需求的子集,這一規律不只體如今Excel讀寫庫中,也體如今pdf讀寫庫中,目前市面上大部分的pdf庫僅支持生成,不支持導入。

若是你不相信NPOI可以很好的理解OLE2文檔格式,那就去下載POIFS Brower。具體能夠參考這篇文章的介紹:Office文件格式解惑。固然單單理解OLE2是不夠的,由於Excel文件格式是BIFF,但BIFF是以OLE2爲基礎的,作個很形象的比喻就是:OLE2至關於磁盤的FAT格式,BIFF至關於文件和文件夾。NPOI負責理解BIFF格式的代碼基本都在HSSF命名空間裏面。

好了,剛纔廢話了一下子,主要是給你們打打基礎,如今進入正題。

 

本文將以DataTable爲容器讀入某xls的第一個工做表的數據(最近羣裏面不少人問這個問題)。

在開始以前,咱們先來補些基礎知識。每個xls都對應一個惟一的HSSFWorkbook,每個HSSFWorkbook會有若干個HSSFSheet,而每個HSSFSheet包含若干HSSFRow(Excel 2003中不得超過65535行),每個HSSFRow又包含若干個HSSFCell(Excel 2003中不得超過256列)。

爲了遍歷全部的單元格,咱們就得得到某一個HSSFSheet的全部HSSFRow,一般能夠用HSSFSheet.GetRowEnumerator()。若是要得到某一特定行,能夠直接用HSSFSheet.GetRow(rowIndex)。另外要遍歷咱們就必須知道邊界,有一些屬性咱們是能夠用的,好比HSSFSheet.FirstRowNum(工做表中第一個有數據行的行號)、HSSFSheet.LastRowNum(工做表中最後一個有數據行的行號)、HSSFRow.FirstCellNum(一行中第一個有數據列的列號)、HSSFRow.LastCellNum(一行中最後一個有數據列的列號)。

基礎知識基本上補得差很少了,如今開工!

 

首先咱們要準備一個用於打開文件流的函數InitializeWorkbook,因爲文件讀完後就沒用了,因此這裏直接用using(養成好習慣,呵呵)。

HSSFWorkbookhssfworkbook;

void InitializeWorkbook(string path)
{
    //read the template via FileStream, it is suggested to use FileAccess.Readto prevent file lock.

    //book1.xlsis an Excel-2007-generated file, so some new unknown BIFF records are added.

    using (FileStream file =new FileStream(path, FileMode.Open,FileAccess.Read))
    {
        hssfworkbook = newHSSFWorkbook(file);
    }
}

接下來咱們要開始寫最重要的函數ConvertToDataTable,即把HSSF的數據放到一個DataTable中。

 

HSSFSheetsheet = hssfworkbook.GetSheetAt(0);
System.Collections.IEnumerator rows = sheet.GetRowEnumerator();

while(rows.MoveNext())
{
    HSSFRow row = (HSSFRow)rows.Current;
    //TODO::Create DataTable row

 

    for (int i = 0; i < row.LastCellNum; i++)
    {
        HSSFCell cell = row.GetCell(i);
        //TODO::set cell value to the cell of DataTables

    }

上面的結構你們都應該能看懂吧,無非就是先遍歷行,再遍歷行中的每一列。這裏引出了一個難點,因爲Excel的單元格有好幾種類型,類型不一樣顯示的東西就不一樣,具體的類型有布爾型、數值型、文本型、公式型、空白、錯誤。

publicenum HSSFCellType
{
    Unknown = -1,
    NUMERIC = 0,
    STRING = 1,
    FORMULA = 2,
    BLANK = 3,
    BOOLEAN = 4,
    ERROR = 5,
}

 

這裏的HSSFCellType描述了全部的類型,但細心的朋友可能已經發現了,這裏沒有日期型,這是爲何呢?這是由於Excel底層並無必定日期型,而是經過數值型來替代,至於如何區分日期和數字,都是由文本顯示的樣式決定的,在NPOI中則是由HSSFDataFormat來處理。爲了可以方便的得到所須要的類型所對應的文本,咱們可使用HSSFCell.ToString()來處理。

因而剛纔的代碼則變成了這樣:

HSSFSheetsheet = hssfworkbook.GetSheetAt(0);
System.Collections.IEnumerator rows = sheet.GetRowEnumerator();

DataTable dt = new DataTable();
for (int j = 0; j < 5;j++)
{
    dt.Columns.Add(Convert.ToChar(((int)'A')+j).ToString());
}

while(rows.MoveNext())
{
    HSSFRow row = (HSSFRow)rows.Current;
    DataRow dr = dt.NewRow();

    for (int i = 0; i < row.LastCellNum; i++)
    {
        HSSFCell cell = row.GetCell(i);

        if (cell == null)
        {
            dr[i] = null;
        }
        else

        {

            dr[i] = cell.ToString();

        }

    }

    dt.Rows.Add(dr);

}

是否是很簡單,呵呵!

固然,若是你要對某個特定的單元格類型作特殊處理,能夠經過判HSSFCell.CellType來解決,好比下面的代碼:

        switch(cell.CellType)
        {
            case HSSFCellType.BLANK:
                dr[i] = "[null]";
                break;
            case HSSFCellType.BOOLEAN:
                dr[i] =cell.BooleanCellValue;
                break;
            case HSSFCellType.NUMERIC:
                dr[i] =cell.ToString();    //This is a trick to get the correct value of the cell.NumericCellValue will return a numeric value no matter the cell value is a dateor a number.

               break;
            case HSSFCellType.STRING:
                dr[i] =cell.StringCellValue;
                break;
            case HSSFCellType.ERROR:
                dr[i] = cell.ErrorCellValue;
                break;
            case HSSFCellType.FORMULA:
            default:
                dr[i] = "="+cell.CellFormula;
                break;
        }

這裏只是舉個簡單的例子。

 

完整代碼下載:http://files.cnblogs.com/tonyqus/ImportXlsToDataTable.zip

注意,此代碼中不包括NPOI的assembly,不然文件會很大,因此建議去npoi.codeplex.com下載。

相關文章
相關標籤/搜索