Unable to wrap long URL in aspose word cell c#. Wrapping URL column is impacting other columns

I am also facing the same issue in aspose word where url is not getting wrapped. Tried with AutoFitTowindow, AutoFitToContent with allow autofit to false as well as true though url column is getting wrapped it is impacting other columns as in below screenshot
Please provide a solution for this issue
Here is snippet of code.

Document doc = new Document();
int counter = 0;
Table table = new Table(doc);
doc.FirstSection.Body.AppendChild(table);
Row rowHeader = GetNewRow(doc);
table.AppendChild(rowHeader);
Style style = GetTableRowHeaderStyle(doc);
style.Font.Size = 8;
Style styleRow = GetTableRowStyle(doc);
styleRow.Font.Size = 8;
string[] headers = new string[] { "ID", "Name", "Value", "Language" };
int[] cellWidths = new int[] { 300, 150, 400, 150 };
BuildRowHeader(doc, rowHeader, headers, style, cellWidths);

foreach (var languagesepecific in alllanguagelinklibrarydetails)
{
    languagesepecific.Value.ForEach((linklib) =>
    {
        counter++;
        Row row = GetNewRow(doc);
        table.AppendChild(row);
        Color cellColor = Color.FromArgb(221, 219, 213);
        if (counter % 2 != 0)
        {
            cellColor = Color.White;
        }

        doc = BuildTableCell(doc, row, Convert.ToString(linklib.code), cellColor, 0, styleRow, false);
        doc = BuildTableCell(doc, row, linklib.name, cellColor, 0, styleRow, false);
        doc = BuildTableCell(doc, row, linklib.value, cellColor, 0, styleRow, false);
        doc = BuildTableCell(doc, row, languagesepecific.Key, cellColor, 0, styleRow, false);
    });

}
table.AutoFit(AutoFitBehavior.AutoFitToWindow); 
table.SetBorders(LineStyle.Single, 1.0, Color.Gray);

indent preformatted text by 4 spaces

private static Document BuildTableCell(Document doc, Row tableRow, string cellText, Color cellBgColor, int borderWPreformattedtextidth, Style cellStyle, bool wrapText = false, double cellWidth = 0)
    {
        var cell = new Cell(doc);
        cell.CellFormat.Shading.BackgroundPatternColor = cellBgColor;
        cell.CellFormat.Borders.LineWidth = borderWidth;
        cell.CellFormat.WrapText = wrapText;
        cell.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
        cell.CellFormat.LeftPadding = 5;

        if (cellWidth != 0)
            cell.CellFormat.Width = cellWidth;
        tableRow.AppendChild(cell);
        var para = new Paragraph(doc);
        para.ParagraphFormat.Style = cellStyle;
        tableRow.LastCell.AppendChild(para);
        var htmlDocument = new HtmlAgilityPack.HtmlDocument();
        htmlDocument.LoadHtml(cellText);
        tableRow.LastCell.FirstParagraph.AppendChild(new Run(doc, htmlDocument.DocumentNode.InnerText));
        return doc;
    }

}

table.png (10.1 KB)

@Anil.Vebilisetty In your case, if you explicitly specify width of cells in your table you should use AutoFitBehavior.FixedColumnWidths. For example see the following simple code:

Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
Table table = builder.StartTable();
builder.InsertCell();
builder.CellFormat.Width = 100;
builder.Write("first cell");

builder.InsertCell();
builder.CellFormat.Width = 100;
builder.Write("https://www.google.com/search?q=this+is+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+url&sxsrf=ALiCzsa1DkcPnV8Vxv-_Z3jYmGpTNxC4hA%3A1664296642371&ei=wiYzY5upFqj6sAfioKXICQ&ved=0ahUKEwibkq2RtLX6AhUoPewKHWJQCZkQ4dUDCA4&uact=5&oq=this+is+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+long+url&gs_lcp=Cgdnd3Mtd2l6EAM6CggAEEcQ1gQQsAM6BAgjECc6CgguEMcBENEDEEM6BQgAEIAEOgQIABBDOgQILhBDOggILhCABBDUAjoFCC4QgAQ6BwgAEMkDEEM6BQguEMsBOgUIABDLAToICC4Q1AIQywE6BggAEB4QFjoFCAAQhgM6CAgAEB4QDxAWOgUIABCiBDoFCCEQoAFKBAhBGABKBAhGGABQ6QtYym5gm3FoAnABeACAAbABiAGNF5IBBDguMTiYAQCgAQGgAQLIAQjAAQE&sclient=gws-wiz");
builder.EndRow();

builder.InsertCell();
builder.CellFormat.Width = 100;
builder.Write("first cell");

builder.InsertCell();
builder.CellFormat.Width = 100;
builder.Write("this is normal text");
builder.EndRow();

builder.EndTable();

table.AllowAutoFit = false;
table.AutoFit(AutoFitBehavior.FixedColumnWidths);

doc.Save(@"C:\Temp\out.docx");

Here is the result: out.docx (7.6 KB)

@alexey.noskov I have tried with FixedColumnWidths as well but no luck

@Anil.Vebilisetty Could you please create a simple console application that will allow us to reproduce the problem? We will check the issue and provide you more information.
The code that you have shared earlier cannot be run and since is difficult to analyze.

@alexey.noskov As request I have written my code in console app as below.

using Aspose.Words;
using Aspose.Words.Tables;
using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.Drawing;

namespace asposewordtesttable
{
    internal class Program
    {
        static void Main(string[] args)
        {
            ConstructDoc();
        }

        private static void ConstructDoc()
        {
            string dataDir = @"C:\Users\avebiliset001\asposewordtest\";
            string Id = "123";
            string Name = "UrlText";
            string Value = "http://chart.apis.google.com/chart?chs=500x500&chma=0,0,100,100&cht=p&chco=FF0000%2CFFFF00%7CFF8000%2C00FF00%7C00FF00%2C0000FF&chd=t%3A122%2C42%2C17%2C10%2C8%2C7%2C7%2C7%2C7%2C6%2C6%2C6%2C6%2C5%2C5&chl=122%7C42%7C17%7C10%7C8%7C7%7C7%7C7%7C7%7C6%7C6%7C6%7C6%7C5%7C5&chdl=android%7Cjava%7Cstack-trace%7Cbroadcastreceiver%7Candroid-ndk%7Cuser-agent%7Candroid-webview%7Cwebview%7Cbackground%7Cmultithreading%7Candroid-source%7Csms%7Cadb%7Csollections%7Cactivity";
            string language = "en-US";
            Document doc = new Document();
            int counter = 0;
            Table table = new Table(doc);
            doc.FirstSection.Body.AppendChild(table);
            Row rowHeader = GetNewRow(doc);
            table.AppendChild(rowHeader);
            Style style = GetTableRowHeaderStyle(doc);
            style.Font.Size = 8;
            Style styleRow = GetTableRowStyle(doc);
            styleRow.Font.Size = 8;
            string[] headers = new string[] { "ID", "Name", "Value", "Language" };
            int[] cellWidths = new int[] { 100, 200, 600, 100 };
            BuildRowHeader(doc, rowHeader, headers, style, cellWidths);
            Row row = GetNewRow(doc);
            table.AppendChild(row);
            Color cellColor = Color.FromArgb(221, 219, 213);
            if (counter % 2 != 0)
            {
                cellColor = Color.White;
            }

            doc = BuildTableCell(doc, row, Id, cellColor, 0, styleRow, false);
            doc = BuildTableCell(doc, row, Name, cellColor, 0, styleRow, false);
            doc = BuildTableCell(doc, row, Value, cellColor, 0, styleRow, false);
            doc = BuildTableCell(doc, row, language, cellColor, 0, styleRow, false);
            table.AutoFit(AutoFitBehavior.FixedColumnWidths);
            table.SetBorders(LineStyle.Single, 1.0, Color.Gray);
            table.LeftIndent = 38.0;
            dataDir = dataDir + "test_1.doc";
            doc.Save(dataDir);
        }

        private static Row GetNewRow(Document doc)
        {
            var row = new Row(doc);
            row.RowFormat.AllowBreakAcrossPages = true;
            return row;
        }

        private static Style GetTableRowHeaderStyle(Document doc)
        {
            var style = doc.Styles.Add(StyleType.Paragraph, "DataViewStyleHeader");
            style.Font.Size = 5;
            style.Font.Name = "Arial";
            style.Font.Color = Color.White;
            style.ParagraphFormat.SpaceAfter = 0;
            style.ParagraphFormat.SpaceBefore = 0;
            return style;
        }

        private static Style GetTableRowStyle(Document doc)
        {
            var styleRow = doc.Styles.Add(StyleType.Paragraph, "DataViewStyleBody");
            styleRow.Font.Size = 5;
            styleRow.Font.Name = "Arial";
            styleRow.Font.Color = Color.Black;
            styleRow.ParagraphFormat.SpaceAfter = 0;
            styleRow.ParagraphFormat.SpaceBefore = 0;
            return styleRow;
        }

        private static void BuildRowHeader(Document doc, Row row, IReadOnlyList<string> headerTitles, Style headerStyle, IReadOnlyList<int> cellWidths = null)
        {
            for (int i = 0; i < headerTitles.Count; i++)
            {
                if (cellWidths != null && i < cellWidths.Count)
                {
                    doc = BuildTableCell(doc, row, headerTitles[i], Color.Red, 0, headerStyle, false, cellWidths[i]);
                }
                else
                {
                    doc = BuildTableCell(doc, row, headerTitles[i], Color.Gray, 0, headerStyle, false);
                }
            }
        }
        private static Document BuildTableCell(Document doc, Row tableRow, string cellText, Color cellBgColor,
           int borderWidth, Style cellStyle, bool wrapText = false, double cellWidth = 0)
        {
            var cell = new Cell(doc);
            cell.CellFormat.Shading.BackgroundPatternColor = cellBgColor;
            cell.CellFormat.Borders.LineWidth = borderWidth;
            cell.CellFormat.WrapText = wrapText;
            cell.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
            cell.CellFormat.LeftPadding = 5;

            if (cellWidth != 0)
                cell.CellFormat.Width = cellWidth;
            tableRow.AppendChild(cell);
            var para = new Paragraph(doc);
            para.ParagraphFormat.Style = cellStyle;
            tableRow.LastCell.AppendChild(para);
            var htmlDocument = new HtmlDocument();
            htmlDocument.LoadHtml(cellText);
            tableRow.LastCell.FirstParagraph.AppendChild(new Run(doc, htmlDocument.DocumentNode.InnerText));
            return doc;
        }
    }
}

Please help to resolve this issue as soon as possible. Thanks in advance.

@Anil.Vebilisetty Thank you for additional information. As I can see you do not specify cell widths in the second row. Please try modifying your code like this:

doc = BuildTableCell(doc, row, Id, cellColor, 0, styleRow, false, cellWidths[0]);
doc = BuildTableCell(doc, row, Name, cellColor, 0, styleRow, false, cellWidths[1]);
doc = BuildTableCell(doc, row, Value, cellColor, 0, styleRow, false, cellWidths[2]);
doc = BuildTableCell(doc, row, language, cellColor, 0, styleRow, false, cellWidths[3]);

Also, I changed widths of cells so the table fit the page:

int[] cellWidths = new int[] { 50, 50, 200, 100 };

The output document looks correct: out.zip (2.4 KB)

Thanks for your detailed response. It is working if I save the above document but when I tried to insert this table document into existing other document which had a placeholder called {{UrlTable}} it is not working as the same.
Below is the code I used to merge in other document
Here document to which I am trying to merge is finaldocument.

ReplaceString("{{UrlTable}}", urltable.Document.ToString(SaveFormat.Html), finaldocument, true);
private static Document ReplaceString(string mergeField, string value, Document mergeDocument, bool formatMaintain = true)
{
    if (string.IsNullOrEmpty(value))
        value = CONTENT_DISPLAY_NONE;
    var op = new FindReplaceOptions();
    op.FindWholeWordsOnly = false;
    op.MatchCase = true;
    op.ReplacingCallback = new FindAndInsertHtml(value, formatMaintain);
    mergeDocument.Range.Replace(new System.Text.RegularExpressions.Regex(mergeField), value, op);
    return mergeDocument;
}

Please help me with the suggestion in this case

@Anil.Vebilisetty As I can see in your code you convert the generated document to HTML and then using InsertHtml method to insert it into the destination document. You should note that HTML and MS Word document’s models are quite different and Word->HTML-Word roundtrip might cause formatting and MS Word features loses.
In your case you can avoid conversion to HTML and insert original generated document using DocumentBuilder.InsertDocument method.

In this documentation couldn’t able to find anything on how to replace a text placeholder in a document with other document. Could please suggest how to achieve that so that I will give a try

@Anil.Vebilisetty You can use code like this to insert a document at the placeholder:

Document doc = new Document(@"C:\Temp\in.docx");

FindReplaceOptions opt = new FindReplaceOptions();
ReplaceEvaluatorFindAndReplaceWithDocument callabck = new ReplaceEvaluatorFindAndReplaceWithDocument();
opt.ReplacingCallback = callabck;

callabck.ReplacementDocument = new Document(@"C:\Temp\replacement.docx");

doc.Range.Replace("[placeholder]", "", opt);
internal class ReplaceEvaluatorFindAndReplaceWithDocument : IReplacingCallback
{
    /// <summary>
    /// This method is called by the Aspose.Words find and replace engine for each match.
    /// </summary>
    ReplaceAction IReplacingCallback.Replacing(ReplacingArgs e)
    {
        Document doc = (Document)e.MatchNode.Document;

        // This is a Run node that contains either the beginning or the complete match.
        Node currentNode = e.MatchNode;

        // The first (and may be the only) run can contain text before the match, 
        // in this case it is necessary to split the run.
        if (e.MatchOffset > 0)
            currentNode = SplitRun((Run)currentNode, e.MatchOffset);

        // This array is used to store all nodes of the match for further deleting.
        List<Run> runs = new List<Run>();

        // Find all runs that contain parts of the match string.
        int remainingLength = e.Match.Value.Length;
        while (
            remainingLength > 0 &&
            currentNode != null &&
            currentNode.GetText().Length <= remainingLength)
        {
            runs.Add((Run)currentNode);
            remainingLength -= currentNode.GetText().Length;

            // Select the next Run node.
            // Have to loop because there could be other nodes such as BookmarkStart etc.
            do
            {
                currentNode = currentNode.NextSibling;
            } while (currentNode != null && currentNode.NodeType != NodeType.Run);
        }

        // Split the last run that contains the match if there is any text left.
        if (currentNode != null && remainingLength > 0)
        {
            SplitRun((Run)currentNode, remainingLength);
            runs.Add((Run)currentNode);
        }

        // Create DocumentBuilder to insert HTML.
        DocumentBuilder builder = new DocumentBuilder(doc);
        // Move builder to the first run.
        builder.MoveTo(runs[0]);
        // Insert Replacement document..
        builder.InsertDocument(ReplacementDocument, ImportFormatMode.KeepSourceFormatting);

        // Delete matched runs
        foreach (Run run in runs)
            run.Remove();

        // Signal to the replace engine to do nothing because we have already done all what we wanted.
        return ReplaceAction.Skip;
    }

    private static Run SplitRun(Run run, int position)
    {
        Run afterRun = (Run)run.Clone(true);
        run.ParentNode.InsertAfter(afterRun, run);
        afterRun.Text = run.Text.Substring(position);
        run.Text = run.Text.Substring((0), (0) + (position));
        return afterRun;
    }

    public Document ReplacementDocument { get; set; }
}

@alexey.noskov Issue resolved. Thank you so much.

1 Like