1. 程式人生 > 其它 >NPOI的使用(著重word文件的寫入)

NPOI的使用(著重word文件的寫入)

之前用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);
            }
        }
    }
}