轉(zhuǎn)自鏈接
2.3.6 CountIf和SumIf函數(shù)
2.3.9通過NPOI獲得公式的返回值
2.4創(chuàng)建圖形
2.4.4畫Grid
2.6
高級(jí)功能
2.6.5顯示/隱藏網(wǎng)格線
2.3.5用NPOI操作EXCEL--If函數(shù)
在Excel中,IF(logical_test,value_if_true,value_if_false)用來用作邏輯判斷。其中Logical_test表示計(jì)算結(jié)果為TRUE或FALSE的任意值或表達(dá)式; value_if_true表示當(dāng)表達(dá)式Logical_test的值為TRUE時(shí)的返回值;value_if_false表示當(dāng)表達(dá)式Logical_test的值為FALSE時(shí)的返回值。同樣在NPOI中也可以利用這個(gè)表達(dá)式進(jìn)行各種邏輯運(yùn)算。如下代碼分別設(shè)置了B2和D2單元格的用于邏輯判斷的公式。
HSSFSheet?sheet1?=?hssfworkbook.CreateSheet("Sheet1");
HSSFRow?row1?=?sheet1.CreateRow(
0);
row1.CreateCell(
0).SetCellValue("姓名");
row1.CreateCell(
1).SetCellValue("身份證號(hào)");
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,\"男\(zhòng)",\"女\")");
row2.CreateCell(
3).SetCellValue(85);
row2.CreateCell(
4).SetCellFormula("IF(D2>60,IF(D2>90,\"優(yōu)秀\",\"合格\"),\"不合格\")");
其中最關(guān)鍵的兩句執(zhí)行結(jié)果如下:
row2.CreateCell(2).SetCellFormula("IF(MOD(MID(B2,18,1),2)=0,\"男\(zhòng)",\"女\")");
row2.CreateCell(4).SetCellFormula("IF(D2>60,IF(D2>90,\"優(yōu)秀\",\"合格\"),\"不合格\")");
下面分別對(duì)這幾個(gè)函數(shù)作一些說明:
MOD(MID(B2,18,1),2)
:我們知道18位身份證號(hào)的第18位表示性別,偶數(shù)為男性,奇數(shù)為女性,所以用了MID(B2,18,1)取第18位數(shù)字(與C#中一般從0計(jì)數(shù)不同,第二個(gè)參數(shù)是從1算起,有關(guān)MID函數(shù)的更多信息,請(qǐng)參見字符串函數(shù)),用MOD取余函數(shù)判斷奇偶。在Excel中對(duì)數(shù)據(jù)類型的控制沒有C#中那么嚴(yán)格,如此例中我截取出來的是字符串,但當(dāng)我做取余運(yùn)算時(shí)Excel會(huì)自動(dòng)轉(zhuǎn)換。
IF(D2>60,IF(D2>90,"
優(yōu)秀","合格"),"不合格"):這是IF的嵌套使用,表示90分以上為優(yōu)秀,60分以上為合格,否則為不合格。
2.3.6用NPOI操作EXCEL--COUNTIF和SUMIF函數(shù)
一、COUNTIF這一節(jié),我們一起來學(xué)習(xí)Excel中另一個(gè)常用的函數(shù)--COUNTIF函數(shù),看函數(shù)名就知道這是一個(gè)用來在做滿足某條件的計(jì)數(shù)的函數(shù)。先來看一看它的語法:COUNTIF(range,criteria),參數(shù)說明如下:
Range需要進(jìn)行讀數(shù)的計(jì)數(shù)
Criteria條件表達(dá)式,只有當(dāng)滿足此條件時(shí)才進(jìn)行計(jì)數(shù)
接下來看一個(gè)例子,代碼如下:
HSSFSheet?sheet1?=?hssfworkbook.CreateSheet("Sheet1");
HSSFRow?row1?=?sheet1.CreateRow(
0);
row1.CreateCell(
0).SetCellValue("姓名");
row1.CreateCell(
1).SetCellValue("成績(jī)");
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("合格人數(shù):");
row7.CreateCell(
1).SetCellFormula("COUNTIF(B2:B6,\">60\")");
執(zhí)行結(jié)果如下:
我們可以看到,CountIf函數(shù)成功的統(tǒng)計(jì)出了區(qū)域“B2:B6”中成績(jī)合格的人數(shù)(這里定義成績(jī)大于60為合格)。
二、SUMIF
接下來,順便談?wù)劻硪粋€(gè)與CountIF類似的函數(shù)—SumIf函數(shù)。此函數(shù)用于統(tǒng)計(jì)某區(qū)域內(nèi)滿足某條件的值的求和(CountIf是計(jì)數(shù))。與CountIF不同,SumIF有三個(gè)參數(shù),語法為SumIF(criteria_range, criteria,sum_range),各參數(shù)的說明如下:
criteria_range條件測(cè)試區(qū)域,第二個(gè)參數(shù)Criteria中的條件將與此區(qū)域中的值進(jìn)行比較
criteria條件測(cè)試值,滿足條件的對(duì)應(yīng)的sum_range項(xiàng)將進(jìn)行求和計(jì)算
sum_range匯總數(shù)據(jù)所在區(qū)域,求和時(shí)會(huì)排除掉不滿足Criteria條件的對(duì)應(yīng)的項(xiàng)
我們還是以例子來加以說明:
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)");
執(zhí)行結(jié)果如下:
如上圖,SUMIF統(tǒng)計(jì)出了不同人一季度的銷售額。
2.3.7用NPOI操作EXCEL--LOOKUP函數(shù)
今天,我們一起學(xué)習(xí)Excel中的查詢函數(shù)--LOOKUP。其基本語法形式為L(zhǎng)OOKUP(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)");
這是一個(gè)根據(jù)工資查詢相應(yīng)稅率的例子。我們首先創(chuàng)建了不同工資區(qū)間對(duì)應(yīng)稅率的字典,然后根據(jù)具體的工資在字典中找出對(duì)應(yīng)的稅率。執(zhí)行后生成的Excel如下:
下面對(duì)各參數(shù)加以說明:第一個(gè)參數(shù):需要查找的內(nèi)容,本例中指向A9單元格,也就是7800;第二個(gè)參數(shù):比較對(duì)象區(qū)域,本例中的工資需要與$A$2:$A$6中的各單元格中的值進(jìn)行比較;第三個(gè)參數(shù):查找結(jié)果區(qū)域,如果匹配到會(huì)將此區(qū)域中對(duì)應(yīng)的數(shù)據(jù)返回。如本例中返回$C$2:$C$6中對(duì)應(yīng)的值??赡苡腥藭?huì)問,字典中沒有7800對(duì)應(yīng)的稅率啊,那么Excel中怎么匹配的呢?答案是模糊匹配,并且LOOKUP函數(shù)只支持模糊匹配。Excel會(huì)在$A$2:$A$6中找小于7800的最大值,也就是A3對(duì)應(yīng)的3001,然后將對(duì)應(yīng)的$C$2:$C$6區(qū)域中的C3中的值返回,這就是最終結(jié)果0.2的由來。這下明白了吧:)
VLOOKUP另外,LOOKUP函數(shù)還有一位大哥--VLOOKUP。兩兄弟有很多相似之處,但大哥本領(lǐng)更大。Vlookup用對(duì)比數(shù)與一個(gè)“表”進(jìn)行對(duì)比,而不是Lookup函數(shù)的某1列或1行,并且Vlookup可以選擇采用精確查詢或是模糊查詢方式,而Lookup只有模糊查詢。將上例中設(shè)置公式的代碼換成:
row9.CreateCell(1).SetCellFormula("VLOOKUP(A9,$A$2:$C$6,3,TRUE)");
執(zhí)行后生成的Excel樣式如下:
第一個(gè)參數(shù):需要查找的內(nèi)容,這里是A9單元格;第二個(gè)參數(shù):需要比較的表,這里是$A$2:$C$6,注意VLOOKUP匹配時(shí)只與表中的第一列進(jìn)行匹配。第三個(gè)參數(shù):匹配結(jié)果對(duì)應(yīng)的列序號(hào)。這里要對(duì)應(yīng)的是稅率列,所以為3。第四個(gè)參數(shù):指明是否模糊匹配。例子中的TRUE表示模糊匹配,與上例中一樣。匹配到的是第三行。如果將此參數(shù)改為FALSE,因?yàn)樵诒碇械牡?列中找不到7800,所以會(huì)報(bào)“#N/A”的計(jì)算錯(cuò)誤。
另外,還有與VLOKUP類似的HLOOKUP。不同的是VLOOKUP用于在表格或數(shù)值數(shù)組的首列查找指定的數(shù)值,并由此返回表格或數(shù)組當(dāng)前行中指定列處的數(shù)值。而HLOOKUP用于在表格或數(shù)值數(shù)組的首行查找指定的數(shù)值,并由此返回表格或數(shù)組當(dāng)前列中指定行處的數(shù)值。讀者可以自已去嘗試。
2.3.8用NPOI操作EXCEL--隨機(jī)數(shù)函數(shù)
我們知道,在大多數(shù)編程語言中都有隨機(jī)數(shù)函數(shù)。在Excel中,同樣存在著這樣一個(gè)函數(shù)—RAND()函數(shù),用于生成隨機(jī)數(shù)。先來看一個(gè)最簡(jiǎn)單的例子:
HSSFSheet?sheet1?=?hssfworkbook.CreateSheet("Sheet1");
sheet1.CreateRow(
0).CreateCell(0).SetCellFormula("RAND()");
RAND()函數(shù)將返回一個(gè)0-1之間的隨機(jī)數(shù),執(zhí)行后生成的Excel文件如下:
這只是最簡(jiǎn)單直接的RAND()函數(shù)的應(yīng)用,只要我們稍加修改,就可以作出很多種變換。如取0-100之前的隨機(jī)整數(shù),可設(shè)置公式為:
sheet1.CreateRow(0).CreateCell(0).SetCellFormula("int(RAND()*100)");
取10-20之間的隨機(jī)實(shí)數(shù),可設(shè)置公式為:
sheet1.CreateRow(0).CreateCell(0).SetCellFormula("rand()*(20-10)+10");
隨機(jī)小寫字母:
sheet1.CreateRow(0).CreateCell(0).SetCellFormula("CHAR(INT(RAND()*26)+97)");
隨機(jī)大寫字母:
sheet1.CreateRow(0).CreateCell(0).SetCellFormula("CHAR(INT(RAND()*26)+65)")
隨機(jī)大小寫字母:
sheet1.CreateRow(0).CreateCell(0).SetCellFormula("CHAR(INT(RAND()*26)+if(INT(RAND()*2)=0,65,97))");
上面幾例中除了用到RAND函數(shù)以外,還用到了CHAR函數(shù)用來將ASCII碼換為字母,INT函數(shù)用來取整。值得注意的是INT函數(shù)不會(huì)四舍五入,無論小數(shù)點(diǎn)后是多少都會(huì)被舍去。這里只是RAND函數(shù)的幾個(gè)簡(jiǎn)單應(yīng)用,還有很多隨機(jī)數(shù)的例子都可以根據(jù)這些,再結(jié)合不同的其它函數(shù)引申出來。
2.3.9用NPOI操作EXCEL--通過NPOI獲得公式的返回值
前面我們學(xué)習(xí)了通過NPOI向Excel中設(shè)置公式,那么有些讀者可能會(huì)問:“NPOI能不能獲取公式的返回值呢?”,答案是可以!一、獲取模板文件中公式的返回值如在D盤中有一個(gè)名為text.xls的Excel文件,其內(nèi)容如下:
注意C1單元格中設(shè)置的是公式“$A1*$B1”,而不是值“12”。利用NPOI,只需要寫簡(jiǎn)單的幾句代碼就可以取得此公式的返回值:
HSSFWorkbook?wb?=newHSSFWorkbook(newFileStream("d:/test.xls",FileMode.Open));
HSSFCell?cell?=?wb.GetSheet(
"Sheet1").GetRow(0).GetCell(2);
System.Console.WriteLine(cell.NumericCellValue);
輸出結(jié)果為:
可見NPOI成功的“解析”了此.xls文件中的公式。注意NumericCellValue屬性會(huì)自動(dòng)根據(jù)單元格的類型處理,如果為空將返0,如果為數(shù)值將返回?cái)?shù)值,如果為公式將返回公式計(jì)算后的結(jié)果。單元格的類型可以通過CellType屬性獲取。
二、獲取NPOI生成的Excel文件中公式的返回值上例中是從一個(gè)已經(jīng)存在的Excel文件中獲取公式的返回值,那么如果Excel文件是通過NPOI創(chuàng)建的,直接用上面的方法獲取,可能得不到想要的結(jié)果。如:
1HSSFWorkbook?hssfworkbook?=newHSSFWorkbook();
2HSSFSheet?sheet1?=?hssfworkbook.CreateSheet("Sheet1");
3HSSFRow?row?=?sheet1.CreateRow(0);
4row.CreateCell(0).SetCellValue(3);
5row.CreateCell(1).SetCellValue(4);
6HSSFCell?cell?=?row.CreateCell(2);
78cell.SetCellFormula("$A1+$B1");
9System.Console.WriteLine(cell.NumericCellValue);
執(zhí)行上面代碼,將輸出結(jié)果“0”,而不是我們想要的結(jié)果“7”。那么將如何解決呢?這時(shí)要用到HSSFFormulaEvaluator類。在第8行后加上這兩句就可以了:
HSSFFormulaEvaluator?e?=newHSSFFormulaEvaluator(hssfworkbook);
cell?=?e.EvaluateInCell(cell);
運(yùn)行結(jié)果如下:
2.4.1用NPOI操作EXCEL--畫線
之所有說NPOI強(qiáng)大,是因?yàn)槌S玫腅xcel操作她都可以通過編程的方式完成。這節(jié)開始,我們開始學(xué)習(xí)NPOI的畫圖功能。先從最簡(jiǎn)單的開始,畫一條直線:
對(duì)應(yīng)的代碼為:
HSSFSheet?sheet1?=?hssfworkbook.CreateSheet("Sheet1");
HSSFPatriarch?patriarch?=?sheet1.CreateDrawingPatriarch();
HSSFClientAnchor?a1?=
newHSSFClientAnchor(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畫圖主要有以下幾個(gè)步驟:
1.
創(chuàng)建一個(gè)Patriarch;
2.
創(chuàng)建一個(gè)Anchor,以確定圖形的位置;
3.
調(diào)用Patriarch創(chuàng)建圖形;
4.
設(shè)置圖形類型(直線,矩形,圓形等)及樣式(顏色,粗細(xì)等)。
關(guān)于HSSFClientAnchor(dx1,dy1,dx2,dy2,col1,row1,col2,row2)的參數(shù),有必要在這里說明一下:
dx1
:起始單元格的x偏移量,如例子中的255表示直線起始位置距A1單元格左側(cè)的距離;
dy1
:起始單元格的y偏移量,如例子中的125表示直線起始位置距A1單元格上側(cè)的距離;
dx2
:終止單元格的x偏移量,如例子中的1023表示直線起始位置距C3單元格左側(cè)的距離;
dy2
:終止單元格的y偏移量,如例子中的150表示直線起始位置距C3單元格上側(cè)的距離;
col1
:起始單元格列序號(hào),從0開始計(jì)算;
row1
:起始單元格行序號(hào),從0開始計(jì)算,如例子中col1=0,row1=0就表示起始單元格為A1;
col2
:終止單元格列序號(hào),從0開始計(jì)算;
row2
:終止單元格行序號(hào),從0開始計(jì)算,如例子中col2=2,row2=2就表示起始單元格為C3;
最后,關(guān)于LineStyle屬性,有如下一些可選值,對(duì)應(yīng)的效果分別如圖所示:
2.4.2用NPOI操作EXCEL--畫矩形
上一節(jié)我們講了NPOI中畫圖的基本步驟:
1.
創(chuàng)建一個(gè)Patriarch;
2.
創(chuàng)建一個(gè)Anchor,以確定圖形的位置;
3.
調(diào)用Patriarch創(chuàng)建圖形;
4.
設(shè)置圖形類型(直線,矩形,圓形等)及樣式(顏色,粗細(xì)等)。
這一節(jié)我們將按照這個(gè)步驟創(chuàng)建一個(gè)矩形。廢話少說,上代碼:
HSSFSheet?sheet1?=?hssfworkbook.CreateSheet("Sheet1");
HSSFPatriarch?patriarch?=?sheet1.CreateDrawingPatriarch();
HSSFClientAnchor?a1?=
newHSSFClientAnchor(255,125,1023,150,0,0,2,2);
HSSFSimpleShape?rec1?=?patriarch.CreateSimpleShape(a1);
//此處設(shè)置圖形類型為矩形rec1.ShapeType?=?HSSFSimpleShape.OBJECT_TYPE_RECTANGLE;
//設(shè)置填充色rec1.SetFillColor(125,125,125);
//設(shè)置邊框樣式rec1.LineStyle?=?HSSFShape.LINESTYLE_DASHGEL;
//設(shè)置邊框?qū)挾萺ec1.LineWidth?=25400;
//設(shè)置邊框顏色rec1.SetLineStyleColor(100,0,100);
代碼執(zhí)行效果:
其中SetFillColor和SetLineStyleColor函數(shù)的三個(gè)參數(shù)分別是RGB三色值,具體表示什么顏色,找個(gè)Photoshop試試:)關(guān)于HSSFClientAnchor參數(shù)說明、邊框樣式,邊框?qū)挾鹊恼f明可以參見前一篇博文:
http://www.cnblogs.com/atao/archive/2009/09/13/1565645.html
2.4.3用NPOI操作EXCEL--畫圓形
前面我們學(xué)習(xí)了NPOI中的畫簡(jiǎn)單直線和矩形的功能,今天我們一起學(xué)習(xí)一下它支持的另一種簡(jiǎn)單圖形--圓形。同樣,按照前面所講的繪圖“四步曲”:
1.
創(chuàng)建一個(gè)Patriarch;
2.
創(chuàng)建一個(gè)Anchor,以確定圖形的位置;
3.
調(diào)用Patriarch創(chuàng)建圖形;
4.
設(shè)置圖形類型(直線,矩形,圓形等)及樣式(顏色,粗細(xì)等)。還是以例子加以說明:
HSSFSheet?sheet1?=?hssfworkbook.CreateSheet("Sheet1");
HSSFPatriarch?patriarch?=?sheet1.CreateDrawingPatriarch();
HSSFClientAnchor?a1?=
newHSSFClientAnchor(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;表示圖形為橢圓。適當(dāng)調(diào)整HSSFClientAnchor的各參數(shù)可以得到圓形。關(guān)于HSSFClientAnchor構(gòu)造函數(shù)和邊框、填充色等前兩節(jié)都有介紹,這里不再重述。詳情情見:畫矩形和畫線。
上面代碼執(zhí)行生成的Excel如下:
2.4.4用NPOI操作EXCEL--畫Grid
在NPOI中,本身沒有畫Grid的方法。但我們知道Grid其實(shí)就是由橫線和豎線構(gòu)成的,所在我們可以通過畫線的方式來模擬畫Grid。
HSSFSheet?sheet1?=?hssfworkbook.CreateSheet("Sheet1");
HSSFRow?row?=?sheet1.CreateRow(
2);
row.CreateCell(
1);
row.HeightInPoints?=
240;
sheet1.SetColumnWidth(
2,9000);
intlinesCount?=20;
HSSFPatriarch?patriarch?=?sheet1.CreateDrawingPatriarch();
//因?yàn)镠SSFClientAnchor中dx只能在0-1023之間,dy只能在0-255之間,所以這里采用比例的方式doublexRatio?=1023.0/?(linesCount*10);
doubleyRatio?=255.0/?(linesCount*10);
//畫豎線intx1?=0;
inty1?=0;
intx2?=0;
inty2?=200;
for(inti?=0;?i?<?linesCount;?i++)
{
HSSFClientAnchor?a2?=
newHSSFClientAnchor();
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(inti?=0;?i?<?linesCount;?i++)
{
HSSFClientAnchor?a2?=
newHSSFClientAnchor();
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;
}
請(qǐng)注意HSSFClientAnchor對(duì)象中的dx只能取0-1023之間的數(shù),dy只能取0-255之間的數(shù)。我們可以理解為是將單元格的寬和高平分成了1023和255份,設(shè)置dx和dy時(shí)相當(dāng)于按比例取對(duì)應(yīng)的座標(biāo)。最終生成的Excel如下:
2.4.5用NPOI操作EXCEL--插入圖片
我們知道,在Excel中是可以插入圖片的。操作菜單是“插入->圖片”,然后選擇要插入圖片,可以很容易地在Excel插入圖片。同樣,在NPOI中,利用代碼也可以實(shí)現(xiàn)同樣的效果。在NPOI中插入圖片的方法與畫圖的方法有點(diǎn)類似:
//add?picture?data?to?this?workbook.
byte[]?bytes?=?System.IO.File.ReadAllBytes(@"D:\MyProject\NPOIDemo\ShapeImage\image1.jpg");
intpictureIdx?=?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?=newHSSFClientAnchor(0,0,1023,0,0,0,1,3);
HSSFPicture?pict?=?patriarch.CreatePicture(anchor,?pictureIdx);
與畫簡(jiǎn)單圖形不同的是,首先要將圖片讀入到byte數(shù)組,然后添加到workbook中;最后調(diào)用的是patriarch.CreatePicture(anchor, pictureIdx)方法顯示圖片,而不是patriarch.CreateSimpleShape(anchor)方法。上面這段代碼執(zhí)行后生成的Excel文件樣式如下:
我們發(fā)現(xiàn),插入的圖片被拉伸填充在HSSFClientAnchor指定的區(qū)域。有時(shí)可能我們并不需要拉伸的效果,怎么辦呢?很簡(jiǎn)單,在最后加上這樣一句用來自動(dòng)調(diào)節(jié)圖片大小:
pict.Resize();
添加代碼后再執(zhí)行上述代碼,生成的Excel樣式如下:
圖片已經(jīng)自動(dòng)伸縮到原始大小了。
NPOI 1.2教程- 2.5打印相關(guān)設(shè)置
作者:Tony Qu
NPOI官方網(wǎng)站:http://npoi.codeplex.com/
打印設(shè)置主要包括方向設(shè)置、縮放、紙張?jiān)O(shè)置、頁邊距等。NPOI 1.2支持大部分打印屬性,能夠讓你輕松滿足客戶的打印需要。
首先是方向設(shè)置,Excel支持兩種頁面方向,即縱向和橫向。
在NPOI中如何設(shè)置呢?你可以通過HSSFSheet.PrintSetup.Landscape來設(shè)置,Landscape是布爾類型的,在英語中是橫向的意思。如果Landscape等于true,則表示頁面方向?yàn)闄M向;否則為縱向。
接著是縮放設(shè)置,
這里的縮放比例對(duì)應(yīng)于HSSFSheet.PrintSetup.Scale,而頁寬和頁高分別對(duì)應(yīng)于HSSFSheet.PrintSetup.FitWidth和HSSFSheet.PrintSetup.FitHeight。要注意的是,這里的PrintSetup.Scale應(yīng)該被設(shè)置為0-100之間的值,而不是小數(shù)。
接下來就是紙張?jiān)O(shè)置了,對(duì)應(yīng)于HSSFSheet.PrintSetup.PaperSize,但這里的PaperSize并不是隨便設(shè)置的,而是由一些固定的值決定的,具體的值與對(duì)應(yīng)的紙張如下表所示:
值紙張
1US Letter 8 1/2 x 11 in
2USLetter Small 8 1/2 x 11 in
3US Tabloid 11 x 17 in
4US Ledger 17 x 11 in
5US Legal 8 1/2 x 14 in
6US Statement 5 1/2 x 8 1/2 in
7US Executive 7 1/4 x 10 1/2 in
8A3 297 x 420 mm
9A4 210 x 297 mm
10A4 Small 210 x 297 mm
11A5 148 x 210 mm
12B4 (JIS) 250 x 354
13B5 (JIS) 182 x 257 mm
14Folio 8 1/2 x 13 in
15Quarto 215 x 275 mm
1610 x 14 in
1711 x 17 in
18US Note 8 1/2 x 11 in
19US Envelope #9 3 7/8 x 8 7/8
20US Envelope #10 4 1/8 x 9 1/2
21US Envelope #11 4 1/2 x 10 3/8
22US Envelope #12 4 \276 x 11
23US Envelope #14 5 x 11 1/2
24C size sheet
25D size sheet
26E size sheet
27Envelope DL 110 x 220mm
28Envelope C5 162 x 229 mm
29Envelope C3 324 x 458 mm
30Envelope C4 229 x 324 mm
31Envelope C6 114 x 162 mm
32Envelope C65 114 x 229 mm
33Envelope B4 250 x 353 mm
34Envelope B5 176 x 250 mm
35Envelope B6 176 x 125 mm
36Envelope 110 x 230 mm
37US Envelope Monarch 3.875 x 7.5 in
386 3/4 US Envelope 3 5/8 x 6 1/2 in
39US Std Fanfold 14 7/8 x 11 in
40German Std Fanfold 8 1/2 x 12 in
41German Legal Fanfold 8 1/2 x 13 in
42B4 (ISO) 250 x 353 mm
43Japanese Postcard 100 x 148 mm
449 x 11 in
4510 x 11 in
4615 x 11 in
47Envelope Invite 220 x 220 mm
48RESERVED--DO NOT USE
49RESERVED--DO NOT USE
50US Letter Extra 9 \275 x 12 in
51US Legal Extra 9 \275 x 15 in
52US Tabloid Extra 11.69 x 18 in
53A4 Extra 9.27 x 12.69 in
54Letter Transverse 8 \275 x 11 in
55A4 Transverse 210 x 297 mm
56Letter Extra Transverse 9\275 x 12 in
57SuperA/SuperA/A4 227 x 356 mm
58SuperB/SuperB/A3 305 x 487 mm
59US Letter Plus 8.5 x 12.69 in
60A4 Plus 210 x 330 mm
61A5 Transverse 148 x 210 mm
62B5 (JIS) Transverse 182 x 257 mm
63A3 Extra 322 x 445 mm
64A5 Extra 174 x 235 mm
65B5 (ISO) Extra 201 x 276 mm
66A2 420 x 594 mm
67A3 Transverse 297 x 420 mm
68A3 Extra Transverse 322 x 445 mm
69Japanese Double Postcard 200 x 148 mm
70A6 105 x 148 mm
71Japanese Envelope Kaku #2
72Japanese Envelope Kaku #3
73Japanese Envelope Chou #3
74Japanese Envelope Chou #4
75Letter Rotated 11 x 8 1/2 11 in
76A3 Rotated 420 x 297 mm
77A4 Rotated 297 x 210 mm
78A5 Rotated 210 x 148 mm
79B4 (JIS) Rotated 364 x 257 mm
80B5 (JIS) Rotated 257 x 182 mm
81Japanese Postcard Rotated 148 x 100 mm
82Double Japanese Postcard Rotated 148 x 200 mm
83A6 Rotated 148 x 105 mm
84Japanese Envelope Kaku #2 Rotated
85Japanese Envelope Kaku #3 Rotated
86Japanese Envelope Chou #3 Rotated
87Japanese Envelope Chou #4 Rotated
88B6 (JIS) 128 x 182 mm
89B6 (JIS) Rotated 182 x 128 mm
9012 x 11 in
91Japanese Envelope You #4
92Japanese Envelope You #4 Rotated
93PRC 16K 146 x 215 mm
94PRC 32K 97 x 151 mm
95PRC 32K(Big) 97 x 151 mm
96PRC Envelope #1 102 x 165 mm
97PRC Envelope #2 102 x 176 mm
98PRC Envelope #3 125 x 176 mm
99PRC Envelope #4 110 x 208 mm
100PRC Envelope #5 110 x 220 mm
101PRC Envelope #6 120 x 230 mm
102PRC Envelope #7 160 x 230 mm
103PRC Envelope #8 120 x 309 mm
104PRC Envelope #9 229 x 324 mm
105PRC Envelope #10 324 x 458 mm
106PRC 16K Rotated
107PRC 32K Rotated
108PRC 32K(Big) Rotated
109PRC Envelope #1 Rotated 165 x 102 mm
110PRC Envelope #2 Rotated 176 x 102 mm
111PRC Envelope #3 Rotated 176 x 125 mm
112PRC Envelope #4 Rotated 208 x 110 mm
113PRC Envelope #5 Rotated 220 x 110 mm
114PRC Envelope #6 Rotated 230 x 120 mm
115PRC Envelope #7 Rotated 230 x 160 mm
116PRC Envelope #8 Rotated 309 x 120 mm
117PRC Envelope #9 Rotated 324 x 229 mm
118PRC Envelope #10 Rotated 458 x 324 mm
(此表摘自《Excel Binary File Format (.xls) Structure Specification.pdf》)
HSSFSheet下面定義了一些xxxx_PAPERSIZE的常量,但都是非常常用的紙張大小,如果滿足不了你的需要,可以根據(jù)上表自己給PaperSize屬性賦值。所以,如果你要設(shè)置紙張大小可以用這樣的代碼:
HSSFSheet.PrintSetup.PaperSize=HSSFSheet.A4_PAPERSIZE;
或
HSSFSheet.PrintSetup.PaperSize=9;(A4 210*297mm)
再下來就是打印的起始頁碼,它對(duì)應(yīng)于HSSFSheet.PrintSetup.PageStart和HSSFSheet.PrintSetup.UsePage,如果UsePage=false,那么就相當(dāng)于“自動(dòng)”,這時(shí)PageStart不起作用;如果UsePage=true,PageStart才會(huì)起作用。所以在設(shè)置PageStart之前,必須先把UsePage設(shè)置為true。
“打印”欄中的“網(wǎng)格線”設(shè)置對(duì)應(yīng)于HSSFSheet.IsPrintGridlines,請(qǐng)注意,這里不是HSSFSheet.PrintSetup下面,所以別搞混了。這里之所以不隸屬于PrintSetup是由底層存儲(chǔ)該信息的record決定的,底層是把IsGridsPrinted放在GridsetRecord里面的,而不是PrintSetupRecord里面的,盡管界面上是放在一起的。另外還有一個(gè)HSSFSheet.IsGridsPrinted屬性,這個(gè)屬性對(duì)應(yīng)于底層的gridset Record,但這個(gè)record是保留的,從微軟的文檔顯示沒有任何意義,所以這個(gè)屬性請(qǐng)不要去設(shè)置。
“單色打印”則對(duì)應(yīng)于HSSFSheet.PrintSetup.NoColors,這是布爾類型的,值為true時(shí),表示單色打印。
“草稿品質(zhì)”對(duì)應(yīng)于HSSFSheet.PrintSetup.IsDraft,也是布爾類型的,值為true時(shí),表示用草稿品質(zhì)打印。
這里的打印順序是由HSSFSheet.PrintSetup.LeftToRight決定的,它是布爾類型的,當(dāng)為true時(shí),則表示“先行后列”;如果是false,則表示“先列后行”。
在NPOI 1.2中,“行號(hào)列標(biāo)”、“批注”和“錯(cuò)誤單元格打印為”、“頁邊距”暫不支持,將在以后的版本中支持。
有關(guān)打印的范例可以參考NPOI 1.2正式版中的SetPrintSettingsInXls項(xiàng)目。
2.6.1用NPOI操作EXCEL--調(diào)整表單顯示比例
在Excel中,可以通過調(diào)整右下角的滾動(dòng)條來調(diào)整Sheet的顯示比例。如圖:
在NPOI中,也能通過代碼實(shí)現(xiàn)這樣的功能,并且代碼非常簡(jiǎn)單:
HSSFSheet?sheet1?=?hssfworkbook.CreateSheet("Sheet1");
sheet1.CreateRow(
0).CreateCell(0).SetCellValue("This?is?a?test.");
//50%?zoom
sheet1.SetZoom(1,2);
我們發(fā)現(xiàn),SetZoom有兩個(gè)參數(shù)。其中第一個(gè)參數(shù)表示縮放比例的分子,第二個(gè)參數(shù)表示縮放比例的分母,所以SetZoom(1,2)就表示縮小到1/2,也就是50%。代碼執(zhí)行后生成的Excel樣式如下:
如果將SetZoom的參數(shù)改成(2,1),代碼執(zhí)行后生成的Excel樣式如下,表示擴(kuò)大兩倍:
2.6.2用NPOI操作EXCEL--設(shè)置密碼
有時(shí),我們可能需要某些單元格只讀,如在做模板時(shí),模板中的數(shù)據(jù)是不能隨意讓別人改的。在Excel中,可以通過“審閱->保護(hù)工作表”來完成,如下圖:
那么,在NPOI中有沒有辦法通過編碼的方式達(dá)到這一效果呢?答案是肯定的。
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");
正如代碼中所看到的,我們通過設(shè)置CellStype的ISLocked為True,表示此單元格將被鎖定。相當(dāng)于在Excel中執(zhí)行了如下操作:
然后通過ProtectSheet設(shè)置密碼。
執(zhí)行結(jié)果如下:
沒被鎖定的列可以任意修改。
被鎖定的列不能修改。
輸入密碼可以解除鎖定。
NPOI 1.2教程-組合行、列
作者:Tony Qu
NPOI官方網(wǎng)站:http://npoi.codeplex.com/
Excel 2007中有一個(gè)面板是專門用于設(shè)置組合功能的,叫做“分級(jí)顯示”面板,如下所示:
可能我們?cè)谶^去生成Excel文件的時(shí)候根本不會(huì)用這個(gè)功能,也沒辦法用,因?yàn)閏vs法和html法沒辦法控制這些東西。這里簡(jiǎn)單的介紹一下什么叫做組合:
組合分為行組合和列組合,所謂行組合,就是讓n行組合成一個(gè)集合,能夠進(jìn)行展開和合攏操作,在Excel中顯示如下:
圖中左側(cè)就是用于控制行組合折疊的圖標(biāo),圖中上部就是用于控制列組合的,是不是有點(diǎn)像TreeView中的折疊節(jié)點(diǎn)?很多時(shí)候由于數(shù)據(jù)太多,為了讓用戶對(duì)于大量數(shù)據(jù)一目了然,我們可以使用行列組合來解決顯示大綱,這和Visual Studio里面的region的概念是類似的。
細(xì)心的朋友可能已經(jīng)注意到了,我們其實(shí)可以對(duì)一行做多次組合操作,這就是分級(jí)顯示的概念,圖中就把行2-3分為2個(gè)組合,第2行到第4行為一個(gè)組合,第2行到第5行一個(gè)組合,所以是分兩級(jí)。
在NPOI中,要實(shí)現(xiàn)分組其實(shí)并不難,你只需要調(diào)用HSSFSheet.GroupRow和HSSFSheet.GroupColumn這兩個(gè)方法就可以了。
首先我們來看HSSFSheet.GroupRow,GroupRow有2個(gè)參數(shù),分別是fromRow和toRow,表示起始行號(hào)和結(jié)束行號(hào),這些行號(hào)都是從0開始算起的。
HSSFWorkbookhssfworkbook =newHSSFWorkbook();
HSSFSheet s =hssfworkbook.CreateSheet("Sheet1");
s.GroupRow(1,3);
上面的代碼把第2行到第4行做了組合。
要組合列,其實(shí)代碼很相似,如下所示:
s.GroupColumn(1,3)
上面的代碼把B至D列做了組合。
正如上圖中Excel的“分級(jí)顯示”面板所示,有“組合”,也一定有“取消組合”,NPOI中你可以用HSSFSheet.UngroupRow和HSSFSheet.UngroupColumn,參數(shù)和GroupXXX是一樣的,如果要取消第2到第4行的組合,就可以用下面的代碼:
s.UngroupColumn(1,3)
相關(guān)范例請(qǐng)見NPOI 1.2正式版中的GroupRowAndColumnInXls項(xiàng)目。
2.6.4用NPOI操作EXCEL--鎖定列
在Excel中,有時(shí)可能會(huì)出現(xiàn)列數(shù)太多或是行數(shù)太多的情況,這時(shí)可以通過鎖定列來凍結(jié)部分列,不隨滾動(dòng)條滑動(dòng),方便查看。在Excel中設(shè)置凍結(jié)列的方法如下:
同樣,利用NPOI,通過代碼也能實(shí)現(xiàn)上面的效果:
HSSFSheet?sheet1?=?hssfworkbook.CreateSheet("Sheet1");
HSSFRow?row1?=?sheet1.CreateRow(
0);
row1.CreateCell(
0).SetCellValue("凍結(jié)列");
sheet1.CreateFreezePane(
1,0,1,0);
代碼執(zhí)行結(jié)果如下:
下面對(duì)CreateFreezePane的參數(shù)作一下說明:第一個(gè)參數(shù)表示要凍結(jié)的列數(shù);第二個(gè)參數(shù)表示要凍結(jié)的行數(shù),這里只凍結(jié)列所以為0;第三個(gè)參數(shù)表示右邊區(qū)域可見的首列序號(hào),從1開始計(jì)算;第四個(gè)參數(shù)表示下邊區(qū)域可見的首行序號(hào),也是從1開始計(jì)算,這里是凍結(jié)列,所以為0;
舉例說明也許更好理解,將各參數(shù)設(shè)置為如下:
sheet1.CreateFreezePane(2,0,5,0);
得到的效果如下圖:
注意圖中C、D和E列默認(rèn)是看不到的,滾動(dòng)才看得到,這就是第三個(gè)參數(shù)5起了作用,是不是很好理解了呢:)
接下來,看一下凍結(jié)行的效果。將上面的代碼稍作修改:
HSSFSheet?sheet1?=?hssfworkbook.CreateSheet("Sheet1");
HSSFRow?row1?=?sheet1.CreateRow(
0);
row1.CreateCell(
0).SetCellValue("凍結(jié)行");
sheet1.CreateFreezePane(
0,1,0,1);
執(zhí)行后生成的Excel文件效果見下圖:
那么,如果要行和列同時(shí)凍結(jié)該怎么做呢?聰明的你一定能想得到,呵呵~~
NPOI 1.2教程-顯示/隱藏Excel網(wǎng)格線
作者:Tony Qu
NPOI官方網(wǎng)站:http://npoi.codeplex.com/
有些時(shí)候,我們需要網(wǎng)格線,而有些時(shí)候我們不需要,這取決于實(shí)際的業(yè)務(wù)需求。前兩天inmegin兄就問我,怎么把網(wǎng)格給去掉,因?yàn)樗麄円袳xcel文檔當(dāng)Word使,也許是因?yàn)镋xcel排版方便吧。
Excel中的網(wǎng)格線設(shè)置是以表(Sheet)為單位進(jìn)行管理的,這也就意味著你可以讓一個(gè)表顯示網(wǎng)格線,而另一個(gè)表不顯示,這是不沖突的。
在Excel 2007中,我們通常用“工作表選項(xiàng)”面板來設(shè)置這個(gè)屬性:
在面板中,你會(huì)發(fā)現(xiàn)有2個(gè)多選框,一個(gè)是查看,一個(gè)是打印,也就是說Excel是把查看和打印網(wǎng)格線作為兩個(gè)設(shè)置來處理的,存儲(chǔ)的Record也是不同的。
在NPOI中,如果要讓網(wǎng)格線在查看時(shí)顯示/隱藏,你可以HSSFSheet.DisplayGridlines屬性,默認(rèn)值為true(這也是為什么默認(rèn)情況下我們能夠看到網(wǎng)格線)。下面的代碼就是讓網(wǎng)格線在查看時(shí)不可見的:
HSSFWorkbookhssfworkbook =newHSSFWorkbook();
HSSFSheet s1= hssfworkbook.CreateSheet("Sheet1");
s1.DisplayGridlines=false;
如果要在打印時(shí)顯示/隱藏網(wǎng)格線,你可以用HSSFSheet.IsGridlinesPrinted屬性,默認(rèn)值為false(這就是默認(rèn)情況下打印看不到網(wǎng)格線的原因)。代碼和上面差不多:
s1.IsGridsPrinted=true;
上面的代碼將在打印時(shí)顯示網(wǎng)格線,打印的效果如下所示。
在此也提醒大家,如果這個(gè)Excel最終客戶有打印意向,可別忘了把IsGridPrinted屬性也設(shè)置上。
相關(guān)范例可以參考NPOI 1.2正式版中的DisplayGridlinesInXls項(xiàng)目。
2.6.6用NPOI操作EXCEL--設(shè)置初始視圖的行、列
有些時(shí)候,我們可能希望生成的Excel文件在被打開的時(shí)候自動(dòng)將焦點(diǎn)定位在某個(gè)單元格或是選中某個(gè)區(qū)域中。在NPOI中可以通過SetAsActiveCell和SetActiveCellRange等幾個(gè)方法實(shí)現(xiàn)。
首先我們看一下設(shè)置初始視圖中選中某個(gè)單元格的方法:
//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)方法用來寫示范數(shù)據(jù),其代碼為(下同):
staticvoidCreateCellArray(HSSFSheet?sheet)
{
for(inti?=0;?i?<300;?i++)
{
HSSFRow?row=sheet.CreateRow(i);
for(intj?=0;?j?<150;?j++)
{
HSSFCell?cell?=?row.CreateCell(j);
cell.SetCellValue(i*j);
}
}
}
生成的Excel打開時(shí)效果如下,注意B6為默認(rèn)選中狀態(tài),TopRow和LeftCol設(shè)置B6為當(dāng)前可見區(qū)域的第一個(gè)單元格:
如果不設(shè)置TopRow和LeftCol屬性,默認(rèn)的可見域的第一個(gè)單元格為A1,如下是另一種設(shè)置活動(dòng)單元格的方法,但沒有設(shè)置此Sheet的TopRow和LeftCol:
HSSFSheet?sheet2?=?hssfworkbook.CreateSheet("Sheet?B");
sheet2.Sheet.SetActiveCell(
1,5);
對(duì)應(yīng)生成的Excel顯示為:
除了設(shè)置某個(gè)單元格為選中狀態(tài)外,還NPOI可以設(shè)置某個(gè)區(qū)域?yàn)檫x中狀態(tài):
//use?Sheet.SetActiveCellRange?to?select?a?cell?range
HSSFSheet?sheet3?=?hssfworkbook.CreateSheet("Sheet?C");
CreateCellArray(sheet3);
sheet3.Sheet.SetActiveCellRange(
2,5,1,5);
以上代碼設(shè)置了Sheet C的選中區(qū)域?yàn)锽3:F6:
還有更強(qiáng)大的,設(shè)置多個(gè)選中區(qū)域:
//use?Sheet.SetActiveCellRange?to?select?multiple?cell?ranges
HSSFSheet?sheet4?=?hssfworkbook.CreateSheet("Sheet?D");
CreateCellArray(sheet4);
List?cellranges?=
newList();
cellranges.Add(
newCellRangeAddress8Bit(1,3,2,5));
cellranges.Add(
newCellRangeAddress8Bit(6,7,8,9));
sheet4.Sheet.SetActiveCellRange(cellranges,
1,6,9);
如果一個(gè)Excel文件中有多個(gè)Sheet,還可以通過如下語句設(shè)置打開時(shí)的初始Sheet:
hssfworkbook.ActiveSheetIndex?=2;
2.6.7用NPOI操作EXCEL--數(shù)據(jù)有效性
在有些情況下(比如Excel引入),我們可能不允許用戶在Excel隨意輸入一些無效數(shù)據(jù),這時(shí)就要在模板中加一些數(shù)據(jù)有效性的驗(yàn)證。在Excel中,設(shè)置數(shù)據(jù)有效性的方步驟如下:(1)先選定一個(gè)區(qū)域;數(shù)據(jù)有效性”中設(shè)置數(shù)據(jù)有效性驗(yàn)證(如圖)。à(2)在菜單“數(shù)據(jù)
同樣,利用NPOI,用代碼也可以實(shí)現(xiàn):
HSSFSheet?sheet1?=?hssfworkbook.CreateSheet("Sheet1");
sheet1.CreateRow(
0).CreateCell(0).SetCellValue("日期列");
CellRangeAddressList?regions1?=
newCellRangeAddressList(1,65535,0,0);
DVConstraint?constraint1?=?DVConstraint.CreateDateConstraint(DVConstraint.OperatorType.BETWEEN,
"1900-01-01","2999-12-31","yyyy-MM-dd");
HSSFDataValidation?dataValidate1?=
newHSSFDataValidation(regions1,?constraint1);
dataValidate1.CreateErrorBox(
"error","You?must?input?a?date.");
sheet1.AddValidationData(dataValidate1);
上面是一個(gè)在第一列要求輸入1900-1-1至2999-12-31之間日期的有效性驗(yàn)證的例子,生成的Excel效果如下,當(dāng)輸入非法時(shí)將給出警告:
下面對(duì)剛才用到的幾個(gè)方法加以說明:
CellRangeAddressList
類表示一個(gè)區(qū)域,構(gòu)造函數(shù)中的四個(gè)參數(shù)分別表示起始行序號(hào),終止行序號(hào),起始列序號(hào),終止列序號(hào)。所以第一列所在區(qū)域就表示為:
//所有序號(hào)都從零算起,第一行標(biāo)題行除外,所以第一個(gè)參數(shù)是1,65535是一個(gè)Sheet的最大行數(shù)newCellRangeAddressList(1,65535,0,0);
另外,CreateDateConstraint的第一個(gè)參數(shù)除了設(shè)置成DVConstraint.OperatorType.BETWEEN外,還可以設(shè)置成如下一些值,大家可以自己一個(gè)個(gè)去試看看效果:
最后,dataValidate1.CreateErrorBox(title,text),用來創(chuàng)建出錯(cuò)時(shí)的提示信息。第一個(gè)參數(shù)表示提示框的標(biāo)題,第二個(gè)參數(shù)表示提示框的內(nèi)容。
理解了上面這些,創(chuàng)建一個(gè)整數(shù)類型的有效性驗(yàn)證也不難實(shí)現(xiàn):
sheet1.CreateRow(0).CreateCell(1).SetCellValue("數(shù)值列");
CellRangeAddressList?regions2?=
newCellRangeAddressList(1,65535,1,1);
DVConstraint?constraint2?=?DVConstraint.CreateNumericConstraint(DVConstraint.ValidationType.INTEGER,DVConstraint.OperatorType.BETWEEN,
"0","100");
HSSFDataValidation?dataValidate2?=
newHSSFDataValidation(regions2,?constraint2);
dataValidate2.CreateErrorBox(
"error","You?must?input?a?numeric?between?0?and?100.");
sheet1.AddValidationData(dataValidate2);
生成的Excel效果為:
下一節(jié)我們將學(xué)習(xí)利用數(shù)據(jù)有效性創(chuàng)建下拉列表的例子。
2.6.8用NPOI操作EXCEL--生成下拉列表
上一節(jié)我們講了簡(jiǎn)單的數(shù)據(jù)有效性驗(yàn)證,這一節(jié)我們學(xué)習(xí)一下數(shù)據(jù)有效性的另一個(gè)應(yīng)用--下拉列表。在Excel中,并沒有類似Web中的下拉控件,其下拉效果是通過數(shù)據(jù)有效性來實(shí)現(xiàn)的。設(shè)置步驟為:(1)選定一個(gè)要生成下拉列表的區(qū)域;(2)設(shè)置數(shù)據(jù)有效性為序列,并在來源中填充可選下拉的值,用“,”隔開(如圖)。
對(duì)應(yīng)的效果為:
同樣,利用NPOI代碼也可以實(shí)現(xiàn)上面的效果:
HSSFSheet?sheet1?=?hssfworkbook.CreateSheet("Sheet1");
CellRangeAddressList?regions?=
newCellRangeAddressList(0,65535,0,0);
DVConstraint?constraint?=?DVConstraint.CreateExplicitListConstraint(
newstring[]?{"itemA","itemB","itemC"});
HSSFDataValidation?dataValidate?=
newHSSFDataValidation(regions,?constraint);
sheet1.AddValidationData(dataValidate);
下面對(duì)代碼作一下簡(jiǎn)要說明:先設(shè)置一個(gè)需要提供下拉的區(qū)域,關(guān)于CellRangeAddressList構(gòu)造函數(shù)參數(shù)的說明請(qǐng)參見上一節(jié):
CellRangeAddressList?regions?=newCellRangeAddressList(0,65535,0,0);
然后將下拉項(xiàng)作為一個(gè)數(shù)組傳給CreateExplicitListConstraint作為參數(shù)創(chuàng)建一個(gè)約束,根據(jù)要控制的區(qū)域和約束創(chuàng)建數(shù)據(jù)有效性就可以了。
但是這樣會(huì)有一個(gè)問題:Excel中允許輸入的序列來源長(zhǎng)度最大為255個(gè)字符,也就是說當(dāng)下拉項(xiàng)的總字符串長(zhǎng)度超過255是將會(huì)出錯(cuò)。那么如果下拉項(xiàng)很多的情況下應(yīng)該怎么處理呢?答案是通過引用的方式。步驟如下:先創(chuàng)建一個(gè)Sheet專門用于存儲(chǔ)下拉項(xiàng)的值,并將各下拉項(xiàng)的值寫入其中:
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");
然后定義一個(gè)名稱,指向剛才創(chuàng)建的下拉項(xiàng)的區(qū)域:
HSSFName?range?=?hssfworkbook.CreateName();
range.Reference?=
"ShtDictionary!$A1:$A3";
range.NameName?=
"dicRange";
最后,設(shè)置數(shù)據(jù)約束時(shí)指向這個(gè)名稱而不是字符數(shù)組:
HSSFSheet?sheet1?=?hssfworkbook.CreateSheet("Sheet1");
CellRangeAddressList?regions?=
newCellRangeAddressList(0,65535,0,0);
DVConstraint?constraint?=?DVConstraint.CreateFormulaListConstraint(
"dicRange");
HSSFDataValidation?dataValidate?=
newHSSFDataValidation(regions,?constraint);
sheet1.AddValidationData(dataValidate);
執(zhí)行這段代碼,生成的Excel效果如下:
在名稱管理器中會(huì)發(fā)現(xiàn)有一個(gè)名為"dicRange"的名稱,指向"ShtDictionary!$A1:$A3"的下拉項(xiàng)區(qū)域:
在數(shù)據(jù)有效性中會(huì)發(fā)現(xiàn)來源變成了"=dicRange",指向上面定義的名稱。而不是以前的"itemA,itemB,itemC":