Draw underline for merge fields and extend until right margin in Aspose.Words

Hello Support,

I have one word document template, which has some merge fields. After mail merge I want that merged text to be underline, but that under line should extend until right margin even if there is blank space after text.

For example below is text from my document. I want underline from starting position of «RecordOwner1Name» and it should go until «RecordOwner4Name». So after mail merge these two line might get converted into 3, 4, 6 lines depending upon text length. I can give you my input doc and output doc, but I dont see any option to attach.

Name of Record Owner: «RecordOwner1Name» «RecordOwner2Name» «RecordOwner3Name» «RecordOwner4Name»

@shripad.maryland,

To ensure a timely and accurate response, please ZIP and attach the following resources here for testing:

  • Your simplified input Word documents
  • Aspose.Words generated output document showing the undesired behavior
  • Your expected document showing the correct output. You can create expected document by using MS Word. Please also list the steps that you performed in MS Word to create expected document.
  • Please also create a simplified standalone application (source code without compilation errors) that helps us to reproduce your current problem on our end and attach it here for testing.

As soon as you get these pieces of information ready, we will start investigation into your scenario and provide you more information. Thanks for your cooperation.

P.S. You can also upload the ZIP file to Dropbox and share the Download link here for testing.

As requested I have send zip file link to download. Zip file contains below

  1. Simplified input word document (B1_Template.docx). This documents also contains comments and those are only for your information.
  2. Aspose.Words generated output document showing the undesired behavior(B1_AfterMailMergeUsingAspose.pdf).
  3. Expected document showing correct output (B1_ExpectedOutput.pdf AND B1_ExpectedOutput.docx). I created this document in MS word manually and then saved as PDF.
  4. Standalone simplified application with source code. (POC_MailMerge FOLDER)

Steps I used to create expected word document.

  1. I used B1_Template.docx and manually typed data in place of merged fields.
  2. Then manually draw line (shape) with precised width so that it will align to Left and Right margin.
  3. Then saved as pdf.

Zipfile download from below
https://www.dropbox.com/s/0uqzo9iqpggo8bh/Aspose.Words.POC.zip?dl=0

Please let me know if you need more information or details.

@shripad.maryland,

We are checking this scenario and will get back to you soon.

Any update on this?

@shripad.maryland,

Please spare us some time for the investigation of this scenario. We will get back to you with our findings soon.

@shripad.maryland,

Sample documents are attached: Docs.zip (92.0 KB)

You can build logic on the following code to get the desired output:

Document document = new Document("E:\\Temp\\Aspose.Words.POC\\B1_Template.docx");
DocumentBuilder builder = new DocumentBuilder(document);

#region pre-process
document.FirstSection.Body.GetChildNodes(NodeType.Shape, true).Clear();
document.FirstSection.Body.GetChildNodes(NodeType.Comment, true).Clear();

foreach(Run run in document.FirstSection.Body.GetChildNodes(NodeType.Run, true))
{
    run.Font.Underline = Underline.None;
}
#endregion

#region add hidden bookmarks before every merge field
int i = 0;
foreach(Field field in document.Range.Fields)
{
    if (field.Type == FieldType.FieldMergeField)
    {
        FieldMergeField mf = (FieldMergeField)field;
        builder.MoveToMergeField(mf.FieldName, false, false);
        builder.StartBookmark("_bm" + i);
        builder.EndBookmark("_bm" + i);
        i++;
    }
}
#endregion

#region perform mail merge
DataTable dt = new DataTable();
dt.Columns.Add("NOIDate");
dt.Columns.Add("RecordOwner1Name");
dt.Columns.Add("RecordOwner2Name");
dt.Columns.Add("RecordOwner3Name");
dt.Columns.Add("RecordOwner4Name");
dt.Columns.Add("RecordOwner1Address");
dt.Columns.Add("RecordOwner2Address");
dt.Columns.Add("RecordOwner3Address");
dt.Columns.Add("RecordOwner4Address");
dt.Columns.Add("PropertyAddress");
dt.Columns.Add("SecuredPartyName");
dt.Columns.Add("SecuredPartyPhone");
dt.Rows.Add("06/26/2019", "ABC INC (RECORD OWNER 1); ", "Tom Hanks (RECORD OWNER 2); ", "Johnny Depp (RECORD OWNER 3); ", "Will Smith (RECORD OWNER 4)",
            "10109 REDOAKPINK WAY, ELLERSLIE, MD, 21529 (RECORD OWNER 1); ", "20108 JEFFERSON WAY, Unit:4205, ELLERSLIE, MD, 21529, 4654 (RECORD OWNER 2); ",
            "30104 REDPINE Park, ELLERSLIE, MD, 21529, 4654 (RECORD OWNER 3); ", "12578 Elkridge WAY, Unit:4205, ELLERSLIE, MD, 21529, 4646 (RECORD OWNER 4)",
            "10100 PINK WAY, Unit:4205, ELLERSLIE, MD, 21529", "ABC Bank", "4654654564");

document.MailMerge.Execute(dt.Rows[0]);
#endregion

#region draw lines underneath each mail-merged line
var collector = new LayoutCollector(document);
var it = new LayoutEnumerator(document);

foreach (Paragraph paragraph in document.FirstSection.Body.GetChildNodes(NodeType.Paragraph, true))
{
    bool hasBookmark = false;
    Bookmark bmFirst = null;
    foreach (Bookmark bm in paragraph.Range.Bookmarks)
    {
        if (bm.Name.StartsWith("_bm"))
        {
            bmFirst = bm;
            hasBookmark = true;
            break;
        }
    }

    if (hasBookmark)
    {
        var paraBreak = collector.GetEntity(paragraph);

        object stop = null;
        var prevItem = paragraph.PreviousSibling;
        if (prevItem != null)
        {
            var prevBreak = collector.GetEntity(prevItem);
            if (prevItem is Paragraph)
            {
                it.Current = collector.GetEntity(prevItem); // para break
                it.MoveParent();    // last line
                stop = it.Current;
            }
            else if (prevItem is Table)
            {
                var table = (Table)prevItem;
                it.Current = collector.GetEntity(table.LastRow.LastCell.LastParagraph); // cell break
                it.MoveParent();    // cell
                it.MoveParent();    // row
                stop = it.Current;
            }
            else
            {
                throw new Exception();
            }
        }

        it.Current = paraBreak;
        it.MoveParent();

        if (it.Rectangle.Width > 0)
            AddLine(paragraph, it.Rectangle.Bottom, it.Rectangle.Left, it.Rectangle.Width);

        while (it.Current != stop)
        {
            if (!it.MovePreviousLogical())
                break;

            if (it.Rectangle.Width > 0)
                AddLine(paragraph, it.Rectangle.Bottom, it.Rectangle.Left, it.Rectangle.Width);
        }

        //foreach (Shape shape in paragraph.GetChildNodes(NodeType.Shape, true))
        //{
        //    shape.Top -= 7;
        //}

        it.Current = collector.GetEntity(bmFirst.BookmarkStart);
        PageSetup ps = paragraph.ParentSection.PageSetup;
        Shape shape = (Shape)paragraph.LastChild;
        shape.Left = it.Rectangle.Left;
        shape.Width = shape.Width - it.Rectangle.Left + ps.LeftMargin;
    }
}
#endregion

#region remove hidden bookmarks
foreach (Bookmark bm in document.Range.Bookmarks)
{
    if (bm.Name.StartsWith("_bm"))
    {
        bm.Remove();
    }
}
#endregion

document.UpdatePageLayout();
document.Save("E:\\Temp\\Aspose.Words.POC\\19.7.pdf");

public static void AddLine(Paragraph para, double top, double left, double width)
{
    DocumentBuilder builder = new DocumentBuilder((Document)para.Document);
    builder.MoveTo(para);

    Shape line = new Shape((Document)para.Document, ShapeType.Line);
    line.StrokeColor = Color.Blue;
    line.RelativeHorizontalPosition = RelativeHorizontalPosition.Page;
    line.RelativeVerticalPosition = RelativeVerticalPosition.Page;
    line.WrapType = WrapType.None;

    builder.InsertNode(line);

    line.Width = width;
    line.Left = left;
    line.Top = top;
}