Best way to update content in Form and Control fields in word keeping the layout information

Hello,

Aspose Word offers me to target a document.Range.Formfields (which I name old form fields) and StructuredDocumentTag (which I name new control form fields).

My use case is that I load a word document, search all fields and replace the content of such fields (text only). I implemented a method that does the job regarding existing documentation. In the documentation there is a .RemoveAllChildren() method that removes everything and after I add new child with my text.

My problem: I loose all format layouts (font, size, color, etc.).
My workaround at the moment is to defined those stuff outside of the control which do not work all the time (it is not handy to create a word document like this, many user fail to build their own working tempaltes).

So what I need:
I just want to replace content and keep all other layouts information.

My current code for this (which needs to be enhanced):

public void SetFormFieldValue(string name, string value)
{
    if (_document == null) return;

    // content controls
    foreach (StructuredDocumentTag sdt in _document.GetChildNodes(NodeType.StructuredDocumentTag, true))
    {
        if (sdt.Tag != name || sdt.SdtType != SdtType.PlainText) continue;
        try
        {
            if (sdt.FirstChild != null)
            {
                if (sdt.FirstChild.NodeType == NodeType.Cell)
                {
                    var para = new Paragraph(_document);
                    var run = new Run(_document, value);
                    para.AppendChild(run);

                    var cell = (Cell)sdt.FirstChild;
                    cell.RemoveAllChildren();
                    cell.AppendChild(para);
                }
                if (sdt.FirstChild.NodeType == NodeType.Paragraph)
                {
                    sdt.RemoveAllChildren();
                    var run = new Run(_document, value);
                    var para = new Paragraph(_document);
                    para.AppendChild(run);
                    sdt.AppendChild(para);
                }
                if (sdt.FirstChild.NodeType == NodeType.Run)
                {
                    sdt.RemoveAllChildren();
                    var run = new Run(_document, value);
                    sdt.AppendChild(run);
                }

            }
            else
            {
                if (sdt.Level == MarkupLevel.Block)
                {
                    sdt.RemoveAllChildren();
                    var run = new Run(_document, value);
                    var para = new Paragraph(_document);
                    para.AppendChild(run);
                    sdt.AppendChild(para);
                }
                else
                {
                    sdt.RemoveAllChildren();
                    var run = new Run(_document, value);
                    sdt.AppendChild(run);
                }
            }
        }
        catch (Exception ex)
        {
            _logger.ToLog(ex.ToString(), Company, "", Logfile);
        }
    }

    // ActiveX controls
    var documentFormFields = _document.Range.FormFields;
    var count = documentFormFields.Count;
    for (var i = 0; i < count; i++)
    {
        if (documentFormFields[i].Name == name)
            documentFormFields[i].SetTextInputValue(value);
    }

}

Hi Yves,

Thanks for your inquiry. In your case, we suggest you following solution.

  1. Get the first Run node of content control and clone it using Node.Clone method.
  2. Set text of cloned Run node to empty string using Run.Text property.
  3. Remove all children nodes of content control using RemoveAllChildren method.
  4. Insert the cloned Run node into content control and set its text with new text.

Hope this helps you. If you still face problem, please share your input and expected output documents here for our reference. We will then provide you more information about your query along with code.

Hello,
thanks for the info. I guessed something like this but as you can see there are different possible sections and I having problems to get it started.

Example NodeType.Cell . This probably have childrens. So you mean find the Run NodeType in this type? And NodeType.Paragraph the same?

If I clone a Run e.g. I can not find a .Text property. Can you give me examples?

Hi Yves,

Thanks for your inquiry. Following code example shows how to modify the content control’s text with same font formatting. You can use the same approach in your application. Hope this helps you.

If you still face problem, please share your input and expected output documents here for our reference. We will then provide you more information about your query along with code.

Document doc = new Document(MyDir + "in.docx");
foreach (StructuredDocumentTag sdt in doc.GetChildNodes(NodeType.StructuredDocumentTag, true))
{
    if (sdt.FirstChild != null)
    {
        if (sdt.FirstChild.NodeType == NodeType.Cell)
        {
            Paragraph paragraph = ((Cell)sdt.FirstChild).FirstParagraph;
            if (paragraph.Runs.Count > 0)
            {
                Run cloneRun = (Run)paragraph.Runs[0].Clone(true);
                paragraph.Runs.Clear();
                cloneRun.Text = "New Text";
                paragraph.AppendChild(cloneRun);
            }
        }
        else if (sdt.FirstChild.NodeType == NodeType.Paragraph)
        {
            Paragraph paragraph = (Paragraph)sdt.FirstChild;
            if (paragraph.Runs.Count > 0)
            {
                Run cloneRun = (Run)paragraph.Runs[0].Clone(true);
                paragraph.Runs.Clear();
                cloneRun.Text = "New Text";
                paragraph.AppendChild(cloneRun);
            }
        }
        else if (sdt.FirstChild.NodeType == NodeType.Run)
        {
            Run cloneRun = (Run)sdt.FirstChild;
            sdt.RemoveAllChildren();
            cloneRun.Text = "New Text";
            sdt.AppendChild(cloneRun);
        }
    }
}
doc.Save(MyDir + "Out.docx");

Works like expected, awesome! Thank you.