0

我有 infopath 2010 表格。设计为学生信息。我想使用带有指定报告模板的 OpenXMl 将报告生成为 word 文档。对我设计了这样的形式,

  • 现在,所有字段都以文本形式放置在 infopath 表单上。

  • 并添加了按钮控件。

  • 在按钮单击上,我正在使用 XPathNavigator 对象获取字段的值。
  • 现在我有一组带有值的字符串变量。
  • 我已经准备好带有内容控件的 .dotx 文件。(我是否需要为每个控件提供 id )

但无法理解如何使用 c# 以编程方式将我的变量值映射到 word 模板内容控件。[特此][1 ] 带有 web 的 OpenXMl 的绝佳示例。但它使用的是自定义 Xml Part ,用于将数据从 xml 文件转储到 word 模板。

我必须做什么才能将我的字符串变量与模板内容控件映射?有任何参考链接吗?

4

1 回答 1

1

我不得不实现一些非常相似的东西,我最终使用了自定义的“PlaceHolder”字段而不是 Word 字段(它们确实有各种限制,例如 - 页眉、页脚和正文都使用不同的对象)。

在我的 word 模板中,我标记了一个像这样的 PlaceHolder - ##MyPlaceHolderName!#。然后,我使用 RegEx 解析 word 模板的文本以查找所有 PlaceHolders,并将它们替换为 InfoPath 表单的实际值。

此解决方案的唯一缺点是,您的 PlaceHolders 和 InfoPath 字段需要具有相同的名称,否则您将无法进行任何匹配。

考虑这种方法:

private void FillDocument(Stream documentStream, string xmlFields)
{
    var doc = new XmlDocument();
    doc.LoadXml(xmlFields);

    var props = doc.SelectSingleNode("properties");
    if (props == null) throw new Exception("No properties found.");

    //transform the xml properties to dictionary for easier replacement
    var fields = props.ChildNodes.Cast<XmlNode>().ToDictionary
        (node => string.Format("##{0}!#", node.Name), node => node.InnerText);


    using (var document = WordprocessingDocument.Open(documentStream, true))
    {
        var main = document.MainDocumentPart;

        //replace the fields in the main document
        main.Document.InnerXml = ReplaceFields(main.Document.InnerXml, fields);

        //replace the fields in the headers
        foreach (var headerPart in main.HeaderParts)
            headerPart.Header.InnerXml = ReplaceFields(headerPart.Header.InnerXml, fields);

        //replace the fields in the footers
        foreach (var footerPart in main.FooterParts)
            footerPart.Footer.InnerXml = ReplaceFields(footerPart.Footer.InnerXml, fields);

        main.Document.Save();
    }
}

private string ReplaceFields(string xmlPart, Dictionary<string, string> fields)
{
    //searches the xml for the declared fields
    var fieldRegex = new Regex("##[^#]*!#");
    var matches = fieldRegex.Matches(xmlPart);

    foreach (Match match in matches)
    {
        //the fields are within tags (InnerText) so remove all other xml stuff
        var innerRegex = new Regex("<[^>]*>");
        string fieldName = innerRegex.Replace(match.Groups[0].Value, "");

        //replace the actual value of the field
        if(fields.ContainsKey(fieldName))
            xmlPart = xmlPart.Replace(match.Groups[0].Value, fields[fieldName]);
    }

    return xmlPart;
}

您将按如下方式使用它:

//open the file from as stream (in this example, the file is opened from SP
using (var stream = templateFile.OpenBinaryStream())
{
    //iterate the properties you need and add them in this format 
    var xmlProperties = "<properties><MyPlaceHolderName>MyPlaceHolderValue</MyPlaceHolderName></properties>";

    //fill out the fields
    FillDocument(stream, xmlProperties);
}

我知道 Xml-Replacing 和 xmlProperties 相对疯狂,但由于我的要求,我不得不像这样实现它(方法由 InfoPath 的 WebService 调用)。如果您需要进一步的帮助,请告诉我。

于 2011-09-13T13:58:32.237 回答