C# 中 NPOI 庫讀寫 Excel 文件的方法【摘】
原作:淡水網誌
NPOI 是開源的 POI 項目的.NET版,可以用來讀寫Excel,Word,PPT文件。在處理Excel文件上,NPOI 可以同時兼容 xls 和 xlsx。官網提供了一份 Examples,給出了很多應用場景的例子,打包好的二進制文件類庫,也僅有幾MB,使用非常方便。
讀Excel
NPOI使用HSSFWorkbook
類來處理xls,XSSFWorkbook
類來處理xlsx,它們都繼承接口IWorkbook
,因此可以通過IWorkbook
來統一處理xls和xlsx格式的文件。
以下是簡單的例子
1 /// <summary> 2 ///讀取excel文件 3 /// </summary> 4 /// <param name="filePath">文件路徑</param> 5 public void ReadFromExcelFile(string filePath) 6 { 7 IWorkbook wk = null; 8 string extension = System.IO.Path.GetExtension(filePath); 9 try 10 {11 FileStream fs = File.OpenRead(filePath); 12 if (extension.Equals(".xls")) 13 { 14 //把xls文件中的數據寫入wk中 15 wk = new HSSFWorkbook(fs); 16 } 17 else 18 { 19 //把xlsx文件中的數據寫入wk中 20 wk = new XSSFWorkbook(fs); 21 } 22 23 fs.Close(); 24 //讀取當前表數據 25 ISheet sheet = wk.GetSheetAt(0); 26 27 IRow row = sheet.GetRow(0); //讀取當前行數據 28 //LastRowNum 是當前表的總行數-1(註意) 29 30 string text = string.Empty; 31 for (int i = 0; i <= sheet.LastRowNum; i++) 32 { 33 row = sheet.GetRow(i); //讀取當前行數據 34 if (row != null) 35 { 36 //LastCellNum 是當前行的總列數 37 for (int j = 0; j < row.LastCellNum; j++) 38 { 39 //讀取該行的第j列數據 40 string value = row.GetCell(j).ToString(); 41 //Console.Write(value.ToString() + " "); 42 text = text + value.ToString() + "\r\n"; 43 } 44 //Console.WriteLine("\n"); 45 } 46 } 47 SetText(text); 48 } 49 50 catch (Exception e) 51 { 52 //只在Debug模式下才輸出 53 //Console.WriteLine(e.Message); 54 this.textBox1.Text = e.Message; 55 } 56 }
Excel中的單元格是有不同數據格式的,例如數字,日期,字符串等,在讀取的時候可以根據格式的不同設置對象的不同類型,方便後期的數據處理。
1 //獲取cell的數據,並設置為對應的數據類型 2 public object GetCellValue(ICell cell) 3 { 4 object value = null; 5 try 6 { 7 if (cell.CellType != CellType.Blank) 8 { 9 switch (cell.CellType) 10 { 11 case CellType.Numeric: 12 // Date comes here 13 if (DateUtil.IsCellDateFormatted(cell)) 14 { 15 value = cell.DateCellValue; 16 } 17 else 18 { 19 // Numeric type 20 value = cell.NumericCellValue; 21 } 22 break; 23 case CellType.Boolean: 24 // Boolean type 25 value = cell.BooleanCellValue; 26 break; 27 case CellType.Formula: 28 value = cell.CellFormula; 29 break; 30 default: 31 // String type 32 value = cell.StringCellValue; 33 break; 34 } 35 } 36 } 37 catch (Exception) 38 { 39 value = ""; 40 } 41 return value; 42 }
特別註意的是CellType
中沒有Date,而日期類型的數據類型是Numeric
,其實日期的數據在Excel中也是以數字的形式存儲。可以使用DateUtil.IsCellDateFormatted
方法來判斷是否是日期類型。
有了GetCellValue
方法,寫數據到Excel中的時候就要有SetCellValue
方法,缺的類型可以自己補。
1 //根據數據類型設置不同類型的cell 2 public static void SetCellValue(ICell cell, object obj) 3 { 4 if (obj.GetType() == typeof(int)) 5 { 6 cell.SetCellValue((int)obj); 7 } 8 else if (obj.GetType() == typeof(double)) 9 { 10 cell.SetCellValue((double)obj); 11 } 12 else if (obj.GetType() == typeof(IRichTextString)) 13 { 14 cell.SetCellValue((IRichTextString)obj); 15 } 16 else if (obj.GetType() == typeof(string)) 17 { 18 cell.SetCellValue(obj.ToString()); 19 } 20 else if (obj.GetType() == typeof(DateTime)) 21 { 22 cell.SetCellValue((DateTime)obj); 23 } 24 else if (obj.GetType() == typeof(bool)) 25 { 26 cell.SetCellValue((bool)obj); 27 } 28 else 29 { 30 cell.SetCellValue(obj.ToString()); 31 } 32 }
cell.SetCellValue()
方法只有四種重載方法,參數分別是string
, bool
, DateTime
, double
, IRichTextString
設置公式使用cell.SetCellFormula(string formula)
寫Excel
以下是簡單的例子,更多信息可以參見官網提供的Examples。
1 public void WriteToExcel(string filePath) 2 { 3 //創建工作薄 4 IWorkbook wb; 5 string extension = System.IO.Path.GetExtension(filePath); 6 //根據指定的文件格式創建對應的類 7 if (extension.Equals(".xls")) 8 { 9 wb = new HSSFWorkbook(); 10 } 11 else 12 { 13 wb = new XSSFWorkbook(); 14 } 15 ICellStyle style1 = wb.CreateCellStyle();//樣式 16 style1.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left;//文字水平對齊方式 17 style1.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;//文字垂直對齊方式 18 //設置邊框 19 style1.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; 20 style1.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; 21 style1.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; 22 style1.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; 23 style1.WrapText = true;//自動換行 24 ICellStyle style2 = wb.CreateCellStyle();//樣式 25 IFont font1 = wb.CreateFont();//字體 26 font1.FontName = "楷體"; 27 font1.Color = HSSFColor.Red.Index;//字體顏色 28 font1.Boldweight = (short)FontBoldWeight.Normal;//字體加粗樣式 29 style2.SetFont(font1);//樣式裏的字體設置具體的字體樣式 30 //設置背景色 31 style2.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index; 32 style2.FillPattern = FillPattern.SolidForeground; 33 style2.FillBackgroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index; 34 style2.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left;//文字水平對齊方式 35 style2.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;//文字垂直對齊方式 36 ICellStyle dateStyle = wb.CreateCellStyle();//樣式 37 dateStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left;//文字水平對齊方式 38 dateStyle.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;//文字垂直對齊方式 39 //設置數據顯示格式 40 IDataFormat dataFormatCustom = wb.CreateDataFormat(); 41 dateStyle.DataFormat = dataFormatCustom.GetFormat("yyyy-MM-dd HH:mm:ss"); 42 //創建一個表單 43 ISheet sheet = wb.CreateSheet("Sheet0"); 44 //設置列寬 45 int[] columnWidth = { 10, 10, 20, 10 }; 46 for (int i = 0; i < columnWidth.Length; i++) 47 { 48 //設置列寬度,256*字符數,因為單位是1/256個字符 49 sheet.SetColumnWidth(i, 256 * columnWidth[i]); 50 } 51 //測試數據 52 int rowCount = 3, columnCount = 4; 53 object[,] data = { 54 {"列0", "列1", "列2", "列3"}, 55 {"", 400, 5.2, 6.01}, 56 {"", true, "2014-07-02", DateTime.Now} 57 //日期可以直接傳字符串,NPOI會自動識別 58 //如果是DateTime類型,則要設置CellStyle.DataFormat,否則會顯示為數字 59 }; 60 IRow row; 61 ICell cell; 62 63 for (int i = 0; i < rowCount; i++) 64 { 65 row = sheet.CreateRow(i);//創建第i行 66 for (int j = 0; j < columnCount; j++) 67 { 68 cell = row.CreateCell(j);//創建第j列 69 cell.CellStyle = j % 2 == 0 ? style1 : style2; 70 //根據數據類型設置不同類型的cell 71 object obj = data[i, j]; 72 SetCellValue(cell, data[i, j]); 73 //如果是日期,則設置日期顯示的格式 74 if (obj.GetType() == typeof(DateTime)) 75 { 76 cell.CellStyle = dateStyle; 77 } 78 //如果要根據內容自動調整列寬,需要先setCellValue再調用 79 //sheet.AutoSizeColumn(j); 80 } 81 } 82 //合並單元格,如果要合並的單元格中都有數據,只會保留左上角的 83 //CellRangeAddress(0, 2, 0, 0),合並0-2行,0-0列的單元格 84 CellRangeAddress region = new CellRangeAddress(0, 2, 0, 0); 85 sheet.AddMergedRegion(region); 86 try 87 { 88 FileStream fs = File.OpenWrite(filePath); 89 wb.Write(fs);//向打開的這個Excel文件中寫入表單並保存。 90 fs.Close(); 91 } 92 catch (Exception e) 93 { 94 Debug.WriteLine(e.Message); 95 } 96 }
如果想要設置單元格為只讀或可寫,可以參考這裏,方法如下:
1 ICellStyle unlocked = wb.CreateCellStyle(); 2 unlocked.IsLocked = false;//設置該單元格為非鎖定 3 cell.SetCellValue("未被鎖定"); 4 cell.CellStyle = unlocked; 5 ... 6 //保護表單,password為解鎖密碼 7 //cell.CellStyle.IsLocked = true;的單元格將為只讀 8 sheet.ProtectSheet("password");
cell.CellStyle.IsLocked
默認就是true,因此sheet.ProtectSheet("password")
一定要執行,才能實現鎖定單元格,對於不想鎖定的單元格,就一定要設置cell
的CellStyle
中的IsLocked = false
C# 中 NPOI 庫讀寫 Excel 文件的方法【摘】