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版本的套版工具?


貌似是用 [$ key $] 去當作抓取的目標,可以隨意調整裡面的屬性,因為替換之後會消失。



        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();

這段文字可以取得醒目文字,可以用這個去當作一個搜尋list找到醒目文字後組成 ["key"]樣式

完整程式碼複製

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/

留言

這個網誌中的熱門文章

無法載入檔案或組件 'System.IO.Compression' 或其相依性的其中之一。

MongoDB 入門

javascript 更改屬性及創建標籤