需要将多个Word文档一键合并成一个新的word文档,同时保留原先多个word文档的格式、样式、及图片。
经过一段时间的选型测试,最终选择了DocumentFormat.OpenXml这款开源库。
原理很简单,通过创建一个空白的word文档,然后遍历需要合并的word文档,追加到新建的word文档中,代码顺利编译通过,上代码如下
/// <summary>
/// 合并文档,合并后的word文档,图片会丢失
/// </summary>
/// <param name="paths">word文档路径集合</param>
/// <param name="breakNewPage">是否新页面</param>
/// <returns></returns>
public static byte[] MergeWordFiles1(string[] paths, bool breakNewPage = true)
{
using (var stream = new MemoryStream())
{
using (WordprocessingDocument mergedDocument = WordprocessingDocument.Create(stream, WordprocessingDocumentType.Document))
{
MainDocumentPart mainPart = mergedDocument.AddMainDocumentPart();
mainPart.Document = new Document();
mainPart.Document.AppendChild(new Body());
for (int i = 0; i < paths.Length; i++)
{
var path = paths[i];
if (!File.Exists(path)) continue;
using (WordprocessingDocument document = WordprocessingDocument.Open(path, false))
{
foreach (var element in document.MainDocumentPart.Document.Body.Elements())
{
mergedDocument.MainDocumentPart.Document.Body.AppendChild(element.CloneNode(true));
}
}
//如果需要换新页面
if (breakNewPage && i < paths.Length - 1)
{
mergedDocument.MainDocumentPart.Document.Body.Append(new Paragraph(new Run(new Break() { Type = BreakValues.Page })));
}
}
mergedDocument.Save();
}
return stream.ToArray();
}
}
通过以上代码,可以顺利合并文档,但当打开合并后的文档时发现存在一些问题,比如表格的边框没有了、图片也不存在了。
原先文档如下
合并后文档
继续查看官方文档,发现有个方法叫AltChunk,可以通过AltChunk这种方式实现文档合并,同时保留完整样式,于是调整代码如下
/// <summary>
/// 合并文档,合并后的文档图片正常
/// </summary>
/// <param name="paths">word文档路径集合</param>
/// <param name="breakNewPage">是否新页面</param>
/// <returns></returns>
public static byte[] MergeWordFiles2(string[] paths, bool breakNewPage = true)
{
using (var stream = new MemoryStream())
{
using (WordprocessingDocument mergedDocument = WordprocessingDocument.Create(stream, WordprocessingDocumentType.Document))
{
var mainPart = mergedDocument.AddMainDocumentPart();
mainPart.Document = new Document();
mainPart.Document.AppendChild(new Body());
for (var i = 0; i < paths.Length; i++)
{
var altChunkId = "cid_" + Guid.NewGuid().ToString().Replace("-", "");
var chunk = mainPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.WordprocessingML, altChunkId);
using (FileStream fileStream = File.Open(paths[i], FileMode.Open))
{
chunk.FeedData(fileStream);
}
var altChunk = new AltChunk();
altChunk.Id = altChunkId;
mainPart.Document.Append(altChunk);
//如果需要换新页面
if (breakNewPage && i < paths.Length - 1)
{
mainPart.Document.Append(new Paragraph(new Run(new Break() { Type = BreakValues.Page })));
}
}
mainPart.Document.Save();
}
return stream.ToArray();
}
}
生成文档如下
我们看到基本保持了原先的样式及图片。