2 什么是 NPOI
NPOI 是指構建在 POI 3.x 版本之上的一個程序,NPOI 可以在沒有安裝 Office 的情況下對 Word 或 Excel 文檔進行讀寫操作。
NPOI 是一個開源的 C# 讀寫 Excel、WORD 等微軟 OLE2 組件文檔的項目。
3 為什么使用 NPOI
比較常用的操作 Excel 的方法如下所示:
1 OLEDB
這種方式是把整個 Excel 文件當做一個數據源來進行數據的讀取操作。
優點:實現方式簡單,讀取速度快。
缺點:讀取 Excel 數據的過程不太靈活,對內存的占用比較高,當數據量變的很大時,容易由於內存空間不足導致內存溢出異常。
2 COM 組件
這種方式是通過 COM 組件 Microsoft.Office.Interop.Excel.dll 實現 Excel 文件的操作。
優點:讀取 Excel 數據非常靈活,可以實現 Excel 具有的各種數據處理功能。
缺點:對數據的訪問時基於單元格方式實現的,所以讀寫數據較慢,特別是當數據量較大時,訪問效率問題更為突出。另一點是要求本機安裝了 Office 組件。
3 NPOI
這種方式是通過 NPOI 庫實現 Excel 文件操作,可以在沒有安裝微軟 Office 的情況下使用。詳情可查看官網。
優點:讀取Excel數據速度較快,操作方式靈活。
缺點:官方文檔較少。
4 ASPOSE
Aspose 公司旗下的最全的一套 office 文檔管理方案。支持 Word, Excel, PowerPoint, Project 等 office 文檔以及 PDF 文檔讀寫操作。
優點:因商業驅動所以會有詳細的使用文檔和技術支持。
缺點:需要收費使用。
這里推薦使用 NPOI,因為 NPOI 不用額外安裝 Office 組件,而且完全免費。接下來介紹如何使用 NPOI 。
4 如何使用 NPOI
4.1 安裝
使用 nuget 方式安裝,命令如下:
Install-Package NPOI
其他命令參考 NuGet Gallery | NPOI 。
4.2 名詞解釋
名詞 解釋
Workbook 工作薄,一個文件包含一個工作薄,一個工作薄可以包含若干個工作表。
Sheet 工作表
HSSFWorkbook 處理 xls 文件類型的 NPOI 操作類,繼承 IWorkbook 。
XSSFWorkbook 處理 xlsx 文件類型的 NPOI 操作類,繼承 IWorkbook 。
4.3 代碼示例
下面列舉常用使用場景,更多的代碼示例可以參考 官方源碼 exmaples 目錄。
示例功能列表如下:
創建工作薄和保存文件
添加自定義屬性
創建工作表、行和列
文件保護
給單元格添加鏈接
設置單元格字體
設置單元格邊框樣式
設置單元格數據格式
設置列寬和行高
合並單元格
循環賦值
下載文件
凍結與分隔
使用簡單公式
插入圖片
4.3.1 創建工作薄和保存文件
// 創建工作薄IWorkbook wb = new XSSFWorkbook();// 保存文件FileStream sw = File.Create("test.xlsx");
wb.Write(sw);
sw.Close();
約定:下文代碼不再重新創建變量 wb,默認引用此處聲明,除非特殊聲明。
4.3.2 添加自定義屬性
POIXMLProperties props = wb.GetProperties();
props.CoreProperties.Creator = "NPOI 2.0.5";
props.CoreProperties.Created = DateTime.Now;if (!props.CustomProperties.Contains("NPOI Team"))
{
props.CustomProperties.AddProperty("NPOI Team", "Hello World!");
}
4.3.3 創建工作表、行和列
// 創建工作表ISheet sheet = wb.CreateSheet("Hyperlinks");// 創建第一行IRow row = sheet.CreateRow(0);// 創建第一列ICell cell = row.CreateCell(0);
注意:工作表的行和列在 NPOI 中都是以 0 開始計數。
約定:下文代碼不不再重新創建變量 sheet 和 cell,默認引用此處聲明,除非特殊聲明。
4.3.4 文件保護
sheet.LockFormatRows();sheet.LockFormatCells();sheet.LockFormatColumns();sheet.LockDeleteColumns();sheet.LockDeleteRows();sheet.LockInsertHyperlinks();sheet.LockInsertColumns();sheet.LockInsertRows();sheet.ProtectSheet("password");
4.3.5 給單元格添加鏈接
ISheet sheet = wb.CreateSheet("Hyperlinks");// URLICell cell = sheet.CreateRow(0).CreateCell(0);
cell.SetCellValue("URL Link");
HSSFHyperlink link = new HSSFHyperlink(HyperlinkType.Url);
link.Address = "http://poi.apache.org/";
cell.Hyperlink = link;
cell.CellStyle = hlink_style;
除此之外,HyperlinkType 枚舉類型還可以是: HyperlinkType.File(文件路徑)、HyperlinkType.Email(電子郵件地址)、HyperlinkType.Document(內部文檔跳轉)。
4.3.6 設置單元格字體
// 創建字體樣式:underlined, italic, red color, fontsize=20IFont font = workbook.CreateFont();
font.Color = IndexedColors.Red.Index;
font.IsItalic = true;
font.Underline = FontUnderlineType.Double;
font.FontHeightInPoints = 20;// 綁定字體樣式到樣式對象上ICellStyle style1 = workbook.CreateCellStyle();
style1.SetFont(font);// 綁定樣式對象到單元格上cell1.CellStyle = style1;
4.3.7 設置單元格邊框樣式
// 創建樣式ICellStyle style = wb.CreateCellStyle();
style.BorderBottom = BorderStyle.Thin;
style.BottomBorderColor = IndexedColors.Black.Index;
style.BorderLeft = BorderStyle.DashDotDot;
style.LeftBorderColor = IndexedColors.Green.Index;
style.BorderRight = BorderStyle.Hair;
style.RightBorderColor = IndexedColors.Blue.Index;
style.BorderTop = BorderStyle.MediumDashed;
style.TopBorderColor = IndexedColors.Orange.Index;// 設置邊框對角線樣式style.BorderDiagonalLineStyle = BorderStyle.Medium; // BorderDiagonalLineStyle 屬性必須在 BorderDiagonal 和 BorderDiagonalColor 之前設置style.BorderDiagonal = BorderDiagonal.Forward;
style.BorderDiagonalColor = IndexedColors.Gold.Index;// 綁定樣式cell.CellStyle = style;
4.3.8 設置單元格數據格式
IDataFormat format = wb.CreateDataFormat();
ICell cell = sheet.CreateRow(0).CreateCell(0);// 小數保留兩位 - "1.20"cell.SetCellValue(1.2);
ICellStyle cellStyle = wb.CreateCellStyle();
cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00");
cell.CellStyle = cellStyle;// 帶逗號分隔的人民幣格式 - "¥20,000"ICell cell2 = sheet.CreateRow(1).CreateCell(0);
cell2.SetCellValue(20000);
ICellStyle cellStyle2 = wb.CreateCellStyle();
cellStyle2.DataFormat = format.GetFormat("¥#,##0");
cell2.CellStyle = cellStyle2;// 科學計數法格式 - "3.15E+00"ICell cell3 = sheet.CreateRow(2).CreateCell(0);
cell3.SetCellValue(3.151234);
ICellStyle cellStyle3 = wb.CreateCellStyle();
cellStyle3.DataFormat = format.GetFormat("0.00E+00");
cell3.CellStyle = cellStyle3;// 百分比格式,小數點后2位數 - "99.33%"ICell cell4 = sheet.CreateRow(3).CreateCell(0);
cell4.SetCellValue(0.99333);
ICellStyle cellStyle4 = wb.CreateCellStyle();
cellStyle4.DataFormat = format.GetFormat("0.00%");
cell4.CellStyle = cellStyle4;// 電話號碼格式 - "021-65881234"ICell cell5 = sheet.CreateRow(4).CreateCell(0);
cell5.SetCellValue(02165881234);
ICellStyle cellStyle5 = wb.CreateCellStyle();
cellStyle5.DataFormat = format.GetFormat("000-00000000");
cell5.CellStyle = cellStyle5;// 中文大寫字符數 - 壹貳叄 元
ICell cell6 = sheet.CreateRow(5).CreateCell(0);
cell6.SetCellValue(02165881234);
ICellStyle cellStyle6 = wb.CreateCellStyle();
cellStyle6.DataFormat = format.GetFormat("[DbNum2][$-804]0 元");
cell6.CellStyle = cellStyle6;// 中文日期格式
ICell cell7 = sheet.CreateRow(6).CreateCell(0);
cell7.SetCellValue(02165881234);
ICellStyle cellStyle7 = wb.CreateCellStyle();
cellStyle7.DataFormat = format.GetFormat("[DbNum2][$-804]0 元");
cell7.CellStyle = cellStyle7;// 具有日期時間樣式的公式值
ICell cell8 = sheet.CreateRow(7).CreateCell(0);
cell8.CellFormula = "DateValue("2005-11-11")+TIMEVALUE("11:11:11")";
ICellStyle cellStyle8 = workbook.CreateCellStyle();
cellStyle8.DataFormat = HSSFDataFormat.GetBuiltinFormat("m/d/yy h:mm");
cell8.CellStyle = cellStyle8;// 顯示當前時間
ICell cell9 = sheet.CreateRow(8).CreateCell(0);
cell9.SetCellValue(02165881234);
ICellStyle cellStyle9 = DateTime.Now;
cellStyle9.DataFormat = format.GetFormat("[$-409]h:mm:ss AM/PM;@");
cell9.CellStyle = cellStyle9;
4.3.9 設置列寬和行高
// 設置列寬,第一個參數為第幾列(從 0 開始計數),第二個參數為寬度值,注意值為 256 的倍數sheet.SetColumnWidth(0, 50 * 256);
sheet.SetColumnWidth(1, 100 * 256);
sheet.SetColumnWidth(2, 150 * 256);// 設置行高,注意值為 20 的倍數sheet.CreateRow(0).Height = 100 * 20;
sheet.CreateRow(1).Height = 200 * 20;
sheet.CreateRow(2).Height = 300 * 20;
4.3.10 合並單元格
IRow row = sheet.CreateRow(1);
ICell cell = row.CreateCell(1);
cell.SetCellValue(new XSSFRichTextString("This is a test of merging"));// 參數格式:new CellRangeAddress(起始第幾行,結束第幾行,起始第幾列,結束第幾列)// 合並 A1 和 B1 兩個單元格sheet.AddMergedRegion(new CellRangeAddress(1, 1, 1, 2));
4.3.11 循環賦值
sheet.CreateRow(0).CreateCell(0).SetCellValue("This is a Sample");int x = 1;// 循環填充 15*15 矩陣內的數據for (int i = 1; i <= 15; i++)
{
IRow row = sheet.CreateRow(i); for (int j = 0; j < 15; j++)
{
row.CreateCell(j).SetCellValue(x++);
}
}
4.3.12 下載文件
// 清理臟數據Response.Clear();// 設置響應頭Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";string filename = "test.xlsx";
Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", filename));// 創建工作簿和工作表XSSFWorkbook workbook = new XSSFWorkbook();
ISheet sheet1 = workbook.CreateSheet("Sheet1");// 填充數據sheet1.CreateRow(0).CreateCell(0).SetCellValue("This is a Sample");// 寫入響應報文中using (var f = File.Create(@"c:\test.xlsx"))
{
workbook.Write(f);
}// workbook.Write(Response.OutputStream); 不能使用 // 根本原因:Response.OutputStream 將不必要的字節插入響應字節。// 參考鏈接:http://social.msdn.microsoft.com/Forums/en-US/3a7bdd79-f926-4a5e-bcb0-ef81b6c09dcf/responseoutputstreamwrite-writes-all-but-insetrs-a-char-every-64k?forum=nclResponse.WriteFile(@"c:\test.xlsx");// 刷新緩存和終止報文寫入Response.Flush();
Response.End();
4.3.13 凍結與分隔
ISheet sheet1 = workbook.CreateSheet("new sheet");
ISheet sheet2 = workbook.CreateSheet("second sheet");
ISheet sheet3 = workbook.CreateSheet("third sheet");
ISheet sheet4 = workbook.CreateSheet("fourth sheet");// CreateFreezePane 方法參數說明:// 第一個參數表示要凍結的列數,從 1 開始計數,如果不需要凍結設為 0。// 第二個參數表示要凍結的行數,從 1 開始計數,如果不需要凍結設為 0。// 第三個參數表示右邊區域可見的首列序號,從 1 開始計數,如果不需要設置則設為 0。// 第四個參數表示下邊區域可見的首行序號,從 1 開始計數,如果不需要設置則設為 0。// 凍結第一行sheet1.CreateFreezePane(0, 1, 0, 1);// 凍結第一列sheet2.CreateFreezePane(1, 0, 1, 0);// 凍結列和行(忽略右下象限的滾動位置)sheet3.CreateFreezePane(2, 2);// 創建一個左下角為活動象限的分割sheet4.CreateSplitPane(2000, 2000, 0, 0, PanePosition.LowerLeft);
4.3.14 使用簡單公式
ISheet s1=workbook.CreateSheet("Sheet1");// 設置 A2s1.CreateRow(1).CreateCell(0).SetCellValue(-5);// 設置 B2s1.GetRow(1).CreateCell(1).SetCellValue(1111);// 設置 C2s1.GetRow(1).CreateCell(2).SetCellValue(7.623);// 設置 A3s1.CreateRow(2).CreateCell(0).SetCellValue(2.2);// 設置 A4=A2+A3s1.CreateRow(3).CreateCell(0).CellFormula = "A2+A3";// 設置 D2=SUM(A2:C2);s1.GetRow(1).CreateCell(3).CellFormula = "SUM(A2:C2)";// 設置 A5=cos(5)+sin(10)s1.CreateRow(4).CreateCell(0).CellFormula="cos(5)+sin(10)";
ISheet s2 = workbook.CreateSheet("Sheet2");// 使用跨工作表引用s2.CreateRow(0).CreateCell(0).CellFormula = "Sheet1!A2+Sheet1!A3";
4.3.15 插入圖片
// 創建繪圖工具對象IDrawing patriarch = sheet.CreateDrawingPatriarch();// 創建錨點// XSSFClientAnchor 參數說明:// XSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2)// dx1:第一個單元格中的x坐標// dy1:第一個單元格中的y坐標// dx2:第二個單元格中的x坐標// dy2:第二個單元格中的y坐標// col1: 第一個單元格的列(從 0 開始計數)。// row1: 第一個單元格的行(從 0 開始計數)。// col1: 第一個單元格的列(從 0 開始計數,個人實踐需加 1)。// row2: 第二個單元格的行(從 0 開始計數,個人實踐需加 1)。XSSFClientAnchor anchor = new XSSFClientAnchor(500, 200, 0, 0, 2, 2, 4, 7);// 設置錨點類型,這里 MoveDontResize 表明移動工作表行和列時,圖片不會自動伸縮。anchor.AnchorType = AnchorType.MoveDontResize;// 添加圖片資源並獲得圖片在當前工作簿中唯一序列號FileStream file = new FileStream(@"d:\your_image.jpg", FileMode.Open, FileAccess.Read);byte[] buffer = new byte[file.Length];
file.Read(buffer, 0, (int)file.Length);int imageId = wb.AddPicture(buffer, PictureType.JPEG);// 繪制圖片XSSFPicture picture = (XSSFPicture)patriarch.CreatePicture(anchor, imageId);// 調用 Reset 將會重新設置圖片尺寸為原圖片尺寸,這里會覆蓋 調用 XSSFClientAnchor 時的設置。//picture.Resize();// 設置圖片邊框樣式picture.LineStyle = LineStyle.DashDotGel;
5 總結
操作 Excel 是大多數系統常用功能之一,所以熟練掌握它將會很大程度上提升你的效率。我發現 NPOI 官方文檔不是很詳盡,好在源碼有例子比較全面,但是依然不方便快速查詢,所以此文把一些常用操作總結和列舉出來作為備忘,希望能對你有幫助!其實還有個另辟蹊徑的方法學習,那就是查看 POI 文檔,里面有很多概念和類名大多數和 NPOI 相同或相似,因為 NPOI 就是從 POI 改版而來,NPOI 是 POI 的 .NET 版本。
作者:慕村9548890
鏈接:https://www.imooc.com/article/273965
來源:慕課網