这个功能用NPOI来做会跟简单一点,NPOI XWPFRun类下有一个AddPicture API 可以直接调用API来替换,我这边因为是做了一个onlyOffice在线编辑的功能,onlyOffice编辑过的文档格式与NPOI兼容,所以找到了这个。
安装包
Install-Package DocumentFormat.OpenXml
2、来一个配置模型
using DocumentFormat.OpenXml.Packaging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace ReportGeneration.Model
{
public class ImageData_Model
{
public string FileName = string.Empty;
public byte[] BinaryData;
public Stream DataStream => new MemoryStream(BinaryData);
public ImagePartType ImageType
{
get
{
var ext = Path.GetExtension(FileName).TrimStart('.').ToLower();
switch (ext)
{
case "jpg":
return ImagePartType.Jpeg;
case "png":
return ImagePartType.Png;
case "":
return ImagePartType.Gif;
case "bmp":
return ImagePartType.Bmp;
}
throw new ApplicationException($"Unsupported image type: {ext}");
}
}
public int SourceWidth;
public int SourceHeight;
public decimal Width;
public decimal Height;
public long WidthInEMU => Convert.ToInt64(Width * CM_TO_EMU);
public long HeightInEMU => Convert.ToInt64(Height * CM_TO_EMU);
private const decimal INCH_TO_CM = 2.54M;
private const decimal CM_TO_EMU = 360000M;
public string ImageName;
public ImageData_Model(string fileName, byte[] data, int dpi = 300)
{
FileName = fileName;
BinaryData = data;
//Bitmap img = new Bitmap(new MemoryStream(data));
SourceWidth = 1;
SourceHeight = 1;
Width = ((decimal)SourceWidth) / dpi * INCH_TO_CM;
Height = ((decimal)SourceHeight) / dpi * INCH_TO_CM;
ImageName = $"IMG_{Guid.NewGuid().ToString().Substring(0, 8)}";
}
public ImageData_Model(string fileName, int dpi = 300) :
this(fileName, File.ReadAllBytes(fileName), dpi)
{
}
}
}
替换帮助类
注意:命名空间的引用,部分命名空间下有相同的属性注意区分
using System.IO;
using System.Linq;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using ReportGeneration.Model;
using A = DocumentFormat.OpenXml.Drawing;
using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using PIC = DocumentFormat.OpenXml.Drawing.Pictures;
namespace ReportGeneration.Helper
{
/// <summary>
/// 使用DocumentFormat.OpenXml替换word中模板字符串为图片
/// </summary>
public class DocxImgHelper
{
/// <summary>
/// 替换word中占位符为图片
/// </summary>
/// <param name="document">word实例</param>
/// <param name="imagePath">图片绝对地址</param>
/// <param name="placeholder">占位符</param>
public static void DocxImageReplace(WordprocessingDocument document,string imagePath,string placeholder)
{
var cat1Img = new ImageData_Model(imagePath)
{
Width = 15,
Height = 9
};
//var cat2Img = new ImageData(imagePaths);
var imgRun = GenerateImageRun(document, cat1Img);
var runCAT = document.MainDocumentPart.Document.Body.Descendants()
.Single(o => o.LocalName == "r" && o.InnerText == placeholder);
//document.MainDocumentPart.Document.Body.AppendChild(new Paragraph(imgRun));
//將 InnerXML 替换成图片 Run 的 InnerXML
runCAT.InnerXml = imgRun.InnerXml;
}
/// <summary>
/// 生成图像
/// </summary>
/// <param name="wordDoc"></param>
/// <param name="img"></param>
/// <returns></returns>
private static Run GenerateImageRun(WordprocessingDocument wordDoc, ImageData_Model img)
{
MainDocumentPart mainPart = wordDoc.MainDocumentPart;
ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Jpeg);
var relationshipId = mainPart.GetIdOfPart(imagePart);
imagePart.FeedData(img.DataStream);
// Define the reference of the image.
var element =
new Drawing(
new DW.Inline(
//Size of image, unit = EMU(English Metric Unit)
//1 cm = 360000 EMUs
new DW.Extent() { Cx = img.WidthInEMU, Cy = img.HeightInEMU },
new DW.EffectExtent()
{
LeftEdge = 0L,
TopEdge = 0L,
RightEdge = 0L,
BottomEdge = 0L
},
new DW.DocProperties()
{
Id = (UInt32Value)1U,
Name = img.ImageName
},
new DW.NonVisualGraphicFrameDrawingProperties(
new A.GraphicFrameLocks() { NoChangeAspect = true }),
new A.Graphic(
new A.GraphicData(
new PIC.Picture(
new PIC.NonVisualPictureProperties(
new PIC.NonVisualDrawingProperties()
{
Id = (UInt32Value)0U,
Name = img.FileName
},
new PIC.NonVisualPictureDrawingProperties()),
new PIC.BlipFill(
new A.Blip(
new A.BlipExtensionList(
new A.BlipExtension()
{
Uri =
"{28A0092B-C50C-407E-A947-70E740481C1C}"
})
)
{
Embed = relationshipId,
CompressionState =
A.BlipCompressionValues.Print
},
new A.Stretch(
new A.FillRectangle())),
new PIC.ShapeProperties(
new A.Transform2D(
new A.Offset() { X = 0L, Y = 0L },
new A.Extents()
{
Cx = img.WidthInEMU,
Cy = img.HeightInEMU
}),
new A.PresetGeometry(
new A.AdjustValueList()
)
{ Preset = A.ShapeTypeValues.Rectangle }))
)
{ Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" })
)
{
DistanceFromTop = (UInt32Value)0U,
DistanceFromBottom = (UInt32Value)0U,
DistanceFromLeft = (UInt32Value)0U,
DistanceFromRight = (UInt32Value)0U,
EditId = "50D07946"
});
return new Run(element);
}
}
}
调用
//图表
//参数注解在帮助类注释上有
DocxImgHelper.DocxImageReplace(document, $"{ImagePath}/{flagConfig.Value}",itemInnerText);