Word Document от OpenXml из формы infopath - PullRequest
0 голосов
/ 09 сентября 2011

У меня есть форма infopath 2010.разработан как информация для студентов.Я хочу создать отчет как документ Word, используя OpenXMl с указанным шаблоном отчета.Чтобы я спроектировал форму так, чтобы

  • Все поля были помещены в форму infopath как текст.

  • и добавил кнопкуcontrol.

  • При нажатии кнопки я выбираю значения полей с помощью объектов XPathNavigator.
  • Теперь у меня есть набор строковых переменных со значениями.
  • У меня естьподготовил файл .dotx с элементами управления контентом.(Нужно ли давать идентификатор каждому элементу управления)

Но я не могу понять, как я могу сопоставить значения моих переменных с элементами управления содержимым шаблона слова программно, используя c #. [При этом] [1 ] отличный пример OpenXMl с сетью.но он использует пользовательскую часть XML, которая использует для выгрузки данных из файла XML в шаблон слова.

Что мне нужно сделать, чтобы сопоставить мои строковые переменные с элементами управления содержимым шаблона?любая ссылка для этого?

1 Ответ

1 голос
/ 13 сентября 2011

Мне пришлось получить что-то очень похожее, и я закончил тем, что использовал пользовательские поля "PlaceHolder" вместо полей Word (у них действительно есть различные ограничения, такие как - header, footer и body - все используют разные объекты).

В моем шаблоне слова я пометил PlaceHolder следующим образом - ## MyPlaceHolderName! #.Затем я проанализировал текст шаблона слова, чтобы найти все PlaceHolders, используя RegEx, и заменил их фактическими значениями формы 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 относительно сумасшедшие, но я должен был реализовать это так из-за моих требований(метод вызывается WebService из InfoPath).Дайте мне знать, если вам понадобится дополнительная помощь.

...