无法使用WordprocessingDocument在SdtElement中设置内容

时间:2015-05-04 11:22:22

标签: c# openxml placeholder wordprocessingml

我有一个模板文件,其中我放置了两个占位符。两者都是纯文本内容控件。我有以下代码,我将值设置为文件中的占位符。

static void Main(string[] args)
{          
    string fileName = "C:\\xxx\\Template.docx";
    byte[] fileContent = File.ReadAllBytes(fileName);
    using (MemoryStream memStream = new MemoryStream())
    {
        memStream.Write(fileContent, 0, (int)fileContent.Length);                
        using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(memStream,true))
        {
            MainDocumentPart mainPart = wordDoc.MainDocumentPart;
            var sdtElements = wordDoc.MainDocumentPart.Document.Descendants<SdtElement>();
            foreach (SdtElement sdtElement in sdtElements)
            {
                Tag blockTag = sdtElement.SdtProperties.Descendants<Tag>().ElementAt(0);
                Run nr = new Run();
                Text txt = new Text();
                txt.Text = "RKS";
                nr.Append(txt);
                Lock lckContent = new Lock();
                bool lockControl = true;
                if (lockControl)
                {
                    lckContent.Val = LockingValues.SdtContentLocked;
                }
                else
                {
                    lckContent.Val = LockingValues.Unlocked;
                }
                if (sdtElement is SdtBlock)
                {
                    (((SdtBlock)sdtElement).SdtContentBlock.ElementAt(0)).RemoveAllChildren();
                    (((SdtBlock)sdtElement).SdtContentBlock.ElementAt(0)).AppendChild<Run>(nr);

                    ((SdtBlock)sdtElement).SdtProperties.Append(lckContent);
                }
                if (sdtElement is SdtCell)
                {
                    ((SdtCell)sdtElement).SdtContentCell.ElementAt(0).Descendants<Paragraph>().ElementAt(0).RemoveAllChildren();                        ((SdtCell)sdtElement).SdtContentCell.ElementAt(0).Descendants<Paragraph>().ElementAt(0).AppendChild<Run>(nr);
                    ((SdtCell)sdtElement).SdtProperties.Append(lckContent);
                }
                if (sdtElement is SdtRun)
                {
                    //SdtContentText text = sdtElement.SdtProperties.Elements<SdtContentText>().FirstOrDefault();
                    //((SdtRun)sdtElement).SdtContentRun.ElementAt(0).AppendChild<Text>(emptyTxt);
                    ((SdtRun)sdtElement).SdtContentRun.ElementAt(0).RemoveAllChildren();
                    ((SdtRun)sdtElement).SdtContentRun.ElementAt(0).AppendChild<Run>(nr);
                    ((SdtRun)sdtElement).SdtProperties.Append(lckContent);
                }
            }
            wordDoc.MainDocumentPart.Document.Save();                    
        }
    }
}

代码成功运行,但更改未反映在文件中。

我错过了什么?

2 个答案:

答案 0 :(得分:1)

您正在从内存流中创建WordprocessingDocument,因此该类无法知道要写入哪个文件。它将所有更改写入内存流,而不是文件。

您可以通过调用WordprocessingDocument方法直接从文件创建WordprocessingDocument.Open并指定文件名称(请参阅https://msdn.microsoft.com/en-us/library/office/documentformat.openxml.packaging.wordprocessingdocument.aspx),然后更改应反映在文件中。

如果由于某种原因需要将文档加载到缓冲区中,则需要手动将数据从缓冲区复制回文件。

答案 1 :(得分:0)

经过一些实验,我无法理解它是如何工作的,但对我来说这很好。我只是用其他名称保存文件。

在代码行之后:wordDoc.MainDocumentPart.Document.Save();我添加了

File.WriteAllBytes("C:\\xxx\\Sample.docx", memStream.ToArray());