1、NPOI版本2.7.0, net框架4.8
2、安装OpenXMLSDKToolV25.msi
3、先创建一个word文档,并设置图片为浮于文字之上
4、OpenXML显示的结果
5、实际代码如下:
public class GenerateWordDemo
{
public GenerateWordDemo()
{
}
//https://blog.fileformat.com/zh/word-processing/npoi-api-for-processing-word-documents-in-net-an-overview/
//https://blog.csdn.net/sD7O95O/article/details/114108985
//https://blog.csdn.net/qq_38544249/article/details/124923848
private void SetPage(XWPFDocument doc)
{
// 设置页面的大小
CT_SectPr m_SectPr = new CT_SectPr(); //实例一个尺寸类的实例
m_SectPr.pgSz.w = 11906; //设置宽度(这里是一个ulong类型)
m_SectPr.pgSz.h = 16838; //设置高度(这里是一个ulong类型)
//页面边距
m_SectPr.pgMar.left = (ulong)80;//左边距
m_SectPr.pgMar.right = (ulong)80;//右边距
m_SectPr.pgMar.top = 80;//上边距
m_SectPr.pgMar.bottom = 80;//下边距
doc.Document.body.sectPr = m_SectPr; //设置页面的尺寸
}
/// <summary>
/// 加入内联二维码
/// </summary>
/// <param name="doc"></param>
/// <param name="paragraphy"></param>
private void AddInlineBarCode(XWPFDocument doc, XWPFParagraph paragraphy)
{
string appPath = System.AppDomain.CurrentDomain.BaseDirectory;
string imagePath = System.IO.Path.Combine(appPath, "Images");
string imageFile = System.IO.Path.Combine(imagePath, "BarCode.jpg");
// 二维码
XWPFRun run = paragraphy.CreateRun();
using (FileStream picFile = new FileStream(imageFile, FileMode.Open, FileAccess.Read))
{
XWPFPicture pic = run.AddPicture(picFile, (int)PictureType.PNG, "barcode.png", 100 * 10857, 100 * 12857);
}
}
private T LoadWordCT<T>(string xml, Func<XmlElement, T> act) where T : class
{
XmlDocument xmlDoc = new XmlDocument();
try
{
xmlDoc.LoadXml(xml);
var element = xmlDoc.DocumentElement;
return act(element);
}
catch (XmlException xe)
{
return null;
}
}
/// <summary>
/// 加入二维码
/// </summary>
/// <param name="doc"></param>
private void AddBarCode(XWPFDocument doc, XWPFParagraph paragraphy)
{
String relationId;
XWPFPictureData picData;
string appPath = System.AppDomain.CurrentDomain.BaseDirectory;
string imagePath = System.IO.Path.Combine(appPath, "Images");
string imageFile = System.IO.Path.Combine(imagePath, "BarCode.jpg");
using (FileStream picFile = new FileStream(imageFile, FileMode.Open, FileAccess.Read))
{
relationId = doc.AddPictureData(picFile, (int)PictureType.PNG);
picData = (XWPFPictureData)doc.GetRelationById(relationId);
}
XWPFRun run = paragraphy.CreateRun();
CT_RPr rpr = new CT_RPr();
rpr.AddNewNoProof();
run.GetCTR().rPr = rpr;
CT_Drawing drawing = run.GetCTR().AddNewDrawing();
drawing.anchor = new List<CT_Anchor>();
CT_Anchor an = new CT_Anchor();
//图片距正文上(distT)、下(distB)、左(distL)、右(distR)的距离。114300EMUS=3.1mm
an.distT = 0;
an.distB = 0;
an.distL = (uint)114300;
an.distR = (uint)114300;
an.relativeHeight = 251658240u;
an.behindDoc = false; //"0",图与文字的上下关系
an.locked = false; //"0"
an.layoutInCell = true; //"1"
an.allowOverlap = true; //"1"
an.simplePos1 = false;
an.simplePos1Specified = false;
//CT_Point2D simplePos = new CT_Point2D();
//simplePos.x = (long)0;
//simplePos.y = (long)0;
//an.simplePos = simplePos;
// https://www.cnblogs.com/zhangliming/archive/2013/04/02/2995655.html
string xml = "<wp:simplePos x=\"0\" y=\"0\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" />";
an.simplePos = LoadWordCT<CT_Point2D>(xml, x => CT_Point2D.Parse(x, null));
//图左上角坐标
CT_PosH posH = new CT_PosH();
posH.relativeFrom = ST_RelFromH.column;
posH.posOffset = -1292; //单位:EMUS,1CM=360000EMUS
an.positionH = posH;
CT_PosV posV = new CT_PosV();
posV.relativeFrom = ST_RelFromV.paragraph;
posV.posOffset = 51661;
an.positionV = posV;
an.extent = new NPOI.OpenXmlFormats.Dml.WordProcessing.CT_PositiveSize2D();
an.extent.cx = 1085700;
an.extent.cy = 1285700;
CT_EffectExtent effectExtent = new CT_EffectExtent();
effectExtent.b = 0L;
effectExtent.l = 0L;
effectExtent.r = 0L;
effectExtent.t = 0L;
an.effectExtent = effectExtent;
an.wrapNone = new CT_WrapNone();
an.docPr = new NPOI.OpenXmlFormats.Dml.WordProcessing.CT_NonVisualDrawingProps();
long id = run.Document.GetNextPicNameNumber((int)PictureType.PNG);
an.docPr.id = (uint)(id);
an.docPr.name = ("Drawing " + id);
an.docPr.descr = "barcode.png";
an.cNvGraphicFramePr = new NPOI.OpenXmlFormats.Dml.WordProcessing.CT_NonVisualGraphicFrameProperties();
an.graphic = new CT_GraphicalObject();
CT_GraphicalObjectData gd = new CT_GraphicalObjectData();
gd.uri = "http://schemas.openxmlformats.org/drawingml/2006/picture";
an.graphic.graphicData = gd;
// Grab the picture object
NPOI.OpenXmlFormats.Dml.Picture.CT_Picture pic = new NPOI.OpenXmlFormats.Dml.Picture.CT_Picture();
// Set it up
NPOI.OpenXmlFormats.Dml.Picture.CT_PictureNonVisual nvPicPr = pic.AddNewNvPicPr();
NPOI.OpenXmlFormats.Dml.CT_NonVisualDrawingProps cNvPr = nvPicPr.AddNewCNvPr();
/* use "0" for the id. See ECM-576, 20.2.2.3 */
cNvPr.id = (0);
/* This name is not visible in Word 2010 anywhere */
cNvPr.name = ("Picture " + id);
cNvPr.descr = "barcode.png";
CT_NonVisualPictureProperties cNvPicPr = nvPicPr.AddNewCNvPicPr();
cNvPicPr.AddNewPicLocks().noChangeAspect = true;
CT_BlipFillProperties blipFill = pic.AddNewBlipFill();
CT_Blip blip = blipFill.AddNewBlip();
blip.embed = run.Paragraph.Part.GetRelationId(picData);
blipFill.AddNewStretch().AddNewFillRect();
CT_ShapeProperties spPr = pic.AddNewSpPr();
CT_Transform2D xfrm = spPr.AddNewXfrm();
CT_Point2D off = xfrm.AddNewOff();
off.x = (0);
off.y = (0);
NPOI.OpenXmlFormats.Dml.CT_PositiveSize2D ext = xfrm.AddNewExt();
ext.cx = 100;
ext.cy = 100;
CT_PresetGeometry2D prstGeom = spPr.AddNewPrstGeom();
prstGeom.prst = (ST_ShapeType.rect);
prstGeom.AddNewAvLst();
using (var ms = RecyclableMemory.GetStream())
{
StreamWriter sw = new StreamWriter(ms);
pic.Write(sw, "pic:pic");
sw.Flush();
ms.Position = 0;
var sr = new StreamReader(ms);
var picXml = sr.ReadToEnd();
gd.AddPicElement(picXml);
}
drawing.anchor.Add(an);
}
private XWPFParagraph AddParagraph(XWPFDocument doc)
{
XWPFParagraph paragraphy = doc.CreateParagraph();
CT_PPr ppr = new CT_PPr();
CT_Spacing sp = ppr.AddNewSpacing();
// w:spacing w:after="20" w:line="430" w:lineRule="auto"
sp.after = 20;
sp.line = "430";
sp.lineRule = ST_LineSpacingRule.auto;
CT_Ind ind = ppr.AddNewInd();
ind.right = "10";
CT_Jc jc = ppr.AddNewJc();
// 左对齐
jc.val = ST_Jc.left;
CT_ParaRPr rpr = ppr.AddNewRPr();
rpr.rFonts = new CT_Fonts();
rpr.rFonts.ascii = "宋体";
rpr.rFonts.hAnsi = "宋体";
rpr.rFonts.eastAsia = "宋体";
rpr.rFonts.cs = "宋体";
rpr.b = new CT_OnOff();
rpr.b.val = true;
rpr.sz = new CT_HpsMeasure();
rpr.sz.val = 32;
paragraphy.GetCTP().pPr = ppr;
return paragraphy;
}
private XWPFParagraph AddTextParagraph(XWPFDocument doc)
{
XWPFParagraph paragraphy = doc.CreateParagraph();
CT_PPr ppr = new CT_PPr();
CT_Spacing sp = ppr.AddNewSpacing();
sp.lineRule = ST_LineSpacingRule.auto;
CT_Ind ind = ppr.AddNewInd();
CT_Jc jc = ppr.AddNewJc();
jc.val = ST_Jc.right;
CT_ParaRPr rpr = ppr.AddNewRPr();
rpr.rFonts = new CT_Fonts();
rpr.rFonts.ascii = "宋体";
rpr.rFonts.hAnsi = "宋体";
rpr.rFonts.eastAsia = "宋体";
rpr.rFonts.cs = "宋体";
rpr.b = new CT_OnOff();
rpr.b.val = true;
rpr.sz = new CT_HpsMeasure();
rpr.sz.val = 32;
paragraphy.GetCTP().pPr = ppr;
return paragraphy;
}
private XWPFRun AddTextRun(XWPFParagraph paragraphy, string text, ulong fontSize)
{
XWPFRun run = paragraphy.CreateRun();
run.IsBold = true;
CT_RPr rpr = new CT_RPr();
CT_Fonts ft = rpr.AddNewRFonts();
ft.ascii = "宋体";
ft.hAnsi = "宋体";
ft.eastAsia = "宋体";
ft.cs = "宋体";
rpr.AddNewB();
CT_HpsMeasure sz = rpr.AddNewSz();
sz.val = fontSize;
run.GetCTR().rPr = rpr;
run.SetText(text);
return run;
}
public bool CreateWordReport(string wordFile)
{
try
{
string appPath = System.AppDomain.CurrentDomain.BaseDirectory;
string checkTime = DateTime.Now.ToString("yyyy年MM月dd日");//检查时间
//TODO:使用FileStream文件流来写入数据(传入参数为:文件所在路径,对文件的操作方式,对文件内数据的操作)
//通过使用文件流,创建文件流对象,向文件流中写入内容,并保存为Word文档格式
using (var stream = new FileStream(wordFile, FileMode.Create, FileAccess.Write))
{
//创建document文档对象对象实例
XWPFDocument doc = new XWPFDocument();
XWPFParagraph paragraphy = AddParagraph(doc);
AddBarCode(doc, paragraphy);
paragraphy = AddTextParagraph(doc);
AddTextRun(paragraphy, "TEST1", 32);
paragraphy = AddTextParagraph(doc);
AddTextRun(paragraphy, "TEST2", 32);
paragraphy = AddTextParagraph(doc);
AddTextRun(paragraphy, "TEST3", 32);
//向文档流中写入内容,生成word
doc.Write(stream);
return true;
}
}
catch (Exception ex)
{
return false;
}
}
}