轉載自黑暗執行緒:https://blog.darkthread.net/blog/openxml-template-parser 個人學習紀錄
前幾天又有網友問起【雛型】Docx套版列印功能試作的程式範例。
當時文章發佈後,網友ABC, alan也問過何時釋出的問題。當時的考量是,我完成的只是PoC(Proof of Concept),尚非經實務驗證可行的解決方案,況且當下專案正式上線在即(文章中寧可用較簡陋的1.0正式版,也不要用2.0 CTP可見一斑),很快就可以檢驗這個做法的彈性及可靠度,等通過考驗再公佈也不遲。無奈,世事多變化,研究出套版方法沒多久,User調整了作業流程規劃,系統不再需要自行套版產生docx... orz 而後來,在其他專案也沒能再遇到實際上場的機會。就這樣,多年下來,這套做法一直維持在PoC階段,只能終年長坐冷板凳,抑鬱不得志,每日藉酒澆愁...
適逢網友再問起,就決定把當時的PoC程式分享出來,供需要參考的朋友自行取用。但必須聲明,這個版本只是PoC,沒實際上過戰場,也跟懶人包不同,在程式考量周延性或完整度上可能仍有欠缺,大家在應用時可想像成是小麥種子,而不是烤好的麵包。也很歡迎有將它實際應用在專案上的朋友能回饋分享自己裁種、收割、烘焙的心得~
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DocumentFormat.OpenXml.Packaging;
using System.IO;
namespace Darkthread.OpenXml
{
/// <summary>
/// Ver 1.0 By Jeffrey Lee, 2009-07-29
/// </summary>
public class DocxHelper
{
/// <summary>
/// Replace the parser tags in docx document
/// </summary>
/// <param name="oxp">OpenXmlPart object</param>
/// <param name="dct">Dictionary contains parser tags to replace</param>
private static void parse(OpenXmlPart oxp, Dictionary<string, string> dct)
{
string xmlString = null;
using (StreamReader sr = new StreamReader(oxp.GetStream()))
{ xmlString = sr.ReadToEnd(); }
foreach (string key in dct.Keys)
xmlString = xmlString.Replace("[$" + key + "$]", dct[key]);
using (StreamWriter sw = new StreamWriter(oxp.GetStream(FileMode.Create)))
{ sw.Write(xmlString); }
}
/// <summary>
/// Parse template file and replace all parser tags, return the binary content of
/// new docx file.
/// </summary>
/// <param name="templateFile">template file path</param>
/// <param name="dct">a Dictionary containing parser tags and values</param>
/// <returns></returns>
public static byte[] MakeDocx(string templateFile, Dictionary<string, string> dct)
{
string tempFile = Path.GetTempPath() + ".docx";
File.Copy(templateFile, tempFile);
using (WordprocessingDocument wd = WordprocessingDocument.Open(
tempFile, true))
{
//Replace document body
parse(wd.MainDocumentPart, dct);
foreach (HeaderPart hp in wd.MainDocumentPart.HeaderParts)
parse(hp, dct);
foreach (FooterPart fp in wd.MainDocumentPart.FooterParts)
parse(fp, dct);
}
byte[] buff = File.ReadAllBytes(tempFile);
File.Delete(tempFile);
return buff;
}
}
}
PS: 雖然當時程式是配合SDK 1.0寫的,經實測這段程式可配合Open XML Format SDK 2.0運作無誤,專案要參照DocumentFormat.OpenXml以及WindowsBase,即可順利編譯、執行。