.NET 8 使用官方OpenXml SDK,替換Word中的文字和圖片

xuxuzhaozhao發表於2024-05-22

安裝好DocumentFormat.OpenXml後,準備好一個docx檔案

using DocumentFormat.OpenXml.Drawing.Wordprocessing;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System.Text.RegularExpressions;
using A = DocumentFormat.OpenXml.Drawing;

namespace Test02
{
    internal class Program
    {
        static void Main(string[] args)
        {
            ReplaceTextRequest textRequest = new ReplaceTextRequest
            {
                FileFullPath = "D:\\test-app\\test.docx",
                TextPlaceholderName = "佔位符",
                Text = "恐怖如斯丶吳彥祖"
            };
            ReplaceText(textRequest);

            var imageRequest = new ReplaceImageRequest
            {
                FileFullPath = "D:\\test-app\\test.docx",
                ImagePlaceholderName = "Picture 1",
                ImageFullPath = "C:\\Users\\xudashan\\Pictures\\高達\\1.png"
            };
            ReplaceImage(imageRequest);

            Console.WriteLine("OK");
        }

        static void ReplaceText(ReplaceTextRequest request)
        {
            using WordprocessingDocument wordDoc = WordprocessingDocument.Open(request.FileFullPath, true);

            if (wordDoc.MainDocumentPart == null)
            {
                throw new Exception("文件為空");
            }

            string docText = string.Empty;
            using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
            {
                docText = sr.ReadToEnd();
            }

            Regex regexText = new Regex(request.TextPlaceholderName);
            docText = regexText.Replace(docText, request.Text);

            using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
            {
                sw.WriteLine(docText);
            }
        }

        static void ReplaceImage(ReplaceImageRequest request)
        {
            using WordprocessingDocument document = WordprocessingDocument.Open(request.FileFullPath, true);

            if (document.MainDocumentPart == null)
            {
                throw new Exception("文件為空");
            }

            IEnumerable<Inline> imageElements = from run in document.MainDocumentPart.Document.Descendants<Run>()
                                                where run.Descendants<Inline>().First() != null
                                                select run.Descendants<Inline>().First();

            Inline selectedImage = (from image in imageElements
                                    where (image.DocProperties != null &&
                                           image.DocProperties.Name == request.ImagePlaceholderName)
                                    select image).First();

            A.Blip blipElement = selectedImage.Descendants<A.Blip>().First();
            if (blipElement.Embed == null || blipElement.Embed.Value == null)
            {
                throw new Exception("錯誤的模板標籤");
            }
            var imageId = blipElement.Embed.Value;

            ImagePart imagePart = (ImagePart)document.MainDocumentPart.GetPartById(imageId);
            byte[] imageBytes = File.ReadAllBytes(request.ImageFullPath);

            using BinaryWriter writer = new BinaryWriter(imagePart.GetStream());
            writer.Write(imageBytes);
        }
    }

    class ReplaceImageRequest
    {
        /// <summary>
        /// docx 檔案地址
        /// </summary>
        public string FileFullPath { get; set; }

        /// <summary>
        /// 圖片佔位的Name
        /// </summary>
        public string ImagePlaceholderName { get; set; }

        /// <summary>
        /// 待替換的圖片檔案
        /// </summary>
        public string ImageFullPath { get; set; }
    }

    class ReplaceTextRequest
    {
        /// <summary>
        /// docx 檔案地址
        /// </summary>
        public string FileFullPath { get; set; }

        /// <summary>
        /// 文字佔位的Name
        /// </summary>
        public string TextPlaceholderName { get; set; }

        /// <summary>
        /// 待替換的文字
        /// </summary>
        public string Text { get; set; }
    }
}

替換後

ps: 高達原圖

相關文章