首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >更换TextBox的InnerText

更换TextBox的InnerText
EN

Stack Overflow用户
提问于 2012-05-01 08:54:39
回答 1查看 4.2K关注 0票数 2

使用MS OpenXml软件开发工具包,我已经能够使用以下代码将模板流复制到结果流,并在正文末尾附加动态文本(w.p>>w.r>>w.t):

代码语言:javascript
复制
var templateStream = File.OpenRead(templatePath);
templateStream.CopyTo(resultStream);

using (var resultPackage = WordprocessingDocument.Open(resultStream, true))
{
     var document = resultPackage.MainDocumentPart.Document;

     var body = document.Body;

     // Add new text.
     var para = body.AppendChild(new Paragraph());
     var run = para.AppendChild(new Run());
     run.AppendChild(new Text(firstName));
     document.Save();
}

我的下一个逻辑步骤是用firstName替换resultStream中文本框的内部文本,如下面的代码所示。

代码语言:javascript
复制
// replacing code in using statement from above
var document = resultPackage.MainDocumentPart.Document;
var textbox = document.Descendants<TextBox>().First();
const string firstNametag = "<<IH.FirstName>>";
if (textbox.InnerText.Contains(firstNametag))
{
   var textboxContent = textbox.Elements<TextBoxContent>().First();
   textboxContent.RemoveAllChildren();
   var paragraph = textboxContent.AppendChild(new Paragraph());
   var run = paragraph.AppendChild(new Run());
   run.AppendChild(new Text(firstName));
}
document.Save();

在第一个示例中,使用一些附加代码将结果流适当地序列化为docx,并在Word中查看时将firstName附加到正文的末尾。在第二个示例中,尽管调试器中的进一步检查显示textboxContent的子项反映了上面所做的更改,但textbox及其内容保持不变。

我是OpenXML开发的新手,所以如果有什么明显的东西,请指出。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-05-03 11:53:01

哦,哇,我甚至不想认为我了解这方面的全部情况,但这里有一个快速的尝试。有更多openXml经验的人请插话...

当您在word中的docx上创建文本框时,document.xml文件get的标记如下:

代码语言:javascript
复制
<w.r>
    <mc.AlertnateContent>
        <mc.Choice Requires="wps">
            <wps:txbx>
                <w:txbxContent>
                    <w:r>
                        <w.t>
                            Text Goes Here
                        </w.t>
                    </w.r>
                </w:txbxContent>
            </wps:txbx>
        </mc.Choice>
        <mc.Fallback>
            <v.textbox>
                <w:txbxContent>
                    <w:r>
                        <w.t>
                            Text Goes Here
                        </w.t>
                    </w.r>
                </w:txbxContent>
            </v.textbox>
        </mc.Fallback>
    </mc.AlertnateContent>
</w.r>

请注意mc.AlternateContent、mc.Choice和mc.Fallback标记。这些到底是什么?有人在我看到的一篇博客文章里这么说-

“就我的理解而言--但不要把我的话当做福音-- AlternateContent可以出现在任何地方,并提供了一种机制,用于在消费应用程序能够处理它的情况下包含增强的功能,如果它不能处理它,还可以提供一个后备。”-Tony Jollans - http://social.msdn.microsoft.com/Forums/en-US/worddev/thread/f8a5c277-7049-48c2-a295-199d2914f4ba/

在我的例子中,我只修改了回退文本框(v.txbx而不是wps.txbx),因为我错误地认为Resharper要求我为我对TextBox对象的依赖导入DocumentFormat.OpenXml.Vml名称空间是正确的。我不确定为什么在我已经包含的名称空间DocumentFormat.OpenXml.Packaging或DocumentFormat.OpenXml.Wordprocessing中没有Textbox定义,但这超出了这个问题的范围。不用说,在意识到这一点并更新我的代码以查找这两个文件的公共w.txbxContent时,我实现了我想要做的事情。

下面是经过一些重构的更新代码,从原始问题中调用using语句中的ReplaceTag方法,并提供一个模型对象而不是字符串。此外,为方便起见,请使用tagToValueSelector字典。

代码语言:javascript
复制
private void ReplaceTags(Document document, SomeModel model)
{
    var textBoxContents = document.Descendants<TextBoxContent>().ToList();
    foreach (var textBoxContent in textBoxContents)
    {
        ReplaceTag(textBoxContent, model);
    }
}

private void ReplaceTag(TextBoxContent textBoxContent, SomeModel model)
{
    var tag = textBoxContent.InnerText.Trim();
    if (!tagsTomValues.ContainsKey(tag)) return;
    var valueSelector = tagsTomValues[tag];
    textBoxContent.RemoveAllChildren();
    var paragraph = textBoxContent.AppendChild(new Paragraph());
    var run = paragraph.AppendChild(new Run());
    run.AppendChild(new Text(valueSelector(model)));
}

// called in the ctor
private static void IntializeTags(IDictionary<string, Func<SomeModel, string>> dictionary)
{
    dictionary.Add("<<IH.Name>>", m => string.Format("{0} {1}", m.FirstName, m.LastName));
}

快乐openXmling :)

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10392309

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档