OpenXml 整理
最近專案交接 對方還在整理中,我也順便整理一下之前囤積的各種網站。
在 Microsoft Office 2007 版本以後的原始文件格式為 Open XML,Open XML 是一種 Ecma 標準,其中文字處理檔案的標記語言稱為 WordprocessingML。
簡單介紹了一下關於Open Xml後 接著來介紹如何使用
首先要用OpenXml 先從nuget中下載DocumentFormat.OpenXml
接著需要使用
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
以下為 參考 這篇 聽說已經棄用很久了,貌似是被稱為PoC版本的套版工具?
static void Example01_WordTmplRendering()
{
var docxBytes = WordRender.GenerateDocx(File.ReadAllBytes("AnnounceTemplate.docx"),
new Dictionary<string, string>()
{
["Title"] = "澄清黑暗執行緒部落格併購傳聞",
["SeqNo"] = "2021-FAKE-001",
["PubDate"] = "2021-04-01",
["Source"] = "亞太地區公關部",
["Content"] = @"
坊間媒體盛傳「史塔克工業將以美金 18 億元併購黑暗執行緒部落格」一事,
本站在此澄清並無此事。\n\n
史塔克公司執行長日前確實曾派遣代表來訪,雙方就技術合作一事交換意見,
相談甚歡,惟本站暫無出售計劃,且傳聞金額亦不符合本站預估價值(謎之聲:180 元都嫌貴),
純屬不實資訊。\n\n
本站將秉持初衷,持續發揚野人獻曝、敝帚自珍精神,歡迎舊雨新知繼續支持。"
});
File.WriteAllBytes(
Path.Combine(ResultFolder, $"套表測試-{DateTime.Now:HHmmss}.docx"),
docxBytes);
}
接著由於他有所謂的醒目文字,因此
var hiliteRuns = elem.Descendants<Run>() //找出鮮明提示
.Where(o => o.RunProperties?.Elements<Highlight>().Any() ?? false).ToList();
完整程式碼複製
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace Examples
{
public static class WordRender
{
static void ReplaceParserTag(this OpenXmlElement elem, Dictionary<string, string> data)
{
var pool = new List<Run>();
var matchText = string.Empty;
var hiliteRuns = elem.Descendants<Run>() //找出鮮明提示
.Where(o => o.RunProperties?.Elements<Highlight>().Any() ?? false).ToList();
foreach (var run in hiliteRuns)
{
var t = run.InnerText;
if (t.StartsWith("["))
{
pool = new List<Run> { run };
matchText = t;
}
else
{
matchText += t;
pool.Add(run);
}
if (t.EndsWith("]"))
{
var m = Regex.Match(matchText, @"\[\$(?<n>\w+)\$\]");
if (m.Success && data.ContainsKey(m.Groups["n"].Value))
{
var firstRun = pool.First();
firstRun.RemoveAllChildren<Text>();
firstRun.RunProperties.RemoveAllChildren<Highlight>();
var newText = data[m.Groups["n"].Value];
var firstLine = true;
foreach (var line in Regex.Split(newText, @"\\n"))
{
if (firstLine) firstLine = false;
else firstRun.Append(new Break());
firstRun.Append(new Text(line));
}
pool.Skip(1).ToList().ForEach(o => o.Remove());
}
}
}
}
public static byte[] GenerateDocx(byte[] template, Dictionary<string, string> data)
{
using (var ms = new MemoryStream())
{
ms.Write(template, 0, template.Length);
using (var docx = WordprocessingDocument.Open(ms, true))
{
docx.MainDocumentPart.HeaderParts.ToList().ForEach(hdr =>
{
hdr.Header.ReplaceParserTag(data);
});
docx.MainDocumentPart.FooterParts.ToList().ForEach(ftr =>
{
ftr.Footer.ReplaceParserTag(data);
});
docx.MainDocumentPart.Document.Body.ReplaceParserTag(data);
docx.Save();
}
return ms.ToArray();
}
}
}
}
參考
https://dotblogs.com.tw/chou/2010/04/30/14954
https://blog.darkthread.net/blog/word-template-rendering-with-openxml-sdk/
留言
張貼留言