NPOI的使用(著重word文件的寫入)
阿新 • • 發佈:2022-04-08
之前用NPOI做word文件的匯出,查詢了大量資料,在此做一記錄
不做過多講解 直接上程式碼(word匯出當中有一些業務處理,檢視時自行甄別)
using System; using System.Collections.Generic; using System.Linq; using System.Web; using NPOI.HSSF.UserModel; using NPOI.HPSF; using NPOI.POIFS.FileSystem; using System.IO; using System.Reflection; using NPOI.SS.UserModel; using System.Data; using NPOI.XSSF.UserModel; using NPOI.XWPF.UserModel; using Models; using IBLL; using Models.Common.Helpers; using Models.Common; using NPOI.OpenXmlFormats.Wordprocessing; using System.Web.Caching; namespace MOM.Helpers { public class NPOIHelper { public NPOIHelper() { } private static HSSFWorkbook hssfworkbook; public static IOrgChkBLL OrgChkBLL { get; set; } public static IFileInfBLL FileInfBLL { get; set; } /// 初始化 /// </summary> private static void InitializeWorkbook() { hssfworkbook = new HSSFWorkbook(); DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation(); dsi.Company = ""; hssfworkbook.DocumentSummaryInformation = dsi; SummaryInformation si = PropertySetFactory.CreateSummaryInformation(); si.Subject = ""; hssfworkbook.SummaryInformation = si; } /**//// <summary> /// DataTable寫入Excel /// </summary> /// <param name="FileName">要儲存的檔名稱 eg:test.xls</param> /// <param name="SheetName">工作薄名稱</param> /// <param name="dt">要寫入的DataTable </param> public static void WriteToDownLoad(string FileName, string SheetName, DataTable dt, List<string> lstTitle) { string filename = FileName; HttpContext.Current.Response.ContentType = "application/vnd.ms-excel"; //HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={}", filename)); HttpContext.Current.Response.Clear(); //初始化Excel資訊 InitializeWorkbook(); //填充資料 DTExcel(SheetName, dt, lstTitle); HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(FileName, System.Text.Encoding.UTF8).ToString()); HttpContext.Current.Response.BinaryWrite(WriteToStream().GetBuffer()); HttpContext.Current.Response.End(); } /// <summary> /// lstTitle 設定表頭 /// </summary> /// List寫入Excel /// </summary> /// <typeparam name="T">實體</typeparam> /// <param name="FileName">要儲存的檔名稱 eg:test.xls</param> /// <param name="SheetName">工作薄名稱</param> /// <param name="lst">要寫入的List</param> public static void WriteToDownLoad<T>(string FileName, string SheetName, IList<T> lst, List<string> lstTitle) { string filename = FileName; HttpContext.Current.Response.ContentType = "application/vnd.ms-excel"; // HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", FileName)); HttpContext.Current.Response.Clear(); HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(FileName, System.Text.Encoding.UTF8).ToString()); //初始化Excel資訊 InitializeWorkbook(); //填充資料 ListExcel<T>(SheetName, lst, lstTitle); HttpContext.Current.Response.BinaryWrite(WriteToStream().GetBuffer()); HttpContext.Current.Response.End(); } private static MemoryStream WriteToStream() { MemoryStream file = new MemoryStream(); hssfworkbook.Write(file); return file; } #region 資料填充部分 /// 將DataTable資料寫入到Excel /// </summary> /// <param name="SheetName"></param> /// <param name="dt"></param> /// <param name="lstTitle"></param> private static void DTExcel(string SheetName, DataTable dt, List<string> lstTitle) { ISheet sheet = hssfworkbook.CreateSheet(SheetName); int y = dt.Columns.Count; int x = dt.Rows.Count; //給定的標題為空,賦值datatable預設的列名 if (lstTitle == null) { lstTitle = new List<string>(); for (int ycount = 0; ycount < y; ycount++) { lstTitle.Add(dt.Columns[ycount].ColumnName); } } IRow hsTitleRow = sheet.CreateRow(0); //標題賦值 for (int yt = 0; yt < lstTitle.Count; yt++) { hsTitleRow.CreateCell(yt).SetCellValue(lstTitle[yt]); } //填充資料項 for (int xcount = 1; xcount < x; xcount++) { IRow hsBodyRow = sheet.CreateRow(xcount); for (int ycBody = 0; ycBody < y; ycBody++) { hsBodyRow.CreateCell(ycBody).SetCellValue(dt.DefaultView[xcount - 1][ycBody].ToString()); } } } private static void ListExcel<T>(string SheetName, IList<T> lst, List<string> lstTitle) { ISheet sheet = hssfworkbook.CreateSheet(SheetName); T _t = (T)Activator.CreateInstance(typeof(T)); PropertyInfo[] propertys = _t.GetType().GetProperties(); //給定的標題為空,賦值T預設的列名 if (lstTitle == null) { lstTitle = new List<string>(); for (int ycount = 0; ycount < propertys.Length; ycount++) { lstTitle.Add(((System.Reflection.MemberInfo)(propertys[ycount])).Name);//獲取實體中列名稱,去掉列型別 } } IRow hsTitleRow = sheet.CreateRow(0); //獲取title設定列 int lstcount = lstTitle.Count(); //標題賦值 for (int yt = 0; yt < lstTitle.Count; yt++) { hsTitleRow.CreateCell(yt).SetCellValue(lstTitle[yt]); } //填充資料項 for (int xcount = 0; xcount < lst.Count; xcount++) { IRow hsBodyRow = sheet.CreateRow(xcount + 1); for (int ycBody = 0; ycBody < lstcount; ycBody++) { PropertyInfo pi = propertys[ycBody]; object obj = pi.GetValue(lst[xcount], null); hsBodyRow.CreateCell(ycBody).SetCellValue(obj.ToString()); } } } #endregion 資料填充部分 /// <summary> /// 將Excel匯入DataTable /// </summary> /// <param name="filepath">匯入的檔案路徑(包括檔名)</param> /// <param name="sheetname">工作表名稱</param> /// <param name="isFirstRowColumn">第一行是否是DataTable的列名</param> /// <param name="numRow">從第幾行開始匯入</param> /// <returns>DataTable</returns> public static DataTable ExcelToDataTable(string filepath, Stream file, string sheetname, bool isFirstRowColumn, int numRow) { numRow = numRow < 1 ? 0 : numRow - 1; ISheet sheet = null;//工作表 DataTable data = new DataTable(); IWorkbook workbook = null; var startrow = 0; using (file) { try { if (filepath.IndexOf(".xlsx") > 0) // 2007版本 workbook = new XSSFWorkbook(file); else if (filepath.IndexOf(".xls") > 0) // 2003版本 workbook = new HSSFWorkbook(file); if (sheetname != null) { sheet = workbook.GetSheet(sheetname); if (sheet == null) //如果沒有找到指定的sheetName對應的sheet,則嘗試獲取第一個sheet { sheet = workbook.GetSheetAt(0); } } else { sheet = workbook.GetSheetAt(0); } if (sheet != null) { IRow firstrow = sheet.GetRow(0); int cellCount = firstrow.LastCellNum; //行最後一個cell的編號 即總的列數 if (isFirstRowColumn) { for (int i = firstrow.FirstCellNum; i < cellCount; i++) { NPOI.SS.UserModel.ICell cell = firstrow.GetCell(i); if (cell != null) { string cellvalue = cell.StringCellValue; if (cellvalue != null) { DataColumn column = new DataColumn(cellvalue); data.Columns.Add(column); } } } startrow = sheet.FirstRowNum + numRow; } else { startrow = sheet.FirstRowNum + numRow; } //讀資料行 int rowcount = sheet.LastRowNum; for (int i = startrow; i <= rowcount; i++) { IRow row = sheet.GetRow(i); if (row == null) { continue; //沒有資料的行預設是null } DataRow datarow = data.NewRow();//具有相同架構的行 for (int j = row.FirstCellNum; j < cellCount; j++) { if (row.GetCell(j) != null) { //如果是公式Cell //則僅讀取其Cell單元格的顯示值 而不是讀取公式 if (row.GetCell(j).CellType == CellType.Formula) { row.GetCell(j).SetCellType(CellType.String); datarow[j] = row.GetCell(j).StringCellValue; } else { datarow[j] = row.GetCell(j).ToString(); } } } data.Rows.Add(datarow); } } return data; } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); return null; } finally { file.Close(); file.Dispose(); } } } /// <summary> /// 新增標題樣式 /// </summary> /// <param name="docxDocument"></param> /// <param name="strStyleId"></param> /// <param name="headingLevel"></param> private static void addCustomHeadingStyle(XWPFDocument docxDocument, String strStyleId, int headingLevel) { CT_Style ctStyle = new CT_Style(); ctStyle.styleId = strStyleId; CT_String styleName = new CT_String(); styleName.val = strStyleId; ctStyle.name = styleName; CT_DecimalNumber indentNumber = new CT_DecimalNumber(); indentNumber.val = headingLevel.ToString(); // lower number > style is more prominent in the formats bar ctStyle.uiPriority = indentNumber; CT_OnOff onoffnull = new CT_OnOff(); ctStyle.unhideWhenUsed = onoffnull; // style shows up in the formats bar ctStyle.qFormat = onoffnull; // style defines a heading of the given level CT_PPr ppr = new CT_PPr(); ppr.outlineLvl = indentNumber; ctStyle.pPr = ppr; XWPFStyle style = new XWPFStyle(ctStyle); // is a null op if already defined XWPFStyles styles = docxDocument.CreateStyles(); style.StyleType = ST_StyleType.paragraph; styles.AddStyle(style); } /// <summary> /// word文件匯出(包含業務程式碼,檢視時需甄別) /// </summary> /// <param name="CpnID">企業程式碼</param> /// <param name="MdlID">模板程式碼</param> /// <param name="OrgID">機構程式碼</param> /// <param name="PstID1">崗位</param> /// <param name="ItemIDFat">父級事項程式碼</param> /// <param name="ItemIDs">事項程式碼</param> /// <param name="Sdt">開始日期</param> /// <param name="Edt">結束日期</param> /// <param name="prmFileInf"></param> /// <param name="IsExplain">是否包含說明</param> /// <param name="IsPicture">是否包含圖片</param> /// <returns></returns> public static OperateReturnInfo CreateWordToOrgchkfl(string CpnID,string key, FileInfInfo prmFileInf,List<OrgChkDtlInfo> orgchkdtls) { CacheHelper.SetCache(key, 0, Cache.NoAbsoluteExpiration, new TimeSpan(1, 0, 0), CacheItemPriority.High); try { //迴圈層級,3-1對應1-3,根據層級計算縮排和字型大小 int lvl = 3;// string.IsNullOrWhiteSpace(ItemIDFat) && string.IsNullOrWhiteSpace(ItemIDs) ? 3 : !string.IsNullOrWhiteSpace(ItemIDFat) && ItemIDFat.Length == 4 && string.IsNullOrWhiteSpace(ItemIDs) ? 2 : !string.IsNullOrWhiteSpace(ItemIDFat) && ItemIDFat.Length == 2 && string.IsNullOrWhiteSpace(ItemIDs) ? 3 : 1; if (lvl == 3) { var dtls = orgchkdtls.GroupBy(x => x.firstItem).Select(y => new OrgChkDtlInfo { ItemID = y.Key.Substring(0, y.Key.IndexOf(' ')), ItemName = y.Key.Substring(y.Key.IndexOf(' ')) }).ToList(); var dtls1 = orgchkdtls.GroupBy(x => x.secondItem).Select(y => new OrgChkDtlInfo { ItemID = y.Key.Substring(0, y.Key.IndexOf(' ')), ItemName = y.Key.Substring(y.Key.IndexOf(' ')) }).ToList(); orgchkdtls.AddRange(dtls); orgchkdtls.AddRange(dtls1); } if (lvl == 2) { orgchkdtls.ToList().AddRange(orgchkdtls.GroupBy(x => x.secondItem).Select(y => new OrgChkDtlInfo { ItemID = y.Key.Substring(0, y.Key.IndexOf(' ')), ItemName = y.Key.Substring(y.Key.IndexOf(' ')) })); } orgchkdtls = orgchkdtls.OrderBy(x => x.ItemID).ToList(); //建立document物件 var doc = new XWPFDocument(); addCustomHeadingStyle(doc, "Heading1", 1); //建立標題 var ptit = doc.CreateParagraph();//段落 ptit.Alignment = ParagraphAlignment.CENTER; //字型居中 var t = ptit.StyleID; var runTitle = ptit.CreateRun(); runTitle.SetText(prmFileInf.AttName.Substring(0, prmFileInf.AttName.LastIndexOf('.'))); runTitle.FontSize = 18; runTitle.IsBold = true; runTitle.SetFontFamily("宋體", FontCharRange.None); //設定 var itemids = orgchkdtls.GroupBy(x => new { x.ItemID, x.ItemName }); int firindex = 0; int secindex = 0; int index = 0; int writeIndex = 0; foreach (var item in itemids) { writeIndex++; string nowspace = ""; string nowindex = string.Empty; int FontSize = 10; //根據層級產生編號,字型大小 if (item.Key.ItemID.Length == 2 && lvl == 3) { FontSize = 14; firindex++; nowindex = firindex.ToString(); secindex = 0; index = 0; } else if (item.Key.ItemID.Length == 4) { if (lvl == 3) nowspace = " "; FontSize = 12; secindex++; nowindex = firindex + "-" + secindex; index = 0; } else { index++; FontSize = 10; if (lvl == 3) { nowindex = firindex + "-" + secindex + "-" + index; nowspace = " "; } else if (lvl == 2) { nowindex = secindex + "-" + index; nowspace = " "; } else nowindex = index.ToString(); if (index > 1)//每個事項間隔一行空白 { var ptit1 = doc.CreateParagraph();//段落 ptit1.Alignment = ParagraphAlignment.CENTER; //字型居中 var runTitle1 = ptit.CreateRun(); runTitle1.SetText(""); } } var p = doc.CreateParagraph();//事項段落 p.Alignment = ParagraphAlignment.LEFT; var run = p.CreateRun(); if (item.Key.ItemID.Length < 6) run.IsBold = true; run.SetText(nowspace + nowindex + "、" + item.Key.ItemName); run.FontSize = FontSize; run.SetFontFamily("宋體", FontCharRange.CS); //設定字型 p.Style = "Heading1"; if (item.Key.ItemID.Length < 6) continue; foreach (var dtl in orgchkdtls.Where(x => x.ItemID == item.Key.ItemID))//新增事項下面所有圖片和說明 { var p1 = doc.CreateParagraph(); var run1 = p1.CreateRun(); run1.SetText(nowspace + dtl.ChrgName); run1.FontSize = 8; run1.SetColor("#959595"); run1.SetFontFamily("宋體", FontCharRange.None); //設定字型 if (!string.IsNullOrEmpty(dtl.FileName)) { string[] files = dtl.FileName.Split(','); for (int i = 0; i < files.Count(); i++) { string path = files[i].Substring(files[i].LastIndexOf('_') + 1); string imgsavepath = MapPath("/Files/NPOI_" + path); try { S3Helper.DownloadS3File(CpnID + "/" + files[i].Substring(0, (files[i].LastIndexOf('_'))).Replace("_", "/"), files[i].Substring(files[i].LastIndexOf('_') + 1), imgsavepath); FileStream gfs = new FileStream(imgsavepath, FileMode.Open, FileAccess.Read); if (gfs != null) { var p2 = doc.CreateParagraph(); var run2 = p2.CreateRun(); run2.AddPicture(gfs, (int)NPOI.XWPF.UserModel.PictureType.JPEG, "1.jpg", 4500000, 3000000); if (i == (files.Count() - 1)) { run2.AddCarriageReturn(); run2.SetText(nowspace + dtl.UptDtt.ToString("MM月dd日") + " " + dtl.Brf); run2.SetTextPosition(10); run2.FontSize = 7; run2.SetFontFamily("宋體", FontCharRange.None); //設定字型 } gfs.Close(); } File.Delete(imgsavepath); } catch (Exception) { var p2 = doc.CreateParagraph(); var run2 = p2.CreateRun(); if (i == (files.Count() - 1)) { run2.AddCarriageReturn(); run2.SetText(nowspace + dtl.UptDtt.ToString("MM月dd日") + " " + dtl.Brf); run2.SetTextPosition(10); run2.FontSize = 7; run2.SetFontFamily("宋體", FontCharRange.None); //設定字型 } } } } else { var p2 = doc.CreateParagraph(); var run2 = p2.CreateRun(); run2.SetText(nowspace + dtl.UptDtt.ToString("MM月dd日") + " " + dtl.Brf); run2.SetTextPosition(10); run2.FontSize = 7; run2.SetFontFamily("宋體", FontCharRange.None); //設定字型 } } var write = Math.Round((decimal)writeIndex / itemids.Count() * 100, 0); CacheHelper.SetCache(key, write > 99 ? 99 : write, Cache.NoAbsoluteExpiration, new TimeSpan(1, 0, 0), CacheItemPriority.High); } //儲存文件至S3 FileStream os = new FileStream(MapPath("/Files/NPOI_" + prmFileInf.KeyVl + ".doc"), FileMode.OpenOrCreate); doc.Write(os); string filesavepath = MapPath("/Files/NPOI_" + prmFileInf.KeyVl + ".doc"); FileStream fileStream = new FileStream(filesavepath, FileMode.Open, FileAccess.Read, FileShare.Read); // 讀取檔案的 byte[] byte[] bytes = new byte[fileStream.Length]; fileStream.Read(bytes, 0, bytes.Length); fileStream.Close(); // 把 byte[] 轉換成 Stream Stream stream = new MemoryStream(bytes); var dt = DateTime.Now; string a = S3Helper.UploadToStream(CpnID + "/" + dt.Year + "/" + dt.Month + "/" + "Orgchkfl", Amazon.S3.S3CannedACL.Private, prmFileInf.KeyVl + ".doc", stream); prmFileInf.Attch = CpnID + "/" + dt.Year + "/" + dt.Month + "/" + "Orgchkfl/" + prmFileInf.KeyVl + ".doc"; File.Delete(filesavepath); CacheHelper.SetCache(key, 100, Cache.NoAbsoluteExpiration, new TimeSpan(1, 0, 0), CacheItemPriority.High); } catch (Exception e) { CacheHelper.RemoveCache(key); foreach (string var in Directory.GetFiles(MapPath("/Files/"))) { if (var.IndexOf("NPOI_") > -1) File.Delete(var); } return new OperateReturnInfo(OperateCode.Failed, "不合格典型案列生成失敗!錯誤:" + e.Message); } FileInfBLL.SaveFileInf(prmFileInf); return new OperateReturnInfo(OperateCode.Success, "不合格典型案列生成成功!"); } private static string MapPath(string strPath) { if (HttpContext.Current != null) { return MapPath(strPath); } else //非web程式引用 { strPath = strPath.Replace("/", "\\"); if (strPath.StartsWith("\\")) { //strPath = strPath.Substring(strPath.IndexOf('\\', 1)).TrimStart('\\'); strPath = strPath.TrimStart('\\'); } return System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, strPath); } } } }