換表頭
class:
/*
參考來源:
Copy header with image from a docx file to another using open xml and c#
https://social.msdn.microsoft.com/Forums/Azure/en-US/7e34c135-361a-44cb-a9df-e6246f6ca781/copy-header-with-image-from-a-docx-file-to-another-using-open-xml-and-c?forum=oxmlsdk
*/
using System;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Drawing.Pictures;
//因為Wordprocessing與Drawing有許多class同名,須指定namespace,所以分別給這兩個namespace別名:
using WPS = DocumentFormat.OpenXml.Wordprocessing;
using DRW = DocumentFormat.OpenXml.Drawing;
using System.IO;
using System.Web.Hosting;
using System.Text;
using System.Collections.Generic;
namespace DMS.WebMVC.ApplicationForm
{
public class DocHeaderCopyer
{
HeaderPart _srcHeaderPart = null;
ImagePart _srcHeaderImage = null;
string _srcFilepath;
Dictionary<string, string> _textToReplace;
WordprocessingDocument _srcWordprocessingDocument, _dstWordprocessingDocument;
public DocHeaderCopyer(string srcFilepath, string dstFilepath, Dictionary<string, string> textToReplace)
{
try
{
ReadSourceDocHeaderWithImg(srcFilepath);
_srcFilepath = dstFilepath;
_textToReplace = textToReplace;
}
catch (Exception err)
{
throw err;
}
}
public bool Copy()
{
bool result = false;
try
{
WriteDestinationDocHeaderWithImg(_srcFilepath);
result = true;
}
catch (Exception err)
{
throw err;
}
finally
{
_srcWordprocessingDocument.Close();
}
return result;
}
private void ReadSourceDocHeaderWithImg(string srcFilepath)
{
try
{
//WordprocessingDocument srcWordprocessingDocument = WordprocessingDocument.Open(srcFilepath, false);
_srcWordprocessingDocument = WordprocessingDocument.Open(srcFilepath, false);
MainDocumentPart srcMainDocumentPart = _srcWordprocessingDocument.MainDocumentPart;
WPS.Document srcDocument = srcMainDocumentPart.Document;
WPS.SectionProperties srcSectionProperties = srcDocument.Descendants<WPS.SectionProperties>().FirstOrDefault();
WPS.HeaderReference srcHeaderReference = srcSectionProperties.Descendants<WPS.HeaderReference>()
.Where(H => H.Type == WPS.HeaderFooterValues.Default)
.FirstOrDefault();
_srcHeaderPart = srcMainDocumentPart.GetPartById(srcHeaderReference.Id) as HeaderPart;
_srcHeaderImage = _srcHeaderPart.ImageParts.FirstOrDefault();
}
catch (Exception err)
{
throw err;
}
}
private void WriteDestinationDocHeaderWithImg(string dstFilepath)
{
try
{
//WordprocessingDocument dstWordprocessingDocument = WordprocessingDocument.Open(dstFilepath, true);
_dstWordprocessingDocument = WordprocessingDocument.Open(dstFilepath, true);
MainDocumentPart dstMainDocumentPart = _dstWordprocessingDocument.MainDocumentPart;
WPS.Document dstDocument = dstMainDocumentPart.Document;
WPS.SectionProperties dstSectionProperties = dstDocument.Descendants<WPS.SectionProperties>().FirstOrDefault();
WPS.HeaderReference dstHeaderReference = dstSectionProperties.Descendants<WPS.HeaderReference>()
.Where(H => H.Type == WPS.HeaderFooterValues.Default)
.FirstOrDefault();
//若目的地檔案原有Header,刪掉它,新建一個
if (dstHeaderReference != null)
{
HeaderPart dstOldHeader = dstMainDocumentPart.GetPartById(dstHeaderReference.Id) as HeaderPart;
dstMainDocumentPart.DeletePart(dstOldHeader);
//把來源的Header(含圖)填入目的地檔案的Header
CreateAndFillNewHeaderPart(dstMainDocumentPart, dstHeaderReference);
}
else
//若目的地檔案原沒有Header,新建一個
{
//新建一個HeaderReference
dstHeaderReference = new WPS.HeaderReference() { Type = WPS.HeaderFooterValues.Default, Id = string.Empty };
//把來源的Header(含圖)填入目的地檔案的Header
CreateAndFillNewHeaderPart(dstMainDocumentPart, dstHeaderReference);
//把填好的新目的地檔案Header,加入到文件中
dstSectionProperties.Append(dstHeaderReference);
}
}
catch (Exception err)
{
throw err;
}
finally
{
_dstWordprocessingDocument.Close();
}
}
/// <summary>
/// 把來源的Header的內容(含圖)填入目的地檔案的Header
/// </summary>
private void CreateAndFillNewHeaderPart(MainDocumentPart dstMainDocumentPart, WPS.HeaderReference dstHeaderReference)
{
try
{
HeaderPart newHeaderPart = dstMainDocumentPart.AddNewPart<HeaderPart>();
if (_srcHeaderPart != null && _srcHeaderImage != null)
{
//不修改內容文字的話,用這個存到目的地檔案Header
//newHeaderPart.FeedData(_srcHeaderPart.GetStream());
#region change text
//換表頭內的文字(Header)
string headerText;
using (StreamReader reader = new StreamReader(_srcHeaderPart.GetStream()))
{
headerText = reader.ReadToEnd();
}
foreach (var item in _textToReplace)
{
headerText = headerText.Replace(item.Key, item.Value);
}
// convert string to stream, 存到目的地檔
byte[] byteArray = Encoding.UTF8.GetBytes(headerText);
using (MemoryStream stream = new MemoryStream(byteArray))
{
newHeaderPart.FeedData(stream);
}
#endregion
ImagePart newImagePart = newHeaderPart.AddImagePart(ImagePartType.Png);
newImagePart.FeedData(_srcHeaderImage.GetStream());
string newImageId = newHeaderPart.GetIdOfPart(newImagePart);
WPS.Header newHeader = newHeaderPart.Header;
WPS.Paragraph newParagraph = newHeader.Descendants<WPS.Paragraph>().FirstOrDefault();
WPS.Run newRun = newParagraph.Descendants<WPS.Run>().First();
WPS.Drawing newDrawing = newRun.Descendants<WPS.Drawing>().First();
DRW.GraphicData newGraphicData = newDrawing.Inline.Graphic.GraphicData;
Picture newPicture = newGraphicData.Descendants<Picture>().FirstOrDefault();
BlipFill newBlipFill = newPicture.Descendants<BlipFill>().FirstOrDefault();
newBlipFill.Blip.Embed = newImageId;
dstHeaderReference.Id = dstMainDocumentPart.GetIdOfPart(newHeaderPart);
}
else
{
throw (new Exception("沒有來源檔案的Header"));
}
}
catch (Exception err)
{
throw err;
}
}
}
}
use:
//testChangeWordHeader.aspx.cs
public string CopyFromTemplateHeader()
{
string strResult;
string serverPath = HostingEnvironment.MapPath("~/Docs");
string srcFilepath = Path.Combine(serverPath, "TemplateHeader.docx");
string dstFilepath = Path.Combine(serverPath, "Destination.docx");
Dictionary<string, string> textToReplace = new Dictionary<string, string>()
{
["-SN-"] = "12345",
["-Author-"] = "李小白",
["-Version-"] = "2.0",
["-ChineseTitle-"] = "月亮",
["-EnglishTitle-"] = "Moon",
};
DocHeaderCopyer copyer = new DocHeaderCopyer(srcFilepath, dstFilepath, textToReplace);
bool boolResult = copyer.Copy();
strResult = boolResult ? "換表頭完成" : "換表頭失敗";
return strResult;
}