C#使用Npoi实现生成Word文档

 更新时间:2024年03月14日 14:41:42   作者:StevenChen85  
这篇文章主要为大家详细介绍了C#如何使用Npoi实现生成Word文档,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下

需求

按数据层级生成WORD文件,要有目录,目录里要有真实的页码,附件内容用表格显示,大标题 做为封面当独显示一页,

PDF内容

大标题,

目录(里有对应的页码)

正文 里有 表格

重点:NPOI 在生成word文件时不会自动生成总页数,所以本人使用了一个固定行索引来计算页码的功能。 使用 12 号字体,一页是44行,按这个方法计算页码。有更好的方法可以在评论区告诉我。

表格使用方法也要注意

1.注意 CreateTable()方法里会默认添加一行,这时如果使用 table.CreateRow() 方法创建新行这时就会有两行。第一行为只有一个默认的单元格。所有正确的方法是使用table.GetRow(0)方法

2.注意 table.CreateRow()方法也会默认添一列,由于第一行已确定了表格的列数所要直接使用GetCell(0)方法获取列对象,0表示列索引 AddNewTableCell()方法会在第一行的列数上再加列,所以正确的用法是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文件流来写入数据(传入参数为:文件所在路径,对文件的操作方式,对文件内数据的操作)
            //通过使用文件流,创建文件流对象,向文件流中写入内容,并保存为Word文档格式
            using (var stream = new FileStream(outMergeFile, FileMode.Create, FileAccess.Write))
            {
                //创建document文档对象对象实例
                XWPFDocument document = new XWPFDocument();
                /**
                 *这里我通过设置公共的Word文档中SetParagraph(段落)实例创建和段落样式格式设置,大大减少了代码的冗余,
                 * 避免每使用一个段落而去创建一次段落实例和设置段落的基本样式
                 *(如下,ParagraphInstanceSetting为段落实例创建和样式设置,后面索引表示为当前是第几行段落,索引从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++;
                }
                //文本标题 要显示一页
                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;
                    //标题
                    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);
                        //内容
                        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, "    (一)检索结果分析列表", 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()方法里会默认添加一行,这时如果使用 table.CreateRow() 方法创建新行这时就会有两行。第一行为只有一个默认的单元格
                        //所有正确的方法是使用table.GetRow(0);方法
                        var table = document.CreateTable();
                        XWPFTableRow tableHeadRow = table.GetRow(0);//新增行
                        tableHeadRow.GetCell(0).SetText("标题");
                        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()方法也会默认添一列,由于第一行已确定了表格的列数所要直接使用GetCell(0)方法获取列对象,0表示列索引
                            //AddNewTableCell()方法会在第一行的列数上再加列,所以正确的用法是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)
                        {
                            //标题
                            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);
 
                            //内容
                            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
                //向文档流中写入内容,生成word
                document.Write(stream);
            }
            return outMergeFile;
        }
 
        /// <summary>
        /// 设置word的Pages 总页数
        /// </summary>
        /// <param name="document"></param>
        /// <param name="rowIndex">行索引</param>
        /// <param name="pageRowCount">每页的总行数</param>
        /// <param name="iPageNum">当前页索引</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;
                }
            }
        }

调用

注意 要调用两次,第一次生成时不知道目录里的内容在第几页,第一次在生成时收集页码。这时会生成一个临时文件。第二次生成的目录里的页码才是真实有效的数据。所以要生成两次。

就好比你在写WORD时也是不知道目录里的内容会写在第几次,都是一、二级标题和内容都写完后,再去生成目录的。这里的道理也是一样的。

//word
                    var fileNameTempPath = generateWordFile(model, caseDetailsViewModels, uploadPath, fileNameTemp);
                    savePath = generateWordFile(model, caseDetailsViewModels, uploadPath, fileName);
                    //删除临时文件
                    if (File.Exists(fileNameTempPath))
                    {
                        File.Delete(fileNameTempPath);
                    }

到此这篇关于C#使用Npoi实现生成Word文档的文章就介绍到这了,更多相关C# Npoi生成Word内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • c# 共享状态的文件读写实现代码

    c# 共享状态的文件读写实现代码

    开发中有时会遇到要对文件进行共享状态的读写操作,代码如下,需要的朋友可以参考下
    2012-06-06
  • 全面分析c# LINQ

    全面分析c# LINQ

    这篇文章主要介绍了c# LINQ的相关资料,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
    2020-08-08
  • Unity实现喷漆效果

    Unity实现喷漆效果

    这篇文章主要为大家详细介绍了Unity实现喷漆效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • C#实现SMTP邮件发送程序实例

    C#实现SMTP邮件发送程序实例

    这篇文章主要介绍了C#实现SMTP邮件发送程序实例,是一个非常常见的实用技巧,需要的朋友可以参考下
    2014-10-10
  • C#插入图片到Excel表格单元格代码详解

    C#插入图片到Excel表格单元格代码详解

    在本篇文章里小编给大家整理了关于C#插入图片到Excel表格单元格的具体方法和实例代码,需要的朋友们可以学习下。
    2019-07-07
  • C#使用JsonConvert全面解析JSON

    C#使用JsonConvert全面解析JSON

    这篇文章主要介绍了C#使用JsonConvert全面解析JSON,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • Winform窗体圆角设计代码

    Winform窗体圆角设计代码

    这篇文章主要为大家详细介绍了Winform窗体圆角设计代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • C#12中的Collection expressions集合表达式语法糖详解

    C#12中的Collection expressions集合表达式语法糖详解

    C#12中引入了新的语法糖来创建常见的集合,并且可以使用..来解构集合,将其内联到另一个集合中,下面就跟随小编一起学习一下C#12中这些语法糖的使用吧
    2023-11-11
  • Winform学生信息管理系统各子窗体剖析(3)

    Winform学生信息管理系统各子窗体剖析(3)

    这篇文章主要针对Winform学生信息管理系统各子窗体进行剖析,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • C#访问SqlServer设置链接超时的方法

    C#访问SqlServer设置链接超时的方法

    这篇文章主要介绍了C#访问SqlServer设置链接超时的方法,涉及CommandTimeout属性的相关设置技巧,非常简单实用,需要的朋友可以参考下
    2015-06-06

最新评论