一、基础

1、创建Word

using NPOI.XWPF.UserModel
XWPFDocument doc = new XWPFDocument(); //创建新的word文档 XWPFParagraph p1 = doc.CreateParagraph(); //向新文档中添加段落
p1.SetAlignment(ParagraphAlignment.CENTER); //段落对其方式为居中 XWPFRun r1 = p1.CreateRun(); //向该段落中添加文字
r1.SetText("测试段落一"); XWPFParagraph p2 = doc.CreateParagraph();
p2.SetAlignment(ParagraphAlignment.LEFT); XWPFRun r2 = p2.CreateRun();
r2.SetText("测试段落二");
     r2.SetFontSize();//设置字体大小
       r2.SetBlod(true);//设置粗体 FileStream sw = File.Create("cutput.docx"); //...
doc.Write(sw); //...
sw.Close(); //在服务端生成文件 FileInfo file = new FileInfo("cutput.docx");//文件保存路径及名称
//注意: 文件保存的父文件夹需添加Everyone用户,并给予其完全控制权限
Response.Clear();
Response.ClearHeaders();
Response.Buffer = false;
Response.ContentType = "application/octet-stream";
Response.AppendHeader("Content-Disposition", "attachment;filename="
+ HttpUtility.UrlEncode("output.docx", System.Text.Encoding.UTF8));
Response.AppendHeader("Content-Length", file.Length.ToString());
Response.WriteFile(file.FullName);
Response.Flush(); //以上将生成的word文件发送至用户浏览器 File.Delete("cutput.docx");

2、特殊字符

代码实现起来很简单。

run之前的代码就不写了。大家可以网上搜索。

run.FontFamily = "Wingdings 2";//这边是特殊字符的字体
text = text.Replace("name", Convert.ToChar(0x0052).ToString());//0x0052是特殊字符的十六进制代码
//text = text.Replace("name", "R");//该代码也可以实现(0x0052对应的字符就是R)

3、NOPI读取Word模板并渲染保存

using NPOI.XWPF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web; namespace TestNPOI
{
public class NPOIHleper
{ public static void Export()
{
string filepath = HttpContext.Current.Server.MapPath("~/simpleTable.docx");
var tt = new { name = "cjc", age = };
using (FileStream stream = File.OpenRead(filepath))
{
XWPFDocument doc = new XWPFDocument(stream);
//遍历段落
foreach (var para in doc.Paragraphs)
{
ReplaceKey(para, tt);
} //遍历表格
var tables = doc.Tables;
foreach (var table in tables)
{
foreach (var row in table.Rows)
{
foreach (var cell in row.GetTableCells())
{
foreach (var para in cell.Paragraphs)
{
ReplaceKey(para, tt);
}
}
}
} FileStream out1 = new FileStream(HttpContext.Current.Server.MapPath("~/simpleTable" + DateTime.Now.Ticks + ".docx"), FileMode.Create);
doc.Write(out1);
out1.Close();
}
} private static void ReplaceKey(XWPFParagraph para, object model)
{
string text = para.ParagraphText;
var runs = para.Runs;
string styleid = para.Style;
for (int i = ; i < runs.Count; i++)
{
var run = runs[i];
text = run.ToString();
Type t = model.GetType();
PropertyInfo[] pi = t.GetProperties();
foreach (PropertyInfo p in pi)
{
//$$与模板中$$对应,也可以改成其它符号,比如{$name},务必做到唯一
if (text.Contains("$" + p.Name + "$"))
{
text = text.Replace("$" + p.Name + "$", p.GetValue(model, null).ToString());
}
}
runs[i].SetText(text, );
}
} }
}

 

模板:

结果:

二、实践(渲染Word模板、插入特殊字符、指定表格位置插入行)

1、项目搭建

1、创建项目

2、创建类库和引入NPOI

报错

报搜尝试解决方案一

在项目下面建立upload文件夹,然后使用相对路径访问。

 在其他目录下请把upload目录权限授予asp.net用户。

 最后直接暴力EveryOney  也无效,找到的原因是参数位置搞错了,文件名+路径最后改为 路径+文件名的方式
 

3、贴上代码

using NPOI.XWPF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web; namespace NPOITest
{
public class NPOIHleper
{ /// <summary>
/// 输出模板docx文档
/// </summary>
/// <param name="tempFilePath">模板文件地址</param>
/// <param name="outFolder">输出文件夹</param >
/// <param name="fileName">文件名</param>
/// <param name="data">数据格式Json->new { name = "cjc", age = 29 }</param>
public static void CreateWord(string tempFilePath, string outFolder, string fileName, object data)
{
using (FileStream stream = File.OpenRead(tempFilePath))
{
XWPFDocument doc = new XWPFDocument(stream);
//遍历段落
foreach (var para in doc.Paragraphs)
{
ReplaceKey(para, data);
} //遍历表格
var tables = doc.Tables;
foreach (var table in tables)
{
foreach (var row in table.Rows)
{
foreach (var cell in row.GetTableCells())
{
foreach (var para in cell.Paragraphs)
{
ReplaceKey(para, data);
}
}
}
}
var fullPath = Path.Combine(outFolder, fileName);
FileStream outFile = new FileStream(fullPath, FileMode.Create);
doc.Write(outFile);
outFile.Close();
}
}
/// <summary>
/// 遍历替换段落位置字符
/// </summary>
/// <param name="para">段落参数</param>
/// <param name="model">数据</param>
private static void ReplaceKey(XWPFParagraph para, object model)
{
string text = para.ParagraphText;
var runs = para.Runs;
string styleid = para.Style;
for (int i = ; i < runs.Count; i++)
{
var run = runs[i];
text = run.ToString();
Type t = model.GetType();
PropertyInfo[] pi = t.GetProperties();
foreach (PropertyInfo p in pi)
{
//$$与模板中$$对应,也可以改成其它符号,比如{$name},务必做到唯一
if (text.Contains("{$"+p.Name+"}"))
{
text = text.Replace("{$" + p.Name+"}", p.GetValue(model, null).ToString());
}
}
runs[i].SetText(text, );
}
}
}
}

调用方式

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace NPOITest.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
var data = new { name = "cjc", age = };
string fileName = Guid.NewGuid() + "_声明.docx";
string folder = Server.MapPath("~/upload"); //当前运行环境
string tempTemplateFile = folder+"/测试.docx";
string folders = "D:\\TempFile"; //当前运行环境
NPOIHleper.CreateWord(tempTemplateFile, folders, fileName, data);
//
ViewBag.Title = "Home Page"; return View();
}
}
}

对应模板

三、实践(指定表格位置插入行)

代码:

using NPOI.OpenXmlFormats.Wordprocessing;
using NPOI.XWPF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web; namespace NPOITest
{
public class NPOIHleper
{ /// <summary>
/// 输出模板docx文档
/// </summary>
/// <param name="tempFilePath">模板文件地址</param>
/// <param name="outFolder">输出文件夹</param >
/// <param name="fileName">文件名</param>
/// <param name="data">数据格式Json->new { name = "cjc", age = 29 }</param>
public static void CreateWord(string tempFilePath, string outFolder, string fileName, object data)
{
using (FileStream stream = File.OpenRead(tempFilePath))
{
XWPFDocument doc = new XWPFDocument(stream);
//遍历段落
foreach (var para in doc.Paragraphs)
{
ReplaceKey(para, data);
} //遍历表格
var tables = doc.Tables;
foreach (var table in tables)
{
foreach (var row in table.Rows)
{
foreach (var cell in row.GetTableCells())
{
foreach (var para in cell.Paragraphs)
{
ReplaceKey(para, data);
}
}
}
}
//单独对表格新增
var oprTable = tables[]; XWPFTableRow m_Row=oprTable.InsertNewTableRow();//创建一行/并且在某个位置添加一行
m_Row.AddNewTableCell().SetText ("创建一行仅有一个单元格"); //XWPFTableRow m_Row2 = oprTable.InsertNewTableRow(2);//创建一行/并且在某个位置添加一行
////m_Row2.AddNewTableCell().SetText("添加的新行");
//XWPFTableCell cellCt_P = m_Row2.CreateCell();//创建一个单元格,创建单元格时就创建了一个CT_P //cellCt_P = m_Row2.CreateCell();
//cellCt_P = m_Row2.CreateCell(); ////单元格行和表
//CT_Tc cttc = cellCt_P.GetCTTc();
//CT_TcPr ctPr = cttc.AddNewTcPr();
////ctPr.gridSpan.val = "3";//合并3列
//ctPr.AddNewVMerge().val = ST_Merge.restart;//合并行
//cellCt_P.SetText("创建一行仅有一个单元格(合并后)"); XWPFTableRow m_Row2 = oprTable.InsertNewTableRow();//创建一行/并且在某个位置添加一行
XWPFTableCell tc3 = m_Row2.CreateCell();//创建单元格
tc3.SetText("创建一行仅有一个单元格(合并后)");
CT_Tc ct3 = tc3.GetCTTc();
CT_TcPr cp3 = ct3.AddNewTcPr();
cp3.gridSpan = new CT_DecimalNumber();
cp3.gridSpan.val = ""; //合并3列 XWPFTableRow m_Row3 = oprTable.InsertNewTableRow();//多个单元格以及合并
m_Row3.AddNewTableCell().SetText("添加的新行单元格1");
m_Row3.AddNewTableCell().SetText("添加的新行单元格2");
m_Row3.AddNewTableCell().SetText("添加的新行单元格3"); var fullPath = Path.Combine(outFolder, fileName);
FileStream outFile = new FileStream(fullPath, FileMode.Create);
doc.Write(outFile);
outFile.Close();
}
}
/// <summary>
/// 遍历替换段落位置字符
/// </summary>
/// <param name="para">段落参数</param>
/// <param name="model">数据</param>
private static void ReplaceKey(XWPFParagraph para, object model)
{
string text = para.ParagraphText;
var runs = para.Runs;
string styleid = para.Style;
for (int i = ; i < runs.Count; i++)
{
var run = runs[i];
text = run.ToString();
Type t = model.GetType();
PropertyInfo[] pi = t.GetProperties();
foreach (PropertyInfo p in pi)
{
//$$与模板中$$对应,也可以改成其它符号,比如{$name},务必做到唯一
if (text.Contains("{$" + p.Name + "}"))
{
text = text.Replace("{$" + p.Name + "}", p.GetValue(model, null).ToString());
}
}
runs[i].SetText(text, );
}
}
}
}

结果:

 

四、实践(指定表格内单元格(字体)下划线+字符)

简单说明:

                XWPFParagraph p1 = doc.CreateParagraph(); //段落
XWPFRun _run = p1.CreateRun();
_run.SetText("一个单元格");
_run.SetUnderline(UnderlinePatterns.Single);//段落下划线

既有文字加文字(下划线)

                XWPFTableRow m_Row2 = oprTable.InsertNewTableRow();//创建一行/并且在某个位置添加一行
XWPFTableCell tc3 = m_Row2.CreateCell();//创建单元格
//tc3.SetText("创建一行仅有一个单元格(合并后)"); XWPFParagraph p1 = doc.CreateParagraph(); //段落
XWPFRun _run = p1.CreateRun();
_run.SetText("一个单元格");
_run.SetUnderline(UnderlinePatterns.Single);//段落 XWPFParagraph p12 = doc.CreateParagraph(); //无段落
XWPFRun _run2 = p1.CreateRun();
_run2.SetText("一个单元格"); tc3.SetParagraph(p1);

这种写法我发现别扭,应该为

                //单独对表格新增
var oprTable = tables[1]; XWPFTableRow m_Row2 = oprTable.InsertNewTableRow(2);//创建一行/并且在某个位置添加一行
XWPFTableCell tc3 = m_Row2.CreateCell();//创建单元格 XWPFParagraph p1 = doc.CreateParagraph(); //段落1开始 1、注意这个段落是Doc创建的会导致表格外有段落出现
XWPFRun _run = p1.CreateRun();
_run.SetText("下划线");
_run.SetUnderline(UnderlinePatterns.Single);//段落1结束 //_run.AddCarriageReturn();2、注意只对表格外换行有效
XWPFRun _run2 = p1.CreateRun();
_run2.SetText("#####"); tc3.SetParagraph(p1);

  发现我需要换行,思路还是不对,经过我读取拿到文档的数据结构,即表格的XWPFTableCell单元格paragraph属性如下:

经更改

                //单独对表格新增
var oprTable = tables[]; XWPFTableRow m_Row2 = oprTable.InsertNewTableRow();//创建一行/并且在某个位置添加一行
XWPFTableCell tc3 = m_Row2.CreateCell();//创建单元格 XWPFParagraph p1 = tc3.AddParagraph();
XWPFRun _run = p1.CreateRun();
_run.SetText("下划线");
_run.SetUnderline(UnderlinePatterns.Single);//段落1结束 //_run.AddCarriageReturn();2、注意只对表格外换行有效
XWPFParagraph p2 = tc3.AddParagraph();
XWPFRun _run2 = p2.CreateRun();
_run2.SetText("####"); //这里设置了一下 //在复制这个就无效了 tc3.SetParagraph(p1); 想要添加通过(add方式)tc3.AddParagraph();
tc3.SetParagraph(p1);

五、实践出现模板渲染替换问题

解决办法:删掉->重新写->可以从记事本复制

其他妙用

//新建段落     

XWPFParagraph p1 = doc.CreateParagraph();

//对齐方式

 p1.SetAlignment(ParagraphAlignment.LEFT);

p1.SetVerticalAlignment(TextAlignment.AUTO);

//Word边框样式

p1.SetBorderBottom(Borders.DOUBLE);
p1.SetBorderTop(Borders.DOUBLE);
p1.SetBorderRight(Borders.DOUBLE);
p1.SetBorderLeft(Borders.DOUBLE); p1.SetBorderBetween(Borders.SINGLE); //新建文字 XWPFRun rUserHead = p1.CreateRun(); //文字内容 rUserHead.SetText("员工 : "); //颜色 rUserHead.SetColor("4F6B72"); //大小 rUserHead.SetFontSize(); //是否加粗 rUserHead.SetBold(true); //字体 rUserHead.SetFontFamily("宋体"); //是否有下划线 //r1.SetUnderline(UnderlinePatterns.DotDotDash); //位置 rUserHead.SetTextPosition(); //增加换行 rUserHead.AddCarriageReturn();

需求整理(动态在某个单元格内插入多个字段)

1、原本样子以及要实现的效果

实现的效果

原因:

需求整理(动态插入表格)

1、原本样子以及要实现的效果

C# 生成word文档(NPOI.XWPF)的更多相关文章

  1. PoiDocxDemo【Android将表单数据生成Word文档的方案之二(基于Poi4.0.0),目前只能java生成】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 这个是<PoiDemo[Android将表单数据生成Word文档的方案之二(基于Poi4.0.0)]>的扩展,上一篇是根 ...

  2. PoiDemo【Android将表单数据生成Word文档的方案之二(基于Poi4.0.0)】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 使用Poi实现android中根据模板文件生成Word文档的功能.这里的模板文件是doc文件.如果模板文件是docx文件的话,请阅读 ...

  3. Aspose.Words简单生成word文档

    Aspose.Words简单生成word文档 Aspose.Words.Document doc = new Aspose.Words.Document(); Aspose.Words.Documen ...

  4. ASP.NET生成WORD文档,服务器部署注意事项

    网上转的,留查备用,我服务器装的office2007所以修改的是Microsoft Office word97 - 2003 文档这一个. ASP.NET生成WORD文档服务器部署注意事项 1.Asp ...

  5. POI生成WORD文档

    h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h ...

  6. PowerDesigner将PDM导出生成WORD文档

    PowerDesigner将PDM导出生成WORD文档 环境 PowerDesigner15 1.点击Report Temlates 制作模板 2.如果没有模板,单击New图标创建.有直接双击进入. ...

  7. velocity模板技术生成word文档

    本文介绍採用velocity技术在Java中生成word文档的方法. 1.新建一个word文档,编辑内容例如以下: 2.将上述word文档另存为htm格式的文件 3.新建一个Java Project项 ...

  8. 使用C#动态生成Word文档/Excel文档的程序测试通过后,部署到IIS服务器上,不能正常使用的问题解决方案

    使用C#动态生成Word文档/Excel文档的程序功能调试.测试通过后,部署到服务器上,不能正常使用的问题解决方案: 原因: 可能asp.net程序或iis访问excel组件时权限不够(Ps:Syst ...

  9. 用php生成word文档

    一.用windows里面自带的com,然后用php生成word文档 <?php $word= new COM("word.application") or die(" ...

  10. c#生成word文档

    参考:http://blog.163.com/zhouchunping_99/blog/static/7837998820085114394716/ 生成word文档 生成word文档 view pl ...

随机推荐

  1. 带你一文搞定 IO 流相关核心问题

    问:简单谈谈 Java IO 流各实现类的特性? 答:java.io 包下面的流基本都是装饰器模式的实现,提供了各种类型流操作的便携性,常见的流分类如下. 以二进制字节方式读写的流: InputStr ...

  2. [LeetCode] 53. Maximum Subarray 最大子数组 --动态规划+分治

    Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...

  3. MaxCompute Studio 使用入门

    MaxCompute Studio 是MaxCompute 平台提供的安装在开发者客户端的大数据集成开发环境工具,是一套基于流行的集成开发平台 IntelliJ IDEA 的开发插件,可以帮助您方便地 ...

  4. kafka消费组、消费者

    consumer group consumer instance 一个消费组可能有一个或者多个消费者.同一个消费组可以订阅一个或者多个主题.主题的某一个分区只能被消费组的某一个消费者消费.那么分区和消 ...

  5. [USACO17DEC]Barn Painting (树形$dp$)

    题目链接 Solution 比较简单的树形 \(dp\) . \(f[i][j]\) 代表 \(i\) 为根的子树 ,\(i\) 涂 \(j\) 号颜色的方案数. 转移很显然 : \[f[i][1]= ...

  6. Python_006(is和==,小数据池)

    一.is和==的区别 1.id()方法,可以查看一个变量的内存地址 lst = ["周杰伦", "燃哥"] lst1 = ["周杰伦", & ...

  7. 【HDOJ6684】Rikka with Game(博弈)

    题意:有一个由小写字母组成的字符串,A和B两个人轮流操作,A想让序列的字典序最大,B想最小 两人都能任意选择一位上的字母将其右移一位(a->b,b->c……z->a)或者直接结束游戏 ...

  8. Appium解决native+webview混合型APP(公众号、小程序)切换webview后元素无法定位问题

    问题:最近在做一个安卓+H5混合开发的APP自动化测试,发现在从native切换到webview后,元素仍然无法找到,报错:no such element 思路:于是思考webview会不会像web页 ...

  9. [CSP-S模拟测试]:神炎皇(数学)

    题目描述 神炎皇乌利亚很喜欢数对,他想找到神奇的数对. 对于一个整数对$(a,b)$,若满足$a+b\leqslant n$且$a+b$是$ab$的因子,则称为神奇的数对.请问这样的数对共有多少呢? ...

  10. php面向对象三大特性

    1.封装: 目的:使类更加安全 步骤:1.成员变量变成private(私有的)2.设置方法/调用方法3.在方法中增加限制 <?php class shao { private $aa;//必须是 ...