首先建立一個空白的工作簿用作測試,並在其中建立空白工作表,在表中建立空白行,在行中建立單元格,並填入內容:
//建立空白工作簿 IWorkbook workbook = new HSSFWorkbook(); //在工作簿中:建立空白工作表 ISheet sheet = workbook.CreateSheet(); //在工作表中:建立行,參數為行號,從0計 IRow row = sheet.CreateRow(0);
//在行中:建立單元格,參數為列號,從0計 ICell cell = row.CreateCell(0); //設置單元格內容 cell.SetCellValue("實習鑒定表");
設置單元格樣式:設置單元格樣式時需要注意,務必創建一個新的樣式對象進行設置,否則會將工作表所有單元格的樣式一同設置,它們應該共享的是一個樣式對象:
ICellStyle style = workbook.CreateCellStyle(); //設置單元格的樣式:水平對齊居中 style.Alignment = HorizontalAlignment.CENTER; //新建一個字體樣式對象
IFont font = workbook.CreateFont();
//設置字體加粗樣式
font.Boldweight = short.MaxValue;
//使用SetFont方法將字體樣式添加到單元格樣式中
style.SetFont(font); //將新的樣式賦給單元格 cell.CellStyle = style;
設置單元格寬高:
設置單元格的高度實際是設置其所在行高,所以要在單元格所在行上設置行高,行高設置數值好像是像素點的1/20,所以*20以便達到設置效果;
設置單元格的寬度實際上是設置其所在列寬,所以要在單元格所在列上設置(列的設置在工作表上),寬度數值好像是字符的1/256,所以*256以便達到設置效果。
//設置單元格的高度 row.Height = 30 * 20; //設置單元格的寬度
sheet.SetColumnWidth(0, 30 * 256);
合並單元格:合並單元格實際上是聲明一個區域,該區域中的單元格將進行合並,合並后的內容與樣式以該區域最左上角的單元格為准。
//設置一個合並單元格區域,使用上下左右定義CellRangeAddress區域
//CellRangeAddress四個參數為:起始行,結束行,起始列,結束列
sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, 10));
添加公式:使用Cell的CellFormula來設置公式,是一個字符串,公式前不需要加=號。
//通過Cell的CellFormula向單元格中寫入公式 //注:直接寫公式內容即可,不需要在最前加'=' ICell cell2 = sheet.CreateRow(1).CreateCell(0); cell2.CellFormula = "HYPERLINK(\"測試圖片.jpg\",\"測試圖片.jpg\")";
將工作簿寫入文件查看效果:
//將工作簿寫入文件 using (FileStream fs = new FileStream("生成效果.xls", FileMode.Create, FileAccess.Write)) { workbook.Write(fs); }
最終效果:
設置Excel的自動篩選功能
單元格數字格式的問題
NPOI向Excel文件中插入數值時,可能會出現數字當作文本的情況(即左上角有個綠色三角),這樣單元格的值就無法參與運算。這是因為在SetCellValue設置單元格值的時候使用了字符串進行賦值,默認被轉換成了字符型。如果需要純數字型的,請向SetCellValue中設置數字型變量。
以上兩個問題的示例代碼如下:
//建立空白工作薄 IWorkbook workbook = new HSSFWorkbook(); //在工作薄中建立工作表 ISheet sheet = workbook.CreateSheet(); //填充篩選的內容 sheet.CreateRow(0).CreateCell(0).SetCellValue("省份"); sheet.CreateRow(1).CreateCell(0).SetCellValue("河北省"); sheet.CreateRow(2).CreateCell(0).SetCellValue("湖南省"); //驗證數字格式問題 sheet.GetRow(1).CreateCell(2).SetCellValue("123"); sheet.GetRow(2).CreateCell(2).SetCellValue(123); //設置Excel的自動篩選 CellRangeAddress c = CellRangeAddress.ValueOf("A1"); sheet.SetAutoFilter(c); //寫文件 using (FileStream fs = new FileStream("haha.xls", FileMode.Create, FileAccess.Write)) { workbook.Write(fs); }
最終的效果顯示:
Npoi導入導出Excel操作
using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace HblGrabPro { class ExcelHelper { public static void DsToExcel(DataSet ds, string strExcelFileName) { HSSFWorkbook workbook = new HSSFWorkbook(); foreach(DataTable dt in ds.Tables ) { try { ISheet sheet = workbook.CreateSheet(string.IsNullOrEmpty(dt.TableName) ? Path.GetFileNameWithoutExtension(strExcelFileName) : dt.TableName); ICellStyle HeadercellStyle = workbook.CreateCellStyle(); HeadercellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; HeadercellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; HeadercellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; HeadercellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; HeadercellStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center; NPOI.SS.UserModel.IFont headerfont = workbook.CreateFont(); headerfont.Boldweight = (short)FontBoldWeight.Bold; HeadercellStyle.SetFont(headerfont); int icolIndex = 0; IRow headerRow = sheet.CreateRow(0); foreach (DataColumn item in dt.Columns) { ICell cell = headerRow.CreateCell(icolIndex); cell.SetCellValue(item.ColumnName); cell.CellStyle = HeadercellStyle; icolIndex++; } ICellStyle cellStyle = workbook.CreateCellStyle(); cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("@"); cellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; cellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; cellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; cellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; NPOI.SS.UserModel.IFont cellfont = workbook.CreateFont(); cellfont.Boldweight = (short)FontBoldWeight.Normal; cellStyle.SetFont(cellfont); //建立內容行 int iRowIndex = 1; int iCellIndex = 0; foreach (DataRow Rowitem in dt.Rows) { IRow DataRow = sheet.CreateRow(iRowIndex); foreach (DataColumn Colitem in dt.Columns) { ICell cell = DataRow.CreateCell(iCellIndex); cell.SetCellValue(Rowitem[Colitem].ToString()); cell.CellStyle = cellStyle; iCellIndex++; } iCellIndex = 0; iRowIndex++; } for (int i = 0; i < icolIndex; i++) { sheet.AutoSizeColumn(i); } } catch (Exception ex) { //ILog log = LogManager.GetLogger("Exception Log"); //log.Error(ex.Message + Environment.NewLine + ex.StackTrace); ////記錄AuditTrail //CCFS.Framework.BLL.AuditTrailBLL.LogAuditTrail(ex); continue; //MessageBox.Show(m_Common_ResourceManager.GetString("Export_to_excel_failed"), m_Common_ResourceManager.GetString("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information); } } FileStream file = new FileStream(strExcelFileName, FileMode.OpenOrCreate); workbook.Write(file); file.Flush(); file.Close(); } public static void DtToExcel(DataTable dt, string strExcelFileName) { HSSFWorkbook workbook = new HSSFWorkbook(); try { ISheet sheet = workbook.CreateSheet("Sheet1"); ICellStyle HeadercellStyle = workbook.CreateCellStyle(); HeadercellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; HeadercellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; HeadercellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; HeadercellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; HeadercellStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center; //字體 NPOI.SS.UserModel.IFont headerfont = workbook.CreateFont(); headerfont.Boldweight = (short)FontBoldWeight.Bold; HeadercellStyle.SetFont(headerfont); //用column name 作為列名 int icolIndex = 0; IRow headerRow = sheet.CreateRow(0); foreach (DataColumn item in dt.Columns) { ICell cell = headerRow.CreateCell(icolIndex); cell.SetCellValue(item.ColumnName); cell.CellStyle = HeadercellStyle; icolIndex++; } ICellStyle cellStyle = workbook.CreateCellStyle(); //為避免日期格式被Excel自動替換,所以設定 format 為 『@』 表示一率當成text來看 cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("@"); cellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; cellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; cellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; cellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; NPOI.SS.UserModel.IFont cellfont = workbook.CreateFont(); cellfont.Boldweight = (short)FontBoldWeight.Normal; cellStyle.SetFont(cellfont); //建立內容行 int iRowIndex = 1; int iCellIndex = 0; foreach (DataRow Rowitem in dt.Rows) { IRow DataRow = sheet.CreateRow(iRowIndex); foreach (DataColumn Colitem in dt.Columns) { ICell cell = DataRow.CreateCell(iCellIndex); cell.SetCellValue(Rowitem[Colitem].ToString()); cell.CellStyle = cellStyle; iCellIndex++; } iCellIndex = 0; iRowIndex++; } //自適應列寬度 for (int i = 0; i < icolIndex; i++) { sheet.AutoSizeColumn(i); } //寫Excel FileStream file = new FileStream(strExcelFileName, FileMode.OpenOrCreate); workbook.Write(file); file.Flush(); file.Close(); //MessageBox.Show(m_Common_ResourceManager.GetString("Export_to_excel_successfully"), m_Common_ResourceManager.GetString("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { //ILog log = LogManager.GetLogger("Exception Log"); //log.Error(ex.Message + Environment.NewLine + ex.StackTrace); ////記錄AuditTrail //CCFS.Framework.BLL.AuditTrailBLL.LogAuditTrail(ex); //MessageBox.Show(m_Common_ResourceManager.GetString("Export_to_excel_failed"), m_Common_ResourceManager.GetString("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information); } finally { workbook = null; } } public static DataTable ExcelToDt(string strFilePath, string strTableName, int iSheetIndex) { string strExtName = Path.GetExtension(strFilePath); DataTable dt = new DataTable(); if (!string.IsNullOrEmpty(strTableName)) { dt.TableName = strTableName; } if (strExtName.Equals(".xls") || strExtName.Equals(".xlsx")) { using (FileStream file = new FileStream(strFilePath, FileMode.Open, FileAccess.Read)) { HSSFWorkbook workbook = new HSSFWorkbook(file); ISheet sheet = workbook.GetSheetAt(iSheetIndex); //列頭 foreach (ICell item in sheet.GetRow(sheet.FirstRowNum).Cells) { dt.Columns.Add(item.ToString(), typeof(string)); } //寫入內容 System.Collections.IEnumerator rows = sheet.GetRowEnumerator(); while (rows.MoveNext()) { IRow row = (HSSFRow)rows.Current; if (row.RowNum == sheet.FirstRowNum) { continue; } DataRow dr = dt.NewRow(); foreach (ICell item in row.Cells) { switch (item.CellType) { case CellType.Boolean: dr[item.ColumnIndex] = item.BooleanCellValue; break; case CellType.Error: //dr[item.ColumnIndex] = ErrorEval.GetText(item.ErrorCellValue); break; case CellType.Formula: switch (item.CachedFormulaResultType) { case CellType.Boolean: dr[item.ColumnIndex] = item.BooleanCellValue; break; case CellType.Error: //dr[item.ColumnIndex] = ErrorEval.GetText(item.ErrorCellValue); break; case CellType.Numeric: if (DateUtil.IsCellDateFormatted(item)) { dr[item.ColumnIndex] = item.DateCellValue.ToString("yyyy-MM-dd hh:MM:ss"); } else { dr[item.ColumnIndex] = item.NumericCellValue; } break; case CellType.String: string str = item.StringCellValue; if (!string.IsNullOrEmpty(str)) { dr[item.ColumnIndex] = str.ToString(); } else { dr[item.ColumnIndex] = null; } break; case CellType.Unknown: case CellType.Blank: default: dr[item.ColumnIndex] = string.Empty; break; } break; case CellType.Numeric: if (DateUtil.IsCellDateFormatted(item)) { dr[item.ColumnIndex] = item.DateCellValue.ToString("yyyy-MM-dd hh:MM:ss"); } else { dr[item.ColumnIndex] = item.NumericCellValue; } break; case CellType.String: string strValue = item.StringCellValue; if (string.IsNullOrEmpty(strValue)) { dr[item.ColumnIndex] = strValue.ToString(); } else { dr[item.ColumnIndex] = null; } break; case CellType.Unknown: case CellType.Blank: default: dr[item.ColumnIndex] = string.Empty; break; } } dt.Rows.Add(dr); } } } return dt; } } }
用NPOI操作EXCEL--生成下拉列表
上一節我們講了簡單的數據有效性驗證,這一節我們學習一下數據有效性的另一個應用--下拉列表。在Excel中,並沒有類似Web中的下拉控件,其下拉效果是通過數據有效性來實現的。設置步驟為:
(1)選定一個要生成下拉列表的區域;
(2)設置數據有效性為序列,並在來源中填充可選下拉的值,用“,”隔開(如圖)。
對應的效果為:
同樣,利用NPOI代碼也可以實現上面的效果:
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);
HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
(1)選定一個要生成下拉列表的區域;
(2)設置數據有效性為序列,並在來源中填充可選下拉的值,用“,”隔開(如圖)。

對應的效果為:

同樣,利用NPOI代碼也可以實現上面的效果:
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");
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";
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);
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":