Pregunta

Tengo el formulario infopath 2010.diseñado como información del estudiante.Quiero generar el informe como documento de Word usando OpenXMl con la plantilla de informe especificada.Para diseñar el formulario de tal manera que,

  • Todos los campos se colocan en el formulario de ruta de información como texto por ahora.

  • y agregó el control del botón.

  • Al hacer clic en el botón, obtengo los valores de los campos utilizando objetos XPathNavigator.
  • Ahora tengo un conjunto de variables de cadena con valores.
  • He preparado el archivo .dotx con controles de contenido.(¿Necesito dar una identificación a cada control?)

Pero no puedo entender cómo puedo asignar los valores de mis variables a los controles de contenido de la plantilla de Word mediante programación usando C#. [Adjunto][1] el gran ejemplo de OpenXMl con web.pero utiliza una parte Xml personalizada, que se utiliza para volcar datos de un archivo xml a una plantilla de Word.

¿Qué tengo que hacer para asignar mis variables de cadena con controles de contenido de plantilla?¿Algún enlace de referencia para esto?

¿Fue útil?

Solución

Tuve que lograr algo muy similar y terminé usando campos "PlaceHolder" personalizados en lugar de los campos de Word (tienen varias limitaciones, como encabezado, pie de página y cuerpo, todos usando objetos diferentes).

En mi plantilla de Word, marqué un PlaceHolder como este: ##MyPlaceHolderName!#.Luego analicé el texto de la plantilla de Word para encontrar todos los PlaceHolders usando RegEx y los reemplacé con los valores reales del formulario de InfoPath.

El único inconveniente de esta solución es que sus PlaceHolders y sus campos de InfoPath deberán tener el mismo nombre; de ​​lo contrario, no podrá realizar ninguna coincidencia.

Considere este método:

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;
}

Lo usarías de la siguiente manera:

//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);
}

Sé que Xml-Replacing y xmlProperties son relativamente locos, pero tuve que implementarlo así debido a mis requisitos (el método lo llama un servicio web desde InfoPath).Déjame saber si necesitas más ayuda.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top