Word OpenXML替换令牌文本

时间:2013-07-29 08:49:20

标签: c# ms-word openxml openxml-sdk

我正在使用OpenXML来修改Word模板,这些模板包含可由某些字符识别的简单令牌(目前是双V形(ascii 171和187))。

我想用我的文本替换这些标记,这些文本可能是多行的(即来自数据库)。

1 个答案:

答案 0 :(得分:5)

首先,您需要打开模板:

        //read file into memory
        byte[] docByteArray = File.ReadAllBytes(templateName);
        using (MemoryStream ms = new MemoryStream())
        {
            //write file to memory stream
            ms.Write(docByteArray, 0, docByteArray.Length);

            //
            ReplaceText(ms);

            //reset stream
            ms.Seek(0L, SeekOrigin.Begin);

            //save output
            using (FileStream outputStream = File.Create(docName))
                ms.CopyTo(outputStream);
        }

搜索正文的内部文本xml的简单方法是最快捷的方法,但不允许插入多行文本,也不会为扩展到更复杂的更改提供基础。

using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(ms, true))
{
     string docText = null;
     //read the entire document into a text
     using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
         docText = sr.ReadToEnd();

     //replace the text
     docText.Replace(oldString, myNewString);

     //write the text back
     using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
         sw.Write(docText);
}

相反,您需要使用元素和结构:

        using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(ms, true))
        {
            //get all the text elements
            IEnumerable<Text> texts = wordDoc.MainDocumentPart.Document.Body.Descendants<Text>();
            //filter them to the ones that contain the QuoteLeft char
            var tokenTexts = texts.Where(t => t.Text.Contains(oldString));

            foreach (var token in tokenTexts)
            {
                //get the parent element
                var parent = token.Parent;
                //deep clone this Text element
                var newToken = token.CloneNode(true);

                //split the text into an array using a regex of all line terminators
                var lines = Regex.Split(myNewString, "\r\n|\r|\n");

                //change the original text element to the first line
                ((Text) newToken).Text = lines[0];
                //if more than one line
                for (int i = 1; i < lines.Length; i++)
                {
                    //append a break to the parent
                    parent.AppendChild<Break>(new Break());
                    //then append the next line
                    parent.AppendChild<Text>(new Text(lines[i]));
                }

                //insert it after the token element
                token.InsertAfterSelf(newToken);
                //remove the token element
                token.Remove();
            }

            wordDoc.MainDocumentPart.Document.Save();
        }

基本上你会找到Text元素(Word是根据文本运行段落构建的),克隆它,更改它(如果需要,插入新的Break和Text元素),然后在原始标记Text元素之后添加它,最后删除原始令牌文本元素。