C#使用Npoi實現(xiàn)生成Word文檔
需求
按數(shù)據(jù)層級生成WORD文件,要有目錄,目錄里要有真實的頁碼,附件內(nèi)容用表格顯示,大標(biāo)題 做為封面當(dāng)獨(dú)顯示一頁,
PDF內(nèi)容
大標(biāo)題,
目錄(里有對應(yīng)的頁碼)
正文 里有 表格
重點(diǎn):NPOI 在生成word文件時不會自動生成總頁數(shù),所以本人使用了一個固定行索引來計算頁碼的功能。 使用 12 號字體,一頁是44行,按這個方法計算頁碼。有更好的方法可以在評論區(qū)告訴我。
表格使用方法也要注意
1.注意 CreateTable()方法里會默認(rèn)添加一行,這時如果使用 table.CreateRow() 方法創(chuàng)建新行這時就會有兩行。第一行為只有一個默認(rèn)的單元格。所有正確的方法是使用table.GetRow(0)方法
2.注意 table.CreateRow()方法也會默認(rèn)添一列,由于第一行已確定了表格的列數(shù)所要直接使用GetCell(0)方法獲取列對象,0表示列索引 AddNewTableCell()方法會在第一行的列數(shù)上再加列,所以正確的用法是GetCell(0)方法
代碼
/// <summary> /// 生成報告詳情文件 pdf /// </summary> /// <param name="model"></param> /// <param name="caseDetailsViewModels"></param> /// <param name="TargetPath">目錄路徑</param> /// <param name="NewFileName">文件名</param> /// <returns></returns> private static string generateWordFile(ViewModel model, List<detailsViewModel> detailsViewModels, string TargetPath, string NewFileName) { string outMergeFile = TargetPath + NewFileName; int rowIndex = 0;//行索引 //TODO:使用FileStream文件流來寫入數(shù)據(jù)(傳入?yún)?shù)為:文件所在路徑,對文件的操作方式,對文件內(nèi)數(shù)據(jù)的操作) //通過使用文件流,創(chuàng)建文件流對象,向文件流中寫入內(nèi)容,并保存為Word文檔格式 using (var stream = new FileStream(outMergeFile, FileMode.Create, FileAccess.Write)) { //創(chuàng)建document文檔對象對象實例 XWPFDocument document = new XWPFDocument(); /** *這里我通過設(shè)置公共的Word文檔中SetParagraph(段落)實例創(chuàng)建和段落樣式格式設(shè)置,大大減少了代碼的冗余, * 避免每使用一個段落而去創(chuàng)建一次段落實例和設(shè)置段落的基本樣式 *(如下,ParagraphInstanceSetting為段落實例創(chuàng)建和樣式設(shè)置,后面索引表示為當(dāng)前是第幾行段落,索引從0開始) */ //12號字 44行一頁 //for (int i = 1; i <= 50; i++) //{ // document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, i.ToString(), true, 12, "黑體", ParagraphAlignment.CENTER), rowIndex); // rowIndex++; //} int iPageNum = 1;//頁索引 int pageRowCount = 44;//每頁44行 //第一頁 for (int i = 1; i <= 21; i++) { document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, String.Empty, true, 12, "黑體", ParagraphAlignment.CENTER), rowIndex); rowIndex++; } //文本標(biāo)題 要顯示一頁 document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, model.TitleModel.F_ContentStr ?? string.Empty, true, 20, "黑體", ParagraphAlignment.CENTER), rowIndex); rowIndex++; for (int i = 1; i <= 22; i++) { document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, String.Empty, true, 12, "黑體", ParagraphAlignment.CENTER), rowIndex); rowIndex++; } //空行 //document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, string.Empty, true, 12, "宋體", ParagraphAlignment.LEFT), rowIndex); //rowIndex++; document.GetProperties().ExtendedProperties.GetUnderlyingProperties().Pages = iPageNum; var fontSizeTwoTitle = 16; var fontSizeTwoBody = 12; var fontSize = 12; iPageNum++; //目錄最大行索引 var catalogueRowCount = iPageNum * pageRowCount; document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, "目錄", true, 16, "黑體", ParagraphAlignment.CENTER), rowIndex); setWordPages(document, ref rowIndex, pageRowCount, ref iPageNum); //一、檢索目的...............................................4~4 var catalogueTest = "一、檢索目的...............................................4~4"; //目錄 要顯示一頁 //TODO:這里一行需要顯示兩個文本 foreach (var item in model.TwoTitleList) { if (!string.IsNullOrEmpty(item.F_ContentStr)) { StringBuilder catalogueText = new StringBuilder(item.F_ContentStr);//string.Format(" {0}.{1}", item.F_ContentStr ?? string.Empty, item.F_Page ?? "1~1"); string pageNameTxt = !string.IsNullOrEmpty(item.F_Page) ? item.F_Page : "1~1"; int beginI = catalogueText.ToString().Length + pageNameTxt.Length; for (int i = beginI; i < catalogueTest.Length; i++) { catalogueText.Append("."); } catalogueText.Append(pageNameTxt); document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, catalogueText.ToString(), false, fontSize, "宋體", ParagraphAlignment.LEFT), rowIndex); setWordPages(document, ref rowIndex, pageRowCount, ref iPageNum); } } for (int i = rowIndex; i < catalogueRowCount; i++) { document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, String.Empty, true, 12, "黑體", ParagraphAlignment.CENTER), rowIndex); setWordPages(document, ref rowIndex, pageRowCount, ref iPageNum); } #region 正文 從第三頁開始 iPageNum = 3; int beginPageNum = 3; foreach (var item in model.TwoTitleList) { beginPageNum = document.GetProperties().ExtendedProperties.GetUnderlyingProperties().Pages; //標(biāo)題 document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, string.Format("{0}", item.F_ContentStr ?? string.Empty), false, fontSizeTwoTitle, "宋體", ParagraphAlignment.LEFT, false, String.Empty, "165DFF"), rowIndex); setWordPages(document, ref rowIndex, pageRowCount, ref iPageNum); foreach (var itemThree in item.ThreeContentList) { itemThree.F_ContentStr = itemThree.F_ContentStr.Replace("\r\n", string.Empty); //內(nèi)容 if (itemThree.F_ContentStr.Contains("</p>")) { var contentStr = itemThree.F_ContentStr.Replace("<p>", string.Empty); var contentList = contentStr.Split("</p>"); foreach (var itemCon in contentList) { var itemConTxt = itemCon.Replace("\n", string.Empty).Trim(); document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, string.Format(" {0}", itemConTxt), false, fontSizeTwoBody, "宋體", ParagraphAlignment.LEFT), rowIndex); setWordPages(document, ref rowIndex, pageRowCount, ref iPageNum); } } else { var F_ContentStrTxt = itemThree.F_ContentStr.Replace("\n", string.Empty).Trim(); document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, string.Format(" {0}", F_ContentStrTxt), false, fontSizeTwoBody, "宋體", ParagraphAlignment.LEFT), rowIndex); setWordPages(document, ref rowIndex, pageRowCount, ref iPageNum); } } int pages = document.GetProperties().ExtendedProperties.GetUnderlyingProperties().Pages; item.F_Page = string.Format("{0}~{1}", beginPageNum, pages); iPageNum = pages; } #endregion #region 附件 if (model.FileList != null && model.FileList.Count > 0) { document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, " (一)檢索結(jié)果分析列表", false, fontSizeTwoTitle, "宋體", ParagraphAlignment.LEFT), rowIndex); setWordPages(document, ref rowIndex, pageRowCount, ref iPageNum); document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, " ", false, fontSize, "宋體", ParagraphAlignment.LEFT), rowIndex); setWordPages(document, ref rowIndex, pageRowCount, ref iPageNum); int groupNum = 1; foreach (var item in model.FileList) { var KeywordTxt = !string.IsNullOrEmpty(item.Keyword) ? item.Keyword : string.Empty; KeywordTxt = KeywordTxt.Replace("\n", string.Empty).Trim(); document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, string.Format(" {0}", KeywordTxt), false, fontSizeTwoBody, "宋體", ParagraphAlignment.LEFT), rowIndex); setWordPages(document, ref rowIndex, pageRowCount, ref iPageNum); document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, " ", false, fontSize, "宋體", ParagraphAlignment.LEFT), rowIndex); setWordPages(document, ref rowIndex, pageRowCount, ref iPageNum); //注意CreateTable()方法里會默認(rèn)添加一行,這時如果使用 table.CreateRow() 方法創(chuàng)建新行這時就會有兩行。第一行為只有一個默認(rèn)的單元格 //所有正確的方法是使用table.GetRow(0);方法 var table = document.CreateTable(); XWPFTableRow tableHeadRow = table.GetRow(0);//新增行 tableHeadRow.GetCell(0).SetText("標(biāo)題"); tableHeadRow.GetCell(0).SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); var tableHeadRowCell_CaseCode = tableHeadRow.AddNewTableCell(); tableHeadRowCell_CaseCode.SetText("案號"); tableHeadRowCell_CaseCode.SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); var tableHeadRowCell_IsAdd = tableHeadRow.AddNewTableCell(); tableHeadRowCell_IsAdd.SetText("是否加入檢索報告"); tableHeadRowCell_IsAdd.SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); var tableHeadRowCell_NoAddCause = tableHeadRow.AddNewTableCell(); tableHeadRowCell_NoAddCause.SetText("未加入檢索報告原因"); tableHeadRowCell_NoAddCause.SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); foreach (var itemKey in item.KeywordFileList) { //注意 table.CreateRow()方法也會默認(rèn)添一列,由于第一行已確定了表格的列數(shù)所要直接使用GetCell(0)方法獲取列對象,0表示列索引 //AddNewTableCell()方法會在第一行的列數(shù)上再加列,所以正確的用法是GetCell(0)方法 XWPFTableRow tableBodyRow = table.CreateRow();//新增行 //var tableBodyRowCell_Title = tableBodyRow.AddNewTableCell(); //tableBodyRowCell_Title.SetText(itemKey.F_CaseTitle ?? String.Empty); //tableBodyRowCell_Title.SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); tableBodyRow.GetCell(0).SetText(itemKey.F_CaseTitle ?? string.Empty); //var tableBodyRowCell_CaseCode = tableBodyRow.AddNewTableCell(); //tableBodyRowCell_CaseCode.SetText(itemKey.F_CaseCode ?? String.Empty); //tableBodyRowCell_CaseCode.SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); tableBodyRow.GetCell(1).SetText(itemKey.F_CaseCode ?? string.Empty); //var tableBodyRowCell_IsAdd = tableBodyRow.AddNewTableCell(); //tableBodyRowCell_IsAdd.SetText(itemKey.F_IsAdd ? "是" : "否"); //tableBodyRowCell_IsAdd.SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); tableBodyRow.GetCell(2).SetText(itemKey.F_IsAdd ? "是" : "否"); tableBodyRow.GetCell(2).SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); //var tableBodyRowCell_NoAddCause = tableBodyRow.AddNewTableCell(); //tableBodyRowCell_NoAddCause.SetText(itemKey.F_NoAddCause ?? String.Empty); //tableBodyRowCell_NoAddCause.SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); tableBodyRow.GetCell(3).SetText(itemKey.F_NoAddCause ?? string.Empty); groupNum++; } } } #endregion #region 生成案例 if (caseDetailsViewModels != null && caseDetailsViewModels.Count > 0) { document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, string.Format(" (二)檢索案例全文"), false, fontSize, "宋體", ParagraphAlignment.LEFT), rowIndex); setWordPages(document, ref rowIndex, pageRowCount, ref iPageNum); document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, " ", false, fontSize, "宋體", ParagraphAlignment.LEFT), rowIndex); setWordPages(document, ref rowIndex, pageRowCount, ref iPageNum); foreach (var item in caseDetailsViewModels) { foreach (var itemCase in item.CaseItemList) { //標(biāo)題 var F_TitleTxt = itemCase.F_Title.Replace("\r\n", string.Empty); document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, string.Format(" {0}", F_TitleTxt), false, fontSize, "宋體", ParagraphAlignment.LEFT), rowIndex); setWordPages(document, ref rowIndex, pageRowCount, ref iPageNum); //內(nèi)容 itemCase.F_Content = itemCase.F_Content.Replace("\r\n", string.Empty); if (itemCase.F_Content.Contains("</p>")) { var contentStr = itemCase.F_Content.Replace("<p>", string.Empty); var contentList = contentStr.Split("</p>"); foreach (var itemCon in contentList) { var itemConTxt = itemCon.Replace("\n", string.Empty).Trim(); document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, string.Format(" {0}", itemConTxt), false, fontSize, "宋體", ParagraphAlignment.LEFT), rowIndex); setWordPages(document, ref rowIndex, pageRowCount, ref iPageNum); //if (writer.PageNumber > iPageNum) //{ // writePageNumber(document, writer, BF_Light); //} } } else { var F_ContentTxt = itemCase.F_Content.Replace("\n", string.Empty).Trim(); document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, string.Format(" {0}", F_ContentTxt), false, fontSize, "宋體", ParagraphAlignment.LEFT), rowIndex); setWordPages(document, ref rowIndex, pageRowCount, ref iPageNum); } } } } #endregion //向文檔流中寫入內(nèi)容,生成word document.Write(stream); } return outMergeFile; } /// <summary> /// 設(shè)置word的Pages 總頁數(shù) /// </summary> /// <param name="document"></param> /// <param name="rowIndex">行索引</param> /// <param name="pageRowCount">每頁的總行數(shù)</param> /// <param name="iPageNum">當(dāng)前頁索引</param> private static void setWordPages(XWPFDocument document, ref int rowIndex, int pageRowCount, ref int iPageNum) { rowIndex++; if (document != null) { if ((rowIndex % pageRowCount) == 0) { iPageNum++; document.GetProperties().ExtendedProperties.GetUnderlyingProperties().Pages = iPageNum; } } }
調(diào)用
注意 要調(diào)用兩次,第一次生成時不知道目錄里的內(nèi)容在第幾頁,第一次在生成時收集頁碼。這時會生成一個臨時文件。第二次生成的目錄里的頁碼才是真實有效的數(shù)據(jù)。所以要生成兩次。
就好比你在寫WORD時也是不知道目錄里的內(nèi)容會寫在第幾次,都是一、二級標(biāo)題和內(nèi)容都寫完后,再去生成目錄的。這里的道理也是一樣的。
//word var fileNameTempPath = generateWordFile(model, caseDetailsViewModels, uploadPath, fileNameTemp); savePath = generateWordFile(model, caseDetailsViewModels, uploadPath, fileName); //刪除臨時文件 if (File.Exists(fileNameTempPath)) { File.Delete(fileNameTempPath); }
到此這篇關(guān)于C#使用Npoi實現(xiàn)生成Word文檔的文章就介紹到這了,更多相關(guān)C# Npoi生成Word內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
結(jié)合.net框架在C#派生類中觸發(fā)基類事件及實現(xiàn)接口事件
這篇文章主要介紹了結(jié)合.net框架在C#派生類中觸發(fā)基類事件及實現(xiàn)接口事件,示例的事件編程中包括接口和類的繼承等面向?qū)ο蟮幕A(chǔ)知識,需要的朋友可以參考下2016-02-02C#簡單訪問SQLite數(shù)據(jù)庫的方法(安裝,連接,查詢等)
這篇文章主要介紹了C#簡單訪問SQLite數(shù)據(jù)庫的方法,涉及SQLite數(shù)據(jù)庫的下載、安裝及使用C#連接、查詢SQLIte數(shù)據(jù)庫的相關(guān)技巧,需要的朋友可以參考下2016-07-07.NET中保證線程安全的高級方法Interlocked類使用介紹
這篇文章主要介紹了.NET中保證線程安全的高級方法Interlocked類使用介紹,Interlocked類可以為為多個線程共享的變量提供原子操作,需要的朋友可以參考下2014-07-07WPF利用WindowChrome實現(xiàn)自定義窗口
這篇文章主要為大家詳細(xì)介紹了WPF如何利用WindowChrome實現(xiàn)自定義窗口,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,需要的可以參考一下2023-02-02C#使用oledb讀取excel表格內(nèi)容到datatable的方法
這篇文章主要介紹了C#使用oledb讀取excel表格內(nèi)容到datatable的方法,涉及C#操作oledb及datatable的相關(guān)技巧,需要的朋友可以參考下2015-05-05c# 動態(tài)加載dll文件,并實現(xiàn)調(diào)用其中的方法(推薦)
下面小編就為大家?guī)硪黄猚# 動態(tài)加載dll文件,并實現(xiàn)調(diào)用其中的方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02C#強(qiáng)制轉(zhuǎn)換和嘗試轉(zhuǎn)換的方法
這篇文章主要為大家詳細(xì)介紹了C#強(qiáng)制轉(zhuǎn)換和嘗試轉(zhuǎn)換的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-09-09